dsh-locator 0.11.8 → 0.13.0
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.
- package/CHANGELOG.md +18 -0
- package/README-es.md +22 -3
- package/README-hi.md +22 -3
- package/README-pt.md +22 -3
- package/README.en.md +22 -3
- package/README.md +22 -3
- package/bin/darwin-arm64/indexd +0 -0
- package/bin/darwin-x64/indexd +0 -0
- package/bin/linux-arm64/indexd +0 -0
- package/bin/linux-x64/indexd +0 -0
- package/bin/win32-arm64/indexd.exe +0 -0
- package/bin/win32-x64/indexd.exe +0 -0
- package/client.js +625 -2
- package/lib/combined.d.ts +16 -1
- package/lib/combined.d.ts.map +1 -1
- package/lib/combined.js +47 -6
- package/lib/combined.js.map +1 -1
- package/lib/config.d.ts +18 -1
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +2 -0
- package/lib/config.js.map +1 -1
- package/lib/content-search.d.ts +9 -0
- package/lib/content-search.d.ts.map +1 -1
- package/lib/content-search.js +19 -1
- package/lib/content-search.js.map +1 -1
- package/lib/content.d.ts +35 -1
- package/lib/content.d.ts.map +1 -1
- package/lib/content.js +194 -23
- package/lib/content.js.map +1 -1
- package/lib/find.d.ts +4 -1
- package/lib/find.d.ts.map +1 -1
- package/lib/find.js +141 -19
- package/lib/find.js.map +1 -1
- package/lib/http.d.ts.map +1 -1
- package/lib/http.js +14 -3
- package/lib/http.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -1
- package/lib/index.js.map +1 -1
- package/lib/ref-tools.d.ts +18 -0
- package/lib/ref-tools.d.ts.map +1 -0
- package/lib/ref-tools.js +299 -0
- package/lib/ref-tools.js.map +1 -0
- package/lib/refs.d.ts +122 -0
- package/lib/refs.d.ts.map +1 -0
- package/lib/refs.js +150 -0
- package/lib/refs.js.map +1 -0
- package/lib/reveal.d.ts +25 -0
- package/lib/reveal.d.ts.map +1 -1
- package/lib/reveal.js +59 -0
- package/lib/reveal.js.map +1 -1
- package/lib/tools.d.ts.map +1 -1
- package/lib/tools.js +64 -16
- package/lib/tools.js.map +1 -1
- package/package.json +1 -1
- package/src/combined.ts +52 -6
- package/src/config.ts +20 -1
- package/src/content-search.ts +29 -1
- package/src/content.ts +183 -21
- package/src/find.ts +135 -21
- package/src/http.ts +15 -2
- package/src/index.ts +5 -1
- package/src/ref-tools.ts +287 -0
- package/src/refs.ts +199 -0
- package/src/reveal.ts +59 -0
- package/src/tools.ts +67 -17
package/client.js
CHANGED
|
@@ -240,6 +240,8 @@ contentWarning: 'Index warning: {list}', contentBudget: 'Content index budget re
|
|
|
240
240
|
copyAll: 'Copy paths', copiedAll: 'Copied {n} paths',
|
|
241
241
|
contentFullIndex: 'full-index', contentReasoningIndex: 'reasoning-indexed',
|
|
242
242
|
panelFilter: 'Filter loaded results…', filterEmpty: 'No loaded result matches this filter', panelLoadMore: 'Load more', panelHistory: 'Recent searches', panelHistoryClear: 'Clear',
|
|
243
|
+
rootFilter: 'Root', allRoots: 'All roots', exportTitle: 'Export results', exportCsv: 'CSV', exportJson: 'JSON', exportDone: 'Exported', exportFailed: 'Export failed',
|
|
244
|
+
includeArchived: "Archived sessions", contentToolResultsIndex: "tool-results-indexed",
|
|
243
245
|
},
|
|
244
246
|
zh: {
|
|
245
247
|
scopeContent: '内容', scopeFiles: '文件', scopeDirs: '目录',
|
|
@@ -290,6 +292,8 @@ contentWarning: '索引警告:{list}', contentBudget: '内容索引已达预
|
|
|
290
292
|
copyAll: '复制路径', copiedAll: '已复制 {n} 条路径',
|
|
291
293
|
contentFullIndex: '全量内容', contentReasoningIndex: '含思考内容',
|
|
292
294
|
panelFilter: '过滤当前结果…', filterEmpty: '已加载结果中没有符合过滤条件的内容', panelLoadMore: '加载更多', panelHistory: '最近搜索', panelHistoryClear: '清空',
|
|
295
|
+
rootFilter: '根目录', allRoots: '全部根目录', exportTitle: '导出结果', exportCsv: 'CSV', exportJson: 'JSON', exportDone: '已导出', exportFailed: '导出失败',
|
|
296
|
+
includeArchived: "包含归档会话", contentToolResultsIndex: "含工具结果",
|
|
293
297
|
},
|
|
294
298
|
es: {
|
|
295
299
|
scopeContent: 'Contenido', scopeFiles: 'Archivos', scopeDirs: 'Carpetas',
|
|
@@ -340,6 +344,8 @@ contentWarning: 'Aviso del índice: {list}', contentBudget: 'Se alcanzó el pres
|
|
|
340
344
|
copyAll: 'Copiar rutas', copiedAll: 'Se copiaron {n} rutas',
|
|
341
345
|
contentFullIndex: 'índice completo', contentReasoningIndex: 'razonamiento indexado',
|
|
342
346
|
panelFilter: 'Filtrar resultados cargados…', filterEmpty: 'Ningún resultado cargado coincide con el filtro', panelLoadMore: 'Cargar más', panelHistory: 'Búsquedas recientes', panelHistoryClear: 'Borrar',
|
|
347
|
+
rootFilter: 'Raíz', allRoots: 'Todas las raíces', exportTitle: 'Exportar resultados', exportCsv: 'CSV', exportJson: 'JSON', exportDone: 'Exportado', exportFailed: 'Error al exportar',
|
|
348
|
+
includeArchived: "Sesiones archivadas", contentToolResultsIndex: "resultados de herramientas",
|
|
343
349
|
},
|
|
344
350
|
pt: {
|
|
345
351
|
scopeContent: 'Conteúdo', scopeFiles: 'Arquivos', scopeDirs: 'Pastas',
|
|
@@ -390,6 +396,8 @@ contentWarning: 'Aviso do índice: {list}', contentBudget: 'O orçamento do índ
|
|
|
390
396
|
copyAll: 'Copiar caminhos', copiedAll: '{n} caminhos copiados',
|
|
391
397
|
contentFullIndex: 'índice completo', contentReasoningIndex: 'raciocínio indexado',
|
|
392
398
|
panelFilter: 'Filtrar resultados carregados…', filterEmpty: 'Nenhum resultado carregado corresponde ao filtro', panelLoadMore: 'Carregar mais', panelHistory: 'Buscas recentes', panelHistoryClear: 'Limpar',
|
|
399
|
+
rootFilter: 'Raiz', allRoots: 'Todas as raízes', exportTitle: 'Exportar resultados', exportCsv: 'CSV', exportJson: 'JSON', exportDone: 'Exportado', exportFailed: 'Falha ao exportar',
|
|
400
|
+
includeArchived: "Sessões arquivadas", contentToolResultsIndex: "resultados de ferramentas",
|
|
393
401
|
},
|
|
394
402
|
hi: {
|
|
395
403
|
scopeContent: 'सामग्री', scopeFiles: 'फ़ाइलें', scopeDirs: 'फ़ोल्डर',
|
|
@@ -440,6 +448,512 @@ contentWarning: 'इंडेक्स चेतावनी: {list}', contentBu
|
|
|
440
448
|
copyAll: 'पथ कॉपी करें', copiedAll: '{n} पथ कॉपी हुए',
|
|
441
449
|
contentFullIndex: 'पूर्ण इंडेक्स', contentReasoningIndex: 'reasoning इंडेक्स',
|
|
442
450
|
panelFilter: 'लोड किए गए परिणाम छाँटें…', filterEmpty: 'लोड किए गए परिणामों में फ़िल्टर से मेल नहीं', panelLoadMore: 'और लोड करें', panelHistory: 'हाल की खोजें', panelHistoryClear: 'साफ़ करें',
|
|
451
|
+
rootFilter: 'रूट', allRoots: 'सभी रूट', exportTitle: 'परिणाम निर्यात करें', exportCsv: 'CSV', exportJson: 'JSON', exportDone: 'निर्यात हुआ', exportFailed: 'निर्यात विफल',
|
|
452
|
+
includeArchived: "संग्रहीत सत्र", contentToolResultsIndex: "टूल परिणाम इंडेक्स",
|
|
453
|
+
},
|
|
454
|
+
ja: {
|
|
455
|
+
scopeContent: "内容",
|
|
456
|
+
scopeFiles: "ファイル",
|
|
457
|
+
scopeDirs: "フォルダ",
|
|
458
|
+
placeholder: "名前・パス・本文・セッションを検索… 例:ext:pdf size:>10mb dm:thisweek path:src",
|
|
459
|
+
searchLabel: "ファイルを検索",
|
|
460
|
+
dialog: "ローカルファイル検索",
|
|
461
|
+
closeTitle: "閉じる (Esc)",
|
|
462
|
+
closeLabel: "閉じる",
|
|
463
|
+
sortLabel: "並べ替え",
|
|
464
|
+
sortMtime: "更新日時",
|
|
465
|
+
sortName: "名前",
|
|
466
|
+
sortSize: "サイズ",
|
|
467
|
+
sortPath: "パス",
|
|
468
|
+
asc: "昇順",
|
|
469
|
+
descOrder: "降順",
|
|
470
|
+
groupContent: "内容",
|
|
471
|
+
groupFiles: "ファイル",
|
|
472
|
+
groupDirs: "フォルダ",
|
|
473
|
+
relevance: "関連度順",
|
|
474
|
+
contentBuilding: "インデックス作成中… {files} ファイル / {messages} メッセージ",
|
|
475
|
+
contentProgressFiles: "インデックス作成中… {scanned}/{total} ファイル",
|
|
476
|
+
contentProgressSessions: "インデックス作成中… {scanned}/{total} セッション",
|
|
477
|
+
contentShort: "本文とセッションを検索するには 3 文字以上入力してください (短い検索は Ctrl+F)",
|
|
478
|
+
contentDisabled: "コンテンツインデックスは無効です (contentIndex: false)",
|
|
479
|
+
contentCapped: "先頭 {n} 件",
|
|
480
|
+
showing: "先頭 {n} 件",
|
|
481
|
+
deduped: "{n} 件の名前ヒットをコンテンツに統合",
|
|
482
|
+
loading: "検索中…",
|
|
483
|
+
emptyQuery: "ファイル名・パス・本文・セッションを検索するには入力してください",
|
|
484
|
+
emptyResults: "一致なし · 範囲を減らすか別のキーワードを試してください",
|
|
485
|
+
emptyScopes: "範囲を 1 つ以上選択してください (内容・ファイル・フォルダ)",
|
|
486
|
+
errorPrefix: "検索に失敗しました:",
|
|
487
|
+
retry: "再試行",
|
|
488
|
+
indexing: "インデックス作成中、結果が不完全な場合があります",
|
|
489
|
+
statusLoading: "インデックス状態を読み込み中…",
|
|
490
|
+
status: "インデックス {entries} 件 · {mode} · ルート {roots} 件",
|
|
491
|
+
live: "リアルタイム",
|
|
492
|
+
snapshot: "スナップショット",
|
|
493
|
+
usn: "USN",
|
|
494
|
+
copiedPath: "パスをコピーしました",
|
|
495
|
+
revealed: "ファイルマネージャーで表示しました",
|
|
496
|
+
opened: "開きました",
|
|
497
|
+
inserted: "@file を挿入しました",
|
|
498
|
+
insertFailed: "挿入に失敗しました。@file をコピーしました",
|
|
499
|
+
jumped: "セッションを開きました",
|
|
500
|
+
jumpFailed: "セッションは開きましたが、一致箇所を特定できませんでした",
|
|
501
|
+
footer: "↑↓ 選択 · Enter 開く/ジャンプ · Ctrl+Shift+C パスをコピー · Ctrl+O 開く · Alt+1–3 範囲 · Esc 閉じる",
|
|
502
|
+
results: "内容 {content} · ファイル {files} · フォルダ {dirs} · {ms} ms",
|
|
503
|
+
launcher: "ローカルファイル検索 (Ctrl+Shift+F)",
|
|
504
|
+
justNow: "たった今",
|
|
505
|
+
minutesAgo: "{n} 分前",
|
|
506
|
+
hoursAgo: "{n} 時間前",
|
|
507
|
+
phraseNotFound: "会話内に一致が見つかりません (まだ読み込まれていない可能性があります)",
|
|
508
|
+
findOpen: "会話内を検索",
|
|
509
|
+
findTitle: "会話内を検索",
|
|
510
|
+
findAria: "会話内を検索",
|
|
511
|
+
findPlaceholder: "会話内を検索…",
|
|
512
|
+
findPlaceholderSelection: "選択範囲内を検索…",
|
|
513
|
+
findPrev: "前の一致 (Shift+F3)",
|
|
514
|
+
findNext: "次の一致 (F3)",
|
|
515
|
+
findClose: "閉じる (Esc)",
|
|
516
|
+
findCase: "大文字と小文字を区別",
|
|
517
|
+
findWhole: "単語単位で検索",
|
|
518
|
+
findWrap: "折り返し",
|
|
519
|
+
findReverse: "逆方向に検索",
|
|
520
|
+
findMode: "モード",
|
|
521
|
+
modeNormal: "通常",
|
|
522
|
+
modeExtended: "拡張",
|
|
523
|
+
modeRegex: "正規表現",
|
|
524
|
+
findScope: "選択範囲内",
|
|
525
|
+
findScopeChip: "選択範囲 {n} 文字",
|
|
526
|
+
findSessionChip: "この会話",
|
|
527
|
+
findNoMatch: "一致なし",
|
|
528
|
+
findEmpty: "この会話内を検索するには入力してください",
|
|
529
|
+
findInvalidRegex: "正規表現が無効です:{message}",
|
|
530
|
+
findInvalidEscape: "拡張エスケープが無効です:{token}",
|
|
531
|
+
findTimeout: "正規表現がタイムアウトしました。式を簡略化してください",
|
|
532
|
+
findRegexUnavailable: "ここでは正規表現検索を利用できません (worker がブロックされています)",
|
|
533
|
+
findWrappedTop: "先頭に戻りました",
|
|
534
|
+
findWrappedBottom: "末尾に戻りました",
|
|
535
|
+
findNoWrapEnd: "最後の一致に到達しました (折り返しオフ)",
|
|
536
|
+
findNoWrapStart: "最初の一致に到達しました (折り返しオフ)",
|
|
537
|
+
findOlder: "以前のメッセージを読み込んで再試行",
|
|
538
|
+
findLoadingOlder: "以前のメッセージを読み込み中…",
|
|
539
|
+
findLoadedOnly: "読み込み済みの範囲のみ · 以前の履歴は未読み込み",
|
|
540
|
+
findCapped: "上限あり",
|
|
541
|
+
findCopied: "一致箇所をコピーしました",
|
|
542
|
+
findSelectionLost: "選択範囲が無効になりました。会話全体を検索します",
|
|
543
|
+
findNoSession: "先に会話を開いてください",
|
|
544
|
+
findOptions: "オプション",
|
|
545
|
+
findExtendedHelp: "拡張:\\n \\r \\t \\0 \\xHH \\\\",
|
|
546
|
+
panelTotal: "選択 {index}/{total}",
|
|
547
|
+
panelRangeAll: "インデックス全体",
|
|
548
|
+
panelRangeSession: "この会話",
|
|
549
|
+
panelSessionHint: "この範囲はインデックス済みのセッションメッセージのみ検索します。会話内のライブ検索は Ctrl+F を使ってください",
|
|
550
|
+
panelRegexPaused: "正規表現モード中はコンテンツ範囲を一時停止",
|
|
551
|
+
panelCountBounded: "≥ {n}",
|
|
552
|
+
panelCountExact: "{n}",
|
|
553
|
+
contentWarning: "インデックス警告:{list}",
|
|
554
|
+
contentBudget: "コンテンツインデックスの上限に達しました。一部のファイルはインデックスされていません",
|
|
555
|
+
contentTooShort: "コンテンツ検索には 3 文字以上必要です (短い検索は Ctrl+F)",
|
|
556
|
+
contentTimeout: "コンテンツ検索がタイムアウトしました。キーワードまたは範囲を絞ってください",
|
|
557
|
+
contentBadChars: "コンテンツ検索は NUL/制御文字に対応していません",
|
|
558
|
+
panelCaseShort: "Aa",
|
|
559
|
+
panelWholeShort: "単語",
|
|
560
|
+
panelModeLabel: "モード",
|
|
561
|
+
watchDegraded: "ファイル監視が低下中 · 定期更新で動作中",
|
|
562
|
+
copyAll: "パスをコピー",
|
|
563
|
+
copiedAll: "{n} 件のパスをコピーしました",
|
|
564
|
+
contentFullIndex: "full-index",
|
|
565
|
+
contentReasoningIndex: "reasoning-indexed",
|
|
566
|
+
panelFilter: "読み込み済みの結果を絞り込む…",
|
|
567
|
+
filterEmpty: "絞り込みに一致する読み込み済みの結果はありません",
|
|
568
|
+
panelLoadMore: "さらに読み込む",
|
|
569
|
+
panelHistory: "最近の検索",
|
|
570
|
+
panelHistoryClear: "クリア",
|
|
571
|
+
rootFilter: "ルート",
|
|
572
|
+
allRoots: "すべてのルート",
|
|
573
|
+
exportTitle: "結果をエクスポート",
|
|
574
|
+
exportCsv: "CSV",
|
|
575
|
+
exportJson: "JSON",
|
|
576
|
+
exportDone: "エクスポートしました",
|
|
577
|
+
exportFailed: "エクスポートに失敗しました",
|
|
578
|
+
includeArchived: "アーカイブ済みセッション", contentToolResultsIndex: "ツール結果インデックス",
|
|
579
|
+
},
|
|
580
|
+
fr: {
|
|
581
|
+
scopeContent: "Contenu",
|
|
582
|
+
scopeFiles: "Fichiers",
|
|
583
|
+
scopeDirs: "Dossiers",
|
|
584
|
+
placeholder: "Recherchez noms, chemins, contenus ou sessions… p. ex. ext:pdf size:>10mb dm:thisweek path:src",
|
|
585
|
+
searchLabel: "Rechercher des fichiers",
|
|
586
|
+
dialog: "Recherche de fichiers locale",
|
|
587
|
+
closeTitle: "Fermer (Échap)",
|
|
588
|
+
closeLabel: "Fermer",
|
|
589
|
+
sortLabel: "Trier",
|
|
590
|
+
sortMtime: "Modification",
|
|
591
|
+
sortName: "Nom",
|
|
592
|
+
sortSize: "Taille",
|
|
593
|
+
sortPath: "Chemin",
|
|
594
|
+
asc: "Croissant",
|
|
595
|
+
descOrder: "Décroissant",
|
|
596
|
+
groupContent: "Contenu",
|
|
597
|
+
groupFiles: "Fichiers",
|
|
598
|
+
groupDirs: "Dossiers",
|
|
599
|
+
relevance: "par pertinence",
|
|
600
|
+
contentBuilding: "indexation… {files} fichiers / {messages} messages",
|
|
601
|
+
contentProgressFiles: "indexation… {scanned}/{total} fichiers",
|
|
602
|
+
contentProgressSessions: "indexation… {scanned}/{total} sessions",
|
|
603
|
+
contentShort: "Saisissez au moins 3 caractères pour chercher dans les contenus et les sessions (Ctrl+F gère les requêtes plus courtes)",
|
|
604
|
+
contentDisabled: "L’index de contenu est désactivé (contentIndex: false)",
|
|
605
|
+
contentCapped: "{n} premiers",
|
|
606
|
+
showing: "{n} premiers",
|
|
607
|
+
deduped: "{n} correspondances de noms fusionnées dans le contenu",
|
|
608
|
+
loading: "Recherche…",
|
|
609
|
+
emptyQuery: "Saisissez pour rechercher des noms, chemins, contenus et sessions",
|
|
610
|
+
emptyResults: "Aucun résultat · essayez moins de portées ou un autre mot-clé",
|
|
611
|
+
emptyScopes: "Sélectionnez au moins une portée (Contenu, Fichiers, Dossiers)",
|
|
612
|
+
errorPrefix: "Échec de la recherche : ",
|
|
613
|
+
retry: "Réessayer",
|
|
614
|
+
indexing: "indexation en cours, résultats peut-être incomplets",
|
|
615
|
+
statusLoading: "Lecture de l’état de l’index…",
|
|
616
|
+
status: "Index : {entries} entrées · {mode} · {roots} racines",
|
|
617
|
+
live: "en direct",
|
|
618
|
+
snapshot: "instantané",
|
|
619
|
+
usn: "USN",
|
|
620
|
+
copiedPath: "Chemin copié",
|
|
621
|
+
revealed: "Révélé dans le gestionnaire de fichiers",
|
|
622
|
+
opened: "Ouvert",
|
|
623
|
+
inserted: "@file inséré",
|
|
624
|
+
insertFailed: "Échec de l’insertion ; @file copié",
|
|
625
|
+
jumped: "Session ouverte",
|
|
626
|
+
jumpFailed: "Session ouverte, mais correspondance introuvable",
|
|
627
|
+
footer: "↑↓ sélectionner · Entrée ouvrir/aller à · Ctrl+Shift+C copier le chemin · Ctrl+O ouvrir · Alt+1–3 portées · Échap fermer",
|
|
628
|
+
results: "contenu {content} · fichiers {files} · dossiers {dirs} · {ms} ms",
|
|
629
|
+
launcher: "Recherche de fichiers locale (Ctrl+Shift+F)",
|
|
630
|
+
justNow: "à l’instant",
|
|
631
|
+
minutesAgo: "il y a {n} min",
|
|
632
|
+
hoursAgo: "il y a {n} h",
|
|
633
|
+
phraseNotFound: "Aucune correspondance dans la conversation (pas encore chargée ?)",
|
|
634
|
+
findOpen: "Rechercher dans la conversation",
|
|
635
|
+
findTitle: "Rechercher dans la conversation",
|
|
636
|
+
findAria: "Rechercher dans la conversation",
|
|
637
|
+
findPlaceholder: "Rechercher dans la conversation…",
|
|
638
|
+
findPlaceholderSelection: "Rechercher dans la sélection…",
|
|
639
|
+
findPrev: "Correspondance précédente (Shift+F3)",
|
|
640
|
+
findNext: "Correspondance suivante (F3)",
|
|
641
|
+
findClose: "Fermer (Échap)",
|
|
642
|
+
findCase: "Respecter la casse",
|
|
643
|
+
findWhole: "Mot entier",
|
|
644
|
+
findWrap: "Boucler",
|
|
645
|
+
findReverse: "Rechercher en arrière",
|
|
646
|
+
findMode: "Mode",
|
|
647
|
+
modeNormal: "Normal",
|
|
648
|
+
modeExtended: "Étendu",
|
|
649
|
+
modeRegex: "Regex",
|
|
650
|
+
findScope: "Dans la sélection",
|
|
651
|
+
findScopeChip: "sélection {n} car.",
|
|
652
|
+
findSessionChip: "cette conversation",
|
|
653
|
+
findNoMatch: "Aucune correspondance",
|
|
654
|
+
findEmpty: "Saisissez pour rechercher dans la conversation",
|
|
655
|
+
findInvalidRegex: "Expression régulière invalide : {message}",
|
|
656
|
+
findInvalidEscape: "Séquence d’échappement étendue invalide : {token}",
|
|
657
|
+
findTimeout: "Délai d’exécution de la regex dépassé ; simplifiez l’expression",
|
|
658
|
+
findRegexUnavailable: "Recherche par regex indisponible ici (worker bloqué)",
|
|
659
|
+
findWrappedTop: "Retour en haut",
|
|
660
|
+
findWrappedBottom: "Retour en bas",
|
|
661
|
+
findNoWrapEnd: "Dernière correspondance atteinte (boucle désactivée)",
|
|
662
|
+
findNoWrapStart: "Première correspondance atteinte (boucle désactivée)",
|
|
663
|
+
findOlder: "Chargez les messages plus anciens et réessayez",
|
|
664
|
+
findLoadingOlder: "Chargement des messages plus anciens…",
|
|
665
|
+
findLoadedOnly: "fenêtre chargée uniquement · historique antérieur non chargé",
|
|
666
|
+
findCapped: "limité",
|
|
667
|
+
findCopied: "Correspondance copiée",
|
|
668
|
+
findSelectionLost: "Sélection expirée ; recherche dans toute la conversation",
|
|
669
|
+
findNoSession: "Ouvrez d’abord une conversation",
|
|
670
|
+
findOptions: "Options",
|
|
671
|
+
findExtendedHelp: "Étendu : \\n \\r \\t \\0 \\xHH \\\\",
|
|
672
|
+
panelTotal: "sélectionné {index}/{total}",
|
|
673
|
+
panelRangeAll: "Tout l’index",
|
|
674
|
+
panelRangeSession: "Cette conversation",
|
|
675
|
+
panelSessionHint: "Cette portée ne cherche que dans les messages de session indexés ; appuyez sur Ctrl+F pour une recherche en direct dans la conversation",
|
|
676
|
+
panelRegexPaused: "Portée contenu suspendue en mode regex",
|
|
677
|
+
panelCountBounded: "≥ {n}",
|
|
678
|
+
panelCountExact: "{n}",
|
|
679
|
+
contentWarning: "Avertissement d’index : {list}",
|
|
680
|
+
contentBudget: "Budget de l’index de contenu atteint ; certains fichiers ne sont pas indexés",
|
|
681
|
+
contentTooShort: "Le contenu nécessite au moins 3 caractères (utilisez Ctrl+F pour les recherches plus courtes)",
|
|
682
|
+
contentTimeout: "Délai de recherche de contenu dépassé ; affinez la requête ou la portée",
|
|
683
|
+
contentBadChars: "La recherche de contenu ne prend pas en charge les caractères NUL/de contrôle",
|
|
684
|
+
panelCaseShort: "Aa",
|
|
685
|
+
panelWholeShort: "Mot",
|
|
686
|
+
panelModeLabel: "Mode",
|
|
687
|
+
watchDegraded: "surveillance dégradée ; actualisation périodique active",
|
|
688
|
+
copyAll: "Copier les chemins",
|
|
689
|
+
copiedAll: "{n} chemins copiés",
|
|
690
|
+
contentFullIndex: "full-index",
|
|
691
|
+
contentReasoningIndex: "reasoning-indexed",
|
|
692
|
+
panelFilter: "Filtrer les résultats chargés…",
|
|
693
|
+
filterEmpty: "Aucun résultat chargé ne correspond à ce filtre",
|
|
694
|
+
panelLoadMore: "Charger plus",
|
|
695
|
+
panelHistory: "Recherches récentes",
|
|
696
|
+
panelHistoryClear: "Effacer",
|
|
697
|
+
rootFilter: "Racine",
|
|
698
|
+
allRoots: "Toutes les racines",
|
|
699
|
+
exportTitle: "Exporter les résultats",
|
|
700
|
+
exportCsv: "CSV",
|
|
701
|
+
exportJson: "JSON",
|
|
702
|
+
exportDone: "Exporté",
|
|
703
|
+
exportFailed: "Échec de l’export",
|
|
704
|
+
includeArchived: "Sessions archivées", contentToolResultsIndex: "résultats d’outils indexés",
|
|
705
|
+
},
|
|
706
|
+
de: {
|
|
707
|
+
scopeContent: "Inhalt",
|
|
708
|
+
scopeFiles: "Dateien",
|
|
709
|
+
scopeDirs: "Ordner",
|
|
710
|
+
placeholder: "Namen, Pfade, Texte oder Sitzungen suchen… z. B. ext:pdf size:>10mb dm:thisweek path:src",
|
|
711
|
+
searchLabel: "Dateien suchen",
|
|
712
|
+
dialog: "Lokale Dateisuche",
|
|
713
|
+
closeTitle: "Schließen (Esc)",
|
|
714
|
+
closeLabel: "Schließen",
|
|
715
|
+
sortLabel: "Sortieren",
|
|
716
|
+
sortMtime: "Geändert",
|
|
717
|
+
sortName: "Name",
|
|
718
|
+
sortSize: "Größe",
|
|
719
|
+
sortPath: "Pfad",
|
|
720
|
+
asc: "Aufsteigend",
|
|
721
|
+
descOrder: "Absteigend",
|
|
722
|
+
groupContent: "Inhalt",
|
|
723
|
+
groupFiles: "Dateien",
|
|
724
|
+
groupDirs: "Ordner",
|
|
725
|
+
relevance: "nach Relevanz",
|
|
726
|
+
contentBuilding: "Indexierung läuft… {files} Dateien / {messages} Nachrichten",
|
|
727
|
+
contentProgressFiles: "Indexierung läuft… {scanned}/{total} Dateien",
|
|
728
|
+
contentProgressSessions: "Indexierung läuft… {scanned}/{total} Sitzungen",
|
|
729
|
+
contentShort: "Mindestens 3 Zeichen eingeben, um Texte und Sitzungen zu durchsuchen (Ctrl+F für kürzere Suchbegriffe)",
|
|
730
|
+
contentDisabled: "Inhaltsindex ist deaktiviert (contentIndex: false)",
|
|
731
|
+
contentCapped: "erste {n}",
|
|
732
|
+
showing: "erste {n}",
|
|
733
|
+
deduped: "{n} Namensreffer in Inhalt zusammengeführt",
|
|
734
|
+
loading: "Suche…",
|
|
735
|
+
emptyQuery: "Tippen, um Dateinamen, Pfade, Texte und Sitzungen zu durchsuchen",
|
|
736
|
+
emptyResults: "Keine Treffer · weniger Bereiche oder anderen Suchbegriff versuchen",
|
|
737
|
+
emptyScopes: "Mindestens einen Bereich auswählen (Inhalt, Dateien, Ordner)",
|
|
738
|
+
errorPrefix: "Suche fehlgeschlagen: ",
|
|
739
|
+
retry: "Erneut versuchen",
|
|
740
|
+
indexing: "Indexierung läuft, Ergebnisse evtl. unvollständig",
|
|
741
|
+
statusLoading: "Indexstatus wird gelesen…",
|
|
742
|
+
status: "Index {entries} Einträge · {mode} · {roots} Stammverzeichnisse",
|
|
743
|
+
live: "live",
|
|
744
|
+
snapshot: "Snapshot",
|
|
745
|
+
usn: "USN",
|
|
746
|
+
copiedPath: "Pfad kopiert",
|
|
747
|
+
revealed: "Im Dateimanager angezeigt",
|
|
748
|
+
opened: "Geöffnet",
|
|
749
|
+
inserted: "@file eingefügt",
|
|
750
|
+
insertFailed: "Einfügen fehlgeschlagen; @file kopiert",
|
|
751
|
+
jumped: "Sitzung geöffnet",
|
|
752
|
+
jumpFailed: "Sitzung geöffnet, Treffer aber nicht gefunden",
|
|
753
|
+
footer: "↑↓ auswählen · Enter öffnen/springen · Ctrl+Shift+C Pfad kopieren · Ctrl+O öffnen · Alt+1–3 Bereiche · Esc schließen",
|
|
754
|
+
results: "Inhalt {content} · Dateien {files} · Ordner {dirs} · {ms} ms",
|
|
755
|
+
launcher: "Lokale Dateisuche (Ctrl+Shift+F)",
|
|
756
|
+
justNow: "gerade eben",
|
|
757
|
+
minutesAgo: "vor {n} Min.",
|
|
758
|
+
hoursAgo: "vor {n} Std.",
|
|
759
|
+
phraseNotFound: "Kein Treffer in der Unterhaltung (evtl. noch nicht geladen)",
|
|
760
|
+
findOpen: "In Unterhaltung suchen",
|
|
761
|
+
findTitle: "In Unterhaltung suchen",
|
|
762
|
+
findAria: "In Unterhaltung suchen",
|
|
763
|
+
findPlaceholder: "In Unterhaltung suchen…",
|
|
764
|
+
findPlaceholderSelection: "In Auswahl suchen…",
|
|
765
|
+
findPrev: "Vorheriger Treffer (Shift+F3)",
|
|
766
|
+
findNext: "Nächster Treffer (F3)",
|
|
767
|
+
findClose: "Schließen (Esc)",
|
|
768
|
+
findCase: "Groß-/Kleinschreibung beachten",
|
|
769
|
+
findWhole: "Ganzes Wort",
|
|
770
|
+
findWrap: "Umlaufend suchen",
|
|
771
|
+
findReverse: "Rückwärts suchen",
|
|
772
|
+
findMode: "Modus",
|
|
773
|
+
modeNormal: "Normal",
|
|
774
|
+
modeExtended: "Erweitert",
|
|
775
|
+
modeRegex: "Regex",
|
|
776
|
+
findScope: "In Auswahl",
|
|
777
|
+
findScopeChip: "Auswahl {n} Zeichen",
|
|
778
|
+
findSessionChip: "diese Unterhaltung",
|
|
779
|
+
findNoMatch: "Keine Treffer",
|
|
780
|
+
findEmpty: "Tippen, um in dieser Unterhaltung zu suchen",
|
|
781
|
+
findInvalidRegex: "Ungültiger regulärer Ausdruck: {message}",
|
|
782
|
+
findInvalidEscape: "Ungültige Extended-Escape-Sequenz: {token}",
|
|
783
|
+
findTimeout: "Zeitüberschreitung bei Regex; Ausdruck vereinfachen",
|
|
784
|
+
findRegexUnavailable: "Regex-Suche ist hier nicht verfügbar (Worker blockiert)",
|
|
785
|
+
findWrappedTop: "Am Anfang fortgesetzt",
|
|
786
|
+
findWrappedBottom: "Am Ende fortgesetzt",
|
|
787
|
+
findNoWrapEnd: "Letzter Treffer erreicht (Umlauf aus)",
|
|
788
|
+
findNoWrapStart: "Erster Treffer erreicht (Umlauf aus)",
|
|
789
|
+
findOlder: "Frühere Nachrichten laden und erneut versuchen",
|
|
790
|
+
findLoadingOlder: "Frühere Nachrichten werden geladen…",
|
|
791
|
+
findLoadedOnly: "nur geladener Bereich · frühere Historie nicht geladen",
|
|
792
|
+
findCapped: "begrenzt",
|
|
793
|
+
findCopied: "Treffer kopiert",
|
|
794
|
+
findSelectionLost: "Auswahl abgelaufen; gesamte Unterhaltung wird durchsucht",
|
|
795
|
+
findNoSession: "Zuerst eine Unterhaltung öffnen",
|
|
796
|
+
findOptions: "Optionen",
|
|
797
|
+
findExtendedHelp: "Erweitert: \\n \\r \\t \\0 \\xHH \\\\",
|
|
798
|
+
panelTotal: "ausgewählt {index}/{total}",
|
|
799
|
+
panelRangeAll: "Gesamter Index",
|
|
800
|
+
panelRangeSession: "Diese Unterhaltung",
|
|
801
|
+
panelSessionHint: "Dieser Bereich durchsucht nur indizierte Sitzungsnachrichten; Ctrl+F für die Live-Suche in der Unterhaltung",
|
|
802
|
+
panelRegexPaused: "Inhaltssuche im Regex-Modus pausiert",
|
|
803
|
+
panelCountBounded: "≥ {n}",
|
|
804
|
+
panelCountExact: "{n}",
|
|
805
|
+
contentWarning: "Indexwarnung: {list}",
|
|
806
|
+
contentBudget: "Budget des Inhaltsindex erreicht; einige Dateien sind nicht indiziert",
|
|
807
|
+
contentTooShort: "Inhalt braucht mindestens 3 Zeichen (Ctrl+F für kürzere Suchen)",
|
|
808
|
+
contentTimeout: "Zeitüberschreitung bei der Inhaltssuche; Suchanfrage oder Bereich einschränken",
|
|
809
|
+
contentBadChars: "Inhaltssuche unterstützt keine NUL-/Steuerzeichen",
|
|
810
|
+
panelCaseShort: "Aa",
|
|
811
|
+
panelWholeShort: "Wort",
|
|
812
|
+
panelModeLabel: "Modus",
|
|
813
|
+
watchDegraded: "Watcher eingeschränkt; regelmäßige Aktualisierung aktiv",
|
|
814
|
+
copyAll: "Pfade kopieren",
|
|
815
|
+
copiedAll: "{n} Pfade kopiert",
|
|
816
|
+
contentFullIndex: "full-index",
|
|
817
|
+
contentReasoningIndex: "reasoning-indexed",
|
|
818
|
+
panelFilter: "Geladene Ergebnisse filtern…",
|
|
819
|
+
filterEmpty: "Kein geladenes Ergebnis entspricht diesem Filter",
|
|
820
|
+
panelLoadMore: "Mehr laden",
|
|
821
|
+
panelHistory: "Letzte Suchen",
|
|
822
|
+
panelHistoryClear: "Löschen",
|
|
823
|
+
rootFilter: "Stammverzeichnis",
|
|
824
|
+
allRoots: "Alle Stammverzeichnisse",
|
|
825
|
+
exportTitle: "Ergebnisse exportieren",
|
|
826
|
+
exportCsv: "CSV",
|
|
827
|
+
exportJson: "JSON",
|
|
828
|
+
exportDone: "Exportiert",
|
|
829
|
+
exportFailed: "Export fehlgeschlagen",
|
|
830
|
+
includeArchived: "Archivierte Sitzungen", contentToolResultsIndex: "Tool-Ergebnisse indiziert",
|
|
831
|
+
},
|
|
832
|
+
ru: {
|
|
833
|
+
scopeContent: "Содержимое",
|
|
834
|
+
scopeFiles: "Файлы",
|
|
835
|
+
scopeDirs: "Папки",
|
|
836
|
+
placeholder: "Поиск по именам, путям, содержимому или сессиям… напр. ext:pdf size:>10mb dm:thisweek path:src",
|
|
837
|
+
searchLabel: "Поиск файлов",
|
|
838
|
+
dialog: "Локальный поиск файлов",
|
|
839
|
+
closeTitle: "Закрыть (Esc)",
|
|
840
|
+
closeLabel: "Закрыть",
|
|
841
|
+
sortLabel: "Сортировка",
|
|
842
|
+
sortMtime: "По изменению",
|
|
843
|
+
sortName: "По имени",
|
|
844
|
+
sortSize: "По размеру",
|
|
845
|
+
sortPath: "По пути",
|
|
846
|
+
asc: "По возрастанию",
|
|
847
|
+
descOrder: "По убыванию",
|
|
848
|
+
groupContent: "Содержимое",
|
|
849
|
+
groupFiles: "Файлы",
|
|
850
|
+
groupDirs: "Папки",
|
|
851
|
+
relevance: "по релевантности",
|
|
852
|
+
contentBuilding: "индексация… {files} файлов / {messages} сообщений",
|
|
853
|
+
contentProgressFiles: "индексация… {scanned}/{total} файлов",
|
|
854
|
+
contentProgressSessions: "индексация… {scanned}/{total} сессий",
|
|
855
|
+
contentShort: "Введите не менее 3 символов для поиска по содержимому и сессиям (для коротких запросов используйте Ctrl+F)",
|
|
856
|
+
contentDisabled: "Индекс содержимого отключён (contentIndex: false)",
|
|
857
|
+
contentCapped: "первые {n}",
|
|
858
|
+
showing: "первые {n}",
|
|
859
|
+
deduped: "{n} совпадений по именам объединено с содержимым",
|
|
860
|
+
loading: "Поиск…",
|
|
861
|
+
emptyQuery: "Введите запрос для поиска по именам файлов, путям, содержимому и сессиям",
|
|
862
|
+
emptyResults: "Нет совпадений · сократите области поиска или смените запрос",
|
|
863
|
+
emptyScopes: "Выберите хотя бы одну область (Содержимое, Файлы, Папки)",
|
|
864
|
+
errorPrefix: "Ошибка поиска: ",
|
|
865
|
+
retry: "Повторить",
|
|
866
|
+
indexing: "идёт индексация, результаты могут быть неполными",
|
|
867
|
+
statusLoading: "Чтение состояния индекса…",
|
|
868
|
+
status: "Индекс: {entries} записей · {mode} · корней: {roots}",
|
|
869
|
+
live: "в реальном времени",
|
|
870
|
+
snapshot: "снимок",
|
|
871
|
+
usn: "USN",
|
|
872
|
+
copiedPath: "Путь скопирован",
|
|
873
|
+
revealed: "Показано в файловом менеджере",
|
|
874
|
+
opened: "Открыто",
|
|
875
|
+
inserted: "Вставлено @file",
|
|
876
|
+
insertFailed: "Вставка не удалась; @file скопирован",
|
|
877
|
+
jumped: "Сессия открыта",
|
|
878
|
+
jumpFailed: "Сессия открыта, но совпадение не найдено",
|
|
879
|
+
footer: "↑↓ выбрать · Enter открыть/перейти · Ctrl+Shift+C копировать путь · Ctrl+O открыть · Alt+1–3 области · Esc закрыть",
|
|
880
|
+
results: "содержимое {content} · файлы {files} · папки {dirs} · {ms} мс",
|
|
881
|
+
launcher: "Локальный поиск файлов (Ctrl+Shift+F)",
|
|
882
|
+
justNow: "только что",
|
|
883
|
+
minutesAgo: "{n} мин назад",
|
|
884
|
+
hoursAgo: "{n} ч назад",
|
|
885
|
+
phraseNotFound: "В беседе нет совпадений (возможно, она ещё не загружена)",
|
|
886
|
+
findOpen: "Найти в беседе",
|
|
887
|
+
findTitle: "Найти в беседе",
|
|
888
|
+
findAria: "Найти в беседе",
|
|
889
|
+
findPlaceholder: "Найти в беседе…",
|
|
890
|
+
findPlaceholderSelection: "Найти в выделении…",
|
|
891
|
+
findPrev: "Предыдущее совпадение (Shift+F3)",
|
|
892
|
+
findNext: "Следующее совпадение (F3)",
|
|
893
|
+
findClose: "Закрыть (Esc)",
|
|
894
|
+
findCase: "С учётом регистра",
|
|
895
|
+
findWhole: "Слово целиком",
|
|
896
|
+
findWrap: "Переход по кругу",
|
|
897
|
+
findReverse: "Обратный поиск",
|
|
898
|
+
findMode: "Режим",
|
|
899
|
+
modeNormal: "Обычный",
|
|
900
|
+
modeExtended: "Расширенный",
|
|
901
|
+
modeRegex: "Regex",
|
|
902
|
+
findScope: "В выделении",
|
|
903
|
+
findScopeChip: "выделено {n} симв.",
|
|
904
|
+
findSessionChip: "эта беседа",
|
|
905
|
+
findNoMatch: "Нет совпадений",
|
|
906
|
+
findEmpty: "Введите текст для поиска в этой беседе",
|
|
907
|
+
findInvalidRegex: "Некорректное регулярное выражение: {message}",
|
|
908
|
+
findInvalidEscape: "Некорректный escape в расширенном режиме: {token}",
|
|
909
|
+
findTimeout: "Время ожидания regex истекло; упростите выражение",
|
|
910
|
+
findRegexUnavailable: "Поиск по regex здесь недоступен (worker заблокирован)",
|
|
911
|
+
findWrappedTop: "Переход к началу",
|
|
912
|
+
findWrappedBottom: "Переход к концу",
|
|
913
|
+
findNoWrapEnd: "Достигнуто последнее совпадение (переход по кругу выключен)",
|
|
914
|
+
findNoWrapStart: "Достигнуто первое совпадение (переход по кругу выключен)",
|
|
915
|
+
findOlder: "Загрузите более ранние сообщения и повторите",
|
|
916
|
+
findLoadingOlder: "Загрузка более ранних сообщений…",
|
|
917
|
+
findLoadedOnly: "только загруженное окно · ранняя история не загружена",
|
|
918
|
+
findCapped: "ограничено",
|
|
919
|
+
findCopied: "Совпадение скопировано",
|
|
920
|
+
findSelectionLost: "Выделение сброшено; поиск по всей беседе",
|
|
921
|
+
findNoSession: "Сначала откройте беседу",
|
|
922
|
+
findOptions: "Параметры",
|
|
923
|
+
findExtendedHelp: "Расширенный: \\n \\r \\t \\0 \\xHH \\\\",
|
|
924
|
+
panelTotal: "выбрано {index}/{total}",
|
|
925
|
+
panelRangeAll: "Весь индекс",
|
|
926
|
+
panelRangeSession: "Эта беседа",
|
|
927
|
+
panelSessionHint: "Эта область ищет только проиндексированные сообщения сессий; для поиска в текущей беседе нажмите Ctrl+F",
|
|
928
|
+
panelRegexPaused: "В режиме regex поиск по содержимому приостановлен",
|
|
929
|
+
panelCountBounded: "≥ {n}",
|
|
930
|
+
panelCountExact: "{n}",
|
|
931
|
+
contentWarning: "Предупреждение индекса: {list}",
|
|
932
|
+
contentBudget: "Достигнут лимит индекса содержимого; часть файлов не проиндексирована",
|
|
933
|
+
contentTooShort: "Для поиска по содержимому нужно не менее 3 символов (для коротких запросов используйте Ctrl+F)",
|
|
934
|
+
contentTimeout: "Время ожидания поиска по содержимому истекло; сузьте запрос или область",
|
|
935
|
+
contentBadChars: "Поиск по содержимому не поддерживает NUL и управляющие символы",
|
|
936
|
+
panelCaseShort: "Aa",
|
|
937
|
+
panelWholeShort: "Слово",
|
|
938
|
+
panelModeLabel: "Режим",
|
|
939
|
+
watchDegraded: "watcher работает в ограниченном режиме; включено периодическое обновление",
|
|
940
|
+
copyAll: "Копировать пути",
|
|
941
|
+
copiedAll: "Скопировано путей: {n}",
|
|
942
|
+
contentFullIndex: "full-index",
|
|
943
|
+
contentReasoningIndex: "reasoning-indexed",
|
|
944
|
+
panelFilter: "Фильтр загруженных результатов…",
|
|
945
|
+
filterEmpty: "Ни один загруженный результат не соответствует фильтру",
|
|
946
|
+
panelLoadMore: "Загрузить ещё",
|
|
947
|
+
panelHistory: "Недавние запросы",
|
|
948
|
+
panelHistoryClear: "Очистить",
|
|
949
|
+
rootFilter: "Корень",
|
|
950
|
+
allRoots: "Все корни",
|
|
951
|
+
exportTitle: "Экспорт результатов",
|
|
952
|
+
exportCsv: "CSV",
|
|
953
|
+
exportJson: "JSON",
|
|
954
|
+
exportDone: "Экспортировано",
|
|
955
|
+
exportFailed: "Не удалось экспортировать",
|
|
956
|
+
includeArchived: "Архивные сессии", contentToolResultsIndex: "результаты инструментов",
|
|
443
957
|
},
|
|
444
958
|
}
|
|
445
959
|
const LANG = (() => {
|
|
@@ -451,6 +965,10 @@ contentWarning: 'इंडेक्स चेतावनी: {list}', contentBu
|
|
|
451
965
|
if (tag.startsWith('es')) return 'es'
|
|
452
966
|
if (tag.startsWith('pt')) return 'pt'
|
|
453
967
|
if (tag.startsWith('hi')) return 'hi'
|
|
968
|
+
if (tag.startsWith('ja')) return 'ja'
|
|
969
|
+
if (tag.startsWith('fr')) return 'fr'
|
|
970
|
+
if (tag.startsWith('de')) return 'de'
|
|
971
|
+
if (tag.startsWith('ru')) return 'ru'
|
|
454
972
|
return 'en'
|
|
455
973
|
})()
|
|
456
974
|
const TEXT = STRINGS[LANG]
|
|
@@ -1376,8 +1894,24 @@ self.onmessage = event => {
|
|
|
1376
1894
|
const loadOlderTimerRef = useRef(0)
|
|
1377
1895
|
const returnFocusRef = useRef(null)
|
|
1378
1896
|
const [anchor, setAnchor] = useState(null)
|
|
1897
|
+
const [queryHistory, setQueryHistory] = useState(readFindHistory)
|
|
1379
1898
|
const composingRef = useRef(false)
|
|
1380
1899
|
|
|
1900
|
+
useEffect(() => {
|
|
1901
|
+
if (!state.open) return undefined
|
|
1902
|
+
const text = state.query.trim()
|
|
1903
|
+
if (text.length < 2) return undefined
|
|
1904
|
+
const timer = setTimeout(() => {
|
|
1905
|
+
setQueryHistory(previous => {
|
|
1906
|
+
if (previous[0] === text) return previous
|
|
1907
|
+
const next = [text, ...previous.filter(value => value !== text)].slice(0, 20)
|
|
1908
|
+
writeFindHistory(next)
|
|
1909
|
+
return next
|
|
1910
|
+
})
|
|
1911
|
+
}, 1200)
|
|
1912
|
+
return () => clearTimeout(timer)
|
|
1913
|
+
}, [state.open, state.query])
|
|
1914
|
+
|
|
1381
1915
|
const applyHighlight = useCallback((index) => {
|
|
1382
1916
|
const matches = matchesRef.current
|
|
1383
1917
|
if (matches.length === 0) { clearFindHighlight('find'); setFindScope(null); return }
|
|
@@ -1699,6 +2233,7 @@ self.onmessage = event => {
|
|
|
1699
2233
|
placeholder: state.scope === 'selection' ? t('findPlaceholderSelection') : t('findPlaceholder'),
|
|
1700
2234
|
'aria-label': t('findAria'),
|
|
1701
2235
|
'aria-invalid': state.error !== '' ? 'true' : undefined,
|
|
2236
|
+
list: 'dsh-locator-find-history',
|
|
1702
2237
|
spellCheck: false,
|
|
1703
2238
|
autoComplete: 'off',
|
|
1704
2239
|
onInput,
|
|
@@ -1757,6 +2292,9 @@ self.onmessage = event => {
|
|
|
1757
2292
|
h('kbd', null, 'Shift+Enter'), h('span', null, '↑'),
|
|
1758
2293
|
h('kbd', null, 'Esc'),
|
|
1759
2294
|
),
|
|
2295
|
+
queryHistory.length > 0
|
|
2296
|
+
? h('datalist', { id: 'dsh-locator-find-history' }, queryHistory.map(value => h('option', { key: value, value })))
|
|
2297
|
+
: null,
|
|
1760
2298
|
)
|
|
1761
2299
|
}
|
|
1762
2300
|
|
|
@@ -1771,6 +2309,17 @@ self.onmessage = event => {
|
|
|
1771
2309
|
try { localStorage.setItem(PANEL_HISTORY_KEY, JSON.stringify(list.slice(0, 10))) } catch { /* ignore */ }
|
|
1772
2310
|
}
|
|
1773
2311
|
|
|
2312
|
+
const FIND_HISTORY_KEY = 'dsh-locator-find-history-v1'
|
|
2313
|
+
function readFindHistory() {
|
|
2314
|
+
try {
|
|
2315
|
+
const parsed = JSON.parse(localStorage.getItem(FIND_HISTORY_KEY) || '[]')
|
|
2316
|
+
return Array.isArray(parsed) ? parsed.filter(value => typeof value === 'string').slice(0, 20) : []
|
|
2317
|
+
} catch { return [] }
|
|
2318
|
+
}
|
|
2319
|
+
function writeFindHistory(list) {
|
|
2320
|
+
try { localStorage.setItem(FIND_HISTORY_KEY, JSON.stringify(list.slice(0, 20))) } catch { /* ignore */ }
|
|
2321
|
+
}
|
|
2322
|
+
|
|
1774
2323
|
function Panel() {
|
|
1775
2324
|
const open = useOpen()
|
|
1776
2325
|
const prefs = useMemo(readPrefs, [])
|
|
@@ -1792,6 +2341,8 @@ self.onmessage = event => {
|
|
|
1792
2341
|
const [caseSensitive, setCaseSensitive] = useState(prefs.caseSensitive === true)
|
|
1793
2342
|
const [wholeWord, setWholeWord] = useState(prefs.wholeWord === true)
|
|
1794
2343
|
const [sessionOnly, setSessionOnly] = useState(false)
|
|
2344
|
+
const [rootFilter, setRootFilter] = useState('')
|
|
2345
|
+
const [includeArchived, setIncludeArchived] = useState(false)
|
|
1795
2346
|
const [selected, setSelected] = useState(0)
|
|
1796
2347
|
const [toast, setToast] = useState('')
|
|
1797
2348
|
const [refreshTick, setRefreshTick] = useState(0)
|
|
@@ -1916,6 +2467,8 @@ self.onmessage = event => {
|
|
|
1916
2467
|
caseSensitive,
|
|
1917
2468
|
wholeWord,
|
|
1918
2469
|
sessionId: sessionOnly ? activeSessionId : '',
|
|
2470
|
+
root: rootFilter,
|
|
2471
|
+
includeArchived,
|
|
1919
2472
|
count: matchMode === 'regex' ? 'none' : 'exact',
|
|
1920
2473
|
}, controller.signal).then(data => {
|
|
1921
2474
|
if (controller.signal.aborted) return
|
|
@@ -1999,6 +2552,51 @@ self.onmessage = event => {
|
|
|
1999
2552
|
copyText(paths.join('\n')).then(() => notify(t('copiedAll', { n: paths.length }))).catch(() => {})
|
|
2000
2553
|
}, [notify, rows])
|
|
2001
2554
|
|
|
2555
|
+
const exportRows = useCallback(format => {
|
|
2556
|
+
if (rows.length === 0) return
|
|
2557
|
+
const records = rows.map(({ group, hit }) => ({
|
|
2558
|
+
group,
|
|
2559
|
+
kind: typeof hit.kind === 'string' ? hit.kind : group,
|
|
2560
|
+
path: typeof hit.path === 'string' ? hit.path : '',
|
|
2561
|
+
name: typeof hit.name === 'string' ? hit.name : (typeof hit.title === 'string' ? hit.title : ''),
|
|
2562
|
+
size: typeof hit.size === 'number' ? hit.size : null,
|
|
2563
|
+
mtime: typeof hit.mtime === 'number' ? hit.mtime : null,
|
|
2564
|
+
line: typeof hit.line === 'number' ? hit.line : null,
|
|
2565
|
+
sessionId: typeof hit.sessionId === 'string' ? hit.sessionId : null,
|
|
2566
|
+
messageId: typeof hit.messageId === 'string' ? hit.messageId : null,
|
|
2567
|
+
snippet: typeof hit.snippet === 'string' ? hit.snippet : '',
|
|
2568
|
+
}))
|
|
2569
|
+
let text, mime, extension
|
|
2570
|
+
if (format === 'json') {
|
|
2571
|
+
text = JSON.stringify(records, null, 2)
|
|
2572
|
+
mime = 'application/json'
|
|
2573
|
+
extension = 'json'
|
|
2574
|
+
} else {
|
|
2575
|
+
const columns = ['group', 'kind', 'path', 'name', 'size', 'mtime', 'line', 'sessionId', 'messageId', 'snippet']
|
|
2576
|
+
const cell = value => {
|
|
2577
|
+
const string = value === null || value === undefined ? '' : String(value)
|
|
2578
|
+
return /[",\r\n]/.test(string) ? '"' + string.replace(/"/g, '""') + '"' : string
|
|
2579
|
+
}
|
|
2580
|
+
text = [columns.join(','), ...records.map(record => columns.map(column => cell(record[column])).join(','))].join('\r\n')
|
|
2581
|
+
mime = 'text/csv'
|
|
2582
|
+
extension = 'csv'
|
|
2583
|
+
}
|
|
2584
|
+
try {
|
|
2585
|
+
const blob = new Blob([text], { type: mime + ';charset=utf-8' })
|
|
2586
|
+
const url = URL.createObjectURL(blob)
|
|
2587
|
+
const link = document.createElement('a')
|
|
2588
|
+
link.href = url
|
|
2589
|
+
link.download = 'dsh-locator-results-' + Date.now() + '.' + extension
|
|
2590
|
+
document.body.appendChild(link)
|
|
2591
|
+
link.click()
|
|
2592
|
+
link.remove()
|
|
2593
|
+
setTimeout(() => URL.revokeObjectURL(url), 1000)
|
|
2594
|
+
notify(t('exportDone'))
|
|
2595
|
+
} catch {
|
|
2596
|
+
notify(t('exportFailed'))
|
|
2597
|
+
}
|
|
2598
|
+
}, [notify, rows])
|
|
2599
|
+
|
|
2002
2600
|
const reveal = useCallback(hit => {
|
|
2003
2601
|
if (!hit || loading) return
|
|
2004
2602
|
post('/dsh-locator/reveal', { path: hit.path }).then(() => notify(t('revealed'))).catch(() => copy(hit))
|
|
@@ -2006,7 +2604,8 @@ self.onmessage = event => {
|
|
|
2006
2604
|
|
|
2007
2605
|
const openFile = useCallback(hit => {
|
|
2008
2606
|
if (!hit || hit.dir || loading) return
|
|
2009
|
-
|
|
2607
|
+
const line = typeof hit.line === 'number' ? hit.line : undefined
|
|
2608
|
+
post('/dsh-locator/open', { path: hit.path, line }).then(() => notify(t('opened'))).catch(() => copy(hit))
|
|
2010
2609
|
}, [copy, loading, notify])
|
|
2011
2610
|
|
|
2012
2611
|
const activate = useCallback(hit => {
|
|
@@ -2141,6 +2740,8 @@ self.onmessage = event => {
|
|
|
2141
2740
|
caseSensitive,
|
|
2142
2741
|
wholeWord,
|
|
2143
2742
|
sessionId: sessionOnly ? activeSessionId : '',
|
|
2743
|
+
root: rootFilter,
|
|
2744
|
+
includeArchived,
|
|
2144
2745
|
count: matchMode === 'regex' ? 'none' : 'exact',
|
|
2145
2746
|
})
|
|
2146
2747
|
setGroups(previous => {
|
|
@@ -2379,7 +2980,22 @@ self.onmessage = event => {
|
|
|
2379
2980
|
scopeBox('content', t('scopeContent'), contentCountText),
|
|
2380
2981
|
scopeBox('files', t('scopeFiles'), filesCountText),
|
|
2381
2982
|
scopeBox('dirs', t('scopeDirs'), dirsCountText),
|
|
2983
|
+
status !== null && Array.isArray(status.roots) && status.roots.length > 1
|
|
2984
|
+
? h('label', { className: 'dsh-locator-check', title: t('rootFilter') }, t('rootFilter'),
|
|
2985
|
+
h('select', {
|
|
2986
|
+
className: 'dsh-locator-sort',
|
|
2987
|
+
value: rootFilter,
|
|
2988
|
+
'aria-label': t('rootFilter'),
|
|
2989
|
+
onChange: event => { setRootFilter(event.target.value); setSelected(0) },
|
|
2990
|
+
},
|
|
2991
|
+
h('option', { value: '' }, t('allRoots')),
|
|
2992
|
+
status.roots.map(root => h('option', { key: root, value: root, title: root }, String(root).split(/[\\/]/).filter(Boolean).pop() || root)),
|
|
2993
|
+
))
|
|
2994
|
+
: null,
|
|
2382
2995
|
h('span', { className: 'grow' }),
|
|
2996
|
+
h('label', { className: 'dsh-locator-check', title: t('includeArchived') },
|
|
2997
|
+
h('input', { type: 'checkbox', checked: includeArchived, onChange: () => setIncludeArchived(value => !value) }),
|
|
2998
|
+
t('includeArchived')),
|
|
2383
2999
|
h('label', { className: 'dsh-locator-check' + (activeSessionId === '' ? ' disabled' : ''),
|
|
2384
3000
|
title: activeSessionId === '' ? t('findNoSession') : t('panelSessionHint') },
|
|
2385
3001
|
h('input', { type: 'checkbox', checked: sessionOnly, disabled: activeSessionId === '',
|
|
@@ -2425,7 +3041,8 @@ self.onmessage = event => {
|
|
|
2425
3041
|
? ' · ' + t('watchDegraded')
|
|
2426
3042
|
: '')
|
|
2427
3043
|
+ (status.content && status.content.fullIndex === true ? ' · ' + t('contentFullIndex') : '')
|
|
2428
|
-
+ (status.content && status.content.reasoningIndex === true ? ' · ' + t('contentReasoningIndex') : '')
|
|
3044
|
+
+ (status.content && status.content.reasoningIndex === true ? ' · ' + t('contentReasoningIndex') : '')
|
|
3045
|
+
+ (status.content && status.content.toolResultsIndex === true ? ' · ' + t('contentToolResultsIndex') : '')),
|
|
2429
3046
|
),
|
|
2430
3047
|
history.length > 0
|
|
2431
3048
|
? h('div', { className: 'dsh-locator-history' },
|
|
@@ -2478,6 +3095,12 @@ self.onmessage = event => {
|
|
|
2478
3095
|
rows.length > 0
|
|
2479
3096
|
? h('button', { className: 'dsh-locator-dirbtn', onClick: copyAll, title: t('copyAll') }, t('copyAll'))
|
|
2480
3097
|
: null,
|
|
3098
|
+
rows.length > 0
|
|
3099
|
+
? h('button', { className: 'dsh-locator-dirbtn', onClick: () => exportRows('csv'), title: t('exportTitle') }, t('exportCsv'))
|
|
3100
|
+
: null,
|
|
3101
|
+
rows.length > 0
|
|
3102
|
+
? h('button', { className: 'dsh-locator-dirbtn', onClick: () => exportRows('json'), title: t('exportTitle') }, t('exportJson'))
|
|
3103
|
+
: null,
|
|
2481
3104
|
canLoadMore
|
|
2482
3105
|
? h('button', { className: 'dsh-locator-dirbtn', disabled: loadingMore, onClick: loadMore }, loadingMore ? t('loading') : t('panelLoadMore'))
|
|
2483
3106
|
: null,
|