@lobehub/lobehub 2.0.0-next.95 → 2.0.0-next.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/locales/ar/common.json +21 -0
  4. package/locales/ar/hotkey.json +4 -0
  5. package/locales/bg-BG/common.json +21 -0
  6. package/locales/bg-BG/hotkey.json +4 -0
  7. package/locales/de-DE/common.json +21 -0
  8. package/locales/de-DE/hotkey.json +4 -0
  9. package/locales/en-US/common.json +21 -0
  10. package/locales/en-US/hotkey.json +4 -0
  11. package/locales/es-ES/common.json +21 -0
  12. package/locales/es-ES/hotkey.json +4 -0
  13. package/locales/fa-IR/common.json +21 -0
  14. package/locales/fa-IR/hotkey.json +4 -0
  15. package/locales/fr-FR/common.json +21 -0
  16. package/locales/fr-FR/hotkey.json +4 -0
  17. package/locales/it-IT/common.json +21 -0
  18. package/locales/it-IT/hotkey.json +4 -0
  19. package/locales/ja-JP/common.json +21 -0
  20. package/locales/ja-JP/hotkey.json +4 -0
  21. package/locales/ko-KR/common.json +21 -0
  22. package/locales/ko-KR/hotkey.json +4 -0
  23. package/locales/nl-NL/common.json +21 -0
  24. package/locales/nl-NL/hotkey.json +4 -0
  25. package/locales/pl-PL/common.json +21 -0
  26. package/locales/pl-PL/hotkey.json +4 -0
  27. package/locales/pt-BR/common.json +21 -0
  28. package/locales/pt-BR/hotkey.json +4 -0
  29. package/locales/ru-RU/common.json +21 -0
  30. package/locales/ru-RU/hotkey.json +4 -0
  31. package/locales/tr-TR/common.json +21 -0
  32. package/locales/tr-TR/hotkey.json +4 -0
  33. package/locales/vi-VN/common.json +21 -0
  34. package/locales/vi-VN/hotkey.json +4 -0
  35. package/locales/zh-CN/common.json +21 -0
  36. package/locales/zh-CN/hotkey.json +4 -0
  37. package/locales/zh-TW/common.json +21 -0
  38. package/locales/zh-TW/hotkey.json +4 -0
  39. package/package.json +3 -1
  40. package/packages/const/src/hotkeys.ts +6 -0
  41. package/packages/conversation-flow/src/__tests__/indexing.test.ts +513 -0
  42. package/packages/conversation-flow/src/__tests__/structuring.test.ts +600 -0
  43. package/packages/types/src/hotkey.ts +1 -0
  44. package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +41 -8
  45. package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +6 -4
  46. package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/index.tsx +16 -4
  47. package/src/app/[variants]/(main)/settings/provider/(list)/index.tsx +15 -3
  48. package/src/app/[variants]/(main)/settings/provider/detail/index.tsx +23 -15
  49. package/src/layout/GlobalProvider/Cmdk.tsx +470 -0
  50. package/src/layout/GlobalProvider/CmdkLazy.tsx +17 -0
  51. package/src/layout/GlobalProvider/index.tsx +2 -0
  52. package/src/locales/default/common.ts +21 -0
  53. package/src/locales/default/hotkey.ts +4 -0
@@ -0,0 +1,600 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { buildHelperMaps } from '../indexing';
4
+ import { buildIdTree } from '../structuring';
5
+ import type { Message } from '../types';
6
+
7
+ describe('buildIdTree', () => {
8
+ describe('basic tree building', () => {
9
+ it('should build tree from single root message', () => {
10
+ const messages: Message[] = [
11
+ {
12
+ content: 'Root',
13
+ createdAt: 1000,
14
+ id: 'msg-1',
15
+ meta: {},
16
+ role: 'user',
17
+ updatedAt: 1000,
18
+ },
19
+ ];
20
+
21
+ const helperMaps = buildHelperMaps(messages);
22
+ const result = buildIdTree(helperMaps);
23
+
24
+ expect(result).toHaveLength(1);
25
+ expect(result[0]).toEqual({
26
+ children: [],
27
+ id: 'msg-1',
28
+ });
29
+ });
30
+
31
+ it('should build tree with linear conversation', () => {
32
+ const messages: Message[] = [
33
+ {
34
+ content: 'Message 1',
35
+ createdAt: 1000,
36
+ id: 'msg-1',
37
+ meta: {},
38
+ role: 'user',
39
+ updatedAt: 1000,
40
+ },
41
+ {
42
+ content: 'Message 2',
43
+ createdAt: 2000,
44
+ id: 'msg-2',
45
+ meta: {},
46
+ parentId: 'msg-1',
47
+ role: 'assistant',
48
+ updatedAt: 2000,
49
+ },
50
+ {
51
+ content: 'Message 3',
52
+ createdAt: 3000,
53
+ id: 'msg-3',
54
+ meta: {},
55
+ parentId: 'msg-2',
56
+ role: 'user',
57
+ updatedAt: 3000,
58
+ },
59
+ ];
60
+
61
+ const helperMaps = buildHelperMaps(messages);
62
+ const result = buildIdTree(helperMaps);
63
+
64
+ expect(result).toHaveLength(1);
65
+ expect(result[0].id).toBe('msg-1');
66
+ expect(result[0].children).toHaveLength(1);
67
+ expect(result[0].children[0].id).toBe('msg-2');
68
+ expect(result[0].children[0].children).toHaveLength(1);
69
+ expect(result[0].children[0].children[0].id).toBe('msg-3');
70
+ });
71
+
72
+ it('should handle multiple root messages', () => {
73
+ const messages: Message[] = [
74
+ {
75
+ content: 'Root 1',
76
+ createdAt: 1000,
77
+ id: 'msg-1',
78
+ meta: {},
79
+ role: 'user',
80
+ updatedAt: 1000,
81
+ },
82
+ {
83
+ content: 'Root 2',
84
+ createdAt: 2000,
85
+ id: 'msg-2',
86
+ meta: {},
87
+ role: 'user',
88
+ updatedAt: 2000,
89
+ },
90
+ ];
91
+
92
+ const helperMaps = buildHelperMaps(messages);
93
+ const result = buildIdTree(helperMaps);
94
+
95
+ expect(result).toHaveLength(2);
96
+ expect(result[0].id).toBe('msg-1');
97
+ expect(result[1].id).toBe('msg-2');
98
+ });
99
+ });
100
+
101
+ describe('branching conversations', () => {
102
+ it('should build tree with branches', () => {
103
+ const messages: Message[] = [
104
+ {
105
+ content: 'Root',
106
+ createdAt: 1000,
107
+ id: 'msg-1',
108
+ meta: {},
109
+ role: 'user',
110
+ updatedAt: 1000,
111
+ },
112
+ {
113
+ content: 'Branch 1',
114
+ createdAt: 2000,
115
+ id: 'msg-2',
116
+ meta: {},
117
+ parentId: 'msg-1',
118
+ role: 'assistant',
119
+ updatedAt: 2000,
120
+ },
121
+ {
122
+ content: 'Branch 2',
123
+ createdAt: 3000,
124
+ id: 'msg-3',
125
+ meta: {},
126
+ parentId: 'msg-1',
127
+ role: 'assistant',
128
+ updatedAt: 3000,
129
+ },
130
+ ];
131
+
132
+ const helperMaps = buildHelperMaps(messages);
133
+ const result = buildIdTree(helperMaps);
134
+
135
+ expect(result).toHaveLength(1);
136
+ expect(result[0].id).toBe('msg-1');
137
+ expect(result[0].children).toHaveLength(2);
138
+ expect(result[0].children[0].id).toBe('msg-2');
139
+ expect(result[0].children[1].id).toBe('msg-3');
140
+ });
141
+
142
+ it('should handle nested branches', () => {
143
+ const messages: Message[] = [
144
+ {
145
+ content: 'Root',
146
+ createdAt: 1000,
147
+ id: 'msg-1',
148
+ meta: {},
149
+ role: 'user',
150
+ updatedAt: 1000,
151
+ },
152
+ {
153
+ content: 'Branch 1',
154
+ createdAt: 2000,
155
+ id: 'msg-2',
156
+ meta: {},
157
+ parentId: 'msg-1',
158
+ role: 'assistant',
159
+ updatedAt: 2000,
160
+ },
161
+ {
162
+ content: 'Branch 1.1',
163
+ createdAt: 3000,
164
+ id: 'msg-3',
165
+ meta: {},
166
+ parentId: 'msg-2',
167
+ role: 'user',
168
+ updatedAt: 3000,
169
+ },
170
+ {
171
+ content: 'Branch 1.2',
172
+ createdAt: 4000,
173
+ id: 'msg-4',
174
+ meta: {},
175
+ parentId: 'msg-2',
176
+ role: 'user',
177
+ updatedAt: 4000,
178
+ },
179
+ ];
180
+
181
+ const helperMaps = buildHelperMaps(messages);
182
+ const result = buildIdTree(helperMaps);
183
+
184
+ expect(result).toHaveLength(1);
185
+ expect(result[0].children[0].id).toBe('msg-2');
186
+ expect(result[0].children[0].children).toHaveLength(2);
187
+ expect(result[0].children[0].children[0].id).toBe('msg-3');
188
+ expect(result[0].children[0].children[1].id).toBe('msg-4');
189
+ });
190
+
191
+ it('should handle deeply nested tree (4 levels)', () => {
192
+ const messages: Message[] = [
193
+ {
194
+ content: 'Level 0',
195
+ createdAt: 1000,
196
+ id: 'msg-1',
197
+ meta: {},
198
+ role: 'user',
199
+ updatedAt: 1000,
200
+ },
201
+ {
202
+ content: 'Level 1',
203
+ createdAt: 2000,
204
+ id: 'msg-2',
205
+ meta: {},
206
+ parentId: 'msg-1',
207
+ role: 'assistant',
208
+ updatedAt: 2000,
209
+ },
210
+ {
211
+ content: 'Level 2',
212
+ createdAt: 3000,
213
+ id: 'msg-3',
214
+ meta: {},
215
+ parentId: 'msg-2',
216
+ role: 'user',
217
+ updatedAt: 3000,
218
+ },
219
+ {
220
+ content: 'Level 3',
221
+ createdAt: 4000,
222
+ id: 'msg-4',
223
+ meta: {},
224
+ parentId: 'msg-3',
225
+ role: 'assistant',
226
+ updatedAt: 4000,
227
+ },
228
+ ];
229
+
230
+ const helperMaps = buildHelperMaps(messages);
231
+ const result = buildIdTree(helperMaps);
232
+
233
+ expect(result).toHaveLength(1);
234
+
235
+ let current = result[0];
236
+ expect(current.id).toBe('msg-1');
237
+
238
+ current = current.children[0];
239
+ expect(current.id).toBe('msg-2');
240
+
241
+ current = current.children[0];
242
+ expect(current.id).toBe('msg-3');
243
+
244
+ current = current.children[0];
245
+ expect(current.id).toBe('msg-4');
246
+ expect(current.children).toHaveLength(0);
247
+ });
248
+ });
249
+
250
+ describe('thread handling', () => {
251
+ it('should exclude messages with threadId from main tree', () => {
252
+ const messages: Message[] = [
253
+ {
254
+ content: 'Root',
255
+ createdAt: 1000,
256
+ id: 'msg-1',
257
+ meta: {},
258
+ role: 'user',
259
+ updatedAt: 1000,
260
+ },
261
+ {
262
+ content: 'Main flow',
263
+ createdAt: 2000,
264
+ id: 'msg-2',
265
+ meta: {},
266
+ parentId: 'msg-1',
267
+ role: 'assistant',
268
+ updatedAt: 2000,
269
+ },
270
+ {
271
+ content: 'Thread message',
272
+ createdAt: 3000,
273
+ id: 'msg-3',
274
+ meta: {},
275
+ parentId: 'msg-1',
276
+ role: 'assistant',
277
+ threadId: 'thread-1',
278
+ updatedAt: 3000,
279
+ },
280
+ ];
281
+
282
+ const helperMaps = buildHelperMaps(messages);
283
+ const result = buildIdTree(helperMaps);
284
+
285
+ expect(result).toHaveLength(1);
286
+ expect(result[0].id).toBe('msg-1');
287
+ expect(result[0].children).toHaveLength(1);
288
+ expect(result[0].children[0].id).toBe('msg-2');
289
+ });
290
+
291
+ it('should exclude root messages with threadId', () => {
292
+ const messages: Message[] = [
293
+ {
294
+ content: 'Main root',
295
+ createdAt: 1000,
296
+ id: 'msg-1',
297
+ meta: {},
298
+ role: 'user',
299
+ updatedAt: 1000,
300
+ },
301
+ {
302
+ content: 'Thread root',
303
+ createdAt: 2000,
304
+ id: 'msg-2',
305
+ meta: {},
306
+ role: 'assistant',
307
+ threadId: 'thread-1',
308
+ updatedAt: 2000,
309
+ },
310
+ ];
311
+
312
+ const helperMaps = buildHelperMaps(messages);
313
+ const result = buildIdTree(helperMaps);
314
+
315
+ expect(result).toHaveLength(1);
316
+ expect(result[0].id).toBe('msg-1');
317
+ });
318
+
319
+ it('should filter out thread children at any level', () => {
320
+ const messages: Message[] = [
321
+ {
322
+ content: 'Root',
323
+ createdAt: 1000,
324
+ id: 'msg-1',
325
+ meta: {},
326
+ role: 'user',
327
+ updatedAt: 1000,
328
+ },
329
+ {
330
+ content: 'Main child',
331
+ createdAt: 2000,
332
+ id: 'msg-2',
333
+ meta: {},
334
+ parentId: 'msg-1',
335
+ role: 'assistant',
336
+ updatedAt: 2000,
337
+ },
338
+ {
339
+ content: 'Main grandchild',
340
+ createdAt: 3000,
341
+ id: 'msg-3',
342
+ meta: {},
343
+ parentId: 'msg-2',
344
+ role: 'user',
345
+ updatedAt: 3000,
346
+ },
347
+ {
348
+ content: 'Thread grandchild',
349
+ createdAt: 4000,
350
+ id: 'msg-4',
351
+ meta: {},
352
+ parentId: 'msg-2',
353
+ role: 'user',
354
+ threadId: 'thread-1',
355
+ updatedAt: 4000,
356
+ },
357
+ ];
358
+
359
+ const helperMaps = buildHelperMaps(messages);
360
+ const result = buildIdTree(helperMaps);
361
+
362
+ expect(result).toHaveLength(1);
363
+ expect(result[0].children[0].id).toBe('msg-2');
364
+ expect(result[0].children[0].children).toHaveLength(1);
365
+ expect(result[0].children[0].children[0].id).toBe('msg-3');
366
+ });
367
+ });
368
+
369
+ describe('edge cases', () => {
370
+ it('should handle empty messages', () => {
371
+ const helperMaps = buildHelperMaps([]);
372
+ const result = buildIdTree(helperMaps);
373
+
374
+ expect(result).toEqual([]);
375
+ });
376
+
377
+ it('should handle messages with no children', () => {
378
+ const messages: Message[] = [
379
+ {
380
+ content: 'Lone message',
381
+ createdAt: 1000,
382
+ id: 'msg-1',
383
+ meta: {},
384
+ role: 'user',
385
+ updatedAt: 1000,
386
+ },
387
+ ];
388
+
389
+ const helperMaps = buildHelperMaps(messages);
390
+ const result = buildIdTree(helperMaps);
391
+
392
+ expect(result).toHaveLength(1);
393
+ expect(result[0]).toEqual({
394
+ children: [],
395
+ id: 'msg-1',
396
+ });
397
+ });
398
+
399
+ it('should handle messages with missing parent references', () => {
400
+ const messages: Message[] = [
401
+ {
402
+ content: 'Orphan',
403
+ createdAt: 1000,
404
+ id: 'msg-1',
405
+ meta: {},
406
+ parentId: 'non-existent',
407
+ role: 'user',
408
+ updatedAt: 1000,
409
+ },
410
+ ];
411
+
412
+ const helperMaps = buildHelperMaps(messages);
413
+ const result = buildIdTree(helperMaps);
414
+
415
+ // Orphan messages without valid parents are not in main flow
416
+ expect(result).toEqual([]);
417
+ });
418
+
419
+ it('should build correct tree when all messages are threaded', () => {
420
+ const messages: Message[] = [
421
+ {
422
+ content: 'Thread 1',
423
+ createdAt: 1000,
424
+ id: 'msg-1',
425
+ meta: {},
426
+ role: 'user',
427
+ threadId: 'thread-1',
428
+ updatedAt: 1000,
429
+ },
430
+ {
431
+ content: 'Thread 2',
432
+ createdAt: 2000,
433
+ id: 'msg-2',
434
+ meta: {},
435
+ role: 'assistant',
436
+ threadId: 'thread-1',
437
+ updatedAt: 2000,
438
+ },
439
+ ];
440
+
441
+ const helperMaps = buildHelperMaps(messages);
442
+ const result = buildIdTree(helperMaps);
443
+
444
+ expect(result).toEqual([]);
445
+ });
446
+ });
447
+
448
+ describe('complex scenarios', () => {
449
+ it('should build tree with mixed branches and linear paths', () => {
450
+ const messages: Message[] = [
451
+ {
452
+ content: 'Root',
453
+ createdAt: 1000,
454
+ id: 'msg-1',
455
+ meta: {},
456
+ role: 'user',
457
+ updatedAt: 1000,
458
+ },
459
+ {
460
+ content: 'Branch A',
461
+ createdAt: 2000,
462
+ id: 'msg-2',
463
+ meta: {},
464
+ parentId: 'msg-1',
465
+ role: 'assistant',
466
+ updatedAt: 2000,
467
+ },
468
+ {
469
+ content: 'Branch A -> Child',
470
+ createdAt: 3000,
471
+ id: 'msg-3',
472
+ meta: {},
473
+ parentId: 'msg-2',
474
+ role: 'user',
475
+ updatedAt: 3000,
476
+ },
477
+ {
478
+ content: 'Branch B',
479
+ createdAt: 4000,
480
+ id: 'msg-4',
481
+ meta: {},
482
+ parentId: 'msg-1',
483
+ role: 'assistant',
484
+ updatedAt: 4000,
485
+ },
486
+ {
487
+ content: 'Branch B -> Child 1',
488
+ createdAt: 5000,
489
+ id: 'msg-5',
490
+ meta: {},
491
+ parentId: 'msg-4',
492
+ role: 'user',
493
+ updatedAt: 5000,
494
+ },
495
+ {
496
+ content: 'Branch B -> Child 2',
497
+ createdAt: 6000,
498
+ id: 'msg-6',
499
+ meta: {},
500
+ parentId: 'msg-4',
501
+ role: 'user',
502
+ updatedAt: 6000,
503
+ },
504
+ ];
505
+
506
+ const helperMaps = buildHelperMaps(messages);
507
+ const result = buildIdTree(helperMaps);
508
+
509
+ expect(result).toHaveLength(1);
510
+ expect(result[0].id).toBe('msg-1');
511
+ expect(result[0].children).toHaveLength(2);
512
+
513
+ // Branch A
514
+ expect(result[0].children[0].id).toBe('msg-2');
515
+ expect(result[0].children[0].children).toHaveLength(1);
516
+ expect(result[0].children[0].children[0].id).toBe('msg-3');
517
+
518
+ // Branch B
519
+ expect(result[0].children[1].id).toBe('msg-4');
520
+ expect(result[0].children[1].children).toHaveLength(2);
521
+ expect(result[0].children[1].children[0].id).toBe('msg-5');
522
+ expect(result[0].children[1].children[1].id).toBe('msg-6');
523
+ });
524
+
525
+ it('should handle multiple root trees', () => {
526
+ const messages: Message[] = [
527
+ // Tree 1
528
+ {
529
+ content: 'Tree 1 Root',
530
+ createdAt: 1000,
531
+ id: 'msg-1',
532
+ meta: {},
533
+ role: 'user',
534
+ updatedAt: 1000,
535
+ },
536
+ {
537
+ content: 'Tree 1 Child',
538
+ createdAt: 2000,
539
+ id: 'msg-2',
540
+ meta: {},
541
+ parentId: 'msg-1',
542
+ role: 'assistant',
543
+ updatedAt: 2000,
544
+ },
545
+ // Tree 2
546
+ {
547
+ content: 'Tree 2 Root',
548
+ createdAt: 3000,
549
+ id: 'msg-3',
550
+ meta: {},
551
+ role: 'user',
552
+ updatedAt: 3000,
553
+ },
554
+ {
555
+ content: 'Tree 2 Child',
556
+ createdAt: 4000,
557
+ id: 'msg-4',
558
+ meta: {},
559
+ parentId: 'msg-3',
560
+ role: 'assistant',
561
+ updatedAt: 4000,
562
+ },
563
+ ];
564
+
565
+ const helperMaps = buildHelperMaps(messages);
566
+ const result = buildIdTree(helperMaps);
567
+
568
+ expect(result).toHaveLength(2);
569
+ expect(result[0].id).toBe('msg-1');
570
+ expect(result[0].children[0].id).toBe('msg-2');
571
+ expect(result[1].id).toBe('msg-3');
572
+ expect(result[1].children[0].id).toBe('msg-4');
573
+ });
574
+ });
575
+
576
+ describe('performance', () => {
577
+ it('should build tree for large dataset efficiently', () => {
578
+ const messages: Message[] = Array.from({ length: 1000 }, (_, i) => ({
579
+ content: `Message ${i}`,
580
+ createdAt: i,
581
+ id: `msg-${i}`,
582
+ meta: {},
583
+ parentId: i > 0 ? `msg-${i - 1}` : undefined,
584
+ role: i % 2 === 0 ? ('user' as const) : ('assistant' as const),
585
+ updatedAt: i,
586
+ }));
587
+
588
+ const helperMaps = buildHelperMaps(messages);
589
+
590
+ const startTime = performance.now();
591
+ const result = buildIdTree(helperMaps);
592
+ const endTime = performance.now();
593
+
594
+ const executionTime = endTime - startTime;
595
+
596
+ expect(result).toHaveLength(1);
597
+ expect(executionTime).toBeLessThan(50); // Should be fast
598
+ });
599
+ });
600
+ });
@@ -60,6 +60,7 @@ export const KeyEnum = {
60
60
  export const HotkeyEnum = {
61
61
  AddUserMessage: 'addUserMessage',
62
62
  ClearCurrentMessages: 'clearCurrentMessages',
63
+ CommandPalette: 'commandPalette',
63
64
  DeleteAndRegenerateMessage: 'deleteAndRegenerateMessage',
64
65
  DeleteLastMessage: 'deleteLastMessage',
65
66
  EditMessage: 'editMessage',
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
3
  import { useResponsive, useTheme } from 'antd-style';
4
- import { memo, useRef } from 'react';
4
+ import { memo, useEffect, useRef } from 'react';
5
5
  import { Flexbox } from 'react-layout-kit';
6
+ import { useSearchParams } from 'react-router-dom';
6
7
 
7
8
  import SettingContainer from '@/features/Setting/SettingContainer';
8
- import { parseAsStringEnum, useQueryParam } from '@/hooks/useQueryParam';
9
9
  import { SettingsTabs } from '@/store/global/initialState';
10
10
 
11
11
  import CategoryContent from '../CategoryContent';
@@ -13,18 +13,51 @@ import SettingsContent from '../SettingsContent';
13
13
  import { LayoutProps } from '../type';
14
14
  import Header from './Header';
15
15
  import SideBar from './SideBar';
16
+ import useMergedState from 'rc-util/lib/hooks/useMergedState';
16
17
 
17
18
  const Layout = memo<LayoutProps>(() => {
18
19
  const ref = useRef<HTMLDivElement | null>(null);
19
20
  const { md = true } = useResponsive();
20
21
  const theme = useTheme();
21
22
 
22
- const [activeTab, setActiveTab] = useQueryParam(
23
- 'active',
24
- parseAsStringEnum(Object.values(SettingsTabs)).withDefault(SettingsTabs.Common),
25
- );
23
+ const [searchParams, setSearchParams] = useSearchParams();
24
+
25
+ const [activeTabState, setActiveTabState] = useMergedState({
26
+ active: searchParams.get('active') as SettingsTabs ? searchParams.get('active') as SettingsTabs : SettingsTabs.Common,
27
+ }, {
28
+ onChange: (obj: {
29
+ active: SettingsTabs;
30
+ provider?: string;
31
+ }) => {
32
+ if (obj.provider) {
33
+ setSearchParams({ active: obj.active, provider: obj.provider });
34
+ } else {
35
+ searchParams.delete('provider');
36
+ setSearchParams({ active: obj.active });
37
+ }
38
+ },
39
+ });
40
+
41
+ const setActiveTab = (tab: SettingsTabs) => {
42
+ if (tab === SettingsTabs.Provider) {
43
+ setActiveTabState({ active: tab, provider: 'all' });
44
+ } else {
45
+ setActiveTabState({
46
+ active: tab,
47
+ });
48
+ }
49
+ };
50
+
51
+ useEffect(() => {
52
+ return () => {
53
+ setSearchParams((prevParams) => {
54
+ prevParams.delete('active');
55
+ return prevParams;
56
+ });
57
+ };
58
+ }, []);
26
59
 
27
- const category = <CategoryContent activeTab={activeTab} onMenuSelect={setActiveTab} />;
60
+ const category = <CategoryContent activeTab={activeTabState.active} onMenuSelect={setActiveTab} />;
28
61
 
29
62
  return (
30
63
  <Flexbox
@@ -39,7 +72,7 @@ const Layout = memo<LayoutProps>(() => {
39
72
  <Header getContainer={() => ref.current!}>{category}</Header>
40
73
  )}
41
74
  <SettingContainer maxWidth={'none'}>
42
- <SettingsContent activeTab={activeTab} mobile={false} />
75
+ <SettingsContent activeTab={activeTabState.active} mobile={false} />
43
76
  </SettingContainer>
44
77
  </Flexbox>
45
78
  );