dsh-skill-hub 0.3.9 → 0.3.11
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/CONTRIBUTING.md +31 -3
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/lib/client.js +1440 -1335
- package/lib/client.js.map +1 -1
- package/lib/index.js +960 -724
- package/lib/types/client/api.d.ts +1 -5
- package/lib/types/client/locales/common.d.ts +1 -3
- package/lib/types/client/locales/market.d.ts +13 -5
- package/lib/types/client/locales/settings.d.ts +0 -2
- package/lib/types/client/locales/skills.d.ts +11 -13
- package/lib/types/client/locales.d.ts +25 -23
- package/lib/types/client/panel/CollectionCard.d.ts +52 -0
- package/lib/types/client/panel/GroupSummary.d.ts +13 -4
- package/lib/types/client/panel/GroupSwitchButton.d.ts +24 -0
- package/lib/types/client/panel/PanelDialogs.d.ts +49 -0
- package/lib/types/client/panel/ProjectTree.d.ts +31 -0
- package/lib/types/client/panel/ReorderButtons.d.ts +15 -0
- package/lib/types/client/panel/SkillDetailView.d.ts +0 -1
- package/lib/types/client/panel/SkillHubPanel.d.ts +5 -4
- package/lib/types/client/panel/SkillRow.d.ts +23 -5
- package/lib/types/client/panel/hooks/shared.d.ts +6 -0
- package/lib/types/client/panel/hooks/useCatalogFlow.d.ts +1 -1
- package/lib/types/client/panel/hooks/useGroupFlow.d.ts +1 -2
- package/lib/types/client/panel/hooks/useMarketFlow.d.ts +11 -10
- package/lib/types/client/panel/hooks/useRepoImportFlow.d.ts +38 -0
- package/lib/types/client/panel/hooks/useSourceFlow.d.ts +1 -1
- package/lib/types/client/panel/useDragReorder.d.ts +34 -0
- package/lib/types/client/panel/useSkillHub.d.ts +1 -3
- package/lib/types/client/settings-card.d.ts +29 -39
- package/lib/types/concurrency.d.ts +6 -0
- package/lib/types/error-text.d.ts +7 -0
- package/lib/types/protocol/stats.d.ts +33 -5
- package/lib/types/provider.d.ts +7 -0
- package/lib/types/repo/api.d.ts +36 -0
- package/lib/types/repo/discovery.d.ts +51 -0
- package/lib/types/repo/github-client.d.ts +0 -1
- package/lib/types/repo/install.d.ts +28 -0
- package/lib/types/repo/types.d.ts +22 -0
- package/lib/types/repo.d.ts +9 -120
- package/lib/types/routes/catalog-data.d.ts +31 -0
- package/lib/types/routes/collection.d.ts +13 -0
- package/lib/types/routes/deps.d.ts +70 -0
- package/lib/types/routes/helpers.d.ts +10 -110
- package/lib/types/routes/http.d.ts +39 -0
- package/lib/types/routes/route-state.d.ts +0 -2
- package/lib/types/skillfs/frontmatter.d.ts +20 -0
- package/lib/types/skillfs/paths.d.ts +7 -0
- package/lib/types/skillfs/scan.d.ts +40 -0
- package/lib/types/skillfs.d.ts +4 -64
- package/lib/types/stats/persistence.d.ts +48 -0
- package/lib/types/stats/scan.d.ts +52 -0
- package/lib/types/stats.d.ts +38 -42
- package/package.json +29 -28
- package/src/client/SkillHubSettingsCard.tsx +40 -98
- package/src/client/api.ts +0 -15
- package/src/client/locales/common.ts +2 -6
- package/src/client/locales/market.ts +25 -9
- package/src/client/locales/settings.ts +0 -4
- package/src/client/locales/skills.ts +22 -26
- package/src/client/panel/CollectionCard.tsx +125 -0
- package/src/client/panel/GroupSummary.tsx +16 -6
- package/src/client/panel/GroupSwitchButton.tsx +40 -0
- package/src/client/panel/MarketSourceRow.tsx +1 -1
- package/src/client/panel/PanelDialogs.tsx +161 -0
- package/src/client/panel/ProjectTree.tsx +106 -0
- package/src/client/panel/ReorderButtons.tsx +42 -0
- package/src/client/panel/RepoScanCard.tsx +21 -11
- package/src/client/panel/ScenesView.tsx +51 -26
- package/src/client/panel/SkillDetailView.tsx +1 -3
- package/src/client/panel/SkillHubPanel.tsx +99 -123
- package/src/client/panel/SkillRow.tsx +36 -17
- package/src/client/panel/SourcesView.tsx +103 -174
- package/src/client/panel/hooks/shared.ts +18 -0
- package/src/client/panel/hooks/useCatalogFlow.ts +14 -33
- package/src/client/panel/hooks/useGroupFlow.ts +8 -53
- package/src/client/panel/hooks/useMarketFlow.ts +26 -202
- package/src/client/panel/hooks/useMetaFlow.ts +2 -2
- package/src/client/panel/hooks/useRepoImportFlow.ts +197 -0
- package/src/client/panel/hooks/useSourceFlow.ts +11 -36
- package/src/client/panel/panel.module.css +121 -75
- package/src/client/panel/useDragReorder.ts +54 -0
- package/src/client/panel/useSkillHub.ts +12 -7
- package/src/client/settings-card.module.css +1 -1
- package/src/client/settings-card.tsx +52 -83
- package/src/concurrency.test.ts +33 -0
- package/src/concurrency.ts +19 -0
- package/src/error-text.test.ts +19 -0
- package/src/error-text.ts +10 -0
- package/src/index.ts +79 -18
- package/src/protocol/stats.ts +31 -5
- package/src/provider.test.ts +16 -0
- package/src/provider.ts +21 -2
- package/src/repo/api.ts +125 -0
- package/src/repo/discovery.ts +201 -0
- package/src/repo/github-client.ts +5 -10
- package/src/repo/install.ts +150 -0
- package/src/repo/types.ts +25 -0
- package/src/repo.ts +30 -503
- package/src/routes/catalog-data.ts +230 -0
- package/src/routes/catalog.ts +58 -47
- package/src/routes/collection.ts +36 -0
- package/src/routes/config.ts +2 -0
- package/src/routes/deps.ts +100 -0
- package/src/routes/groups.ts +15 -21
- package/src/routes/helpers.test.ts +57 -0
- package/src/routes/helpers.ts +43 -424
- package/src/routes/http.ts +119 -0
- package/src/routes/market.ts +10 -14
- package/src/routes/repo-import.ts +10 -12
- package/src/routes/route-state.test.ts +82 -0
- package/src/routes/route-state.ts +11 -6
- package/src/routes/sources.ts +18 -36
- package/src/routes.test.ts +72 -0
- package/src/skillfs/frontmatter.ts +179 -0
- package/src/skillfs/paths.ts +40 -0
- package/src/skillfs/scan.ts +175 -0
- package/src/skillfs.ts +11 -373
- package/src/stats/persistence.ts +85 -0
- package/src/stats/scan.ts +271 -0
- package/src/stats.test.ts +270 -6
- package/src/stats.ts +75 -207
- package/src/store/migrate.ts +25 -0
- package/src/store/store.ts +2 -0
- package/src/store.test.ts +29 -0
- package/src/update.ts +8 -42
package/lib/client.js
CHANGED
|
@@ -206,10 +206,6 @@ window.__ModuleLoader__.load({
|
|
|
206
206
|
config() {
|
|
207
207
|
return this.get(SKILL_HUB_API.config);
|
|
208
208
|
}
|
|
209
|
-
/** Patch the hub's runtime config (null clears a saved override). */
|
|
210
|
-
saveConfig(patch) {
|
|
211
|
-
return this.post(SKILL_HUB_API.config, patch);
|
|
212
|
-
}
|
|
213
209
|
/** 用户 tag 分组 + 系统集合组 + origin 映射。 */
|
|
214
210
|
groups() {
|
|
215
211
|
return this.get(SKILL_HUB_API.groups);
|
|
@@ -233,10 +229,6 @@ window.__ModuleLoader__.load({
|
|
|
233
229
|
async reorderTags(orderedIds) {
|
|
234
230
|
return (await this.post(SKILL_HUB_API.tagReorder, { orderedIds })).tags;
|
|
235
231
|
}
|
|
236
|
-
/** 拖拽重排来源集合 */
|
|
237
|
-
async reorderCollections(orderedNames) {
|
|
238
|
-
return (await this.post(SKILL_HUB_API.collectionReorder, { orderedNames })).collections;
|
|
239
|
-
}
|
|
240
232
|
/** 拖拽重排来源顶层分组(project / collections / personal) */
|
|
241
233
|
async reorderSourceGroups(orderedKeys) {
|
|
242
234
|
return (await this.post(SKILL_HUB_API.sourceGroupReorder, { orderedKeys })).order;
|
|
@@ -284,8 +276,8 @@ window.__ModuleLoader__.load({
|
|
|
284
276
|
//#region src/client/locales/common.ts
|
|
285
277
|
/** 面板框架与通用:入口/视图切换/面板/图例/报错/更新检查/新建表单/诊断修复。从 locales.ts 按前缀拆出,键集合不变。 */
|
|
286
278
|
const zhCommon = {
|
|
279
|
+
"drag.reorder": "拖拽调整顺序",
|
|
287
280
|
"entry.label": "技能",
|
|
288
|
-
"entry.tooltip": "技能中枢:浏览、分组与同步管理本地技能",
|
|
289
281
|
"view.sources": "来源",
|
|
290
282
|
"view.scenes": "场景",
|
|
291
283
|
"view.market": "市场",
|
|
@@ -299,7 +291,6 @@ window.__ModuleLoader__.load({
|
|
|
299
291
|
"legend.model": "模型可调 — Agent 可自动调用",
|
|
300
292
|
"legend.user": "用户可调 — 仅显式点名时触发",
|
|
301
293
|
"legend.hint": "每个技能最多一个圆点;无圆点 = 不可被调用。",
|
|
302
|
-
"panel.enabled": "已启用",
|
|
303
294
|
"panel.disabled": "已禁用",
|
|
304
295
|
"panel.diagnostics": "发现诊断",
|
|
305
296
|
"panel.empty": "没有匹配的技能。",
|
|
@@ -314,7 +305,6 @@ window.__ModuleLoader__.load({
|
|
|
314
305
|
"update.upToDate": "已是最新版本 v{version}",
|
|
315
306
|
"update.available": "发现新版本 v{version}(当前 v{current})",
|
|
316
307
|
"update.newVersion": "新版本 v{version}",
|
|
317
|
-
"update.viewRelease": "查看发布",
|
|
318
308
|
"update.error": "检查更新失败:{error}",
|
|
319
309
|
"update.unavailable": "暂无可用的发布版本",
|
|
320
310
|
"diag.fix": "修复",
|
|
@@ -334,8 +324,8 @@ window.__ModuleLoader__.load({
|
|
|
334
324
|
"err.dismiss": "知道了"
|
|
335
325
|
};
|
|
336
326
|
const enCommon = {
|
|
327
|
+
"drag.reorder": "Drag to reorder",
|
|
337
328
|
"entry.label": "Skills",
|
|
338
|
-
"entry.tooltip": "Skill hub: browse, group, and sync local skills",
|
|
339
329
|
"view.sources": "Sources",
|
|
340
330
|
"view.scenes": "Scenes",
|
|
341
331
|
"view.market": "Market",
|
|
@@ -349,7 +339,6 @@ window.__ModuleLoader__.load({
|
|
|
349
339
|
"legend.model": "Model-invocable — agents may call automatically",
|
|
350
340
|
"legend.user": "User-invocable — explicit invocation only",
|
|
351
341
|
"legend.hint": "At most one dot per skill; no dot = not invocable.",
|
|
352
|
-
"panel.enabled": "Enabled",
|
|
353
342
|
"panel.disabled": "Disabled",
|
|
354
343
|
"panel.diagnostics": "Discovery diagnostics",
|
|
355
344
|
"panel.empty": "No matching skills.",
|
|
@@ -364,7 +353,6 @@ window.__ModuleLoader__.load({
|
|
|
364
353
|
"update.upToDate": "Up to date: v{version}",
|
|
365
354
|
"update.available": "Update available: v{version} (current v{current})",
|
|
366
355
|
"update.newVersion": "New version v{version}",
|
|
367
|
-
"update.viewRelease": "View release",
|
|
368
356
|
"update.error": "Update check failed: {error}",
|
|
369
357
|
"update.unavailable": "No release available",
|
|
370
358
|
"diag.fix": "Fix",
|
|
@@ -418,6 +406,7 @@ window.__ModuleLoader__.load({
|
|
|
418
406
|
//#region src/client/locales/market.ts
|
|
419
407
|
/** 市场与仓库扫描导入。从 locales.ts 按前缀拆出,键集合不变。 */
|
|
420
408
|
const zhMarket = {
|
|
409
|
+
"market.syncHint": "将同步到上游最新版并提示可更新的本地技能",
|
|
421
410
|
"market.addPlaceholder": "owner/repo 或 https://github.com/…",
|
|
422
411
|
"market.addSource": "添加源",
|
|
423
412
|
"market.noSources": "还没有市场源。从下方内置市场添加,或输入一个 GitHub 仓库。",
|
|
@@ -440,13 +429,11 @@ window.__ModuleLoader__.load({
|
|
|
440
429
|
"market.deleteSource": "移除源",
|
|
441
430
|
"market.scan": "扫描",
|
|
442
431
|
"market.scanning": "扫描中…",
|
|
443
|
-
"market.check": "检查",
|
|
444
432
|
"market.checkUpdate": "检查更新",
|
|
445
433
|
"market.checking": "检查中…",
|
|
446
434
|
"market.upToDate": "已是最新",
|
|
447
435
|
"market.update": "更新",
|
|
448
436
|
"market.updateCount": "更新 {count} 个",
|
|
449
|
-
"market.sync": "同步",
|
|
450
437
|
"market.syncing": "同步中…",
|
|
451
438
|
"market.updated": "有更新",
|
|
452
439
|
"market.newRelease": "新版本 v{version}",
|
|
@@ -469,10 +456,19 @@ window.__ModuleLoader__.load({
|
|
|
469
456
|
"market.syncNone": "该来源还没有导入本地技能。",
|
|
470
457
|
"market.syncCancel": "跳过",
|
|
471
458
|
"market.removeHint": "移除源不影响已安装的技能。",
|
|
459
|
+
"repo.scanTitle": "扫描结果",
|
|
460
|
+
"repo.close": "关闭",
|
|
461
|
+
"repo.searchPlaceholder": "搜索技能名…",
|
|
462
|
+
"repo.allRoots": "全部 {count}",
|
|
463
|
+
"repo.selection": "已选 {selected}/{total} · {size} · 显示 {shown}/{filtered}(过滤后)",
|
|
464
|
+
"repo.noMatch": "无匹配技能",
|
|
465
|
+
"repo.loadMore": "加载更多 {step} (剩余 {remaining})",
|
|
466
|
+
"repo.skillProgress": "{done}/{total} 个技能",
|
|
472
467
|
"repo.ready": "发现 {count} 个可导入技能",
|
|
473
468
|
"repo.truncated": "⚠ 仓库过大,仅展示部分技能(GitHub 截断),可缩小仓库或指定子目录",
|
|
474
469
|
"repo.empty": "没有找到可导入技能。",
|
|
475
|
-
"repo.
|
|
470
|
+
"repo.selectVisible": "全选当前显示",
|
|
471
|
+
"repo.selectAllN": "全选全部 {count}",
|
|
476
472
|
"repo.clearAll": "清空",
|
|
477
473
|
"repo.import": "导入所选 ({count})",
|
|
478
474
|
"repo.importing": "导入中…",
|
|
@@ -484,11 +480,12 @@ window.__ModuleLoader__.load({
|
|
|
484
480
|
"repo.cancel": "取消",
|
|
485
481
|
"repo.cancelled": "已取消 · 已导入 {imported}/{total} 已保留,临时文件已清理",
|
|
486
482
|
"repo.importingCurrent": "正在导入: {name} ({done}/{total})",
|
|
487
|
-
"repo.root.skills": "
|
|
488
|
-
"repo.root.designTemplates": "
|
|
483
|
+
"repo.root.skills": "skills",
|
|
484
|
+
"repo.root.designTemplates": "design-templates",
|
|
489
485
|
"repo.root.generic": "{root}"
|
|
490
486
|
};
|
|
491
487
|
const enMarket = {
|
|
488
|
+
"market.syncHint": "Sync to the latest upstream and report local skills that can update",
|
|
492
489
|
"market.addPlaceholder": "owner/repo or https://github.com/…",
|
|
493
490
|
"market.addSource": "Add source",
|
|
494
491
|
"market.noSources": "No market sources yet. Add one from the built-in catalog below, or enter a GitHub repo.",
|
|
@@ -511,13 +508,11 @@ window.__ModuleLoader__.load({
|
|
|
511
508
|
"market.deleteSource": "Remove source",
|
|
512
509
|
"market.scan": "Scan",
|
|
513
510
|
"market.scanning": "Scanning…",
|
|
514
|
-
"market.check": "Check",
|
|
515
511
|
"market.checkUpdate": "Check for updates",
|
|
516
512
|
"market.checking": "Checking…",
|
|
517
513
|
"market.upToDate": "Up to date",
|
|
518
514
|
"market.update": "Update",
|
|
519
515
|
"market.updateCount": "Update {count}",
|
|
520
|
-
"market.sync": "Sync",
|
|
521
516
|
"market.syncing": "Syncing…",
|
|
522
517
|
"market.updated": "Updates available",
|
|
523
518
|
"market.newRelease": "New release v{version}",
|
|
@@ -540,10 +535,19 @@ window.__ModuleLoader__.load({
|
|
|
540
535
|
"market.syncNone": "No local skills tracked from this repo yet.",
|
|
541
536
|
"market.syncCancel": "Skip",
|
|
542
537
|
"market.removeHint": "Removing a source does not affect installed skills.",
|
|
538
|
+
"repo.scanTitle": "Scan result",
|
|
539
|
+
"repo.close": "Close",
|
|
540
|
+
"repo.searchPlaceholder": "Search skill name…",
|
|
541
|
+
"repo.allRoots": "All {count}",
|
|
542
|
+
"repo.selection": "Selected {selected}/{total} · {size} · showing {shown}/{filtered} (filtered)",
|
|
543
|
+
"repo.noMatch": "No matching skills",
|
|
544
|
+
"repo.loadMore": "Load {step} more ({remaining} left)",
|
|
545
|
+
"repo.skillProgress": "{done}/{total} skills",
|
|
543
546
|
"repo.ready": "{count} importable skills found",
|
|
544
547
|
"repo.truncated": "⚠ Repo too large, only partial skills shown (GitHub truncated)",
|
|
545
548
|
"repo.empty": "No importable skills found.",
|
|
546
|
-
"repo.
|
|
549
|
+
"repo.selectVisible": "Select visible",
|
|
550
|
+
"repo.selectAllN": "Select all {count}",
|
|
547
551
|
"repo.clearAll": "Clear",
|
|
548
552
|
"repo.import": "Import selected ({count})",
|
|
549
553
|
"repo.importing": "Importing…",
|
|
@@ -556,7 +560,7 @@ window.__ModuleLoader__.load({
|
|
|
556
560
|
"repo.cancelled": "Cancelled · {imported}/{total} kept, temp files cleaned",
|
|
557
561
|
"repo.importingCurrent": "Importing: {name} ({done}/{total})",
|
|
558
562
|
"repo.root.skills": "Skills",
|
|
559
|
-
"repo.root.designTemplates": "Templates
|
|
563
|
+
"repo.root.designTemplates": "Templates",
|
|
560
564
|
"repo.root.generic": "{root}"
|
|
561
565
|
};
|
|
562
566
|
//#endregion
|
|
@@ -587,8 +591,6 @@ window.__ModuleLoader__.load({
|
|
|
587
591
|
"settings.githubTokenHint": "市场/来源走 GitHub API,匿名每小时 60 次,填 token 后 5000 次。细粒度 token 无需任何权限。明文存本地设置,仅回环可读;留空即匿名(或跟随 GITHUB_TOKEN 环境变量)。",
|
|
588
592
|
"settings.githubTokenPlaceholder": "ghp_… / github_pat_…(留空为匿名)",
|
|
589
593
|
"settings.inherit": "继承",
|
|
590
|
-
"settings.on": "开",
|
|
591
|
-
"settings.off": "关",
|
|
592
594
|
"settings.overridden": "已覆盖",
|
|
593
595
|
"settings.reset": "恢复默认",
|
|
594
596
|
"settings.unsaved": "未保存",
|
|
@@ -626,8 +628,6 @@ window.__ModuleLoader__.load({
|
|
|
626
628
|
"settings.githubTokenHint": "Market/sources use the GitHub API: 60 req/h anonymous, 5000/hr with a token. A fine-grained token needs no permissions. Stored plaintext in local settings, loopback-only; empty means anonymous (or GITHUB_TOKEN env).",
|
|
627
629
|
"settings.githubTokenPlaceholder": "ghp_… / github_pat_… (empty = anonymous)",
|
|
628
630
|
"settings.inherit": "Inherit",
|
|
629
|
-
"settings.on": "On",
|
|
630
|
-
"settings.off": "Off",
|
|
631
631
|
"settings.overridden": "Overridden",
|
|
632
632
|
"settings.reset": "Reset to default",
|
|
633
633
|
"settings.unsaved": "Unsaved",
|
|
@@ -644,15 +644,14 @@ window.__ModuleLoader__.load({
|
|
|
644
644
|
//#region src/client/locales/skills.ts
|
|
645
645
|
/** 技能浏览:行徽章/分组/场景/过滤排序/相对时间。从 locales.ts 按前缀拆出,键集合不变。 */
|
|
646
646
|
const zhSkills = {
|
|
647
|
-
"
|
|
648
|
-
"
|
|
649
|
-
"
|
|
650
|
-
"group.runtime": "运行时",
|
|
651
|
-
"group.user-dsh": "用户 ~/.dsh/skills",
|
|
652
|
-
"group.user-agents": "用户 ~/.agents/skills",
|
|
653
|
-
"group.bundled": "内置",
|
|
654
|
-
"group.other": "其他来源",
|
|
647
|
+
"edit.start": "编辑",
|
|
648
|
+
"edit.hint": "开启后显示删除与排序操作",
|
|
649
|
+
"edit.done": "完成",
|
|
655
650
|
"groups.new": "新建场景",
|
|
651
|
+
"groups.collapseAll": "全部折叠",
|
|
652
|
+
"groups.expandAll": "全部展开",
|
|
653
|
+
"reorder.up": "上移",
|
|
654
|
+
"reorder.down": "下移",
|
|
656
655
|
"groups.namePlaceholder": "场景名",
|
|
657
656
|
"groups.edit": "编辑",
|
|
658
657
|
"groups.rename": "保存名称",
|
|
@@ -671,6 +670,10 @@ window.__ModuleLoader__.load({
|
|
|
671
670
|
"groups.conflictTitle": "关闭此组?",
|
|
672
671
|
"groups.conflictText": "以下技能也在其他组中开启,关闭它们会影响那些组:",
|
|
673
672
|
"filter.allSources": "全部来源",
|
|
673
|
+
"filter.title": "筛选",
|
|
674
|
+
"filter.source": "来源",
|
|
675
|
+
"filter.invocation": "调用方式",
|
|
676
|
+
"filter.clear": "清除筛选",
|
|
674
677
|
"filter.private": "个人",
|
|
675
678
|
"sort.name": "按名称",
|
|
676
679
|
"sort.added": "按添加时间",
|
|
@@ -694,11 +697,6 @@ window.__ModuleLoader__.load({
|
|
|
694
697
|
"row.open": "查看 {name} 详情(回车)",
|
|
695
698
|
"row.duplicate": "重名",
|
|
696
699
|
"row.duplicateHint": "同名技能存在多个来源,当前显示为优先级最高的版本",
|
|
697
|
-
"row.copy": "复制",
|
|
698
|
-
"row.copyMention": "复制 $mention",
|
|
699
|
-
"row.copied": "已复制",
|
|
700
|
-
"row.copyPath": "复制路径",
|
|
701
|
-
"filter.invocation": "调用",
|
|
702
700
|
"filter.invocationAll": "全部调用",
|
|
703
701
|
"filter.modelOnly": "模型可调",
|
|
704
702
|
"filter.userOnly": "用户可调",
|
|
@@ -707,15 +705,14 @@ window.__ModuleLoader__.load({
|
|
|
707
705
|
"filter.shortened": "短描述 {count} 条,悬浮看全文"
|
|
708
706
|
};
|
|
709
707
|
const enSkills = {
|
|
710
|
-
"
|
|
711
|
-
"
|
|
712
|
-
"
|
|
713
|
-
"group.runtime": "Runtime",
|
|
714
|
-
"group.user-dsh": "User ~/.dsh/skills",
|
|
715
|
-
"group.user-agents": "User ~/.agents/skills",
|
|
716
|
-
"group.bundled": "Bundled",
|
|
717
|
-
"group.other": "Other sources",
|
|
708
|
+
"edit.start": "Edit",
|
|
709
|
+
"edit.hint": "Show delete and reorder actions",
|
|
710
|
+
"edit.done": "Done",
|
|
718
711
|
"groups.new": "New scene",
|
|
712
|
+
"groups.collapseAll": "Collapse all",
|
|
713
|
+
"groups.expandAll": "Expand all",
|
|
714
|
+
"reorder.up": "Move up",
|
|
715
|
+
"reorder.down": "Move down",
|
|
719
716
|
"groups.namePlaceholder": "Scene name",
|
|
720
717
|
"groups.edit": "Edit",
|
|
721
718
|
"groups.rename": "Save name",
|
|
@@ -734,6 +731,10 @@ window.__ModuleLoader__.load({
|
|
|
734
731
|
"groups.conflictTitle": "Close this group?",
|
|
735
732
|
"groups.conflictText": "These skills are also enabled in other groups; closing them affects those groups:",
|
|
736
733
|
"filter.allSources": "All sources",
|
|
734
|
+
"filter.title": "Filter",
|
|
735
|
+
"filter.source": "Source",
|
|
736
|
+
"filter.invocation": "Invocation",
|
|
737
|
+
"filter.clear": "Clear filters",
|
|
737
738
|
"filter.private": "Personal",
|
|
738
739
|
"sort.name": "By name",
|
|
739
740
|
"sort.added": "By added",
|
|
@@ -757,11 +758,6 @@ window.__ModuleLoader__.load({
|
|
|
757
758
|
"row.open": "View {name} details (Enter)",
|
|
758
759
|
"row.duplicate": "duplicate",
|
|
759
760
|
"row.duplicateHint": "Multiple sources provide this name; the highest-priority one is shown",
|
|
760
|
-
"row.copy": "Copy",
|
|
761
|
-
"row.copyMention": "Copy $mention",
|
|
762
|
-
"row.copied": "Copied",
|
|
763
|
-
"row.copyPath": "Copy path",
|
|
764
|
-
"filter.invocation": "Invocation",
|
|
765
761
|
"filter.invocationAll": "All",
|
|
766
762
|
"filter.modelOnly": "Model",
|
|
767
763
|
"filter.userOnly": "User",
|
|
@@ -1331,7 +1327,7 @@ window.__ModuleLoader__.load({
|
|
|
1331
1327
|
}
|
|
1332
1328
|
//#endregion
|
|
1333
1329
|
//#region \0dsh-css:/Users/huanyi/Documents/personal/tools/dsh-skill-hub/src/client/settings-card.module.css.mjs
|
|
1334
|
-
const css$1 = ".TqD_hG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.TqD_hG_card:hover{border-color:var(--dsw-alias-label-dimmed)}.TqD_hG_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.TqD_hG_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.TqD_hG_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.TqD_hG_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.TqD_hG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.TqD_hG_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.TqD_hG_versionTag{opacity:.45;white-space:nowrap;font-variant-numeric:tabular-nums;vertical-align:1px;margin-left:6px;font-size:12px;font-weight:500}.TqD_hG_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.TqD_hG_chevron,.TqD_hG_chevronOpen{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.TqD_hG_chevronOpen{transform:rotate(180deg)}.TqD_hG_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.TqD_hG_readOnly,.TqD_hG_notExposed{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.TqD_hG_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.TqD_hG_failed{min-width:0;color:var(--dsw-alias-
|
|
1330
|
+
const css$1 = ".TqD_hG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.TqD_hG_card:hover{border-color:var(--dsw-alias-label-dimmed)}.TqD_hG_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.TqD_hG_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.TqD_hG_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.TqD_hG_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.TqD_hG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.TqD_hG_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.TqD_hG_versionTag{opacity:.45;white-space:nowrap;font-variant-numeric:tabular-nums;vertical-align:1px;margin-left:6px;font-size:12px;font-weight:500}.TqD_hG_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.TqD_hG_chevron,.TqD_hG_chevronOpen{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.TqD_hG_chevronOpen{transform:rotate(180deg)}.TqD_hG_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.TqD_hG_readOnly,.TqD_hG_notExposed{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.TqD_hG_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.TqD_hG_failed{min-width:0;color:var(--dsw-alias-state-error-primary,#d1242f);flex:1;margin:0;font-size:12px;line-height:1.5}.TqD_hG_discard,.TqD_hG_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.TqD_hG_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.TqD_hG_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.TqD_hG_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.TqD_hG_discard:disabled,.TqD_hG_save:disabled{opacity:.4;cursor:default}.TqD_hG_discard:focus-visible,.TqD_hG_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.TqD_hG_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.TqD_hG_field+.TqD_hG_field{border-top:1px solid var(--dsw-alias-border-l2)}.TqD_hG_head{align-items:center;gap:8px;display:flex}.TqD_hG_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.TqD_hG_badges{align-items:center;gap:8px;display:inline-flex}.TqD_hG_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.TqD_hG_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.TqD_hG_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.TqD_hG_reset:disabled{cursor:default}.TqD_hG_input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.TqD_hG_input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.TqD_hG_input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.TqD_hG_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.TqD_hG_colorRow{align-items:center;gap:8px;display:flex}.TqD_hG_colorInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);cursor:pointer;border-radius:8px;width:34px;height:34px;padding:0}.TqD_hG_colorInput:disabled{opacity:.5;cursor:default}.TqD_hG_colorInput::-webkit-color-swatch-wrapper{padding:2px}.TqD_hG_colorInput::-webkit-color-swatch{border:none;border-radius:4px}.TqD_hG_colorText{flex:1;min-width:0}.TqD_hG_switchRow{align-items:center;gap:12px;display:flex}.TqD_hG_switchText{flex:1;min-width:0}.TqD_hG_switch,.TqD_hG_switchOn{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);cursor:pointer;border-radius:999px;flex:none;width:38px;height:22px;padding:2px;transition:background .15s,border-color .15s}.TqD_hG_switchOn{border-color:var(--dsw-alias-state-business-primary,#2f81f7);background:var(--dsw-alias-state-business-primary,#2f81f7)}.TqD_hG_switch:disabled,.TqD_hG_switchOn:disabled{opacity:.4;cursor:default}.TqD_hG_switchThumb{background:#fff;border-radius:50%;width:16px;height:16px;transition:transform .15s;display:block;transform:translate(0);box-shadow:0 1px 2px #00000040}.TqD_hG_switchOn .TqD_hG_switchThumb{transform:translate(16px)}";
|
|
1335
1331
|
const tagId$1 = "dsh-skill-hub/settings-card.module.css";
|
|
1336
1332
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
1337
1333
|
const tag = document.createElement("style");
|
|
@@ -1474,6 +1470,35 @@ window.__ModuleLoader__.load({
|
|
|
1474
1470
|
}) : null]
|
|
1475
1471
|
});
|
|
1476
1472
|
}
|
|
1473
|
+
/**
|
|
1474
|
+
* The head row every staged field shares: the label (plain text when the
|
|
1475
|
+
* control has no id) plus the overridden badge and its reset button.
|
|
1476
|
+
*/
|
|
1477
|
+
function FieldShell(props) {
|
|
1478
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1479
|
+
className: settings_card_module_css_default.head,
|
|
1480
|
+
children: [props.id !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
1481
|
+
className: settings_card_module_css_default.label,
|
|
1482
|
+
htmlFor: props.id,
|
|
1483
|
+
children: props.label
|
|
1484
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1485
|
+
className: settings_card_module_css_default.label,
|
|
1486
|
+
children: props.label
|
|
1487
|
+
}), props.overridden ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1488
|
+
className: settings_card_module_css_default.badges,
|
|
1489
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1490
|
+
className: settings_card_module_css_default.badge,
|
|
1491
|
+
children: props.overriddenLabel
|
|
1492
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1493
|
+
type: "button",
|
|
1494
|
+
className: settings_card_module_css_default.reset,
|
|
1495
|
+
disabled: props.disabled,
|
|
1496
|
+
onClick: props.onReset,
|
|
1497
|
+
children: props.resetLabel
|
|
1498
|
+
})]
|
|
1499
|
+
}) : null]
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1477
1502
|
function SwitchField(props) {
|
|
1478
1503
|
const checked = props.text !== "false";
|
|
1479
1504
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -1482,25 +1507,7 @@ window.__ModuleLoader__.load({
|
|
|
1482
1507
|
className: settings_card_module_css_default.switchRow,
|
|
1483
1508
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1484
1509
|
className: settings_card_module_css_default.switchText,
|
|
1485
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1486
|
-
className: settings_card_module_css_default.head,
|
|
1487
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1488
|
-
className: settings_card_module_css_default.label,
|
|
1489
|
-
children: props.label
|
|
1490
|
-
}), props.overridden ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1491
|
-
className: settings_card_module_css_default.badges,
|
|
1492
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1493
|
-
className: settings_card_module_css_default.badge,
|
|
1494
|
-
children: props.overriddenLabel
|
|
1495
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1496
|
-
type: "button",
|
|
1497
|
-
className: settings_card_module_css_default.reset,
|
|
1498
|
-
disabled: props.disabled,
|
|
1499
|
-
onClick: props.onReset,
|
|
1500
|
-
children: props.resetLabel
|
|
1501
|
-
})]
|
|
1502
|
-
}) : null]
|
|
1503
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1510
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldShell, { ...props }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1504
1511
|
className: settings_card_module_css_default.hint,
|
|
1505
1512
|
children: props.hint
|
|
1506
1513
|
})]
|
|
@@ -1524,26 +1531,7 @@ window.__ModuleLoader__.load({
|
|
|
1524
1531
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1525
1532
|
className: settings_card_module_css_default.field,
|
|
1526
1533
|
children: [
|
|
1527
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1528
|
-
className: settings_card_module_css_default.head,
|
|
1529
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
1530
|
-
className: settings_card_module_css_default.label,
|
|
1531
|
-
htmlFor: props.id,
|
|
1532
|
-
children: props.label
|
|
1533
|
-
}), props.overridden ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1534
|
-
className: settings_card_module_css_default.badges,
|
|
1535
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1536
|
-
className: settings_card_module_css_default.badge,
|
|
1537
|
-
children: props.overriddenLabel
|
|
1538
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1539
|
-
type: "button",
|
|
1540
|
-
className: settings_card_module_css_default.reset,
|
|
1541
|
-
disabled: props.disabled,
|
|
1542
|
-
onClick: props.onReset,
|
|
1543
|
-
children: props.resetLabel
|
|
1544
|
-
})]
|
|
1545
|
-
}) : null]
|
|
1546
|
-
}),
|
|
1534
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldShell, { ...props }),
|
|
1547
1535
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1548
1536
|
className: settings_card_module_css_default.colorRow,
|
|
1549
1537
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
@@ -1577,26 +1565,7 @@ window.__ModuleLoader__.load({
|
|
|
1577
1565
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1578
1566
|
className: settings_card_module_css_default.field,
|
|
1579
1567
|
children: [
|
|
1580
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1581
|
-
className: settings_card_module_css_default.head,
|
|
1582
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
1583
|
-
className: settings_card_module_css_default.label,
|
|
1584
|
-
htmlFor: props.id,
|
|
1585
|
-
children: props.label
|
|
1586
|
-
}), props.overridden ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1587
|
-
className: settings_card_module_css_default.badges,
|
|
1588
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1589
|
-
className: settings_card_module_css_default.badge,
|
|
1590
|
-
children: props.overriddenLabel
|
|
1591
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1592
|
-
type: "button",
|
|
1593
|
-
className: settings_card_module_css_default.reset,
|
|
1594
|
-
disabled: props.disabled,
|
|
1595
|
-
onClick: props.onReset,
|
|
1596
|
-
children: props.resetLabel
|
|
1597
|
-
})]
|
|
1598
|
-
}) : null]
|
|
1599
|
-
}),
|
|
1568
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldShell, { ...props }),
|
|
1600
1569
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1601
1570
|
id: props.id,
|
|
1602
1571
|
type: "password",
|
|
@@ -1622,26 +1591,7 @@ window.__ModuleLoader__.load({
|
|
|
1622
1591
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1623
1592
|
className: settings_card_module_css_default.field,
|
|
1624
1593
|
children: [
|
|
1625
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1626
|
-
className: settings_card_module_css_default.head,
|
|
1627
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
1628
|
-
className: settings_card_module_css_default.label,
|
|
1629
|
-
htmlFor: props.id,
|
|
1630
|
-
children: props.label
|
|
1631
|
-
}), props.overridden ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1632
|
-
className: settings_card_module_css_default.badges,
|
|
1633
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1634
|
-
className: settings_card_module_css_default.badge,
|
|
1635
|
-
children: props.overriddenLabel
|
|
1636
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1637
|
-
type: "button",
|
|
1638
|
-
className: settings_card_module_css_default.reset,
|
|
1639
|
-
disabled: props.disabled,
|
|
1640
|
-
onClick: props.onReset,
|
|
1641
|
-
children: props.resetLabel
|
|
1642
|
-
})]
|
|
1643
|
-
}) : null]
|
|
1644
|
-
}),
|
|
1594
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldShell, { ...props }),
|
|
1645
1595
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1646
1596
|
id: props.id,
|
|
1647
1597
|
type: "text",
|
|
@@ -2669,6 +2619,77 @@ window.__ModuleLoader__.load({
|
|
|
2669
2619
|
};
|
|
2670
2620
|
}
|
|
2671
2621
|
};
|
|
2622
|
+
/** The card's field rows in render order; the rendered DOM order follows it. */
|
|
2623
|
+
const FIELD_ROWS = [
|
|
2624
|
+
{
|
|
2625
|
+
kind: "switch",
|
|
2626
|
+
field: "enabled",
|
|
2627
|
+
label: "settings.enabled",
|
|
2628
|
+
hint: "settings.enabledHint"
|
|
2629
|
+
},
|
|
2630
|
+
{
|
|
2631
|
+
kind: "switch",
|
|
2632
|
+
field: "announceToAgent",
|
|
2633
|
+
label: "settings.announceToAgent",
|
|
2634
|
+
hint: "settings.announceToAgentHint"
|
|
2635
|
+
},
|
|
2636
|
+
{
|
|
2637
|
+
kind: "color",
|
|
2638
|
+
field: "dotModelColor",
|
|
2639
|
+
id: "skill-hub-dot-model-color",
|
|
2640
|
+
label: "settings.dotModelColor",
|
|
2641
|
+
hint: "settings.dotModelColorHint",
|
|
2642
|
+
defaultColor: DEFAULT_DOT_MODEL_COLOR
|
|
2643
|
+
},
|
|
2644
|
+
{
|
|
2645
|
+
kind: "color",
|
|
2646
|
+
field: "dotUserColor",
|
|
2647
|
+
id: "skill-hub-dot-user-color",
|
|
2648
|
+
label: "settings.dotUserColor",
|
|
2649
|
+
hint: "settings.dotUserColorHint",
|
|
2650
|
+
defaultColor: DEFAULT_DOT_USER_COLOR
|
|
2651
|
+
},
|
|
2652
|
+
{
|
|
2653
|
+
kind: "switch",
|
|
2654
|
+
field: "showUseCount",
|
|
2655
|
+
label: "settings.showUseCount",
|
|
2656
|
+
hint: "settings.showUseCountHint"
|
|
2657
|
+
},
|
|
2658
|
+
{
|
|
2659
|
+
kind: "switch",
|
|
2660
|
+
field: "showUseTime",
|
|
2661
|
+
label: "settings.showUseTime",
|
|
2662
|
+
hint: "settings.showUseTimeHint"
|
|
2663
|
+
},
|
|
2664
|
+
{
|
|
2665
|
+
kind: "switch",
|
|
2666
|
+
field: "showGroupSummary",
|
|
2667
|
+
label: "settings.showGroupSummary",
|
|
2668
|
+
hint: "settings.showGroupSummaryHint"
|
|
2669
|
+
},
|
|
2670
|
+
{
|
|
2671
|
+
kind: "number",
|
|
2672
|
+
field: "statsWindowDays",
|
|
2673
|
+
id: "skill-hub-stats-window-days",
|
|
2674
|
+
label: "settings.statsWindowDays",
|
|
2675
|
+
hint: "settings.statsWindowDaysHint"
|
|
2676
|
+
},
|
|
2677
|
+
{
|
|
2678
|
+
kind: "number",
|
|
2679
|
+
field: "statsScanMinutes",
|
|
2680
|
+
id: "skill-hub-stats-scan-minutes",
|
|
2681
|
+
label: "settings.statsScanMinutes",
|
|
2682
|
+
hint: "settings.statsScanMinutesHint"
|
|
2683
|
+
},
|
|
2684
|
+
{
|
|
2685
|
+
kind: "secret",
|
|
2686
|
+
field: "githubToken",
|
|
2687
|
+
id: "skill-hub-github-token",
|
|
2688
|
+
label: "settings.githubToken",
|
|
2689
|
+
hint: "settings.githubTokenHint",
|
|
2690
|
+
placeholder: "settings.githubTokenPlaceholder"
|
|
2691
|
+
}
|
|
2692
|
+
];
|
|
2672
2693
|
/**
|
|
2673
2694
|
* Render the dsh-skill-hub card.
|
|
2674
2695
|
* @param props - locale copy, the card snapshot, and its form actions.
|
|
@@ -2693,7 +2714,7 @@ window.__ModuleLoader__.load({
|
|
|
2693
2714
|
resetLabel: t("settings.reset"),
|
|
2694
2715
|
disabled
|
|
2695
2716
|
};
|
|
2696
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2717
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PluginSettingsCard, {
|
|
2697
2718
|
t,
|
|
2698
2719
|
titleKey: "settings.title",
|
|
2699
2720
|
descriptionKey: "settings.description",
|
|
@@ -2701,151 +2722,43 @@ window.__ModuleLoader__.load({
|
|
|
2701
2722
|
state,
|
|
2702
2723
|
onSave: props.save,
|
|
2703
2724
|
onDiscard: props.discard,
|
|
2704
|
-
children:
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
...state.enabled,
|
|
2710
|
-
onEdit: (text) => {
|
|
2711
|
-
props.edit("enabled", text);
|
|
2712
|
-
},
|
|
2713
|
-
onReset: () => {
|
|
2714
|
-
props.resetField("enabled");
|
|
2715
|
-
}
|
|
2716
|
-
}),
|
|
2717
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchField, {
|
|
2718
|
-
label: t("settings.announceToAgent"),
|
|
2719
|
-
hint: t("settings.announceToAgentHint"),
|
|
2720
|
-
...fieldProps,
|
|
2721
|
-
...state.announceToAgent,
|
|
2722
|
-
onEdit: (text) => {
|
|
2723
|
-
props.edit("announceToAgent", text);
|
|
2724
|
-
},
|
|
2725
|
-
onReset: () => {
|
|
2726
|
-
props.resetField("announceToAgent");
|
|
2727
|
-
}
|
|
2728
|
-
}),
|
|
2729
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ColorField, {
|
|
2730
|
-
id: "skill-hub-dot-model-color",
|
|
2731
|
-
label: t("settings.dotModelColor"),
|
|
2732
|
-
hint: t("settings.dotModelColorHint"),
|
|
2733
|
-
inheritLabel: t("settings.inherit"),
|
|
2734
|
-
defaultColor: DEFAULT_DOT_MODEL_COLOR,
|
|
2735
|
-
...fieldProps,
|
|
2736
|
-
...state.dotModelColor,
|
|
2737
|
-
onEdit: (text) => {
|
|
2738
|
-
props.edit("dotModelColor", text);
|
|
2739
|
-
},
|
|
2740
|
-
onReset: () => {
|
|
2741
|
-
props.resetField("dotModelColor");
|
|
2742
|
-
}
|
|
2743
|
-
}),
|
|
2744
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ColorField, {
|
|
2745
|
-
id: "skill-hub-dot-user-color",
|
|
2746
|
-
label: t("settings.dotUserColor"),
|
|
2747
|
-
hint: t("settings.dotUserColorHint"),
|
|
2748
|
-
inheritLabel: t("settings.inherit"),
|
|
2749
|
-
defaultColor: DEFAULT_DOT_USER_COLOR,
|
|
2750
|
-
...fieldProps,
|
|
2751
|
-
...state.dotUserColor,
|
|
2752
|
-
onEdit: (text) => {
|
|
2753
|
-
props.edit("dotUserColor", text);
|
|
2754
|
-
},
|
|
2755
|
-
onReset: () => {
|
|
2756
|
-
props.resetField("dotUserColor");
|
|
2757
|
-
}
|
|
2758
|
-
}),
|
|
2759
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchField, {
|
|
2760
|
-
label: t("settings.showUseCount"),
|
|
2761
|
-
hint: t("settings.showUseCountHint"),
|
|
2762
|
-
...fieldProps,
|
|
2763
|
-
...state.showUseCount,
|
|
2764
|
-
onEdit: (text) => {
|
|
2765
|
-
props.edit("showUseCount", text);
|
|
2766
|
-
},
|
|
2767
|
-
onReset: () => {
|
|
2768
|
-
props.resetField("showUseCount");
|
|
2769
|
-
}
|
|
2770
|
-
}),
|
|
2771
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchField, {
|
|
2772
|
-
label: t("settings.showUseTime"),
|
|
2773
|
-
hint: t("settings.showUseTimeHint"),
|
|
2774
|
-
...fieldProps,
|
|
2775
|
-
...state.showUseTime,
|
|
2776
|
-
onEdit: (text) => {
|
|
2777
|
-
props.edit("showUseTime", text);
|
|
2778
|
-
},
|
|
2779
|
-
onReset: () => {
|
|
2780
|
-
props.resetField("showUseTime");
|
|
2781
|
-
}
|
|
2782
|
-
}),
|
|
2783
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchField, {
|
|
2784
|
-
label: t("settings.showGroupSummary"),
|
|
2785
|
-
hint: t("settings.showGroupSummaryHint"),
|
|
2786
|
-
...fieldProps,
|
|
2787
|
-
...state.showGroupSummary,
|
|
2788
|
-
onEdit: (text) => {
|
|
2789
|
-
props.edit("showGroupSummary", text);
|
|
2790
|
-
},
|
|
2791
|
-
onReset: () => {
|
|
2792
|
-
props.resetField("showGroupSummary");
|
|
2793
|
-
}
|
|
2794
|
-
}),
|
|
2795
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NumberField, {
|
|
2796
|
-
id: "skill-hub-stats-window-days",
|
|
2797
|
-
label: t("settings.statsWindowDays"),
|
|
2798
|
-
hint: t("settings.statsWindowDaysHint"),
|
|
2799
|
-
inheritLabel: t("settings.inherit"),
|
|
2725
|
+
children: FIELD_ROWS.map((row) => {
|
|
2726
|
+
const value = state[row.field];
|
|
2727
|
+
const common = {
|
|
2728
|
+
label: t(row.label),
|
|
2729
|
+
hint: t(row.hint),
|
|
2800
2730
|
...fieldProps,
|
|
2801
|
-
|
|
2802
|
-
overridden: state.statsWindowDays.overridden,
|
|
2803
|
-
invalid: state.statsWindowDays.invalid,
|
|
2731
|
+
...value,
|
|
2804
2732
|
onEdit: (text) => {
|
|
2805
|
-
props.edit(
|
|
2733
|
+
props.edit(row.field, text);
|
|
2806
2734
|
},
|
|
2807
2735
|
onReset: () => {
|
|
2808
|
-
props.resetField(
|
|
2736
|
+
props.resetField(row.field);
|
|
2809
2737
|
}
|
|
2810
|
-
}
|
|
2811
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2738
|
+
};
|
|
2739
|
+
if (row.kind === "switch") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchField, { ...common }, row.field);
|
|
2740
|
+
if (row.kind === "color") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ColorField, {
|
|
2741
|
+
...common,
|
|
2742
|
+
id: row.id,
|
|
2815
2743
|
inheritLabel: t("settings.inherit"),
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
label: t("settings.githubToken"),
|
|
2830
|
-
hint: t("settings.githubTokenHint"),
|
|
2831
|
-
placeholder: t("settings.githubTokenPlaceholder"),
|
|
2832
|
-
...fieldProps,
|
|
2833
|
-
text: state.githubToken.text,
|
|
2834
|
-
overridden: state.githubToken.overridden,
|
|
2835
|
-
invalid: state.githubToken.invalid,
|
|
2836
|
-
onEdit: (text) => {
|
|
2837
|
-
props.edit("githubToken", text);
|
|
2838
|
-
},
|
|
2839
|
-
onReset: () => {
|
|
2840
|
-
props.resetField("githubToken");
|
|
2841
|
-
}
|
|
2842
|
-
})
|
|
2843
|
-
]
|
|
2744
|
+
defaultColor: row.defaultColor
|
|
2745
|
+
}, row.field);
|
|
2746
|
+
if (row.kind === "number") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NumberField, {
|
|
2747
|
+
...common,
|
|
2748
|
+
id: row.id,
|
|
2749
|
+
inheritLabel: t("settings.inherit")
|
|
2750
|
+
}, row.field);
|
|
2751
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SecretField, {
|
|
2752
|
+
...common,
|
|
2753
|
+
id: row.id,
|
|
2754
|
+
placeholder: t(row.placeholder)
|
|
2755
|
+
}, row.field);
|
|
2756
|
+
})
|
|
2844
2757
|
});
|
|
2845
2758
|
}
|
|
2846
2759
|
//#endregion
|
|
2847
2760
|
//#region \0dsh-css:/Users/huanyi/Documents/personal/tools/dsh-skill-hub/src/client/panel/panel.module.css.mjs
|
|
2848
|
-
const css = "._6VtqdG_panel{-webkit-font-smoothing:antialiased;color-scheme:light dark;--hub-model:#2f81f7;--hub-user:#3fb950;flex-direction:column;gap:14px;max-width:720px;margin:0 auto;padding:28px 20px 44px;font-family:-apple-system,BlinkMacSystemFont,SF Pro Text,Helvetica Neue,sans-serif;display:flex}._6VtqdG_header{flex-wrap:wrap;align-items:baseline;gap:10px;display:flex}._6VtqdG_title{letter-spacing:-.02em;margin:0;font-size:24px;font-weight:700}._6VtqdG_hint{opacity:.5;font-size:12px}._6VtqdG_actions{gap:8px;margin-left:auto;display:flex}._6VtqdG_segmented{background:#80808024;border-radius:9px;gap:2px;padding:2px;display:flex}._6VtqdG_segBtn{color:inherit;opacity:.62;cursor:pointer;background:0 0;border:none;border-radius:7px;padding:5px 13px;font-size:12px;transition:background .15s,opacity .15s}._6VtqdG_segBtn:hover{opacity:.9}._6VtqdG_segBtnActive{opacity:1;background:#80808047;font-weight:600}._6VtqdG_search{width:100%;color:inherit;background:#8080801f;border:none;border-radius:10px;outline:none;padding:10px 14px;font-size:13px;transition:background .15s}._6VtqdG_search::placeholder{opacity:.45}._6VtqdG_search:focus{background:#8080802e}._6VtqdG_section{background:#8080800f;border-radius:12px;flex-direction:column;margin-top:4px;display:flex;overflow:hidden;box-shadow:0 1px 2px #00000008,0 4px 12px #0000000a}._6VtqdG_sectionTitle{margin:14px 16px 2px;font-size:13px;font-weight:700}._6VtqdG_groupHead{box-sizing:border-box;align-items:center;gap:8px;min-height:44px;padding:10px 14px;display:flex}._6VtqdG_groupTitle{opacity:.92;flex:1;align-items:center;gap:6px;min-width:0;font-size:13px;font-weight:600;line-height:1;display:inline-flex}._6VtqdG_groupOps{flex-wrap:wrap;flex:none;align-items:center;gap:6px;display:inline-flex}._6VtqdG_opBtn{color:inherit;cursor:pointer;background:#80808021;border:none;border-radius:999px;padding:3px 11px;font-size:11px;transition:background .15s}._6VtqdG_opBtn:hover{background:#80808038}._6VtqdG_opBtn:disabled{opacity:.4;cursor:default}._6VtqdG_row{cursor:pointer;background:0 0;align-items:center;gap:12px;padding:10px 14px;transition:background .12s;display:flex}._6VtqdG_row:hover{background:#80808014}._6VtqdG_row:focus-visible{outline:2px solid var(--hub-model);outline-offset:-2px}._6VtqdG_rowStatic{cursor:default}._6VtqdG_rowStatic:hover{background:0 0}._6VtqdG_row+._6VtqdG_row{border-top:.5px solid #80808021}._6VtqdG_rowMain{flex:1;min-width:0}._6VtqdG_rowName{align-items:center;gap:5px;font-size:13.5px;display:flex}._6VtqdG_rowNameText{font-weight:600}._6VtqdG_rowDesc{opacity:.52;white-space:nowrap;text-overflow:ellipsis;margin-top:1px;font-size:12.5px;overflow:hidden}._6VtqdG_badges{flex:none;align-items:center;gap:6px;display:flex}._6VtqdG_badge{opacity:.8;white-space:nowrap;border:.5px solid #8080804d;border-radius:999px;padding:1px 7px;font-size:10.5px}._6VtqdG_badgeReadonly{opacity:.5}._6VtqdG_switch{cursor:pointer;background:#8080804d;border:none;border-radius:999px;flex:none;width:36px;height:21px;padding:2px;transition:background .18s}._6VtqdG_switch:disabled{opacity:.5;cursor:default}._6VtqdG_switchOn{background:#34c759}._6VtqdG_switchThumb{background:#fff;border-radius:50%;width:17px;height:17px;transition:transform .18s;display:block;transform:translate(0);box-shadow:0 1px 2px #00000040}._6VtqdG_switchOn ._6VtqdG_switchThumb{transform:translate(15px)}._6VtqdG_empty{opacity:.5;text-align:center;padding:20px 0;font-size:13px}._6VtqdG_diagRow{background:#d299220f;border-left:3px solid #d29922;padding:9px 14px;font-size:12px}._6VtqdG_diagPath{opacity:.75;word-break:break-all;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}._6VtqdG_diagReason{opacity:.65;margin-top:1px}._6VtqdG_updateLink{color:inherit;font-weight:600;text-decoration:underline}._6VtqdG_errorBanner{color:#d1242f;white-space:pre-wrap;word-break:break-all;background:#d1242f12;border-radius:10px;align-items:flex-start;gap:10px;padding:10px 14px;font-size:12.5px;display:flex}._6VtqdG_successBanner{color:#3fb950;white-space:pre-wrap;word-break:break-all;background:#3fb95014;border-radius:10px;align-items:flex-start;gap:10px;padding:10px 14px;font-size:12.5px;display:flex}._6VtqdG_detailHead{flex-wrap:wrap;align-items:center;gap:10px;display:flex}._6VtqdG_back{color:inherit;cursor:pointer;background:#8080801f;border:none;border-radius:8px;padding:6px 12px;font-size:12.5px}._6VtqdG_back:hover{background:#80808033}._6VtqdG_detailName{letter-spacing:-.01em;font-size:19px;font-weight:700}._6VtqdG_detailMeta{opacity:.6;flex-direction:column;gap:4px;font-size:12px;display:flex}._6VtqdG_detailMetaLine{word-break:break-all}._6VtqdG_detailContent{white-space:pre-wrap;word-break:break-word;background:#8080800d;border-radius:12px;max-height:62vh;padding:14px 16px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.6;overflow:auto}._6VtqdG_form{background:#8080800d;border-radius:12px;flex-direction:column;gap:10px;padding:14px 16px;display:flex;box-shadow:0 1px 2px #00000008,0 4px 12px #0000000a}._6VtqdG_formRow{flex-direction:column;gap:5px;display:flex}._6VtqdG_formLabel{opacity:.6;font-size:12px}._6VtqdG_input,._6VtqdG_select{color:inherit;background:#8080801f;border:none;border-radius:9px;outline:none;padding:9px 12px;font-size:13px}._6VtqdG_input:focus,._6VtqdG_select:focus{background:#8080802e}._6VtqdG_buttons{align-items:center;gap:8px;display:flex}._6VtqdG_button{cursor:pointer;color:inherit;background:#8080801f;border:none;border-radius:8px;padding:6px 13px;font-size:12.5px;transition:background .15s}._6VtqdG_button:hover{background:#80808033}._6VtqdG_primary{background:var(--hub-model);color:#fff}._6VtqdG_primary:hover{opacity:.92;background:#2f81f7}._6VtqdG_primary:disabled{opacity:.45;cursor:default}._6VtqdG_danger{color:#fff;background:#d1242f}._6VtqdG_danger:hover{opacity:.92;background:#d1242f}._6VtqdG_danger:disabled{opacity:.45;cursor:default}._6VtqdG_formError{color:#d1242f}._6VtqdG_formSuccess{color:#3fb950}._6VtqdG_muted{opacity:.55}._6VtqdG_dot{vertical-align:middle;border-radius:50%;width:7px;height:7px;margin-left:5px;display:inline-block}._6VtqdG_dotModel{background:var(--hub-model)}._6VtqdG_dotUser{background:var(--hub-user)}._6VtqdG_displayName{opacity:.55;white-space:nowrap;text-overflow:ellipsis;flex-shrink:1;min-width:0;max-width:160px;margin-left:6px;font-size:11px;font-weight:400;overflow:hidden}._6VtqdG_legend{opacity:.55;flex-wrap:wrap;align-items:center;gap:12px;padding:2px 2px 0;font-size:11.5px;display:flex}._6VtqdG_legendItem{align-items:center;gap:4px;display:inline-flex}._6VtqdG_legendItem ._6VtqdG_dot{margin-left:0}._6VtqdG_legendHint{opacity:.8}._6VtqdG_badgeSource,._6VtqdG_badgeCount{opacity:.72;background:#8080801a;border:none}._6VtqdG_disclosure{min-width:0;color:inherit;cursor:pointer;text-align:left;background:0 0;border:none;flex:1;align-items:center;gap:7px;min-height:24px;padding:2px 0;display:flex}._6VtqdG_disclosure:hover ._6VtqdG_groupTitle{opacity:1}._6VtqdG_chevron{opacity:.55;border-bottom:1.5px solid;border-right:1.5px solid;flex:none;align-self:center;width:8px;height:8px;margin-right:2px;transition:transform .15s;transform:rotate(45deg)translateY(-1px)}._6VtqdG_chevronCollapsed{transform:rotate(-45deg)translateY(-1px)}._6VtqdG_headerCount{opacity:.5;white-space:nowrap;margin-left:2px;font-size:12px}._6VtqdG_pluginVersion{opacity:.45;white-space:nowrap;font-variant-numeric:tabular-nums;margin-left:6px;font-size:12px;font-weight:500}._6VtqdG_subbar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._6VtqdG_legendToggle{width:22px;height:22px;color:inherit;cursor:pointer;opacity:.55;background:#80808024;border:none;border-radius:50%;flex:none;font-size:12px;line-height:1;transition:opacity .15s,background .15s}._6VtqdG_legendToggle:hover{opacity:1}._6VtqdG_legendToggleActive{opacity:1;background:#80808047}._6VtqdG_filterBar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._6VtqdG_filterBar ._6VtqdG_formLabel{margin:0}._6VtqdG_useCount{color:#d29922;vertical-align:1px;background:#d299221f;border-radius:999px;margin-left:6px;padding:0 6px;font-size:11px;font-weight:700;line-height:1.6;display:inline-block}._6VtqdG_useTime{opacity:.45;white-space:nowrap;margin-left:auto;font-size:11px}._6VtqdG_switchMixed{background:#2f81f773}._6VtqdG_switchMixed ._6VtqdG_switchThumb{transform:translate(7.5px);box-shadow:0 1px 2px #00000040}._6VtqdG_groupTitleInner{align-items:baseline;display:inline-flex}._6VtqdG_sourceLink{color:inherit;opacity:.9;border-bottom:1px dotted;font-weight:600;text-decoration:none}._6VtqdG_sourceLink:hover{opacity:1}._6VtqdG_statusBadges{flex:none;align-items:center;gap:4px;display:inline-flex}._6VtqdG_statusBadge{opacity:.8;white-space:nowrap;background:#8080801a;border:.5px solid #8080804d;border-radius:999px;padding:1px 7px;font-size:10.5px}._6VtqdG_statusOk{color:#3fb950;background:0 0;border-color:currentColor}._6VtqdG_statusUpdated{color:#d29922;background:#d2992214;border-color:currentColor}._6VtqdG_statusError{color:#d1242f;background:#d1242f14;border-color:currentColor}._6VtqdG_statusWrap{cursor:pointer;background:0 0;border:none;align-items:center;gap:4px;padding:0;font-family:inherit;display:inline-flex}._6VtqdG_statusWrap:hover ._6VtqdG_statusBadge{opacity:1}._6VtqdG_statusButton{cursor:pointer;font-family:inherit}._6VtqdG_statusButton:hover{opacity:1}._6VtqdG_opDanger{color:#d1242f;background:#d1242f1a}._6VtqdG_opDanger:hover{background:#d1242f2e}._6VtqdG_iconBtn{border-radius:999px;justify-content:center;align-items:center;width:24px;height:24px;padding:0;display:inline-flex}._6VtqdG_sourceCard{background:#8080800d;border-radius:12px;flex-direction:column;gap:4px;padding:12px 14px;font-size:12px;display:flex}._6VtqdG_sourceCardTitle{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._6VtqdG_dialogOverlay{z-index:50;-webkit-backdrop-filter:blur(2px);background:#00000059;justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}._6VtqdG_dialog{background:var(--dsw-surface,#f5f5f7);min-width:min(320px,100%);max-width:380px;color:var(--dsw-text,#1d1d1f);border-radius:14px;padding:18px 18px 14px;box-shadow:0 12px 40px #00000047,0 2px 8px #00000029}@media (prefers-color-scheme:dark){._6VtqdG_dialog{color:#f5f5f7;background:#2c2c2e}}._6VtqdG_dialogTitle{letter-spacing:-.01em;margin:0 0 8px;font-size:15px;font-weight:700}._6VtqdG_dialogText{opacity:.65;margin:0 0 10px;font-size:12.5px;line-height:1.5}._6VtqdG_dialogList{flex-direction:column;gap:5px;max-height:200px;margin:0 0 14px;padding:0;list-style:none;display:flex;overflow:auto}._6VtqdG_dialogList li{opacity:.85;word-break:break-all;font-size:12.5px}._6VtqdG_dialogActions{justify-content:flex-end;gap:8px;display:flex}._6VtqdG_filterBar ._6VtqdG_search{flex:1;min-width:160px}._6VtqdG_filterBar ._6VtqdG_formLabel{flex:none}._6VtqdG_filterBar ._6VtqdG_select{flex:none;max-width:150px}._6VtqdG_filterBar ._6VtqdG_segmented{flex:none}._6VtqdG_titleIcon{vertical-align:-2px;opacity:.8;margin-right:2px;display:inline-block}._6VtqdG_grow{flex:1}._6VtqdG_hintLine{opacity:.55;margin:0;font-size:11.5px}._6VtqdG_hintPadded{margin:6px 12px 2px}._6VtqdG_hintInline{margin:4px 2px}._6VtqdG_rowMuted{cursor:default;opacity:.55}._6VtqdG_actionsPadded{padding:8px 12px}._6VtqdG_actionsTop{margin-top:8px}._6VtqdG_groupTime{margin-left:6px}._6VtqdG_sectionHeadRow{align-items:center;gap:8px;display:flex}._6VtqdG_sectionTitleFill{flex:1}._6VtqdG_dialogSelect{width:100%;margin-bottom:12px}._6VtqdG_dialogRow{align-items:center;gap:8px;display:flex}._6VtqdG_workspaceBox{align-items:center;gap:6px;display:inline-flex}._6VtqdG_workspaceInput{width:200px;padding:6px 10px;font-size:12px}._6VtqdG_projectNest{border-left:1px solid #80808024;flex-direction:column;margin:2px 0 0 14px;display:flex}._6VtqdG_dragHandle{cursor:grab;opacity:.28;letter-spacing:0;user-select:none;flex:none;justify-content:center;align-self:center;align-items:center;width:8px;height:16px;padding:0 1px;font-size:10px;display:inline-flex;overflow:hidden}._6VtqdG_dragHandle:active{cursor:grabbing}._6VtqdG_dragging{opacity:.45}._6VtqdG_dragOver{outline:2px dashed var(--hub-model,#2f81f7);outline-offset:-2px;background:#2f81f712}._6VtqdG_scanList{background:#8080800f;border:.5px solid #80808021;border-radius:12px;max-height:360px;margin-top:8px;overflow:auto}._6VtqdG_scanProgressTrack{background:#80808021;border-radius:4px;flex:1;height:6px;overflow:hidden}._6VtqdG_scanProgressFill{background:var(--hub-model,#2f81f7);height:100%;transition:width .2s}";
|
|
2761
|
+
const css = "._6VtqdG_panel{-webkit-font-smoothing:antialiased;color-scheme:light dark;--hub-model:#2f81f7;--hub-user:#3fb950;--hub-accent:var(--dsw-alias-state-business-primary,#2f81f7);--hub-text:var(--dsw-alias-label-primary,currentColor);--hub-text-2:var(--dsw-alias-label-secondary,#61666b);--hub-text-3:var(--dsw-alias-label-tertiary,#81858c);--hub-text-4:var(--dsw-alias-label-caption,#adb2b8);--hub-surface:var(--dsw-alias-bg-module-platform,#8080800f);--hub-hover:var(--dsw-alias-interactive-bg-hover,#80808014);--hub-active:var(--dsw-alias-interactive-bg-active,#80808029);--hub-border:var(--dsw-alias-border-l2,#80808021);--hub-border-2:var(--dsw-alias-border-l3,#80808033);--hub-danger:var(--dsw-alias-state-error-primary,#d1242f);--hub-success:var(--dsw-alias-state-success-primary,#3fb950);--hub-warn:var(--dsw-alias-state-warn-primary,#d29922);--hub-on-accent:var(--dsw-alias-label-primary-foreground,#fff);--hub-skeleton:var(--dsw-alias-bg-skeleton,#8080801a);flex-direction:column;gap:14px;max-width:720px;margin:0 auto;padding:28px 20px 44px;font-family:-apple-system,BlinkMacSystemFont,SF Pro Text,Helvetica Neue,sans-serif;display:flex}._6VtqdG_header{flex-wrap:wrap;align-items:baseline;gap:10px;display:flex}._6VtqdG_title{letter-spacing:-.02em;margin:0;font-size:24px;font-weight:700}._6VtqdG_hint{color:var(--hub-text-3);font-size:12px}._6VtqdG_actions{gap:8px;margin-left:auto;display:flex}._6VtqdG_segmented{background:var(--hub-hover);border-radius:9px;gap:2px;padding:2px;display:flex}._6VtqdG_segBtn{color:var(--hub-text-2);cursor:pointer;background:0 0;border:none;border-radius:7px;padding:5px 13px;font-size:12px;transition:background .15s,opacity .15s}._6VtqdG_segBtn:hover{color:var(--hub-text)}._6VtqdG_segBtnActive{background:var(--hub-active);opacity:1;font-weight:600}._6VtqdG_search{background:var(--hub-surface);width:100%;color:inherit;border:none;border-radius:10px;outline:none;padding:10px 14px;font-size:13px;transition:background .15s}._6VtqdG_search::placeholder{opacity:.45}._6VtqdG_search:focus{background:var(--hub-active)}._6VtqdG_section{background:var(--hub-surface);border-radius:12px;flex-direction:column;margin-top:4px;display:flex;overflow:hidden;box-shadow:0 1px 2px #00000008,0 4px 12px #0000000a}._6VtqdG_sectionTitle{margin:14px 16px 2px;font-size:13px;font-weight:700}._6VtqdG_groupHead{box-sizing:border-box;align-items:center;gap:8px;min-height:44px;padding:10px 14px;display:flex}._6VtqdG_groupTitle{color:var(--hub-text);flex:1;align-items:center;gap:6px;min-width:0;font-size:13px;font-weight:600;line-height:1;display:inline-flex}._6VtqdG_groupOps{flex-wrap:wrap;flex:none;align-items:center;gap:6px;display:inline-flex}._6VtqdG_opBtn{background:var(--hub-hover);color:inherit;cursor:pointer;border:none;border-radius:999px;padding:3px 11px;font-size:11px;transition:background .15s}._6VtqdG_opBtn:hover{background:var(--hub-active)}._6VtqdG_opBtn:disabled{opacity:.4;cursor:default}._6VtqdG_row{cursor:pointer;background:0 0;align-items:center;gap:12px;padding:10px 14px;transition:background .12s;display:flex}._6VtqdG_row:hover{background:var(--hub-hover)}._6VtqdG_row:focus-visible{outline:2px solid var(--hub-accent);outline-offset:-2px}._6VtqdG_rowStatic{cursor:default}._6VtqdG_rowStatic:hover{background:0 0}._6VtqdG_row+._6VtqdG_row{border-top:.5px solid var(--hub-border)}._6VtqdG_rowMain{flex:1;min-width:0}._6VtqdG_rowName{align-items:center;gap:5px;font-size:13.5px;display:flex}._6VtqdG_rowNameText{font-weight:600}._6VtqdG_rowDesc{color:var(--hub-text-3);white-space:nowrap;text-overflow:ellipsis;margin-top:1px;font-size:12.5px;overflow:hidden}._6VtqdG_badges{flex:none;align-items:center;gap:6px;display:flex}._6VtqdG_badge{border:.5px solid var(--hub-border-2);color:var(--hub-text-2);white-space:nowrap;border-radius:999px;padding:1px 7px;font-size:10.5px}._6VtqdG_badgeReadonly{opacity:.5}._6VtqdG_switch{border:1px solid var(--hub-border-2);background:var(--dsw-alias-bg-module-platform,#8080804d);cursor:pointer;border-radius:999px;flex:none;width:36px;height:21px;padding:2px;transition:background .18s}._6VtqdG_switch:disabled{opacity:.5;cursor:default}._6VtqdG_switchOn{background:var(--dsw-alias-state-business-primary,#34c759)}._6VtqdG_switchThumb{background:#fff;border-radius:50%;width:17px;height:17px;transition:transform .18s;display:block;transform:translate(0);box-shadow:0 1px 2px #00000040}._6VtqdG_switchOn ._6VtqdG_switchThumb{transform:translate(15px)}._6VtqdG_empty{color:var(--hub-text-3);text-align:center;padding:20px 0;font-size:13px}._6VtqdG_diagRow{border-left:3px solid var(--hub-warn);background:#d299220f;padding:9px 14px;font-size:12px}._6VtqdG_diagPath{color:var(--hub-text-2);word-break:break-all;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}._6VtqdG_diagReason{color:var(--hub-text-3);margin-top:1px}._6VtqdG_updateLink{color:inherit;font-weight:600;text-decoration:underline}._6VtqdG_errorBanner{color:var(--hub-danger);white-space:pre-wrap;word-break:break-all;background:#d1242f12;border-radius:10px;align-items:flex-start;gap:10px;padding:10px 14px;font-size:12.5px;display:flex}._6VtqdG_successBanner{color:var(--hub-success);white-space:pre-wrap;word-break:break-all;background:#3fb95014;border-radius:10px;align-items:flex-start;gap:10px;padding:10px 14px;font-size:12.5px;display:flex}._6VtqdG_detailHead{flex-wrap:wrap;align-items:center;gap:10px;display:flex}._6VtqdG_back{background:var(--hub-hover);color:inherit;cursor:pointer;border:none;border-radius:8px;padding:6px 12px;font-size:12.5px}._6VtqdG_back:hover{background:var(--hub-active)}._6VtqdG_detailName{letter-spacing:-.01em;font-size:19px;font-weight:700}._6VtqdG_detailMeta{color:var(--hub-text-3);flex-direction:column;gap:4px;font-size:12px;display:flex}._6VtqdG_detailMetaLine{word-break:break-all}._6VtqdG_detailContent{white-space:pre-wrap;word-break:break-word;background:var(--hub-surface);border-radius:12px;max-height:62vh;padding:14px 16px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.6;overflow:auto}._6VtqdG_form{background:var(--hub-surface);border-radius:12px;flex-direction:column;gap:10px;padding:14px 16px;display:flex;box-shadow:0 1px 2px #00000008,0 4px 12px #0000000a}._6VtqdG_formRow{flex-direction:column;gap:5px;display:flex}._6VtqdG_formLabel{color:var(--hub-text-3);font-size:12px}._6VtqdG_input,._6VtqdG_select{background:var(--hub-surface);color:inherit;border:none;border-radius:9px;outline:none;padding:9px 12px;font-size:13px}._6VtqdG_input:focus,._6VtqdG_select:focus{background:var(--hub-active)}._6VtqdG_buttons{align-items:center;gap:8px;display:flex}._6VtqdG_button{cursor:pointer;background:var(--hub-hover);color:inherit;border:none;border-radius:8px;padding:6px 13px;font-size:12.5px;transition:background .15s}._6VtqdG_button:hover{background:var(--hub-active)}._6VtqdG_primary{background:var(--hub-accent);color:var(--hub-on-accent)}._6VtqdG_primary:hover{background:var(--hub-accent);opacity:.92}._6VtqdG_primary:disabled{opacity:.45;cursor:default}._6VtqdG_danger{background:var(--hub-danger);color:var(--hub-on-accent)}._6VtqdG_danger:hover{background:var(--hub-danger);opacity:.92}._6VtqdG_danger:disabled{opacity:.45;cursor:default}._6VtqdG_formError{color:var(--hub-danger)}._6VtqdG_formSuccess{color:var(--hub-success)}._6VtqdG_dot{vertical-align:middle;border-radius:50%;width:7px;height:7px;margin-left:5px;display:inline-block}._6VtqdG_dotModel{background:var(--hub-model)}._6VtqdG_dotUser{background:var(--hub-user)}._6VtqdG_displayName{color:var(--hub-text-3);white-space:nowrap;text-overflow:ellipsis;flex-shrink:1;min-width:0;max-width:160px;margin-left:6px;font-size:11px;font-weight:400;overflow:hidden}._6VtqdG_legend{color:var(--hub-text-3);flex-wrap:wrap;align-items:center;gap:12px;padding:2px 2px 0;font-size:11.5px;display:flex}._6VtqdG_legendItem{align-items:center;gap:4px;display:inline-flex}._6VtqdG_legendItem ._6VtqdG_dot{margin-left:0}._6VtqdG_legendHint{opacity:.8}._6VtqdG_badgeSource,._6VtqdG_badgeCount{background:var(--hub-hover);opacity:.72;border:none}._6VtqdG_disclosure{min-width:0;color:inherit;cursor:pointer;text-align:left;background:0 0;border:none;flex:1;align-items:center;gap:7px;min-height:24px;padding:2px 0;display:flex}._6VtqdG_disclosure:hover ._6VtqdG_groupTitle{opacity:1}._6VtqdG_chevron{opacity:.55;border-bottom:1.5px solid;border-right:1.5px solid;flex:none;align-self:center;width:8px;height:8px;margin-right:2px;transition:transform .15s;transform:rotate(45deg)translateY(-1px)}._6VtqdG_chevronCollapsed{transform:rotate(-45deg)translateY(-1px)}._6VtqdG_headerCount{color:var(--hub-text-3);white-space:nowrap;margin-left:2px;font-size:12px}._6VtqdG_pluginVersion{color:var(--hub-text-4);white-space:nowrap;font-variant-numeric:tabular-nums;margin-left:6px;font-size:12px;font-weight:500}._6VtqdG_subbar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._6VtqdG_legendToggle{background:var(--hub-hover);width:22px;height:22px;color:inherit;cursor:pointer;opacity:.55;border:none;border-radius:50%;flex:none;font-size:12px;line-height:1;transition:opacity .15s,background .15s}._6VtqdG_legendToggle:hover{opacity:1}._6VtqdG_legendToggleActive{opacity:1;background:var(--hub-active)}._6VtqdG_filterBar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._6VtqdG_filterBar ._6VtqdG_formLabel{margin:0}._6VtqdG_useCount{color:var(--hub-warn);vertical-align:1px;background:#d299221f;border-radius:999px;margin-left:6px;padding:0 6px;font-size:11px;font-weight:700;line-height:1.6;display:inline-block}._6VtqdG_useTime{color:var(--hub-text-4);white-space:nowrap;margin-left:auto;font-size:11px}._6VtqdG_switchMixed{background:#2f81f773;background:color-mix(in srgb, var(--hub-accent) 45%, transparent)}._6VtqdG_switchMixed ._6VtqdG_switchThumb{transform:translate(7.5px);box-shadow:0 1px 2px #00000040}._6VtqdG_groupTitleInner{align-items:baseline;display:inline-flex}._6VtqdG_sourceLink{color:inherit;opacity:.9;border-bottom:1px dotted;font-weight:600;text-decoration:none}._6VtqdG_sourceLink:hover{opacity:1}._6VtqdG_statusBadges{flex:none;align-items:center;gap:4px;display:inline-flex}._6VtqdG_statusBadge{border:.5px solid var(--hub-border-2);opacity:.8;white-space:nowrap;background:var(--hub-hover);border-radius:999px;padding:1px 7px;font-size:10.5px}._6VtqdG_statusOk{color:var(--hub-success);background:0 0;border-color:currentColor}._6VtqdG_statusUpdated{color:var(--hub-warn);background:#d2992214;border-color:currentColor}._6VtqdG_statusError{color:var(--hub-danger);background:#d1242f14;border-color:currentColor}._6VtqdG_statusWrap{cursor:pointer;background:0 0;border:none;align-items:center;gap:4px;padding:0;font-family:inherit;display:inline-flex}._6VtqdG_statusWrap:hover ._6VtqdG_statusBadge{opacity:1}._6VtqdG_statusButton{cursor:pointer;font-family:inherit}._6VtqdG_statusButton:hover{opacity:1}._6VtqdG_opDanger{color:var(--hub-danger);background:#d1242f1a}._6VtqdG_opDanger:hover{background:#d1242f2e}._6VtqdG_iconBtn{border-radius:999px;justify-content:center;align-items:center;width:24px;height:24px;padding:0;display:inline-flex}._6VtqdG_sourceCard{background:var(--hub-surface);border-radius:12px;flex-direction:column;gap:4px;padding:12px 14px;font-size:12px;display:flex}._6VtqdG_sourceCardTitle{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._6VtqdG_dialogOverlay{z-index:50;-webkit-backdrop-filter:blur(2px);background:#00000059;justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}._6VtqdG_dialog{background:var(--dsw-alias-bg-layer-1,#f5f5f7);min-width:min(320px,100%);max-width:380px;color:var(--dsw-alias-label-primary,#1d1d1f);border-radius:14px;padding:18px 18px 14px;box-shadow:0 12px 40px #00000047,0 2px 8px #00000029}._6VtqdG_dialogTitle{letter-spacing:-.01em;margin:0 0 8px;font-size:15px;font-weight:700}._6VtqdG_dialogText{color:var(--hub-text-3);margin:0 0 10px;font-size:12.5px;line-height:1.5}._6VtqdG_dialogList{flex-direction:column;gap:5px;max-height:200px;margin:0 0 14px;padding:0;list-style:none;display:flex;overflow:auto}._6VtqdG_dialogList li{opacity:.85;word-break:break-all;font-size:12.5px}._6VtqdG_dialogActions{justify-content:flex-end;gap:8px;display:flex}._6VtqdG_filterBar ._6VtqdG_search{flex:1;min-width:160px}._6VtqdG_filterBar ._6VtqdG_formLabel{flex:none}._6VtqdG_filterBar ._6VtqdG_select{flex:none;max-width:150px}._6VtqdG_filterBar ._6VtqdG_segmented{flex:none}._6VtqdG_titleIcon{vertical-align:-2px;opacity:.8;margin-right:2px;display:inline-block}._6VtqdG_grow{flex:1}._6VtqdG_hintLine{color:var(--hub-text-3);margin:0;font-size:11.5px}._6VtqdG_hintPadded{margin:6px 12px 2px}._6VtqdG_hintInline{margin:4px 2px}._6VtqdG_rowMuted{cursor:default;opacity:.55}._6VtqdG_actionsPadded{padding:8px 12px}._6VtqdG_actionsTop{margin-top:8px}._6VtqdG_groupTime{margin-left:6px}._6VtqdG_sectionHeadRow{align-items:center;gap:8px;display:flex}._6VtqdG_sectionTitleFill{flex:1}._6VtqdG_dialogSelect{width:100%;margin-bottom:12px}._6VtqdG_dialogRow{align-items:center;gap:8px;display:flex}._6VtqdG_workspaceBox{align-items:center;gap:6px;display:inline-flex}._6VtqdG_workspaceInput{width:200px;padding:6px 10px;font-size:12px}._6VtqdG_projectNest{border-left:1px solid var(--dsw-alias-border-l1,#80808024);flex-direction:column;margin:2px 0 0 14px;display:flex}._6VtqdG_dragHandle{cursor:grab;opacity:.28;letter-spacing:0;user-select:none;flex:none;justify-content:center;align-self:center;align-items:center;width:8px;height:16px;padding:0 1px;font-size:10px;display:inline-flex;overflow:hidden}._6VtqdG_dragHandle:active{cursor:grabbing}._6VtqdG_dragging{opacity:.45}._6VtqdG_dragOver{outline:2px dashed var(--hub-accent);outline-offset:-2px;background:#2f81f712}._6VtqdG_scanList{border:.5px solid var(--hub-border-2);background:var(--hub-surface);border-radius:12px;max-height:360px;margin-top:8px;overflow:auto}._6VtqdG_scanProgressTrack{background:var(--hub-surface);border-radius:4px;flex:1;height:6px;overflow:hidden}._6VtqdG_scanProgressFill{background:var(--hub-accent);height:100%;transition:width .2s}._6VtqdG_filterPanel{background:var(--hub-surface);border-radius:10px;flex-wrap:wrap;align-items:center;gap:12px;padding:10px 12px;display:flex}._6VtqdG_filterField{align-items:center;gap:6px;display:inline-flex}._6VtqdG_filterField ._6VtqdG_formLabel{margin:0}._6VtqdG_filterField ._6VtqdG_select{max-width:150px}._6VtqdG_listTools{justify-content:flex-end;align-items:center;gap:8px;padding:0 2px;display:flex}._6VtqdG_opBtn:focus-visible,._6VtqdG_button:focus-visible,._6VtqdG_segBtn:focus-visible,._6VtqdG_disclosure:focus-visible,._6VtqdG_switch:focus-visible,._6VtqdG_legendToggle:focus-visible,._6VtqdG_back:focus-visible,._6VtqdG_statusWrap:focus-visible,._6VtqdG_input:focus-visible,._6VtqdG_select:focus-visible,._6VtqdG_search:focus-visible,._6VtqdG_sourceLink:focus-visible{outline:2px solid var(--hub-accent);outline-offset:2px}._6VtqdG_opBtn{padding:4px 12px}._6VtqdG_segBtn{padding:6px 13px}._6VtqdG_iconBtn,._6VtqdG_legendToggle{width:28px;height:28px}._6VtqdG_dragHandle{opacity:.45;width:16px}._6VtqdG_dragHandle:hover{opacity:1}._6VtqdG_skeleton{background:var(--hub-surface);border-radius:12px;flex-direction:column;gap:8px;padding:14px;display:flex}._6VtqdG_skeletonRow{background:var(--hub-skeleton);border-radius:7px;height:14px;animation:1.4s ease-in-out infinite _6VtqdG_hubPulse}._6VtqdG_skeletonRow:nth-child(2){width:82%}._6VtqdG_skeletonRow:nth-child(3){width:64%}@keyframes _6VtqdG_hubPulse{0%,to{opacity:.55}50%{opacity:1}}@media (prefers-reduced-motion:reduce){._6VtqdG_panel *,._6VtqdG_panel :before,._6VtqdG_panel :after{transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}}";
|
|
2849
2762
|
const tagId = "dsh-skill-hub/panel.module.css";
|
|
2850
2763
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
2851
2764
|
const tag = document.createElement("style");
|
|
@@ -2896,6 +2809,8 @@ window.__ModuleLoader__.load({
|
|
|
2896
2809
|
"empty": "_6VtqdG_empty",
|
|
2897
2810
|
"errorBanner": "_6VtqdG_errorBanner",
|
|
2898
2811
|
"filterBar": "_6VtqdG_filterBar",
|
|
2812
|
+
"filterField": "_6VtqdG_filterField",
|
|
2813
|
+
"filterPanel": "_6VtqdG_filterPanel",
|
|
2899
2814
|
"form": "_6VtqdG_form",
|
|
2900
2815
|
"formError": "_6VtqdG_formError",
|
|
2901
2816
|
"formLabel": "_6VtqdG_formLabel",
|
|
@@ -2913,6 +2828,7 @@ window.__ModuleLoader__.load({
|
|
|
2913
2828
|
"hintInline": "_6VtqdG_hintInline",
|
|
2914
2829
|
"hintLine": "_6VtqdG_hintLine",
|
|
2915
2830
|
"hintPadded": "_6VtqdG_hintPadded",
|
|
2831
|
+
"hubPulse": "_6VtqdG_hubPulse",
|
|
2916
2832
|
"iconBtn": "_6VtqdG_iconBtn",
|
|
2917
2833
|
"input": "_6VtqdG_input",
|
|
2918
2834
|
"legend": "_6VtqdG_legend",
|
|
@@ -2920,7 +2836,7 @@ window.__ModuleLoader__.load({
|
|
|
2920
2836
|
"legendItem": "_6VtqdG_legendItem",
|
|
2921
2837
|
"legendToggle": "_6VtqdG_legendToggle",
|
|
2922
2838
|
"legendToggleActive": "_6VtqdG_legendToggleActive",
|
|
2923
|
-
"
|
|
2839
|
+
"listTools": "_6VtqdG_listTools",
|
|
2924
2840
|
"opBtn": "_6VtqdG_opBtn",
|
|
2925
2841
|
"opDanger": "_6VtqdG_opDanger",
|
|
2926
2842
|
"panel": "_6VtqdG_panel",
|
|
@@ -2946,6 +2862,8 @@ window.__ModuleLoader__.load({
|
|
|
2946
2862
|
"segBtnActive": "_6VtqdG_segBtnActive",
|
|
2947
2863
|
"segmented": "_6VtqdG_segmented",
|
|
2948
2864
|
"select": "_6VtqdG_select",
|
|
2865
|
+
"skeleton": "_6VtqdG_skeleton",
|
|
2866
|
+
"skeletonRow": "_6VtqdG_skeletonRow",
|
|
2949
2867
|
"sourceCard": "_6VtqdG_sourceCard",
|
|
2950
2868
|
"sourceCardTitle": "_6VtqdG_sourceCardTitle",
|
|
2951
2869
|
"sourceLink": "_6VtqdG_sourceLink",
|
|
@@ -3034,7 +2952,7 @@ window.__ModuleLoader__.load({
|
|
|
3034
2952
|
* panel stays the single owner of state.
|
|
3035
2953
|
*/
|
|
3036
2954
|
function SkillDetailView(props) {
|
|
3037
|
-
const { detail, hubConfig, uses, groupsState, sourcesState, sourceCheck, checkingSource, syncingSource,
|
|
2955
|
+
const { detail, hubConfig, uses, groupsState, sourcesState, sourceCheck, checkingSource, syncingSource, disabled, onEnable, onBack, onCheck, onSync, onFollowDelete } = props;
|
|
3038
2956
|
const detailSource = sourcesState?.sources.find((source) => source.skills.includes(detail.name));
|
|
3039
2957
|
const detailCheck = detailSource !== void 0 ? sourceCheck[detailSource.repo] : void 0;
|
|
3040
2958
|
const [copied, setCopied] = (0, react.useState)(null);
|
|
@@ -3260,10 +3178,6 @@ window.__ModuleLoader__.load({
|
|
|
3260
3178
|
className: panel_module_css_default.hintLine,
|
|
3261
3179
|
children: tt("source.private")
|
|
3262
3180
|
}),
|
|
3263
|
-
loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3264
|
-
className: panel_module_css_default.muted,
|
|
3265
|
-
children: tt("detail.loading")
|
|
3266
|
-
}) : null,
|
|
3267
3181
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
3268
3182
|
className: panel_module_css_default.detailContent,
|
|
3269
3183
|
children: detail.content
|
|
@@ -3386,19 +3300,19 @@ window.__ModuleLoader__.load({
|
|
|
3386
3300
|
//#endregion
|
|
3387
3301
|
//#region src/client/panel/SkillRow.tsx
|
|
3388
3302
|
function SkillRow(props) {
|
|
3389
|
-
const { skill,
|
|
3390
|
-
const stat =
|
|
3303
|
+
const { skill, uses, hubConfig, busyNames, editMode, tagBusy, duplicateNames, toggle, openDetail, requestDeleteSkill } = props;
|
|
3304
|
+
const stat = uses.get(skill.name);
|
|
3391
3305
|
const count = stat?.count ?? 0;
|
|
3392
3306
|
const lastUsed = stat?.lastUsed;
|
|
3393
|
-
const isDuplicate =
|
|
3307
|
+
const isDuplicate = duplicateNames.has(skill.name);
|
|
3394
3308
|
/** 单一状态圆点:模型可调 → 蓝;否则用户可调 → 绿。与聊天 / 菜单同规则。 */
|
|
3395
3309
|
const dot = skill.invocation.modelInvocable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3396
3310
|
className: panel_module_css_default.dot + " " + panel_module_css_default.dotModel,
|
|
3397
|
-
style: dotStyle(
|
|
3311
|
+
style: dotStyle(hubConfig?.dotModelColor),
|
|
3398
3312
|
title: tt("legend.model")
|
|
3399
3313
|
}) : skill.invocation.userInvocable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3400
3314
|
className: panel_module_css_default.dot + " " + panel_module_css_default.dotUser,
|
|
3401
|
-
style: dotStyle(
|
|
3315
|
+
style: dotStyle(hubConfig?.dotUserColor),
|
|
3402
3316
|
title: tt("legend.user")
|
|
3403
3317
|
}) : null;
|
|
3404
3318
|
/** 键盘打开详情:Enter 或空格。仅当焦点在行本身(而非行内按钮)时生效。 */
|
|
@@ -3406,7 +3320,7 @@ window.__ModuleLoader__.load({
|
|
|
3406
3320
|
if (event.target !== event.currentTarget) return;
|
|
3407
3321
|
if (event.key === "Enter" || event.key === " ") {
|
|
3408
3322
|
event.preventDefault();
|
|
3409
|
-
|
|
3323
|
+
openDetail(skill.name);
|
|
3410
3324
|
}
|
|
3411
3325
|
};
|
|
3412
3326
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -3415,7 +3329,7 @@ window.__ModuleLoader__.load({
|
|
|
3415
3329
|
tabIndex: 0,
|
|
3416
3330
|
"aria-label": tt("row.open", { name: skill.name }),
|
|
3417
3331
|
onClick: () => {
|
|
3418
|
-
|
|
3332
|
+
openDetail(skill.name);
|
|
3419
3333
|
},
|
|
3420
3334
|
onKeyDown,
|
|
3421
3335
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -3432,7 +3346,7 @@ window.__ModuleLoader__.load({
|
|
|
3432
3346
|
title: skill.displayName,
|
|
3433
3347
|
children: skill.displayName
|
|
3434
3348
|
}) : null,
|
|
3435
|
-
count > 0 &&
|
|
3349
|
+
count > 0 && hubConfig?.showUseCount !== false ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3436
3350
|
className: panel_module_css_default.useCount,
|
|
3437
3351
|
children: count
|
|
3438
3352
|
}) : null,
|
|
@@ -3442,7 +3356,7 @@ window.__ModuleLoader__.load({
|
|
|
3442
3356
|
title: tt("row.duplicateHint"),
|
|
3443
3357
|
children: tt("row.duplicate")
|
|
3444
3358
|
}) : null,
|
|
3445
|
-
lastUsed !== void 0 &&
|
|
3359
|
+
lastUsed !== void 0 && hubConfig?.showUseTime !== false ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3446
3360
|
className: panel_module_css_default.useTime,
|
|
3447
3361
|
children: relativeTimeText(lastUsed)
|
|
3448
3362
|
}) : null
|
|
@@ -3458,21 +3372,21 @@ window.__ModuleLoader__.load({
|
|
|
3458
3372
|
"aria-checked": true,
|
|
3459
3373
|
"aria-label": tt("row.disable"),
|
|
3460
3374
|
className: panel_module_css_default.switch + " " + panel_module_css_default.switchOn,
|
|
3461
|
-
disabled:
|
|
3375
|
+
disabled: busyNames.has(skill.name),
|
|
3462
3376
|
onClick: (event) => {
|
|
3463
3377
|
event.stopPropagation();
|
|
3464
|
-
|
|
3378
|
+
toggle(skill, false);
|
|
3465
3379
|
},
|
|
3466
3380
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.switchThumb })
|
|
3467
|
-
}),
|
|
3381
|
+
}), editMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3468
3382
|
type: "button",
|
|
3469
3383
|
className: panel_module_css_default.opBtn + " " + panel_module_css_default.opDanger + " " + panel_module_css_default.iconBtn,
|
|
3470
|
-
disabled:
|
|
3384
|
+
disabled: busyNames.has(skill.name) || tagBusy,
|
|
3471
3385
|
title: tt("row.delete"),
|
|
3472
3386
|
"aria-label": tt("row.delete"),
|
|
3473
3387
|
onClick: (event) => {
|
|
3474
3388
|
event.stopPropagation();
|
|
3475
|
-
|
|
3389
|
+
requestDeleteSkill(skill.name);
|
|
3476
3390
|
},
|
|
3477
3391
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconTrashOutline16, { size: 14 })
|
|
3478
3392
|
}) : null] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -3547,27 +3461,363 @@ window.__ModuleLoader__.load({
|
|
|
3547
3461
|
//#endregion
|
|
3548
3462
|
//#region src/client/panel/GroupSummary.tsx
|
|
3549
3463
|
function GroupSummary(props) {
|
|
3550
|
-
const { members,
|
|
3464
|
+
const { members, uses, hubConfig } = props;
|
|
3551
3465
|
let total = 0;
|
|
3552
3466
|
let latest;
|
|
3553
3467
|
for (const name of members) {
|
|
3554
|
-
const stat =
|
|
3468
|
+
const stat = uses.get(name);
|
|
3555
3469
|
if (stat === void 0) continue;
|
|
3556
3470
|
total += stat.count;
|
|
3557
3471
|
if (stat.lastUsed !== void 0 && (latest === void 0 || stat.lastUsed > latest)) latest = stat.lastUsed;
|
|
3558
3472
|
}
|
|
3559
3473
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3560
3474
|
className: panel_module_css_default.groupTitleInner,
|
|
3561
|
-
children: [
|
|
3475
|
+
children: [hubConfig?.showGroupSummary !== false && total > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3562
3476
|
className: panel_module_css_default.useCount,
|
|
3563
3477
|
children: total
|
|
3564
|
-
}) : null,
|
|
3478
|
+
}) : null, hubConfig?.showGroupSummary !== false && latest !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3565
3479
|
className: panel_module_css_default.useTime + " " + panel_module_css_default.groupTime,
|
|
3566
3480
|
children: relativeTimeText(latest)
|
|
3567
3481
|
}) : null]
|
|
3568
3482
|
});
|
|
3569
3483
|
}
|
|
3570
3484
|
//#endregion
|
|
3485
|
+
//#region src/client/panel/useDragReorder.ts
|
|
3486
|
+
/**
|
|
3487
|
+
* Build the drag-reorder props for one container key.
|
|
3488
|
+
* @param options - the list's drag state and its reorder callback.
|
|
3489
|
+
* @returns a factory producing the props for a given container key.
|
|
3490
|
+
*/
|
|
3491
|
+
function useDragReorder(options) {
|
|
3492
|
+
const { dragKey, overKey, setDragKey, setOverKey, onDrop } = options;
|
|
3493
|
+
return (key) => {
|
|
3494
|
+
const isDragging = dragKey === key;
|
|
3495
|
+
const isOver = overKey === key && dragKey !== key;
|
|
3496
|
+
return {
|
|
3497
|
+
className: panel_module_css_default.section + (isDragging ? " " + panel_module_css_default.dragging : "") + (isOver ? " " + panel_module_css_default.dragOver : ""),
|
|
3498
|
+
draggable: true,
|
|
3499
|
+
onDragStart: (event) => {
|
|
3500
|
+
setDragKey(key);
|
|
3501
|
+
event.dataTransfer.effectAllowed = "move";
|
|
3502
|
+
event.dataTransfer.setData("text/plain", key);
|
|
3503
|
+
},
|
|
3504
|
+
onDragOver: (event) => {
|
|
3505
|
+
event.preventDefault();
|
|
3506
|
+
if (overKey !== key) setOverKey(key);
|
|
3507
|
+
},
|
|
3508
|
+
onDragLeave: () => {
|
|
3509
|
+
if (overKey === key) setOverKey(null);
|
|
3510
|
+
},
|
|
3511
|
+
onDrop: (event) => {
|
|
3512
|
+
event.preventDefault();
|
|
3513
|
+
onDrop(key);
|
|
3514
|
+
setOverKey(null);
|
|
3515
|
+
},
|
|
3516
|
+
onDragEnd: () => {
|
|
3517
|
+
setDragKey(null);
|
|
3518
|
+
setOverKey(null);
|
|
3519
|
+
}
|
|
3520
|
+
};
|
|
3521
|
+
};
|
|
3522
|
+
}
|
|
3523
|
+
//#endregion
|
|
3524
|
+
//#region src/client/panel/ReorderButtons.tsx
|
|
3525
|
+
function ReorderButtons(props) {
|
|
3526
|
+
const { canMoveUp, canMoveDown, onMove } = props;
|
|
3527
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3528
|
+
type: "button",
|
|
3529
|
+
className: panel_module_css_default.opBtn + " " + panel_module_css_default.iconBtn,
|
|
3530
|
+
disabled: !canMoveUp,
|
|
3531
|
+
"aria-label": tt("reorder.up"),
|
|
3532
|
+
title: tt("reorder.up"),
|
|
3533
|
+
onClick: (event) => {
|
|
3534
|
+
event.stopPropagation();
|
|
3535
|
+
onMove(-1);
|
|
3536
|
+
},
|
|
3537
|
+
children: "↑"
|
|
3538
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3539
|
+
type: "button",
|
|
3540
|
+
className: panel_module_css_default.opBtn + " " + panel_module_css_default.iconBtn,
|
|
3541
|
+
disabled: !canMoveDown,
|
|
3542
|
+
"aria-label": tt("reorder.down"),
|
|
3543
|
+
title: tt("reorder.down"),
|
|
3544
|
+
onClick: (event) => {
|
|
3545
|
+
event.stopPropagation();
|
|
3546
|
+
onMove(1);
|
|
3547
|
+
},
|
|
3548
|
+
children: "↓"
|
|
3549
|
+
})] });
|
|
3550
|
+
}
|
|
3551
|
+
//#endregion
|
|
3552
|
+
//#region src/client/panel/ProjectTree.tsx
|
|
3553
|
+
function ProjectTree(props) {
|
|
3554
|
+
const { skills, collapsedGroups, toggleGroupCollapse, subdividedProjects, toggleSubdivide, rowProps, dragProps, editMode, canMoveUp, canMoveDown, onMove } = props;
|
|
3555
|
+
const topCollapsed = collapsedGroups.has("project");
|
|
3556
|
+
const byProject = /* @__PURE__ */ new Map();
|
|
3557
|
+
for (const skill of skills) {
|
|
3558
|
+
const key = skill.workspace ?? skill.source;
|
|
3559
|
+
const entry = byProject.get(key);
|
|
3560
|
+
if (entry === void 0) byProject.set(key, {
|
|
3561
|
+
title: skill.workspaceTitle ?? skill.workspace ?? tt("groups.project"),
|
|
3562
|
+
skills: [skill]
|
|
3563
|
+
});
|
|
3564
|
+
else entry.skills.push(skill);
|
|
3565
|
+
}
|
|
3566
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3567
|
+
...dragProps,
|
|
3568
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3569
|
+
className: panel_module_css_default.groupHead,
|
|
3570
|
+
children: [
|
|
3571
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3572
|
+
className: panel_module_css_default.dragHandle,
|
|
3573
|
+
"aria-hidden": true,
|
|
3574
|
+
title: tt("drag.reorder"),
|
|
3575
|
+
children: "⋮⋮"
|
|
3576
|
+
}),
|
|
3577
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3578
|
+
type: "button",
|
|
3579
|
+
className: panel_module_css_default.disclosure,
|
|
3580
|
+
"aria-expanded": !topCollapsed,
|
|
3581
|
+
onClick: () => {
|
|
3582
|
+
toggleGroupCollapse("project");
|
|
3583
|
+
},
|
|
3584
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.chevron + (topCollapsed ? " " + panel_module_css_default.chevronCollapsed : "") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3585
|
+
className: panel_module_css_default.groupTitle,
|
|
3586
|
+
children: [
|
|
3587
|
+
tt("groups.project"),
|
|
3588
|
+
" · ",
|
|
3589
|
+
byProject.size
|
|
3590
|
+
]
|
|
3591
|
+
})]
|
|
3592
|
+
}),
|
|
3593
|
+
editMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3594
|
+
className: panel_module_css_default.groupOps,
|
|
3595
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReorderButtons, {
|
|
3596
|
+
canMoveUp,
|
|
3597
|
+
canMoveDown,
|
|
3598
|
+
onMove
|
|
3599
|
+
})
|
|
3600
|
+
}) : null
|
|
3601
|
+
]
|
|
3602
|
+
}), !topCollapsed ? [...byProject.entries()].map(([key, proj]) => {
|
|
3603
|
+
const projKey = "project:" + key;
|
|
3604
|
+
const projCollapsed = collapsedGroups.has(projKey);
|
|
3605
|
+
const subdivided = subdividedProjects.has(key);
|
|
3606
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3607
|
+
className: panel_module_css_default.projectNest,
|
|
3608
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3609
|
+
className: panel_module_css_default.groupHead,
|
|
3610
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3611
|
+
type: "button",
|
|
3612
|
+
className: panel_module_css_default.disclosure,
|
|
3613
|
+
"aria-expanded": !projCollapsed,
|
|
3614
|
+
onClick: () => {
|
|
3615
|
+
toggleGroupCollapse(projKey);
|
|
3616
|
+
},
|
|
3617
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.chevron + (projCollapsed ? " " + panel_module_css_default.chevronCollapsed : "") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3618
|
+
className: panel_module_css_default.groupTitle,
|
|
3619
|
+
children: [
|
|
3620
|
+
proj.title,
|
|
3621
|
+
" · ",
|
|
3622
|
+
proj.skills.length,
|
|
3623
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupSummary, {
|
|
3624
|
+
members: proj.skills.map((s) => s.name),
|
|
3625
|
+
uses: rowProps.uses,
|
|
3626
|
+
hubConfig: rowProps.hubConfig
|
|
3627
|
+
})
|
|
3628
|
+
]
|
|
3629
|
+
})]
|
|
3630
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3631
|
+
className: panel_module_css_default.groupOps,
|
|
3632
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3633
|
+
type: "button",
|
|
3634
|
+
className: panel_module_css_default.opBtn,
|
|
3635
|
+
onClick: (event) => {
|
|
3636
|
+
event.stopPropagation();
|
|
3637
|
+
toggleSubdivide(key);
|
|
3638
|
+
},
|
|
3639
|
+
children: subdivided ? tt("groups.merge") : tt("groups.subdivide")
|
|
3640
|
+
})
|
|
3641
|
+
})]
|
|
3642
|
+
}), !projCollapsed ? subdivided ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3643
|
+
className: panel_module_css_default.projectNest,
|
|
3644
|
+
children: ["project-dsh", "project-agents"].map((source) => {
|
|
3645
|
+
const list = proj.skills.filter((skill) => skill.source === source);
|
|
3646
|
+
if (list.length === 0) return null;
|
|
3647
|
+
const srcKey = projKey + ":" + source;
|
|
3648
|
+
const srcCollapsed = collapsedGroups.has(srcKey);
|
|
3649
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3650
|
+
className: panel_module_css_default.projectNest,
|
|
3651
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3652
|
+
className: panel_module_css_default.groupHead,
|
|
3653
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3654
|
+
type: "button",
|
|
3655
|
+
className: panel_module_css_default.disclosure,
|
|
3656
|
+
"aria-expanded": !srcCollapsed,
|
|
3657
|
+
onClick: () => {
|
|
3658
|
+
toggleGroupCollapse(srcKey);
|
|
3659
|
+
},
|
|
3660
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.chevron + (srcCollapsed ? " " + panel_module_css_default.chevronCollapsed : "") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3661
|
+
className: panel_module_css_default.groupTitle,
|
|
3662
|
+
children: [
|
|
3663
|
+
tt("badge.source." + source),
|
|
3664
|
+
" · ",
|
|
3665
|
+
list.length
|
|
3666
|
+
]
|
|
3667
|
+
})]
|
|
3668
|
+
})
|
|
3669
|
+
}), !srcCollapsed ? list.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillRow, {
|
|
3670
|
+
skill,
|
|
3671
|
+
...rowProps
|
|
3672
|
+
}, skill.name)) : null]
|
|
3673
|
+
}, srcKey);
|
|
3674
|
+
})
|
|
3675
|
+
}) : proj.skills.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillRow, {
|
|
3676
|
+
skill,
|
|
3677
|
+
...rowProps
|
|
3678
|
+
}, skill.name)) : null]
|
|
3679
|
+
}, projKey);
|
|
3680
|
+
}) : null]
|
|
3681
|
+
});
|
|
3682
|
+
}
|
|
3683
|
+
//#endregion
|
|
3684
|
+
//#region src/client/panel/GroupSwitchButton.tsx
|
|
3685
|
+
function GroupSwitchButton(props) {
|
|
3686
|
+
const { state, label, memberCount, batchBusy, hasWritable, onToggle } = props;
|
|
3687
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3688
|
+
type: "button",
|
|
3689
|
+
role: "switch",
|
|
3690
|
+
"aria-checked": state !== "off",
|
|
3691
|
+
"aria-label": label,
|
|
3692
|
+
className: panel_module_css_default.switch + (state === "on" ? " " + panel_module_css_default.switchOn : state === "mixed" ? " " + panel_module_css_default.switchMixed : ""),
|
|
3693
|
+
disabled: batchBusy || memberCount === 0 || state !== "off" && !hasWritable,
|
|
3694
|
+
title: state !== "off" && !hasWritable ? tt("groups.noWritable") : void 0,
|
|
3695
|
+
onClick: (event) => {
|
|
3696
|
+
event.stopPropagation();
|
|
3697
|
+
onToggle();
|
|
3698
|
+
},
|
|
3699
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.switchThumb })
|
|
3700
|
+
});
|
|
3701
|
+
}
|
|
3702
|
+
//#endregion
|
|
3703
|
+
//#region src/client/panel/CollectionCard.tsx
|
|
3704
|
+
function CollectionCard(props) {
|
|
3705
|
+
const { collection, skills, disabledMembers, collapsed, view, check, hasWritable, editMode, canMoveUp, canMoveDown, onMove, checkingSource, syncingSource, batchBusy, rowProps, dragProps, toggleGroupCollapse, checkSources, requestSync, requestDelete, toggleGroup, requestDeleteGroup, enableDisabled, openDetail } = props;
|
|
3706
|
+
const { busyNames, duplicateNames, uses, hubConfig } = rowProps;
|
|
3707
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3708
|
+
...dragProps,
|
|
3709
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3710
|
+
className: panel_module_css_default.groupHead,
|
|
3711
|
+
children: [
|
|
3712
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3713
|
+
className: panel_module_css_default.dragHandle,
|
|
3714
|
+
"aria-hidden": true,
|
|
3715
|
+
title: tt("drag.reorder"),
|
|
3716
|
+
children: "⋮⋮"
|
|
3717
|
+
}),
|
|
3718
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3719
|
+
type: "button",
|
|
3720
|
+
className: panel_module_css_default.disclosure,
|
|
3721
|
+
"aria-expanded": !collapsed,
|
|
3722
|
+
onClick: () => {
|
|
3723
|
+
toggleGroupCollapse("col:" + collection.name);
|
|
3724
|
+
},
|
|
3725
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.chevron + (collapsed ? " " + panel_module_css_default.chevronCollapsed : "") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3726
|
+
className: panel_module_css_default.groupTitle,
|
|
3727
|
+
children: [
|
|
3728
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3729
|
+
className: panel_module_css_default.sourceLink,
|
|
3730
|
+
href: "https://github.com/" + collection.name,
|
|
3731
|
+
target: "_blank",
|
|
3732
|
+
rel: "noreferrer",
|
|
3733
|
+
onClick: (event) => {
|
|
3734
|
+
event.stopPropagation();
|
|
3735
|
+
},
|
|
3736
|
+
children: collection.name
|
|
3737
|
+
}),
|
|
3738
|
+
" · " + collection.skillNames.length,
|
|
3739
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupSummary, {
|
|
3740
|
+
members: collection.skillNames,
|
|
3741
|
+
uses,
|
|
3742
|
+
hubConfig
|
|
3743
|
+
})
|
|
3744
|
+
]
|
|
3745
|
+
})]
|
|
3746
|
+
}),
|
|
3747
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3748
|
+
className: panel_module_css_default.groupOps,
|
|
3749
|
+
children: [
|
|
3750
|
+
editMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReorderButtons, {
|
|
3751
|
+
canMoveUp,
|
|
3752
|
+
canMoveDown,
|
|
3753
|
+
onMove
|
|
3754
|
+
}) : null,
|
|
3755
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SourceStatusBadge, {
|
|
3756
|
+
check,
|
|
3757
|
+
checking: checkingSource === collection.name,
|
|
3758
|
+
onCheck: () => {
|
|
3759
|
+
checkSources(collection.name);
|
|
3760
|
+
}
|
|
3761
|
+
}),
|
|
3762
|
+
check !== void 0 && check.changed && check.updated.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3763
|
+
type: "button",
|
|
3764
|
+
className: panel_module_css_default.opBtn,
|
|
3765
|
+
disabled: syncingSource !== null,
|
|
3766
|
+
onClick: (event) => {
|
|
3767
|
+
event.stopPropagation();
|
|
3768
|
+
requestSync(collection.name, check.updated);
|
|
3769
|
+
},
|
|
3770
|
+
children: syncingSource === collection.name ? tt("source.syncing") : tt("source.sync")
|
|
3771
|
+
}) : null,
|
|
3772
|
+
check !== void 0 && check.deleted.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3773
|
+
type: "button",
|
|
3774
|
+
className: panel_module_css_default.opBtn + " " + panel_module_css_default.opDanger,
|
|
3775
|
+
onClick: (event) => {
|
|
3776
|
+
event.stopPropagation();
|
|
3777
|
+
requestDelete(collection.name, check.deleted);
|
|
3778
|
+
},
|
|
3779
|
+
children: tt("source.followDelete")
|
|
3780
|
+
}) : null,
|
|
3781
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupSwitchButton, {
|
|
3782
|
+
state: view.state,
|
|
3783
|
+
label: collection.name,
|
|
3784
|
+
memberCount: collection.skillNames.length,
|
|
3785
|
+
batchBusy,
|
|
3786
|
+
hasWritable,
|
|
3787
|
+
onToggle: () => {
|
|
3788
|
+
toggleGroup("col:" + collection.name, collection.name, view.state);
|
|
3789
|
+
}
|
|
3790
|
+
}),
|
|
3791
|
+
editMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3792
|
+
type: "button",
|
|
3793
|
+
className: panel_module_css_default.opBtn + " " + panel_module_css_default.opDanger,
|
|
3794
|
+
title: tt("source.deleteGroupHint", { count: collection.skillNames.length }),
|
|
3795
|
+
onClick: (event) => {
|
|
3796
|
+
event.stopPropagation();
|
|
3797
|
+
requestDeleteGroup(collection.name, collection.skillNames);
|
|
3798
|
+
},
|
|
3799
|
+
children: tt("source.deleteGroup")
|
|
3800
|
+
}) : null
|
|
3801
|
+
]
|
|
3802
|
+
})
|
|
3803
|
+
]
|
|
3804
|
+
}), !collapsed ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [skills.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillRow, {
|
|
3805
|
+
skill,
|
|
3806
|
+
...rowProps
|
|
3807
|
+
}, skill.name)), disabledMembers.map((record) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DisabledRow, {
|
|
3808
|
+
record,
|
|
3809
|
+
busy: busyNames.has(record.name),
|
|
3810
|
+
duplicate: duplicateNames.has(record.name),
|
|
3811
|
+
onEnable: () => {
|
|
3812
|
+
enableDisabled(record);
|
|
3813
|
+
},
|
|
3814
|
+
onOpen: () => {
|
|
3815
|
+
openDetail(record.name);
|
|
3816
|
+
}
|
|
3817
|
+
}, record.name))] }) : null]
|
|
3818
|
+
});
|
|
3819
|
+
}
|
|
3820
|
+
//#endregion
|
|
3571
3821
|
//#region src/client/panel/SourcesView.tsx
|
|
3572
3822
|
/**
|
|
3573
3823
|
* Sources tab: the flat skill list or the grouped view — a project-level
|
|
@@ -3578,19 +3828,18 @@ window.__ModuleLoader__.load({
|
|
|
3578
3828
|
*/
|
|
3579
3829
|
function SourcesView(props) {
|
|
3580
3830
|
const { hub } = props;
|
|
3581
|
-
const { catalog, groupsState, skillView, sourceFilter, origins, sorted, normalized, collapsedGroups, viewNames, sourceCheck, actionNames, checkingSource, syncingSource, batchBusy, busyNames, toggleGroupCollapse, checkSources, requestSync, requestDelete, requestDeleteGroup, toggleGroup, enableDisabled } = hub;
|
|
3831
|
+
const { catalog, groupsState, skillView, sourceFilter, origins, sorted, normalized, collapsedGroups, viewNames, sourceCheck, actionNames, checkingSource, syncingSource, batchBusy, busyNames, toggleGroupCollapse, setAllGroupsCollapsed, checkSources, requestSync, requestDelete, requestDeleteGroup, toggleGroup, enableDisabled } = hub;
|
|
3582
3832
|
const [topDragKey, setTopDragKey] = (0, react.useState)(null);
|
|
3583
3833
|
const [topOverKey, setTopOverKey] = (0, react.useState)(null);
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
hub
|
|
3587
|
-
}, skill.name)) });
|
|
3834
|
+
/** 重复技能名集合:整表只建一次,行内用 has 取代逐行线性 includes。 */
|
|
3835
|
+
const duplicateNames = (0, react.useMemo)(() => new Set(catalog?.duplicateNames ?? []), [catalog]);
|
|
3588
3836
|
const projectSkillsAll = filterBySource(sorted, sourceFilter, origins).filter((skill) => isProjectSource(skill.source));
|
|
3589
3837
|
const hasProject = projectSkillsAll.length > 0;
|
|
3590
3838
|
const collections = groupsState?.collections ?? [];
|
|
3591
3839
|
const uncategorized = filterBySource(sorted, sourceFilter, origins).filter((skill) => origins[skill.name] === void 0 && !isProjectSource(skill.source));
|
|
3592
|
-
const
|
|
3593
|
-
const
|
|
3840
|
+
const personalDisabled = (catalog?.disabled ?? []).filter((record) => origins[record.name] === void 0).filter((record) => normalized.length === 0 || record.name.toLocaleLowerCase().includes(normalized) || record.description.toLocaleLowerCase().includes(normalized)).filter((record) => sourceFilter === "all" || sourceFilter === "private");
|
|
3841
|
+
const allPersonalNames = [...uncategorized.map((s) => s.name), ...personalDisabled.map((r) => r.name)];
|
|
3842
|
+
const hasPersonal = allPersonalNames.length > 0;
|
|
3594
3843
|
const defaultTopKeys = [
|
|
3595
3844
|
...hasProject ? ["project"] : [],
|
|
3596
3845
|
...collections.map((c) => "col:" + c.name),
|
|
@@ -3615,389 +3864,185 @@ window.__ModuleLoader__.load({
|
|
|
3615
3864
|
next.splice(to, 0, moved);
|
|
3616
3865
|
hub.reorderSourceGroups(next);
|
|
3617
3866
|
};
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3867
|
+
const drag = useDragReorder({
|
|
3868
|
+
dragKey: topDragKey,
|
|
3869
|
+
overKey: topOverKey,
|
|
3870
|
+
setDragKey: setTopDragKey,
|
|
3871
|
+
setOverKey: setTopOverKey,
|
|
3872
|
+
onDrop: handleTopDrop
|
|
3873
|
+
});
|
|
3874
|
+
/** 顶层分组是否已全部折叠(决定「全部折叠/展开」按钮的文案)。 */
|
|
3875
|
+
const allTopCollapsed = topOrderedKeys.length > 0 && topOrderedKeys.every((key) => collapsedGroups.has(key));
|
|
3876
|
+
/** 键盘可用的排序:与相邻项交换后落盘(与拖拽走同一条 store 路径)。 */
|
|
3877
|
+
const moveTop = (key, direction) => {
|
|
3878
|
+
const from = topOrderedKeys.indexOf(key);
|
|
3879
|
+
const to = from + direction;
|
|
3880
|
+
if (from === -1 || to < 0 || to >= topOrderedKeys.length) return;
|
|
3881
|
+
const next = [...topOrderedKeys];
|
|
3882
|
+
const [moved] = next.splice(from, 1);
|
|
3883
|
+
next.splice(to, 0, moved);
|
|
3884
|
+
hub.reorderSourceGroups(next);
|
|
3885
|
+
};
|
|
3886
|
+
/** SkillRow 收窄后的 props:父组件统一传入它实际消费的字段。 */
|
|
3887
|
+
const rowProps = {
|
|
3888
|
+
uses: hub.uses,
|
|
3889
|
+
hubConfig: hub.hubConfig,
|
|
3890
|
+
busyNames,
|
|
3891
|
+
editMode: hub.editMode,
|
|
3892
|
+
tagBusy: hub.tagBusy,
|
|
3893
|
+
duplicateNames,
|
|
3894
|
+
toggle: hub.toggle,
|
|
3895
|
+
openDetail: hub.openDetail,
|
|
3896
|
+
requestDeleteSkill: hub.requestDeleteSkill
|
|
3897
|
+
};
|
|
3898
|
+
if (skillView === "flat") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: filterBySource(sorted, sourceFilter, origins).map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillRow, {
|
|
3899
|
+
skill,
|
|
3900
|
+
...rowProps
|
|
3901
|
+
}, skill.name)) });
|
|
3902
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3903
|
+
!hasProject && collections.length === 0 && !hasPersonal ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3904
|
+
className: panel_module_css_default.empty,
|
|
3905
|
+
children: tt("groups.noCollections")
|
|
3906
|
+
}) : null,
|
|
3907
|
+
topOrderedKeys.length > 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3908
|
+
className: panel_module_css_default.listTools,
|
|
3909
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3910
|
+
type: "button",
|
|
3911
|
+
className: panel_module_css_default.opBtn,
|
|
3912
|
+
onClick: () => {
|
|
3913
|
+
setAllGroupsCollapsed(allTopCollapsed ? null : topOrderedKeys);
|
|
3914
|
+
},
|
|
3915
|
+
children: allTopCollapsed ? tt("groups.expandAll") : tt("groups.collapseAll")
|
|
3916
|
+
})
|
|
3917
|
+
}) : null,
|
|
3918
|
+
topOrderedKeys.map((topKey) => {
|
|
3919
|
+
if (topKey === "project" && hasProject) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProjectTree, {
|
|
3920
|
+
editMode: hub.editMode,
|
|
3921
|
+
canMoveUp: topOrderedKeys.indexOf(topKey) > 0,
|
|
3922
|
+
canMoveDown: topOrderedKeys.indexOf(topKey) < topOrderedKeys.length - 1,
|
|
3923
|
+
onMove: (direction) => {
|
|
3924
|
+
moveTop(topKey, direction);
|
|
3925
|
+
},
|
|
3926
|
+
skills: projectSkillsAll,
|
|
3927
|
+
collapsedGroups,
|
|
3928
|
+
toggleGroupCollapse,
|
|
3929
|
+
subdividedProjects: hub.subdividedProjects,
|
|
3930
|
+
toggleSubdivide: hub.toggleSubdivide,
|
|
3931
|
+
rowProps,
|
|
3932
|
+
dragProps: drag("project")
|
|
3933
|
+
}, "project");
|
|
3934
|
+
if (topKey.startsWith("col:")) {
|
|
3935
|
+
const colName = topKey.slice(4);
|
|
3936
|
+
const collection = collections.find((c) => c.name === colName);
|
|
3937
|
+
if (collection === void 0) return null;
|
|
3938
|
+
const skills = filterBySource(sorted, sourceFilter, origins).filter((skill) => collection.skillNames.includes(skill.name));
|
|
3939
|
+
const disabledMembers = (catalog?.disabled ?? []).filter((record) => collection.skillNames.includes(record.name) && (normalized.length === 0 || record.name.toLocaleLowerCase().includes(normalized) || record.description.toLocaleLowerCase().includes(normalized)) && (sourceFilter === "all" || (origins[record.name] ?? "private") === sourceFilter));
|
|
3940
|
+
const collapsed = collapsedGroups.has("col:" + collection.name);
|
|
3941
|
+
const view = groupSwitchView(collection.skillNames, viewNames);
|
|
3942
|
+
const check = sourceCheck[collection.name];
|
|
3943
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionCard, {
|
|
3944
|
+
collection,
|
|
3945
|
+
skills,
|
|
3946
|
+
disabledMembers,
|
|
3947
|
+
collapsed,
|
|
3948
|
+
view,
|
|
3949
|
+
check,
|
|
3950
|
+
hasWritable: collection.skillNames.some((name) => actionNames.has(name)),
|
|
3951
|
+
editMode: hub.editMode,
|
|
3952
|
+
canMoveUp: topOrderedKeys.indexOf(topKey) > 0,
|
|
3953
|
+
canMoveDown: topOrderedKeys.indexOf(topKey) < topOrderedKeys.length - 1,
|
|
3954
|
+
onMove: (direction) => {
|
|
3955
|
+
moveTop(topKey, direction);
|
|
3956
|
+
},
|
|
3957
|
+
checkingSource,
|
|
3958
|
+
syncingSource,
|
|
3959
|
+
batchBusy,
|
|
3960
|
+
rowProps,
|
|
3961
|
+
dragProps: drag(topKey),
|
|
3962
|
+
toggleGroupCollapse,
|
|
3963
|
+
checkSources,
|
|
3964
|
+
requestSync,
|
|
3965
|
+
requestDelete,
|
|
3966
|
+
toggleGroup,
|
|
3967
|
+
requestDeleteGroup,
|
|
3968
|
+
enableDisabled,
|
|
3969
|
+
openDetail: hub.openDetail
|
|
3970
|
+
}, "col:" + collection.name);
|
|
3971
|
+
}
|
|
3972
|
+
if (topKey === "uncategorized-source" && hasPersonal) {
|
|
3973
|
+
if (allPersonalNames.length === 0) return null;
|
|
3974
|
+
const collapsed = collapsedGroups.has("uncategorized-source");
|
|
3975
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3976
|
+
...drag("uncategorized-source"),
|
|
3977
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3978
|
+
className: panel_module_css_default.groupHead,
|
|
3979
|
+
children: [
|
|
3980
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3981
|
+
className: panel_module_css_default.dragHandle,
|
|
3982
|
+
"aria-hidden": true,
|
|
3983
|
+
title: tt("drag.reorder"),
|
|
3984
|
+
children: "⋮⋮"
|
|
3985
|
+
}),
|
|
3986
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3692
3987
|
type: "button",
|
|
3693
3988
|
className: panel_module_css_default.disclosure,
|
|
3694
|
-
"aria-expanded": !
|
|
3989
|
+
"aria-expanded": !collapsed,
|
|
3695
3990
|
onClick: () => {
|
|
3696
|
-
toggleGroupCollapse(
|
|
3991
|
+
toggleGroupCollapse("uncategorized-source");
|
|
3697
3992
|
},
|
|
3698
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.chevron + (
|
|
3993
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.chevron + (collapsed ? " " + panel_module_css_default.chevronCollapsed : "") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3699
3994
|
className: panel_module_css_default.groupTitle,
|
|
3700
3995
|
children: [
|
|
3701
|
-
|
|
3996
|
+
tt("groups.personal"),
|
|
3702
3997
|
" · ",
|
|
3703
|
-
|
|
3998
|
+
allPersonalNames.length,
|
|
3704
3999
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupSummary, {
|
|
3705
|
-
members:
|
|
3706
|
-
hub
|
|
4000
|
+
members: allPersonalNames,
|
|
4001
|
+
uses: hub.uses,
|
|
4002
|
+
hubConfig: hub.hubConfig
|
|
3707
4003
|
})
|
|
3708
4004
|
]
|
|
3709
4005
|
})]
|
|
3710
|
-
}),
|
|
4006
|
+
}),
|
|
4007
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3711
4008
|
className: panel_module_css_default.groupOps,
|
|
3712
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
hub.toggleSubdivide(key);
|
|
3718
|
-
},
|
|
3719
|
-
children: subdivided ? tt("groups.merge") : tt("groups.subdivide")
|
|
3720
|
-
})
|
|
3721
|
-
})]
|
|
3722
|
-
}), !projCollapsed ? subdivided ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3723
|
-
className: panel_module_css_default.projectNest,
|
|
3724
|
-
children: ["project-dsh", "project-agents"].map((source) => {
|
|
3725
|
-
const list = proj.skills.filter((skill) => skill.source === source);
|
|
3726
|
-
if (list.length === 0) return null;
|
|
3727
|
-
const srcKey = projKey + ":" + source;
|
|
3728
|
-
const srcCollapsed = collapsedGroups.has(srcKey);
|
|
3729
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3730
|
-
className: panel_module_css_default.projectNest,
|
|
3731
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3732
|
-
className: panel_module_css_default.groupHead,
|
|
3733
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3734
|
-
type: "button",
|
|
3735
|
-
className: panel_module_css_default.disclosure,
|
|
3736
|
-
"aria-expanded": !srcCollapsed,
|
|
3737
|
-
onClick: () => {
|
|
3738
|
-
toggleGroupCollapse(srcKey);
|
|
3739
|
-
},
|
|
3740
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.chevron + (srcCollapsed ? " " + panel_module_css_default.chevronCollapsed : "") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3741
|
-
className: panel_module_css_default.groupTitle,
|
|
3742
|
-
children: [
|
|
3743
|
-
tt("badge.source." + source),
|
|
3744
|
-
" · ",
|
|
3745
|
-
list.length
|
|
3746
|
-
]
|
|
3747
|
-
})]
|
|
3748
|
-
})
|
|
3749
|
-
}), !srcCollapsed ? list.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillRow, {
|
|
3750
|
-
skill,
|
|
3751
|
-
hub
|
|
3752
|
-
}, skill.name)) : null]
|
|
3753
|
-
}, srcKey);
|
|
3754
|
-
})
|
|
3755
|
-
}) : proj.skills.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillRow, {
|
|
3756
|
-
skill,
|
|
3757
|
-
hub
|
|
3758
|
-
}, skill.name)) : null]
|
|
3759
|
-
}, projKey);
|
|
3760
|
-
}) : null]
|
|
3761
|
-
}, "project");
|
|
3762
|
-
}
|
|
3763
|
-
if (topKey.startsWith("col:")) {
|
|
3764
|
-
const colName = topKey.slice(4);
|
|
3765
|
-
const collection = collections.find((c) => c.name === colName);
|
|
3766
|
-
if (collection === void 0) return null;
|
|
3767
|
-
const skills = filterBySource(sorted, sourceFilter, origins).filter((skill) => collection.skillNames.includes(skill.name));
|
|
3768
|
-
const disabledMembers = (catalog?.disabled ?? []).filter((record) => collection.skillNames.includes(record.name) && (normalized.length === 0 || record.name.toLocaleLowerCase().includes(normalized) || record.description.toLocaleLowerCase().includes(normalized)) && (sourceFilter === "all" || (origins[record.name] ?? "private") === sourceFilter));
|
|
3769
|
-
const collapsed = collapsedGroups.has("col:" + collection.name);
|
|
3770
|
-
const view = groupSwitchView(collection.skillNames, viewNames);
|
|
3771
|
-
const check = sourceCheck[collection.name];
|
|
3772
|
-
const hasWritable = collection.skillNames.some((name) => actionNames.has(name));
|
|
3773
|
-
const isDragging = topDragKey === topKey;
|
|
3774
|
-
const isOver = topOverKey === topKey && topDragKey !== topKey;
|
|
3775
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3776
|
-
className: panel_module_css_default.section + (isDragging ? " " + panel_module_css_default.dragging : "") + (isOver ? " " + panel_module_css_default.dragOver : ""),
|
|
3777
|
-
draggable: true,
|
|
3778
|
-
onDragStart: (e) => {
|
|
3779
|
-
setTopDragKey(topKey);
|
|
3780
|
-
e.dataTransfer.effectAllowed = "move";
|
|
3781
|
-
e.dataTransfer.setData("text/plain", topKey);
|
|
3782
|
-
},
|
|
3783
|
-
onDragOver: (e) => {
|
|
3784
|
-
e.preventDefault();
|
|
3785
|
-
if (topOverKey !== topKey) setTopOverKey(topKey);
|
|
3786
|
-
},
|
|
3787
|
-
onDragLeave: () => {
|
|
3788
|
-
if (topOverKey === topKey) setTopOverKey(null);
|
|
3789
|
-
},
|
|
3790
|
-
onDrop: (e) => {
|
|
3791
|
-
e.preventDefault();
|
|
3792
|
-
handleTopDrop(topKey);
|
|
3793
|
-
setTopOverKey(null);
|
|
3794
|
-
},
|
|
3795
|
-
onDragEnd: () => {
|
|
3796
|
-
setTopDragKey(null);
|
|
3797
|
-
setTopOverKey(null);
|
|
3798
|
-
},
|
|
3799
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3800
|
-
className: panel_module_css_default.groupHead,
|
|
3801
|
-
children: [
|
|
3802
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3803
|
-
className: panel_module_css_default.dragHandle,
|
|
3804
|
-
"aria-hidden": true,
|
|
3805
|
-
title: "拖拽调整顺序",
|
|
3806
|
-
children: "⋮⋮"
|
|
3807
|
-
}),
|
|
3808
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3809
|
-
type: "button",
|
|
3810
|
-
className: panel_module_css_default.disclosure,
|
|
3811
|
-
"aria-expanded": !collapsed,
|
|
3812
|
-
onClick: () => {
|
|
3813
|
-
toggleGroupCollapse("col:" + collection.name);
|
|
3814
|
-
},
|
|
3815
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.chevron + (collapsed ? " " + panel_module_css_default.chevronCollapsed : "") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3816
|
-
className: panel_module_css_default.groupTitle,
|
|
3817
|
-
children: [
|
|
3818
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3819
|
-
className: panel_module_css_default.sourceLink,
|
|
3820
|
-
href: "https://github.com/" + collection.name,
|
|
3821
|
-
target: "_blank",
|
|
3822
|
-
rel: "noreferrer",
|
|
3823
|
-
onClick: (event) => {
|
|
3824
|
-
event.stopPropagation();
|
|
3825
|
-
},
|
|
3826
|
-
children: collection.name
|
|
3827
|
-
}),
|
|
3828
|
-
" · " + collection.skillNames.length,
|
|
3829
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupSummary, {
|
|
3830
|
-
members: collection.skillNames,
|
|
3831
|
-
hub
|
|
3832
|
-
})
|
|
3833
|
-
]
|
|
3834
|
-
})]
|
|
3835
|
-
}),
|
|
3836
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3837
|
-
className: panel_module_css_default.groupOps,
|
|
3838
|
-
children: [
|
|
3839
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SourceStatusBadge, {
|
|
3840
|
-
check,
|
|
3841
|
-
checking: checkingSource === collection.name,
|
|
3842
|
-
onCheck: () => {
|
|
3843
|
-
checkSources(collection.name);
|
|
4009
|
+
children: hub.editMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReorderButtons, {
|
|
4010
|
+
canMoveUp: topOrderedKeys.indexOf(topKey) > 0,
|
|
4011
|
+
canMoveDown: topOrderedKeys.indexOf(topKey) < topOrderedKeys.length - 1,
|
|
4012
|
+
onMove: (direction) => {
|
|
4013
|
+
moveTop(topKey, direction);
|
|
3844
4014
|
}
|
|
3845
|
-
}),
|
|
3846
|
-
check !== void 0 && check.changed && check.updated.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3847
|
-
type: "button",
|
|
3848
|
-
className: panel_module_css_default.opBtn,
|
|
3849
|
-
disabled: syncingSource !== null,
|
|
3850
|
-
onClick: (event) => {
|
|
3851
|
-
event.stopPropagation();
|
|
3852
|
-
requestSync(collection.name, check.updated);
|
|
3853
|
-
},
|
|
3854
|
-
children: syncingSource === collection.name ? tt("source.syncing") : tt("source.sync")
|
|
3855
|
-
}) : null,
|
|
3856
|
-
check !== void 0 && check.deleted.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3857
|
-
type: "button",
|
|
3858
|
-
className: panel_module_css_default.opBtn + " " + panel_module_css_default.opDanger,
|
|
3859
|
-
onClick: (event) => {
|
|
3860
|
-
event.stopPropagation();
|
|
3861
|
-
requestDelete(collection.name, check.deleted);
|
|
3862
|
-
},
|
|
3863
|
-
children: tt("source.followDelete")
|
|
3864
|
-
}) : null,
|
|
3865
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3866
|
-
type: "button",
|
|
3867
|
-
role: "switch",
|
|
3868
|
-
"aria-checked": view.state !== "off",
|
|
3869
|
-
"aria-label": collection.name,
|
|
3870
|
-
className: panel_module_css_default.switch + (view.state === "on" ? " " + panel_module_css_default.switchOn : view.state === "mixed" ? " " + panel_module_css_default.switchMixed : ""),
|
|
3871
|
-
disabled: batchBusy || collection.skillNames.length === 0 || view.state !== "off" && !hasWritable,
|
|
3872
|
-
title: view.state !== "off" && !hasWritable ? tt("groups.noWritable") : void 0,
|
|
3873
|
-
onClick: (event) => {
|
|
3874
|
-
event.stopPropagation();
|
|
3875
|
-
toggleGroup("col:" + collection.name, collection.name, view.state);
|
|
3876
|
-
},
|
|
3877
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.switchThumb })
|
|
3878
|
-
}),
|
|
3879
|
-
hub.editMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4015
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3880
4016
|
type: "button",
|
|
3881
4017
|
className: panel_module_css_default.opBtn + " " + panel_module_css_default.opDanger,
|
|
3882
|
-
title: tt("source.deleteGroupHint", { count:
|
|
4018
|
+
title: tt("source.deleteGroupHint", { count: allPersonalNames.length }),
|
|
3883
4019
|
onClick: (event) => {
|
|
3884
4020
|
event.stopPropagation();
|
|
3885
|
-
requestDeleteGroup(
|
|
4021
|
+
requestDeleteGroup(tt("groups.personal"), allPersonalNames);
|
|
3886
4022
|
},
|
|
3887
4023
|
children: tt("source.deleteGroup")
|
|
3888
|
-
}) : null
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
}
|
|
3905
|
-
},
|
|
3906
|
-
}
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
const personalDisabled = (catalog?.disabled ?? []).filter((record) => origins[record.name] === void 0).filter((record) => normalized.length === 0 || record.name.toLocaleLowerCase().includes(normalized) || record.description.toLocaleLowerCase().includes(normalized)).filter((record) => sourceFilter === "all" || sourceFilter === "private");
|
|
3911
|
-
const allPersonalNames = [...uncategorized.map((s) => s.name), ...personalDisabled.map((r) => r.name)];
|
|
3912
|
-
if (allPersonalNames.length === 0) return null;
|
|
3913
|
-
const collapsed = collapsedGroups.has("uncategorized-source");
|
|
3914
|
-
const isDragging = topDragKey === "uncategorized-source";
|
|
3915
|
-
const isOver = topOverKey === "uncategorized-source" && topDragKey !== "uncategorized-source";
|
|
3916
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3917
|
-
className: panel_module_css_default.section + (isDragging ? " " + panel_module_css_default.dragging : "") + (isOver ? " " + panel_module_css_default.dragOver : ""),
|
|
3918
|
-
draggable: true,
|
|
3919
|
-
onDragStart: (e) => {
|
|
3920
|
-
setTopDragKey("uncategorized-source");
|
|
3921
|
-
e.dataTransfer.effectAllowed = "move";
|
|
3922
|
-
e.dataTransfer.setData("text/plain", "uncategorized-source");
|
|
3923
|
-
},
|
|
3924
|
-
onDragOver: (e) => {
|
|
3925
|
-
e.preventDefault();
|
|
3926
|
-
if (topOverKey !== "uncategorized-source") setTopOverKey("uncategorized-source");
|
|
3927
|
-
},
|
|
3928
|
-
onDragLeave: () => {
|
|
3929
|
-
if (topOverKey === "uncategorized-source") setTopOverKey(null);
|
|
3930
|
-
},
|
|
3931
|
-
onDrop: (e) => {
|
|
3932
|
-
e.preventDefault();
|
|
3933
|
-
handleTopDrop("uncategorized-source");
|
|
3934
|
-
setTopOverKey(null);
|
|
3935
|
-
},
|
|
3936
|
-
onDragEnd: () => {
|
|
3937
|
-
setTopDragKey(null);
|
|
3938
|
-
setTopOverKey(null);
|
|
3939
|
-
},
|
|
3940
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3941
|
-
className: panel_module_css_default.groupHead,
|
|
3942
|
-
children: [
|
|
3943
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3944
|
-
className: panel_module_css_default.dragHandle,
|
|
3945
|
-
"aria-hidden": true,
|
|
3946
|
-
title: "拖拽调整顺序",
|
|
3947
|
-
children: "⋮⋮"
|
|
3948
|
-
}),
|
|
3949
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3950
|
-
type: "button",
|
|
3951
|
-
className: panel_module_css_default.disclosure,
|
|
3952
|
-
"aria-expanded": !collapsed,
|
|
3953
|
-
onClick: () => {
|
|
3954
|
-
toggleGroupCollapse("uncategorized-source");
|
|
3955
|
-
},
|
|
3956
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.chevron + (collapsed ? " " + panel_module_css_default.chevronCollapsed : "") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3957
|
-
className: panel_module_css_default.groupTitle,
|
|
3958
|
-
children: [
|
|
3959
|
-
tt("groups.personal"),
|
|
3960
|
-
" · ",
|
|
3961
|
-
allPersonalNames.length,
|
|
3962
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupSummary, {
|
|
3963
|
-
members: allPersonalNames,
|
|
3964
|
-
hub
|
|
3965
|
-
})
|
|
3966
|
-
]
|
|
3967
|
-
})]
|
|
3968
|
-
}),
|
|
3969
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3970
|
-
className: panel_module_css_default.groupOps,
|
|
3971
|
-
children: hub.editMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3972
|
-
type: "button",
|
|
3973
|
-
className: panel_module_css_default.opBtn + " " + panel_module_css_default.opDanger,
|
|
3974
|
-
title: tt("source.deleteGroupHint", { count: allPersonalNames.length }),
|
|
3975
|
-
onClick: (event) => {
|
|
3976
|
-
event.stopPropagation();
|
|
3977
|
-
requestDeleteGroup(tt("groups.personal"), allPersonalNames);
|
|
3978
|
-
},
|
|
3979
|
-
children: tt("source.deleteGroup")
|
|
3980
|
-
}) : null
|
|
3981
|
-
})
|
|
3982
|
-
]
|
|
3983
|
-
}), !collapsed ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [uncategorized.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillRow, {
|
|
3984
|
-
skill,
|
|
3985
|
-
hub
|
|
3986
|
-
}, skill.name)), personalDisabled.map((record) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DisabledRow, {
|
|
3987
|
-
record,
|
|
3988
|
-
busy: busyNames.has(record.name),
|
|
3989
|
-
duplicate: catalog?.duplicateNames?.includes(record.name) === true,
|
|
3990
|
-
onEnable: () => {
|
|
3991
|
-
enableDisabled(record);
|
|
3992
|
-
},
|
|
3993
|
-
onOpen: () => {
|
|
3994
|
-
hub.openDetail(record.name);
|
|
3995
|
-
}
|
|
3996
|
-
}, record.name))] }) : null]
|
|
3997
|
-
}, "uncategorized-source");
|
|
3998
|
-
}
|
|
3999
|
-
return null;
|
|
4000
|
-
})] });
|
|
4024
|
+
})] }) : null
|
|
4025
|
+
})
|
|
4026
|
+
]
|
|
4027
|
+
}), !collapsed ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [uncategorized.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillRow, {
|
|
4028
|
+
skill,
|
|
4029
|
+
...rowProps
|
|
4030
|
+
}, skill.name)), personalDisabled.map((record) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DisabledRow, {
|
|
4031
|
+
record,
|
|
4032
|
+
busy: busyNames.has(record.name),
|
|
4033
|
+
duplicate: duplicateNames.has(record.name),
|
|
4034
|
+
onEnable: () => {
|
|
4035
|
+
enableDisabled(record);
|
|
4036
|
+
},
|
|
4037
|
+
onOpen: () => {
|
|
4038
|
+
hub.openDetail(record.name);
|
|
4039
|
+
}
|
|
4040
|
+
}, record.name))] }) : null]
|
|
4041
|
+
}, "uncategorized-source");
|
|
4042
|
+
}
|
|
4043
|
+
return null;
|
|
4044
|
+
})
|
|
4045
|
+
] });
|
|
4001
4046
|
}
|
|
4002
4047
|
//#endregion
|
|
4003
4048
|
//#region src/client/panel/ScenesView.tsx
|
|
@@ -4009,9 +4054,11 @@ window.__ModuleLoader__.load({
|
|
|
4009
4054
|
*/
|
|
4010
4055
|
function ScenesView(props) {
|
|
4011
4056
|
const { hub } = props;
|
|
4012
|
-
const { catalog, groupsState, sorted, normalized, collapsedGroups, viewNames, actionNames, batchBusy, busyNames, newTagName, setNewTagName, tagBusy, createTag, toggleGroupCollapse, toggleGroup, setEditingTag, setEditName, setMembersDraft, setEditSearch, enableDisabled } = hub;
|
|
4057
|
+
const { catalog, groupsState, sorted, normalized, collapsedGroups, viewNames, actionNames, batchBusy, busyNames, newTagName, setNewTagName, tagBusy, createTag, toggleGroupCollapse, setAllGroupsCollapsed, toggleGroup, setEditingTag, setEditName, setMembersDraft, setEditSearch, enableDisabled } = hub;
|
|
4013
4058
|
const [dragId, setDragId] = (0, react.useState)(null);
|
|
4014
4059
|
const [overId, setOverId] = (0, react.useState)(null);
|
|
4060
|
+
/** 重复技能名集合:整表只建一次,行内用 has 取代逐行线性 includes。 */
|
|
4061
|
+
const duplicateNames = (0, react.useMemo)(() => new Set(catalog?.duplicateNames ?? []), [catalog]);
|
|
4015
4062
|
const handleDrop = (targetId) => {
|
|
4016
4063
|
if (dragId === null || dragId === targetId || groupsState === null) return;
|
|
4017
4064
|
const ids = groupsState.tags.map((t) => t.id);
|
|
@@ -4023,6 +4070,38 @@ window.__ModuleLoader__.load({
|
|
|
4023
4070
|
next.splice(to, 0, moved);
|
|
4024
4071
|
hub.reorderTags(next);
|
|
4025
4072
|
};
|
|
4073
|
+
const drag = useDragReorder({
|
|
4074
|
+
dragKey: dragId,
|
|
4075
|
+
overKey: overId,
|
|
4076
|
+
setDragKey: setDragId,
|
|
4077
|
+
setOverKey: setOverId,
|
|
4078
|
+
onDrop: handleDrop
|
|
4079
|
+
});
|
|
4080
|
+
const tagKeys = (groupsState?.tags ?? []).map((tag) => "tag:" + tag.id);
|
|
4081
|
+
/** 所有场景是否已折叠(决定「全部折叠/展开」按钮的文案)。 */
|
|
4082
|
+
const allTagsCollapsed = tagKeys.length > 0 && tagKeys.every((key) => collapsedGroups.has(key));
|
|
4083
|
+
/** 键盘可用的排序:与拖拽同一条 store 路径。 */
|
|
4084
|
+
const moveTag = (index, direction) => {
|
|
4085
|
+
const ids = (groupsState?.tags ?? []).map((tag) => tag.id);
|
|
4086
|
+
const to = index + direction;
|
|
4087
|
+
if (to < 0 || to >= ids.length) return;
|
|
4088
|
+
const next = [...ids];
|
|
4089
|
+
const [moved] = next.splice(index, 1);
|
|
4090
|
+
next.splice(to, 0, moved);
|
|
4091
|
+
hub.reorderTags(next);
|
|
4092
|
+
};
|
|
4093
|
+
/** SkillRow 收窄后的 props:父组件统一传入它实际消费的字段。 */
|
|
4094
|
+
const rowProps = {
|
|
4095
|
+
uses: hub.uses,
|
|
4096
|
+
hubConfig: hub.hubConfig,
|
|
4097
|
+
busyNames,
|
|
4098
|
+
editMode: hub.editMode,
|
|
4099
|
+
tagBusy,
|
|
4100
|
+
duplicateNames,
|
|
4101
|
+
toggle: hub.toggle,
|
|
4102
|
+
openDetail: hub.openDetail,
|
|
4103
|
+
requestDeleteSkill: hub.requestDeleteSkill
|
|
4104
|
+
};
|
|
4026
4105
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4027
4106
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("form", {
|
|
4028
4107
|
className: panel_module_css_default.form,
|
|
@@ -4050,45 +4129,32 @@ window.__ModuleLoader__.load({
|
|
|
4050
4129
|
className: panel_module_css_default.empty,
|
|
4051
4130
|
children: tt("groups.empty")
|
|
4052
4131
|
}) : null,
|
|
4053
|
-
|
|
4132
|
+
tagKeys.length > 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4133
|
+
className: panel_module_css_default.listTools,
|
|
4134
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4135
|
+
type: "button",
|
|
4136
|
+
className: panel_module_css_default.opBtn,
|
|
4137
|
+
onClick: () => {
|
|
4138
|
+
setAllGroupsCollapsed(allTagsCollapsed ? null : tagKeys);
|
|
4139
|
+
},
|
|
4140
|
+
children: allTagsCollapsed ? tt("groups.expandAll") : tt("groups.collapseAll")
|
|
4141
|
+
})
|
|
4142
|
+
}) : null,
|
|
4143
|
+
groupsState?.tags.map((tag, index) => {
|
|
4054
4144
|
const skills = sorted.filter((skill) => tag.skillNames.includes(skill.name));
|
|
4055
4145
|
const disabledMembers = (catalog?.disabled ?? []).filter((record) => tag.skillNames.includes(record.name) && (normalized.length === 0 || record.name.toLocaleLowerCase().includes(normalized) || record.description.toLocaleLowerCase().includes(normalized)));
|
|
4056
4146
|
const collapsed = collapsedGroups.has("tag:" + tag.id);
|
|
4057
4147
|
const view = groupSwitchView(tag.skillNames, viewNames);
|
|
4058
4148
|
const hasWritable = tag.skillNames.some((name) => actionNames.has(name));
|
|
4059
|
-
const isDragging = dragId === tag.id;
|
|
4060
|
-
const isOver = overId === tag.id && dragId !== tag.id;
|
|
4061
4149
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4062
|
-
|
|
4063
|
-
draggable: true,
|
|
4064
|
-
onDragStart: (e) => {
|
|
4065
|
-
setDragId(tag.id);
|
|
4066
|
-
e.dataTransfer.effectAllowed = "move";
|
|
4067
|
-
e.dataTransfer.setData("text/plain", tag.id);
|
|
4068
|
-
},
|
|
4069
|
-
onDragOver: (e) => {
|
|
4070
|
-
e.preventDefault();
|
|
4071
|
-
if (overId !== tag.id) setOverId(tag.id);
|
|
4072
|
-
},
|
|
4073
|
-
onDragLeave: () => {
|
|
4074
|
-
if (overId === tag.id) setOverId(null);
|
|
4075
|
-
},
|
|
4076
|
-
onDrop: (e) => {
|
|
4077
|
-
e.preventDefault();
|
|
4078
|
-
handleDrop(tag.id);
|
|
4079
|
-
setOverId(null);
|
|
4080
|
-
},
|
|
4081
|
-
onDragEnd: () => {
|
|
4082
|
-
setDragId(null);
|
|
4083
|
-
setOverId(null);
|
|
4084
|
-
},
|
|
4150
|
+
...drag(tag.id),
|
|
4085
4151
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4086
4152
|
className: panel_module_css_default.groupHead,
|
|
4087
4153
|
children: [
|
|
4088
4154
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4089
4155
|
className: panel_module_css_default.dragHandle,
|
|
4090
4156
|
"aria-hidden": true,
|
|
4091
|
-
title: "
|
|
4157
|
+
title: tt("drag.reorder"),
|
|
4092
4158
|
children: "⋮⋮"
|
|
4093
4159
|
}),
|
|
4094
4160
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -4106,46 +4172,53 @@ window.__ModuleLoader__.load({
|
|
|
4106
4172
|
tag.skillNames.length,
|
|
4107
4173
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupSummary, {
|
|
4108
4174
|
members: tag.skillNames,
|
|
4109
|
-
hub
|
|
4175
|
+
uses: hub.uses,
|
|
4176
|
+
hubConfig: hub.hubConfig
|
|
4110
4177
|
})
|
|
4111
4178
|
]
|
|
4112
4179
|
})]
|
|
4113
4180
|
}),
|
|
4114
4181
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4115
4182
|
className: panel_module_css_default.groupOps,
|
|
4116
|
-
children: [
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4183
|
+
children: [
|
|
4184
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupSwitchButton, {
|
|
4185
|
+
state: view.state,
|
|
4186
|
+
label: tag.name,
|
|
4187
|
+
memberCount: tag.skillNames.length,
|
|
4188
|
+
batchBusy,
|
|
4189
|
+
hasWritable,
|
|
4190
|
+
onToggle: () => {
|
|
4191
|
+
toggleGroup("tag:" + tag.id, tag.name, view.state);
|
|
4192
|
+
}
|
|
4193
|
+
}),
|
|
4194
|
+
hub.editMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReorderButtons, {
|
|
4195
|
+
canMoveUp: index > 0,
|
|
4196
|
+
canMoveDown: index < (groupsState?.tags.length ?? 1) - 1,
|
|
4197
|
+
onMove: (direction) => {
|
|
4198
|
+
moveTag(index, direction);
|
|
4199
|
+
}
|
|
4200
|
+
}) : null,
|
|
4201
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4202
|
+
type: "button",
|
|
4203
|
+
className: panel_module_css_default.opBtn,
|
|
4204
|
+
onClick: () => {
|
|
4205
|
+
setEditingTag(tag);
|
|
4206
|
+
setEditName(tag.name);
|
|
4207
|
+
setMembersDraft(new Set(tag.skillNames));
|
|
4208
|
+
setEditSearch("");
|
|
4209
|
+
},
|
|
4210
|
+
children: tt("groups.edit")
|
|
4211
|
+
})
|
|
4212
|
+
]
|
|
4140
4213
|
})
|
|
4141
4214
|
]
|
|
4142
4215
|
}), !collapsed ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [skills.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillRow, {
|
|
4143
4216
|
skill,
|
|
4144
|
-
|
|
4217
|
+
...rowProps
|
|
4145
4218
|
}, skill.name)), disabledMembers.map((record) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DisabledRow, {
|
|
4146
4219
|
record,
|
|
4147
4220
|
busy: busyNames.has(record.name),
|
|
4148
|
-
duplicate:
|
|
4221
|
+
duplicate: duplicateNames.has(record.name),
|
|
4149
4222
|
onEnable: () => {
|
|
4150
4223
|
enableDisabled(record);
|
|
4151
4224
|
},
|
|
@@ -4613,7 +4686,7 @@ window.__ModuleLoader__.load({
|
|
|
4613
4686
|
type: "button",
|
|
4614
4687
|
className: panel_module_css_default.opBtn + (updateDanger ? " " + panel_module_css_default.opDanger : ""),
|
|
4615
4688
|
disabled: updateDisabled,
|
|
4616
|
-
title: hasUpdate ? "
|
|
4689
|
+
title: hasUpdate ? tt("market.syncHint") : void 0,
|
|
4617
4690
|
onClick: updateAction,
|
|
4618
4691
|
children: updateLabel
|
|
4619
4692
|
}),
|
|
@@ -4642,6 +4715,15 @@ window.__ModuleLoader__.load({
|
|
|
4642
4715
|
* 勾选导入+进度+结果)都包在这里。搜索/过滤/分页是卡片级本地状态,
|
|
4643
4716
|
* 随卡片挂载而生、关闭而灭。从 MarketView.tsx 原样搬出,渲染逻辑不变。
|
|
4644
4717
|
*/
|
|
4718
|
+
/**
|
|
4719
|
+
* 已知技能根的显示名键;未知根直接显示目录名。
|
|
4720
|
+
* zh 字典里这两项就是目录名本身(与接线前的硬编码文本一致)。
|
|
4721
|
+
*/
|
|
4722
|
+
function rootLabelKey(root) {
|
|
4723
|
+
if (root === "skills") return "repo.root.skills";
|
|
4724
|
+
if (root === "design-templates") return "repo.root.designTemplates";
|
|
4725
|
+
return "repo.root.generic";
|
|
4726
|
+
}
|
|
4645
4727
|
function RepoScanCard(props) {
|
|
4646
4728
|
const { hub } = props;
|
|
4647
4729
|
const { repoDiscoverState, scanningRepo, repoResult, repoSelected, setRepoSelected, repoImporting, toggleRepoSelected, importRepo, cancelImport } = hub;
|
|
@@ -4672,7 +4754,7 @@ window.__ModuleLoader__.load({
|
|
|
4672
4754
|
alignItems: "center",
|
|
4673
4755
|
gap: 6
|
|
4674
4756
|
},
|
|
4675
|
-
children: ["
|
|
4757
|
+
children: [tt("repo.scanTitle"), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4676
4758
|
style: {
|
|
4677
4759
|
fontWeight: 400,
|
|
4678
4760
|
opacity: .75
|
|
@@ -4695,7 +4777,7 @@ window.__ModuleLoader__.load({
|
|
|
4695
4777
|
onClick: () => {
|
|
4696
4778
|
hub.clearScan();
|
|
4697
4779
|
},
|
|
4698
|
-
children: "
|
|
4780
|
+
children: tt("repo.close")
|
|
4699
4781
|
})]
|
|
4700
4782
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4701
4783
|
style: { padding: "0 12px 12px" },
|
|
@@ -4773,9 +4855,9 @@ window.__ModuleLoader__.load({
|
|
|
4773
4855
|
},
|
|
4774
4856
|
value: repoSearch,
|
|
4775
4857
|
onChange: (e) => setRepoSearch(e.target.value),
|
|
4776
|
-
placeholder: "
|
|
4858
|
+
placeholder: tt("repo.searchPlaceholder")
|
|
4777
4859
|
}),
|
|
4778
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4860
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4779
4861
|
type: "button",
|
|
4780
4862
|
className: panel_module_css_default.button + (repoFilter === "all" ? " " + panel_module_css_default.primary : ""),
|
|
4781
4863
|
style: {
|
|
@@ -4783,7 +4865,7 @@ window.__ModuleLoader__.load({
|
|
|
4783
4865
|
fontSize: 12
|
|
4784
4866
|
},
|
|
4785
4867
|
onClick: () => setRepoFilter("all"),
|
|
4786
|
-
children:
|
|
4868
|
+
children: tt("repo.allRoots", { count: entries.length })
|
|
4787
4869
|
}),
|
|
4788
4870
|
roots.map((root) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4789
4871
|
type: "button",
|
|
@@ -4794,7 +4876,7 @@ window.__ModuleLoader__.load({
|
|
|
4794
4876
|
},
|
|
4795
4877
|
onClick: () => setRepoFilter(root),
|
|
4796
4878
|
children: [
|
|
4797
|
-
root,
|
|
4879
|
+
tt(rootLabelKey(root), { root }),
|
|
4798
4880
|
" ",
|
|
4799
4881
|
counts.get(root) ?? 0
|
|
4800
4882
|
]
|
|
@@ -4810,19 +4892,13 @@ window.__ModuleLoader__.load({
|
|
|
4810
4892
|
flexWrap: "wrap",
|
|
4811
4893
|
gap: 8
|
|
4812
4894
|
},
|
|
4813
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
" · 显示 ",
|
|
4821
|
-
paged.length,
|
|
4822
|
-
"/",
|
|
4823
|
-
filtered.length,
|
|
4824
|
-
"(过滤后)"
|
|
4825
|
-
] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4895
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("repo.selection", {
|
|
4896
|
+
selected: selected.length,
|
|
4897
|
+
total: entries.length,
|
|
4898
|
+
size: formatBytes(selectedBytes),
|
|
4899
|
+
shown: paged.length,
|
|
4900
|
+
filtered: filtered.length
|
|
4901
|
+
}) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4826
4902
|
style: {
|
|
4827
4903
|
display: "flex",
|
|
4828
4904
|
gap: 6
|
|
@@ -4838,9 +4914,9 @@ window.__ModuleLoader__.load({
|
|
|
4838
4914
|
onClick: () => {
|
|
4839
4915
|
setRepoSelected(new Set(filtered.filter((e) => !isExisting(e)).slice(0, visibleCount).map((e) => e.path)));
|
|
4840
4916
|
},
|
|
4841
|
-
children: "
|
|
4917
|
+
children: tt("repo.selectVisible")
|
|
4842
4918
|
}),
|
|
4843
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4919
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4844
4920
|
type: "button",
|
|
4845
4921
|
className: panel_module_css_default.button,
|
|
4846
4922
|
style: {
|
|
@@ -4850,7 +4926,7 @@ window.__ModuleLoader__.load({
|
|
|
4850
4926
|
onClick: () => {
|
|
4851
4927
|
setRepoSelected(new Set(entries.filter((e) => !isExisting(e)).map((e) => e.path)));
|
|
4852
4928
|
},
|
|
4853
|
-
children:
|
|
4929
|
+
children: tt("repo.selectAllN", { count: entries.filter((e) => !isExisting(e)).length })
|
|
4854
4930
|
}),
|
|
4855
4931
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4856
4932
|
type: "button",
|
|
@@ -4872,7 +4948,7 @@ window.__ModuleLoader__.load({
|
|
|
4872
4948
|
children: paged.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4873
4949
|
className: panel_module_css_default.empty,
|
|
4874
4950
|
style: { padding: 20 },
|
|
4875
|
-
children: "
|
|
4951
|
+
children: tt("repo.noMatch")
|
|
4876
4952
|
}) : paged.map((entry) => {
|
|
4877
4953
|
const existing = isExisting(entry);
|
|
4878
4954
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
@@ -4919,15 +4995,14 @@ window.__ModuleLoader__.load({
|
|
|
4919
4995
|
textAlign: "center",
|
|
4920
4996
|
marginTop: 8
|
|
4921
4997
|
},
|
|
4922
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
4998
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4923
4999
|
type: "button",
|
|
4924
5000
|
className: panel_module_css_default.button,
|
|
4925
5001
|
onClick: () => setVisibleCount((n) => n + 50),
|
|
4926
|
-
children:
|
|
4927
|
-
|
|
4928
|
-
filtered.length - visibleCount
|
|
4929
|
-
|
|
4930
|
-
]
|
|
5002
|
+
children: tt("repo.loadMore", {
|
|
5003
|
+
step: 50,
|
|
5004
|
+
remaining: filtered.length - visibleCount
|
|
5005
|
+
})
|
|
4931
5006
|
})
|
|
4932
5007
|
}) : null,
|
|
4933
5008
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -4986,10 +5061,10 @@ window.__ModuleLoader__.load({
|
|
|
4986
5061
|
formatBytes(repoResult.totalBytes),
|
|
4987
5062
|
speed !== "" ? ` · ${speed}` : "",
|
|
4988
5063
|
" · ",
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
5064
|
+
tt("repo.skillProgress", {
|
|
5065
|
+
done: repoResult.done,
|
|
5066
|
+
total: repoResult.total
|
|
5067
|
+
})
|
|
4993
5068
|
]
|
|
4994
5069
|
}),
|
|
4995
5070
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -5196,24 +5271,175 @@ window.__ModuleLoader__.load({
|
|
|
5196
5271
|
] });
|
|
5197
5272
|
}
|
|
5198
5273
|
//#endregion
|
|
5199
|
-
//#region src/client/panel/
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5274
|
+
//#region src/client/panel/PanelDialogs.tsx
|
|
5275
|
+
function PanelDialogs(props) {
|
|
5276
|
+
const { conflictDialog, tags, collections, setConflictDialog, resolveConflict, confirmDialog, setConfirmDialog, runConfirmed, branchChoice, branchBusy, setBranchChoice, confirmBranchChoice, versionDialog, versionBusy, setVersionDialog, confirmVersionDialog, marketSyncDialog, syncBusy, setMarketSyncDialog, confirmMarketSync, deleteSkillDialog, setDeleteSkillDialog, runDeleteSkill, deleteGroupDialog, setDeleteGroupDialog, runDeleteGroup, confirmClearTrash, setConfirmClearTrash, clearTrash } = props;
|
|
5277
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
5278
|
+
conflictDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConflictDialog, {
|
|
5279
|
+
dialog: conflictDialog,
|
|
5280
|
+
tags,
|
|
5281
|
+
collections,
|
|
5282
|
+
onClose: () => {
|
|
5283
|
+
setConflictDialog(null);
|
|
5284
|
+
},
|
|
5285
|
+
onKeepOn: () => {
|
|
5286
|
+
resolveConflict(false);
|
|
5287
|
+
},
|
|
5288
|
+
onCloseAll: () => {
|
|
5289
|
+
resolveConflict(true);
|
|
5290
|
+
}
|
|
5291
|
+
}) : null,
|
|
5292
|
+
confirmDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
|
|
5293
|
+
title: confirmDialog.kind === "sync" ? tt("source.syncConfirmTitle") : tt("source.deleteConfirmTitle"),
|
|
5294
|
+
text: confirmDialog.kind === "sync" ? tt("source.syncConfirmText") : tt("source.deleteConfirmText"),
|
|
5295
|
+
items: confirmDialog.skills,
|
|
5296
|
+
confirmLabel: confirmDialog.kind === "sync" ? tt("source.sync") : tt("source.followDelete"),
|
|
5297
|
+
danger: confirmDialog.kind === "delete",
|
|
5298
|
+
onCancel: () => {
|
|
5299
|
+
setConfirmDialog(null);
|
|
5300
|
+
},
|
|
5301
|
+
onConfirm: () => {
|
|
5302
|
+
runConfirmed();
|
|
5303
|
+
}
|
|
5304
|
+
}) : null,
|
|
5305
|
+
branchChoice !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BranchChoiceDialog, {
|
|
5306
|
+
choice: branchChoice,
|
|
5307
|
+
busy: branchBusy,
|
|
5308
|
+
onSelect: (selected) => {
|
|
5309
|
+
setBranchChoice({
|
|
5310
|
+
...branchChoice,
|
|
5311
|
+
selected
|
|
5312
|
+
});
|
|
5313
|
+
},
|
|
5314
|
+
onCancel: () => {
|
|
5315
|
+
setBranchChoice(null);
|
|
5316
|
+
},
|
|
5317
|
+
onConfirm: () => {
|
|
5318
|
+
confirmBranchChoice();
|
|
5319
|
+
}
|
|
5320
|
+
}) : null,
|
|
5321
|
+
versionDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionChoiceDialog, {
|
|
5322
|
+
choice: versionDialog,
|
|
5323
|
+
busy: versionBusy,
|
|
5324
|
+
onSelect: (selected) => {
|
|
5325
|
+
setVersionDialog({
|
|
5326
|
+
...versionDialog,
|
|
5327
|
+
selected
|
|
5328
|
+
});
|
|
5329
|
+
},
|
|
5330
|
+
onCustom: (custom) => {
|
|
5331
|
+
setVersionDialog({
|
|
5332
|
+
...versionDialog,
|
|
5333
|
+
custom
|
|
5334
|
+
});
|
|
5335
|
+
},
|
|
5336
|
+
onCancel: () => {
|
|
5337
|
+
setVersionDialog(null);
|
|
5338
|
+
},
|
|
5339
|
+
onConfirm: () => {
|
|
5340
|
+
confirmVersionDialog();
|
|
5341
|
+
}
|
|
5342
|
+
}) : null,
|
|
5343
|
+
marketSyncDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarketSyncDialog, {
|
|
5344
|
+
dialog: marketSyncDialog,
|
|
5345
|
+
busy: syncBusy,
|
|
5346
|
+
onToggle: (name, checked) => {
|
|
5347
|
+
const next = new Set(marketSyncDialog.selected);
|
|
5348
|
+
if (checked) next.add(name);
|
|
5349
|
+
else next.delete(name);
|
|
5350
|
+
setMarketSyncDialog({
|
|
5351
|
+
...marketSyncDialog,
|
|
5352
|
+
selected: next
|
|
5353
|
+
});
|
|
5354
|
+
},
|
|
5355
|
+
onCancel: () => {
|
|
5356
|
+
setMarketSyncDialog(null);
|
|
5357
|
+
},
|
|
5358
|
+
onConfirm: () => {
|
|
5359
|
+
confirmMarketSync();
|
|
5360
|
+
}
|
|
5361
|
+
}) : null,
|
|
5362
|
+
deleteSkillDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
|
|
5363
|
+
title: tt("delete.confirmTitle"),
|
|
5364
|
+
text: tt("delete.confirmText", { name: deleteSkillDialog }),
|
|
5365
|
+
confirmLabel: tt("delete.confirm"),
|
|
5366
|
+
danger: true,
|
|
5367
|
+
onCancel: () => {
|
|
5368
|
+
setDeleteSkillDialog(null);
|
|
5369
|
+
},
|
|
5370
|
+
onConfirm: () => {
|
|
5371
|
+
runDeleteSkill();
|
|
5372
|
+
}
|
|
5373
|
+
}) : null,
|
|
5374
|
+
deleteGroupDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
|
|
5375
|
+
title: tt("source.deleteGroupTitle"),
|
|
5376
|
+
text: tt("source.deleteGroupText", {
|
|
5377
|
+
name: deleteGroupDialog.name,
|
|
5378
|
+
count: deleteGroupDialog.skillNames.length
|
|
5379
|
+
}),
|
|
5380
|
+
items: deleteGroupDialog.skillNames,
|
|
5381
|
+
confirmLabel: tt("source.deleteGroup"),
|
|
5382
|
+
danger: true,
|
|
5383
|
+
onCancel: () => {
|
|
5384
|
+
setDeleteGroupDialog(null);
|
|
5385
|
+
},
|
|
5386
|
+
onConfirm: () => {
|
|
5387
|
+
runDeleteGroup();
|
|
5388
|
+
}
|
|
5389
|
+
}) : null,
|
|
5390
|
+
confirmClearTrash ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
|
|
5391
|
+
title: tt("source.clearTrashConfirmTitle"),
|
|
5392
|
+
text: tt("source.clearTrashConfirmText"),
|
|
5393
|
+
confirmLabel: tt("source.clearTrashConfirm"),
|
|
5394
|
+
danger: true,
|
|
5395
|
+
onCancel: () => {
|
|
5396
|
+
setConfirmClearTrash(false);
|
|
5397
|
+
},
|
|
5398
|
+
onConfirm: () => {
|
|
5399
|
+
clearTrash();
|
|
5400
|
+
}
|
|
5401
|
+
}) : null
|
|
5402
|
+
] });
|
|
5403
|
+
}
|
|
5404
|
+
//#endregion
|
|
5405
|
+
//#region src/client/panel/hooks/shared.ts
|
|
5406
|
+
/**
|
|
5407
|
+
* 统一异步动作外壳:清错 → 执行 → 异常转错误条幅 → 收尾(忙碌开关)。
|
|
5408
|
+
* 只用于同形的 clearFail/try/catch/finally 站点;成功后清错、自定义收尾、
|
|
5409
|
+
* 需要返回值的站点保持内联。
|
|
5410
|
+
*/
|
|
5411
|
+
async function runFlow(shared, body, settle = () => {}) {
|
|
5412
|
+
shared.clearFail();
|
|
5413
|
+
try {
|
|
5414
|
+
return await body();
|
|
5415
|
+
} catch (error) {
|
|
5416
|
+
shared.fail(errorMessage(error));
|
|
5417
|
+
return;
|
|
5418
|
+
} finally {
|
|
5419
|
+
settle();
|
|
5420
|
+
}
|
|
5421
|
+
}
|
|
5422
|
+
/** Catalog poll interval while the panel is mounted (the provider watcher feeds this). */
|
|
5423
|
+
const POLL_MS = 5e3;
|
|
5424
|
+
/** Relaxed poll for slower-changing data (stats, groups, sources, config). */
|
|
5425
|
+
const SLOW_POLL_MS = 6e4;
|
|
5426
|
+
/** localStorage key of the last daily auto-check timestamp (survives sessions). */
|
|
5427
|
+
const AUTO_CHECK_KEY = "skill-hub.last-auto-check";
|
|
5428
|
+
/** Daily auto-check interval: at most one network round per day. */
|
|
5429
|
+
const AUTO_CHECK_INTERVAL_MS = 1440 * 6e4;
|
|
5430
|
+
/** Whether the daily auto-check should run now (first visit or ≥24h since the last). */
|
|
5431
|
+
function shouldAutoCheck() {
|
|
5432
|
+
try {
|
|
5433
|
+
const raw = localStorage.getItem(AUTO_CHECK_KEY);
|
|
5434
|
+
const last = raw === null ? NaN : Number(raw);
|
|
5435
|
+
if (!Number.isFinite(last)) return true;
|
|
5436
|
+
return Date.now() - last >= AUTO_CHECK_INTERVAL_MS;
|
|
5437
|
+
} catch {
|
|
5438
|
+
return true;
|
|
5439
|
+
}
|
|
5440
|
+
}
|
|
5441
|
+
/** Record that the daily auto-check ran. */
|
|
5442
|
+
function markAutoChecked() {
|
|
5217
5443
|
try {
|
|
5218
5444
|
localStorage.setItem(AUTO_CHECK_KEY, String(Date.now()));
|
|
5219
5445
|
} catch {}
|
|
@@ -5263,7 +5489,7 @@ window.__ModuleLoader__.load({
|
|
|
5263
5489
|
usesCatchUp.current += 1;
|
|
5264
5490
|
loadUses();
|
|
5265
5491
|
if (usesCatchUp.current >= 72) window.clearInterval(timer);
|
|
5266
|
-
},
|
|
5492
|
+
}, POLL_MS);
|
|
5267
5493
|
return () => {
|
|
5268
5494
|
window.clearInterval(timer);
|
|
5269
5495
|
};
|
|
@@ -5325,14 +5551,9 @@ window.__ModuleLoader__.load({
|
|
|
5325
5551
|
]);
|
|
5326
5552
|
const openDetail = (0, react.useCallback)(async (name) => {
|
|
5327
5553
|
setDetailLoading(true);
|
|
5328
|
-
shared
|
|
5329
|
-
try {
|
|
5554
|
+
await runFlow(shared, async () => {
|
|
5330
5555
|
setDetail(await api.skill(name, workspace !== "" ? { cwd: workspace } : void 0));
|
|
5331
|
-
}
|
|
5332
|
-
shared.fail(errorMessage(error));
|
|
5333
|
-
} finally {
|
|
5334
|
-
setDetailLoading(false);
|
|
5335
|
-
}
|
|
5556
|
+
}, () => setDetailLoading(false));
|
|
5336
5557
|
}, [
|
|
5337
5558
|
api,
|
|
5338
5559
|
workspace,
|
|
@@ -5340,68 +5561,54 @@ window.__ModuleLoader__.load({
|
|
|
5340
5561
|
]);
|
|
5341
5562
|
const toggle = (0, react.useCallback)(async (skill, enabled) => {
|
|
5342
5563
|
setBusyNames((previous) => new Set(previous).add(skill.name));
|
|
5343
|
-
shared
|
|
5344
|
-
try {
|
|
5564
|
+
await runFlow(shared, async () => {
|
|
5345
5565
|
const next = await api.toggle(skill.name, enabled);
|
|
5346
5566
|
setCatalog(next);
|
|
5347
|
-
}
|
|
5348
|
-
shared.fail(errorMessage(error));
|
|
5349
|
-
} finally {
|
|
5567
|
+
}, () => {
|
|
5350
5568
|
setBusyNames((previous) => {
|
|
5351
5569
|
const next = new Set(previous);
|
|
5352
5570
|
next.delete(skill.name);
|
|
5353
5571
|
return next;
|
|
5354
5572
|
});
|
|
5355
|
-
}
|
|
5573
|
+
});
|
|
5356
5574
|
}, [api, shared]);
|
|
5357
5575
|
const enableDisabled = (0, react.useCallback)(async (record) => {
|
|
5358
5576
|
setBusyNames((previous) => new Set(previous).add(record.name));
|
|
5359
|
-
shared
|
|
5360
|
-
try {
|
|
5577
|
+
await runFlow(shared, async () => {
|
|
5361
5578
|
const next = await api.toggle(record.name, true);
|
|
5362
5579
|
setCatalog(next);
|
|
5363
|
-
}
|
|
5364
|
-
shared.fail(errorMessage(error));
|
|
5365
|
-
} finally {
|
|
5580
|
+
}, () => {
|
|
5366
5581
|
setBusyNames((previous) => {
|
|
5367
5582
|
const next = new Set(previous);
|
|
5368
5583
|
next.delete(record.name);
|
|
5369
5584
|
return next;
|
|
5370
5585
|
});
|
|
5371
|
-
}
|
|
5586
|
+
});
|
|
5372
5587
|
}, [api, shared]);
|
|
5373
5588
|
/** Toggle an explicit name set in one write (enables disabled members too). */
|
|
5374
5589
|
const batchToggleNames = (0, react.useCallback)(async (names, enabled) => {
|
|
5375
5590
|
if (names.length === 0) return;
|
|
5376
5591
|
shared.setBatchBusy(true);
|
|
5377
|
-
shared
|
|
5378
|
-
try {
|
|
5592
|
+
await runFlow(shared, async () => {
|
|
5379
5593
|
const next = await api.toggleBatch(names, enabled);
|
|
5380
5594
|
setCatalog(next.catalog);
|
|
5381
5595
|
if (next.failures.length > 0) shared.fail("toggle-batch: " + next.failures.map((failure) => failure.name + ": " + failure.error).join("; "));
|
|
5382
|
-
}
|
|
5383
|
-
shared.fail(errorMessage(error));
|
|
5384
|
-
} finally {
|
|
5385
|
-
shared.setBatchBusy(false);
|
|
5386
|
-
}
|
|
5596
|
+
}, () => shared.setBatchBusy(false));
|
|
5387
5597
|
}, [api, shared]);
|
|
5388
5598
|
const fixDiagnostic = (0, react.useCallback)(async (path) => {
|
|
5389
5599
|
setFixingPaths((previous) => new Set(previous).add(path));
|
|
5390
|
-
shared
|
|
5391
|
-
try {
|
|
5600
|
+
await runFlow(shared, async () => {
|
|
5392
5601
|
if (!window.confirm(tt("diag.fixConfirm", { path }))) return;
|
|
5393
5602
|
await api.fixDiagnostic(path);
|
|
5394
5603
|
await load();
|
|
5395
5604
|
shared.succeed(tt("diag.fixed"));
|
|
5396
|
-
}
|
|
5397
|
-
shared.fail(errorMessage(error));
|
|
5398
|
-
} finally {
|
|
5605
|
+
}, () => {
|
|
5399
5606
|
setFixingPaths((previous) => {
|
|
5400
5607
|
const next = new Set(previous);
|
|
5401
5608
|
next.delete(path);
|
|
5402
5609
|
return next;
|
|
5403
5610
|
});
|
|
5404
|
-
}
|
|
5611
|
+
});
|
|
5405
5612
|
}, [
|
|
5406
5613
|
api,
|
|
5407
5614
|
load,
|
|
@@ -5603,15 +5810,10 @@ window.__ModuleLoader__.load({
|
|
|
5603
5810
|
const name = newTagName.trim();
|
|
5604
5811
|
if (name === "") return;
|
|
5605
5812
|
shared.setTagBusy(true);
|
|
5606
|
-
shared
|
|
5607
|
-
try {
|
|
5813
|
+
await runFlow(shared, async () => {
|
|
5608
5814
|
applyTags(await api.saveTag({ name }));
|
|
5609
5815
|
setNewTagName("");
|
|
5610
|
-
}
|
|
5611
|
-
shared.fail(errorMessage(error));
|
|
5612
|
-
} finally {
|
|
5613
|
-
shared.setTagBusy(false);
|
|
5614
|
-
}
|
|
5816
|
+
}, () => shared.setTagBusy(false));
|
|
5615
5817
|
}, [
|
|
5616
5818
|
api,
|
|
5617
5819
|
applyTags,
|
|
@@ -5620,15 +5822,10 @@ window.__ModuleLoader__.load({
|
|
|
5620
5822
|
]),
|
|
5621
5823
|
deleteTag: (0, react.useCallback)(async (id) => {
|
|
5622
5824
|
shared.setTagBusy(true);
|
|
5623
|
-
shared
|
|
5624
|
-
try {
|
|
5825
|
+
await runFlow(shared, async () => {
|
|
5625
5826
|
applyTags(await api.deleteTag(id));
|
|
5626
5827
|
setEditingTag(null);
|
|
5627
|
-
}
|
|
5628
|
-
shared.fail(errorMessage(error));
|
|
5629
|
-
} finally {
|
|
5630
|
-
shared.setTagBusy(false);
|
|
5631
|
-
}
|
|
5828
|
+
}, () => shared.setTagBusy(false));
|
|
5632
5829
|
}, [
|
|
5633
5830
|
api,
|
|
5634
5831
|
applyTags,
|
|
@@ -5636,8 +5833,7 @@ window.__ModuleLoader__.load({
|
|
|
5636
5833
|
]),
|
|
5637
5834
|
saveTag: (0, react.useCallback)(async (id, name, memberNames) => {
|
|
5638
5835
|
shared.setTagBusy(true);
|
|
5639
|
-
shared
|
|
5640
|
-
try {
|
|
5836
|
+
await runFlow(shared, async () => {
|
|
5641
5837
|
const safeName = name.trim();
|
|
5642
5838
|
let tags = null;
|
|
5643
5839
|
if (safeName !== "") tags = await api.saveTag({
|
|
@@ -5648,11 +5844,7 @@ window.__ModuleLoader__.load({
|
|
|
5648
5844
|
if (tags === null) return;
|
|
5649
5845
|
applyTags(tags);
|
|
5650
5846
|
setEditingTag(null);
|
|
5651
|
-
}
|
|
5652
|
-
shared.fail(errorMessage(error));
|
|
5653
|
-
} finally {
|
|
5654
|
-
shared.setTagBusy(false);
|
|
5655
|
-
}
|
|
5847
|
+
}, () => shared.setTagBusy(false));
|
|
5656
5848
|
}, [
|
|
5657
5849
|
api,
|
|
5658
5850
|
applyTags,
|
|
@@ -5683,39 +5875,6 @@ window.__ModuleLoader__.load({
|
|
|
5683
5875
|
groupsState,
|
|
5684
5876
|
shared
|
|
5685
5877
|
]),
|
|
5686
|
-
reorderCollections: (0, react.useCallback)(async (orderedNames) => {
|
|
5687
|
-
shared.setTagBusy(true);
|
|
5688
|
-
shared.clearFail();
|
|
5689
|
-
try {
|
|
5690
|
-
const collections = await api.reorderCollections(orderedNames);
|
|
5691
|
-
setGroupsState((prev) => prev === null ? prev : {
|
|
5692
|
-
...prev,
|
|
5693
|
-
collections
|
|
5694
|
-
});
|
|
5695
|
-
loadGroups();
|
|
5696
|
-
} catch (error) {
|
|
5697
|
-
const msg = errorMessage(error);
|
|
5698
|
-
if (msg.includes("404") || msg.toLowerCase().includes("not found")) {
|
|
5699
|
-
setGroupsState((prev) => {
|
|
5700
|
-
if (prev === null) return prev;
|
|
5701
|
-
const map = new Map(prev.collections.map((c) => [c.name, c]));
|
|
5702
|
-
const reordered = orderedNames.map((n) => map.get(n)).filter((c) => c !== void 0);
|
|
5703
|
-
for (const c of prev.collections) if (!reordered.some((r) => r.name === c.name)) reordered.push(c);
|
|
5704
|
-
return {
|
|
5705
|
-
...prev,
|
|
5706
|
-
collections: reordered
|
|
5707
|
-
};
|
|
5708
|
-
});
|
|
5709
|
-
shared.succeed("已临时调整顺序(本地生效,重启宿主后持久化)");
|
|
5710
|
-
} else shared.fail(msg);
|
|
5711
|
-
} finally {
|
|
5712
|
-
shared.setTagBusy(false);
|
|
5713
|
-
}
|
|
5714
|
-
}, [
|
|
5715
|
-
api,
|
|
5716
|
-
loadGroups,
|
|
5717
|
-
shared
|
|
5718
|
-
]),
|
|
5719
5878
|
reorderSourceGroups: (0, react.useCallback)(async (orderedKeys) => {
|
|
5720
5879
|
shared.setTagBusy(true);
|
|
5721
5880
|
shared.clearFail();
|
|
@@ -5789,17 +5948,12 @@ window.__ModuleLoader__.load({
|
|
|
5789
5948
|
loadSources,
|
|
5790
5949
|
checkSources: (0, react.useCallback)(async (repo) => {
|
|
5791
5950
|
setCheckingSource(repo ?? "all");
|
|
5792
|
-
shared
|
|
5793
|
-
try {
|
|
5951
|
+
await runFlow(shared, async () => {
|
|
5794
5952
|
const result = await api.checkSources(repo);
|
|
5795
5953
|
const next = { ...sourceCheck };
|
|
5796
5954
|
for (const item of result.results) next[item.repo] = item;
|
|
5797
5955
|
setSourceCheck(next);
|
|
5798
|
-
}
|
|
5799
|
-
shared.fail(errorMessage(error));
|
|
5800
|
-
} finally {
|
|
5801
|
-
setCheckingSource(null);
|
|
5802
|
-
}
|
|
5956
|
+
}, () => setCheckingSource(null));
|
|
5803
5957
|
}, [
|
|
5804
5958
|
api,
|
|
5805
5959
|
sourceCheck,
|
|
@@ -5825,8 +5979,7 @@ window.__ModuleLoader__.load({
|
|
|
5825
5979
|
setConfirmDialog(null);
|
|
5826
5980
|
if (dialog.kind === "sync") {
|
|
5827
5981
|
setSyncingSource(dialog.repo);
|
|
5828
|
-
shared
|
|
5829
|
-
try {
|
|
5982
|
+
await runFlow(shared, async () => {
|
|
5830
5983
|
const result = await api.syncSource(dialog.repo, dialog.skills);
|
|
5831
5984
|
await Promise.all([
|
|
5832
5985
|
reloadCatalog(),
|
|
@@ -5834,11 +5987,7 @@ window.__ModuleLoader__.load({
|
|
|
5834
5987
|
loadSources()
|
|
5835
5988
|
]);
|
|
5836
5989
|
if (result.failed.length > 0) shared.fail("sync: " + result.failed.map((failure) => failure.name + ": " + failure.error).join("; "));
|
|
5837
|
-
}
|
|
5838
|
-
shared.fail(errorMessage(error));
|
|
5839
|
-
} finally {
|
|
5840
|
-
setSyncingSource(null);
|
|
5841
|
-
}
|
|
5990
|
+
}, () => setSyncingSource(null));
|
|
5842
5991
|
} else {
|
|
5843
5992
|
shared.clearFail();
|
|
5844
5993
|
try {
|
|
@@ -5862,19 +6011,14 @@ window.__ModuleLoader__.load({
|
|
|
5862
6011
|
]),
|
|
5863
6012
|
restoreTrash: (0, react.useCallback)(async (name) => {
|
|
5864
6013
|
shared.setTagBusy(true);
|
|
5865
|
-
shared
|
|
5866
|
-
try {
|
|
6014
|
+
await runFlow(shared, async () => {
|
|
5867
6015
|
await api.restoreSource(name);
|
|
5868
6016
|
await Promise.all([
|
|
5869
6017
|
reloadCatalog(),
|
|
5870
6018
|
reloadGroups(),
|
|
5871
6019
|
loadSources()
|
|
5872
6020
|
]);
|
|
5873
|
-
}
|
|
5874
|
-
shared.fail(errorMessage(error));
|
|
5875
|
-
} finally {
|
|
5876
|
-
shared.setTagBusy(false);
|
|
5877
|
-
}
|
|
6021
|
+
}, () => shared.setTagBusy(false));
|
|
5878
6022
|
}, [
|
|
5879
6023
|
api,
|
|
5880
6024
|
reloadCatalog,
|
|
@@ -5885,16 +6029,11 @@ window.__ModuleLoader__.load({
|
|
|
5885
6029
|
clearTrash: (0, react.useCallback)(async () => {
|
|
5886
6030
|
setConfirmClearTrash(false);
|
|
5887
6031
|
shared.setTagBusy(true);
|
|
5888
|
-
shared
|
|
5889
|
-
try {
|
|
6032
|
+
await runFlow(shared, async () => {
|
|
5890
6033
|
const result = await api.clearTrash();
|
|
5891
6034
|
if (result.failed.length > 0) shared.fail("clear trash: " + result.failed.map((failure) => failure.name + ": " + failure.error).join("; "));
|
|
5892
6035
|
await Promise.all([reloadCatalog(), loadSources()]);
|
|
5893
|
-
}
|
|
5894
|
-
shared.fail(errorMessage(error));
|
|
5895
|
-
} finally {
|
|
5896
|
-
shared.setTagBusy(false);
|
|
5897
|
-
}
|
|
6036
|
+
}, () => shared.setTagBusy(false));
|
|
5898
6037
|
}, [
|
|
5899
6038
|
api,
|
|
5900
6039
|
reloadCatalog,
|
|
@@ -5909,19 +6048,14 @@ window.__ModuleLoader__.load({
|
|
|
5909
6048
|
if (name === null) return;
|
|
5910
6049
|
setDeleteSkillDialog(null);
|
|
5911
6050
|
shared.setTagBusy(true);
|
|
5912
|
-
shared
|
|
5913
|
-
try {
|
|
6051
|
+
await runFlow(shared, async () => {
|
|
5914
6052
|
await api.deleteSkill(name);
|
|
5915
6053
|
await Promise.all([
|
|
5916
6054
|
reloadCatalog(),
|
|
5917
6055
|
reloadGroups(),
|
|
5918
6056
|
loadSources()
|
|
5919
6057
|
]);
|
|
5920
|
-
}
|
|
5921
|
-
shared.fail(errorMessage(error));
|
|
5922
|
-
} finally {
|
|
5923
|
-
shared.setTagBusy(false);
|
|
5924
|
-
}
|
|
6058
|
+
}, () => shared.setTagBusy(false));
|
|
5925
6059
|
}, [
|
|
5926
6060
|
api,
|
|
5927
6061
|
deleteSkillDialog,
|
|
@@ -5969,11 +6103,236 @@ window.__ModuleLoader__.load({
|
|
|
5969
6103
|
};
|
|
5970
6104
|
}
|
|
5971
6105
|
//#endregion
|
|
6106
|
+
//#region src/client/panel/hooks/useRepoImportFlow.ts
|
|
6107
|
+
/**
|
|
6108
|
+
* useRepoImportFlow — 市场子域:仓库扫描/分支选择/导入任务(轮询+取消)。
|
|
6109
|
+
* 从 useMarketFlow 原样搬出:状态、动作、卸载中断与依赖顺序不变;市场源
|
|
6110
|
+
* 列表刷新(loadMarket)与目录/分组/来源重载经参数注入,不直接碰其他域。
|
|
6111
|
+
*/
|
|
6112
|
+
function useRepoImportFlow(api, shared, loadMarket, reloadCatalog, reloadGroups, reloadSources) {
|
|
6113
|
+
const [repoDiscoverState, setRepoDiscoverState] = (0, react.useState)({ status: "idle" });
|
|
6114
|
+
/** Market repo currently being scanned (null when idle); per-row busy state. */
|
|
6115
|
+
const [scanningRepo, setScanningRepo] = (0, react.useState)(null);
|
|
6116
|
+
const [repoSelected, setRepoSelected] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
6117
|
+
const [repoImporting, setRepoImporting] = (0, react.useState)(false);
|
|
6118
|
+
const [repoResult, setRepoResult] = (0, react.useState)(null);
|
|
6119
|
+
const [importJobId, setImportJobId] = (0, react.useState)(null);
|
|
6120
|
+
const [branchChoice, setBranchChoice] = (0, react.useState)(null);
|
|
6121
|
+
const [branchBusy, setBranchBusy] = (0, react.useState)(false);
|
|
6122
|
+
const pollAbortRef = (0, react.useRef)(null);
|
|
6123
|
+
/** 扫描一个市场源(或手动输入)的仓库。 */
|
|
6124
|
+
const scanRepo = (0, react.useCallback)(async (input) => {
|
|
6125
|
+
const value = input.trim();
|
|
6126
|
+
if (value === "") return;
|
|
6127
|
+
setRepoResult(null);
|
|
6128
|
+
setRepoSelected(/* @__PURE__ */ new Set());
|
|
6129
|
+
setScanningRepo(value);
|
|
6130
|
+
setRepoDiscoverState({ status: "scanning" });
|
|
6131
|
+
shared.clearFail();
|
|
6132
|
+
try {
|
|
6133
|
+
const data = await api.repoDiscover(value);
|
|
6134
|
+
if (data.ref === null) {
|
|
6135
|
+
setBranchChoice({
|
|
6136
|
+
repo: data.repo,
|
|
6137
|
+
branches: data.branches ?? [],
|
|
6138
|
+
selected: (data.branches ?? [])[0] ?? "main"
|
|
6139
|
+
});
|
|
6140
|
+
setRepoDiscoverState({ status: "idle" });
|
|
6141
|
+
return;
|
|
6142
|
+
}
|
|
6143
|
+
setRepoDiscoverState({
|
|
6144
|
+
status: "ready",
|
|
6145
|
+
data
|
|
6146
|
+
});
|
|
6147
|
+
loadMarket();
|
|
6148
|
+
} catch (error) {
|
|
6149
|
+
setRepoDiscoverState({
|
|
6150
|
+
status: "error",
|
|
6151
|
+
message: errorMessage(error)
|
|
6152
|
+
});
|
|
6153
|
+
} finally {
|
|
6154
|
+
setScanningRepo(null);
|
|
6155
|
+
}
|
|
6156
|
+
}, [
|
|
6157
|
+
api,
|
|
6158
|
+
loadMarket,
|
|
6159
|
+
shared
|
|
6160
|
+
]);
|
|
6161
|
+
/** 确认分支选择:持久化 ref 后重新扫描。 */
|
|
6162
|
+
const confirmBranchChoice = (0, react.useCallback)(async () => {
|
|
6163
|
+
if (branchChoice === null) return;
|
|
6164
|
+
setBranchBusy(true);
|
|
6165
|
+
await runFlow(shared, async () => {
|
|
6166
|
+
await api.setMarketSourceRef(branchChoice.repo, branchChoice.selected);
|
|
6167
|
+
setBranchChoice(null);
|
|
6168
|
+
await scanRepo(branchChoice.repo);
|
|
6169
|
+
}, () => setBranchBusy(false));
|
|
6170
|
+
}, [
|
|
6171
|
+
api,
|
|
6172
|
+
branchChoice,
|
|
6173
|
+
scanRepo,
|
|
6174
|
+
shared
|
|
6175
|
+
]);
|
|
6176
|
+
/** Toggle one repo preview row. */
|
|
6177
|
+
const toggleRepoSelected = (0, react.useCallback)((path, checked) => {
|
|
6178
|
+
setRepoSelected((previous) => {
|
|
6179
|
+
const next = new Set(previous);
|
|
6180
|
+
if (checked) next.add(path);
|
|
6181
|
+
else next.delete(path);
|
|
6182
|
+
return next;
|
|
6183
|
+
});
|
|
6184
|
+
}, []);
|
|
6185
|
+
/** Import every checked, non-existing repo skill (B方案:job+轮询+进度). */
|
|
6186
|
+
const importRepo = (0, react.useCallback)(async () => {
|
|
6187
|
+
if (repoDiscoverState.status !== "ready") return;
|
|
6188
|
+
setRepoImporting(true);
|
|
6189
|
+
setRepoResult(null);
|
|
6190
|
+
setImportJobId(null);
|
|
6191
|
+
shared.clearFail();
|
|
6192
|
+
let finalProgress = null;
|
|
6193
|
+
try {
|
|
6194
|
+
const created = await api.repoImport(repoDiscoverState.data.repo, [...repoSelected], repoDiscoverState.data.ref ?? void 0);
|
|
6195
|
+
setImportJobId(created.jobId);
|
|
6196
|
+
setRepoResult({
|
|
6197
|
+
ok: true,
|
|
6198
|
+
jobId: created.jobId,
|
|
6199
|
+
status: "running",
|
|
6200
|
+
total: created.total,
|
|
6201
|
+
done: 0,
|
|
6202
|
+
totalBytes: created.totalBytes,
|
|
6203
|
+
downloadedBytes: 0,
|
|
6204
|
+
imported: [],
|
|
6205
|
+
skipped: [],
|
|
6206
|
+
failed: []
|
|
6207
|
+
});
|
|
6208
|
+
pollAbortRef.current?.abort();
|
|
6209
|
+
pollAbortRef.current = new AbortController();
|
|
6210
|
+
const signal = pollAbortRef.current.signal;
|
|
6211
|
+
let attempt = 0;
|
|
6212
|
+
for (;;) {
|
|
6213
|
+
if (signal.aborted) break;
|
|
6214
|
+
const delay = Math.min(2e3, 800 + attempt * 200);
|
|
6215
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
6216
|
+
if (signal.aborted) break;
|
|
6217
|
+
try {
|
|
6218
|
+
const progress = await api.repoImportProgress(created.jobId);
|
|
6219
|
+
setRepoResult(progress);
|
|
6220
|
+
finalProgress = progress;
|
|
6221
|
+
if (progress.status !== "running") break;
|
|
6222
|
+
attempt = 0;
|
|
6223
|
+
} catch (pollError) {
|
|
6224
|
+
if (errorMessage(pollError).includes("not found")) break;
|
|
6225
|
+
attempt += 1;
|
|
6226
|
+
if (attempt > 8) break;
|
|
6227
|
+
}
|
|
6228
|
+
}
|
|
6229
|
+
await Promise.all([
|
|
6230
|
+
reloadCatalog(),
|
|
6231
|
+
loadMarket(),
|
|
6232
|
+
reloadGroups(),
|
|
6233
|
+
reloadSources()
|
|
6234
|
+
]);
|
|
6235
|
+
} catch (error) {
|
|
6236
|
+
shared.fail(errorMessage(error));
|
|
6237
|
+
} finally {
|
|
6238
|
+
if (finalProgress !== null && (finalProgress.imported.length > 0 || finalProgress.skipped.length > 0)) {
|
|
6239
|
+
const doneNames = /* @__PURE__ */ new Set([...finalProgress.imported.map((r) => r.name), ...finalProgress.skipped.map((r) => r.name)]);
|
|
6240
|
+
const donePaths = new Set(repoDiscoverState.data.entries.filter((e) => doneNames.has(e.name)).map((e) => e.path));
|
|
6241
|
+
setRepoSelected((prev) => {
|
|
6242
|
+
const next = new Set(prev);
|
|
6243
|
+
for (const p of donePaths) next.delete(p);
|
|
6244
|
+
return next;
|
|
6245
|
+
});
|
|
6246
|
+
setRepoDiscoverState((prev) => {
|
|
6247
|
+
if (prev.status !== "ready") return prev;
|
|
6248
|
+
return {
|
|
6249
|
+
...prev,
|
|
6250
|
+
data: {
|
|
6251
|
+
...prev.data,
|
|
6252
|
+
entries: prev.data.entries.map((e) => doneNames.has(e.name) ? {
|
|
6253
|
+
...e,
|
|
6254
|
+
existing: true
|
|
6255
|
+
} : e)
|
|
6256
|
+
}
|
|
6257
|
+
};
|
|
6258
|
+
});
|
|
6259
|
+
}
|
|
6260
|
+
setRepoImporting(false);
|
|
6261
|
+
}
|
|
6262
|
+
}, [
|
|
6263
|
+
api,
|
|
6264
|
+
repoDiscoverState,
|
|
6265
|
+
repoSelected,
|
|
6266
|
+
reloadCatalog,
|
|
6267
|
+
loadMarket,
|
|
6268
|
+
reloadGroups,
|
|
6269
|
+
reloadSources,
|
|
6270
|
+
shared
|
|
6271
|
+
]);
|
|
6272
|
+
(0, react.useEffect)(() => {
|
|
6273
|
+
return () => {
|
|
6274
|
+
pollAbortRef.current?.abort();
|
|
6275
|
+
};
|
|
6276
|
+
}, []);
|
|
6277
|
+
return {
|
|
6278
|
+
repoDiscoverState,
|
|
6279
|
+
scanningRepo,
|
|
6280
|
+
repoSelected,
|
|
6281
|
+
repoImporting,
|
|
6282
|
+
repoResult,
|
|
6283
|
+
importJobId,
|
|
6284
|
+
branchChoice,
|
|
6285
|
+
branchBusy,
|
|
6286
|
+
setBranchChoice,
|
|
6287
|
+
setRepoSelected,
|
|
6288
|
+
setRepoDiscoverState,
|
|
6289
|
+
setScanningRepo,
|
|
6290
|
+
setRepoResult,
|
|
6291
|
+
scanRepo,
|
|
6292
|
+
confirmBranchChoice,
|
|
6293
|
+
toggleRepoSelected,
|
|
6294
|
+
importRepo,
|
|
6295
|
+
cancelImport: (0, react.useCallback)(async () => {
|
|
6296
|
+
if (importJobId === null) return;
|
|
6297
|
+
pollAbortRef.current?.abort();
|
|
6298
|
+
try {
|
|
6299
|
+
const res = await api.repoImportCancel(importJobId);
|
|
6300
|
+
try {
|
|
6301
|
+
const progress = await api.repoImportProgress(importJobId);
|
|
6302
|
+
setRepoResult(progress);
|
|
6303
|
+
} catch {
|
|
6304
|
+
setRepoResult((prev) => prev !== null ? {
|
|
6305
|
+
...prev,
|
|
6306
|
+
status: res.status
|
|
6307
|
+
} : prev);
|
|
6308
|
+
}
|
|
6309
|
+
} catch (error) {
|
|
6310
|
+
shared.fail(errorMessage(error));
|
|
6311
|
+
} finally {
|
|
6312
|
+
setRepoImporting(false);
|
|
6313
|
+
}
|
|
6314
|
+
}, [
|
|
6315
|
+
api,
|
|
6316
|
+
importJobId,
|
|
6317
|
+
shared
|
|
6318
|
+
]),
|
|
6319
|
+
clearScan: (0, react.useCallback)(() => {
|
|
6320
|
+
setRepoDiscoverState({ status: "idle" });
|
|
6321
|
+
setScanningRepo(null);
|
|
6322
|
+
setRepoResult(null);
|
|
6323
|
+
setRepoSelected(/* @__PURE__ */ new Set());
|
|
6324
|
+
setImportJobId(null);
|
|
6325
|
+
pollAbortRef.current?.abort();
|
|
6326
|
+
}, [])
|
|
6327
|
+
};
|
|
6328
|
+
}
|
|
6329
|
+
//#endregion
|
|
5972
6330
|
//#region src/client/panel/hooks/useMarketFlow.ts
|
|
5973
6331
|
/**
|
|
5974
|
-
* useMarketFlow —
|
|
5975
|
-
*
|
|
5976
|
-
*
|
|
6332
|
+
* useMarketFlow — 市场域:市场源增删、更新检查、星标统计、版本同步、全部
|
|
6333
|
+
* 更新;仓库扫描/分支选择/导入任务在 useRepoImportFlow(这里组装它并透传
|
|
6334
|
+
* 同样的返回字段)。目录/分组/来源的刷新与来源检查经聚合根传入,不直接
|
|
6335
|
+
* 碰其他域的 state。
|
|
5977
6336
|
*/
|
|
5978
6337
|
function useMarketFlow(api, shared, reloadCatalog, reloadGroups, reloadSources, checkSources, sourceCheck) {
|
|
5979
6338
|
const [marketState, setMarketState] = (0, react.useState)({
|
|
@@ -5981,20 +6340,10 @@ window.__ModuleLoader__.load({
|
|
|
5981
6340
|
repos: []
|
|
5982
6341
|
});
|
|
5983
6342
|
const [marketCheck, setMarketCheck] = (0, react.useState)({});
|
|
5984
|
-
const [branchChoice, setBranchChoice] = (0, react.useState)(null);
|
|
5985
|
-
const [branchBusy, setBranchBusy] = (0, react.useState)(false);
|
|
5986
6343
|
const [marketSyncDialog, setMarketSyncDialog] = (0, react.useState)(null);
|
|
5987
6344
|
const [syncingMarket, setSyncingMarket] = (0, react.useState)(null);
|
|
5988
6345
|
const [syncBusy, setSyncBusy] = (0, react.useState)(false);
|
|
5989
6346
|
const [newSourceName, setNewSourceName] = (0, react.useState)("");
|
|
5990
|
-
const [repoDiscoverState, setRepoDiscoverState] = (0, react.useState)({ status: "idle" });
|
|
5991
|
-
/** Market repo currently being scanned (null when idle); per-row busy state. */
|
|
5992
|
-
const [scanningRepo, setScanningRepo] = (0, react.useState)(null);
|
|
5993
|
-
const [repoSelected, setRepoSelected] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
5994
|
-
const [repoImporting, setRepoImporting] = (0, react.useState)(false);
|
|
5995
|
-
const [repoResult, setRepoResult] = (0, react.useState)(null);
|
|
5996
|
-
const [importJobId, setImportJobId] = (0, react.useState)(null);
|
|
5997
|
-
const pollAbortRef = (0, react.useRef)(null);
|
|
5998
6347
|
/** 市场源星星/下载数(SWR 缓存)。 */
|
|
5999
6348
|
const [marketStats, setMarketStats] = (0, react.useState)({});
|
|
6000
6349
|
/** 版本对话框:打开时拉 releases + branches,确认后定版并重扫。 */
|
|
@@ -6017,6 +6366,7 @@ window.__ModuleLoader__.load({
|
|
|
6017
6366
|
shared.fail(errorMessage(error));
|
|
6018
6367
|
}
|
|
6019
6368
|
}, [api, shared]);
|
|
6369
|
+
const { repoDiscoverState, scanningRepo, repoSelected, repoImporting, repoResult, importJobId, branchChoice, branchBusy, setBranchChoice, setRepoSelected, setRepoDiscoverState, setScanningRepo, setRepoResult, scanRepo, confirmBranchChoice, toggleRepoSelected, importRepo, cancelImport, clearScan } = useRepoImportFlow(api, shared, loadMarket, reloadCatalog, reloadGroups, reloadSources);
|
|
6020
6370
|
/** 添加一个市场源(内置市场目录与手动输入共用),并立即扫描它。 */
|
|
6021
6371
|
const addSource = (0, react.useCallback)(async (input) => {
|
|
6022
6372
|
const value = input.trim();
|
|
@@ -6050,86 +6400,23 @@ window.__ModuleLoader__.load({
|
|
|
6050
6400
|
}
|
|
6051
6401
|
} catch (error) {
|
|
6052
6402
|
shared.fail(errorMessage(error));
|
|
6053
|
-
}
|
|
6054
|
-
}, [api, shared]);
|
|
6055
|
-
/** 手动输入框的添加动作。 */
|
|
6056
|
-
const addMarketSource = (0, react.useCallback)(async () => {
|
|
6057
|
-
await addSource(newSourceName);
|
|
6058
|
-
}, [addSource, newSourceName]);
|
|
6059
|
-
/** 删除一个市场源(不影响已装技能)。 */
|
|
6060
|
-
const removeMarketSource = (0, react.useCallback)(async (repo) => {
|
|
6061
|
-
shared.setTagBusy(true);
|
|
6062
|
-
shared
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
shared.fail(errorMessage(error));
|
|
6071
|
-
} finally {
|
|
6072
|
-
shared.setTagBusy(false);
|
|
6073
|
-
}
|
|
6074
|
-
}, [api, shared]);
|
|
6075
|
-
/** 扫描一个市场源(或手动输入)的仓库。 */
|
|
6076
|
-
const scanRepo = (0, react.useCallback)(async (input) => {
|
|
6077
|
-
const value = input.trim();
|
|
6078
|
-
if (value === "") return;
|
|
6079
|
-
setRepoResult(null);
|
|
6080
|
-
setRepoSelected(/* @__PURE__ */ new Set());
|
|
6081
|
-
setScanningRepo(value);
|
|
6082
|
-
setRepoDiscoverState({ status: "scanning" });
|
|
6083
|
-
shared.clearFail();
|
|
6084
|
-
try {
|
|
6085
|
-
const data = await api.repoDiscover(value);
|
|
6086
|
-
if (data.ref === null) {
|
|
6087
|
-
setBranchChoice({
|
|
6088
|
-
repo: data.repo,
|
|
6089
|
-
branches: data.branches ?? [],
|
|
6090
|
-
selected: (data.branches ?? [])[0] ?? "main"
|
|
6091
|
-
});
|
|
6092
|
-
setRepoDiscoverState({ status: "idle" });
|
|
6093
|
-
return;
|
|
6094
|
-
}
|
|
6095
|
-
setRepoDiscoverState({
|
|
6096
|
-
status: "ready",
|
|
6097
|
-
data
|
|
6098
|
-
});
|
|
6099
|
-
loadMarket();
|
|
6100
|
-
} catch (error) {
|
|
6101
|
-
setRepoDiscoverState({
|
|
6102
|
-
status: "error",
|
|
6103
|
-
message: errorMessage(error)
|
|
6104
|
-
});
|
|
6105
|
-
} finally {
|
|
6106
|
-
setScanningRepo(null);
|
|
6107
|
-
}
|
|
6108
|
-
}, [
|
|
6109
|
-
api,
|
|
6110
|
-
loadMarket,
|
|
6111
|
-
shared
|
|
6112
|
-
]);
|
|
6113
|
-
/** 确认分支选择:持久化 ref 后重新扫描。 */
|
|
6114
|
-
const confirmBranchChoice = (0, react.useCallback)(async () => {
|
|
6115
|
-
if (branchChoice === null) return;
|
|
6116
|
-
setBranchBusy(true);
|
|
6117
|
-
shared.clearFail();
|
|
6118
|
-
try {
|
|
6119
|
-
await api.setMarketSourceRef(branchChoice.repo, branchChoice.selected);
|
|
6120
|
-
setBranchChoice(null);
|
|
6121
|
-
await scanRepo(branchChoice.repo);
|
|
6122
|
-
} catch (error) {
|
|
6123
|
-
shared.fail(errorMessage(error));
|
|
6124
|
-
} finally {
|
|
6125
|
-
setBranchBusy(false);
|
|
6126
|
-
}
|
|
6127
|
-
}, [
|
|
6128
|
-
api,
|
|
6129
|
-
branchChoice,
|
|
6130
|
-
scanRepo,
|
|
6131
|
-
shared
|
|
6132
|
-
]);
|
|
6403
|
+
}
|
|
6404
|
+
}, [api, shared]);
|
|
6405
|
+
/** 手动输入框的添加动作。 */
|
|
6406
|
+
const addMarketSource = (0, react.useCallback)(async () => {
|
|
6407
|
+
await addSource(newSourceName);
|
|
6408
|
+
}, [addSource, newSourceName]);
|
|
6409
|
+
/** 删除一个市场源(不影响已装技能)。 */
|
|
6410
|
+
const removeMarketSource = (0, react.useCallback)(async (repo) => {
|
|
6411
|
+
shared.setTagBusy(true);
|
|
6412
|
+
await runFlow(shared, async () => {
|
|
6413
|
+
const result = await api.removeMarketSource(repo);
|
|
6414
|
+
setMarketState({
|
|
6415
|
+
status: "ready",
|
|
6416
|
+
repos: result.repos
|
|
6417
|
+
});
|
|
6418
|
+
}, () => shared.setTagBusy(false));
|
|
6419
|
+
}, [api, shared]);
|
|
6133
6420
|
const openVersionDialog = (0, react.useCallback)(async (repo) => {
|
|
6134
6421
|
const current = marketState.repos.find((item) => item.repo === repo)?.ref;
|
|
6135
6422
|
setVersionDialog({
|
|
@@ -6167,17 +6454,12 @@ window.__ModuleLoader__.load({
|
|
|
6167
6454
|
const ref = versionDialog.custom.trim() !== "" ? versionDialog.custom.trim() : versionDialog.selected;
|
|
6168
6455
|
if (ref === "") return;
|
|
6169
6456
|
setVersionBusy(true);
|
|
6170
|
-
shared
|
|
6171
|
-
try {
|
|
6457
|
+
await runFlow(shared, async () => {
|
|
6172
6458
|
await api.setMarketSourceRef(versionDialog.repo, ref);
|
|
6173
6459
|
setVersionDialog(null);
|
|
6174
6460
|
await loadMarket();
|
|
6175
6461
|
await scanRepo(versionDialog.repo);
|
|
6176
|
-
}
|
|
6177
|
-
shared.fail(errorMessage(error));
|
|
6178
|
-
} finally {
|
|
6179
|
-
setVersionBusy(false);
|
|
6180
|
-
}
|
|
6462
|
+
}, () => setVersionBusy(false));
|
|
6181
6463
|
}, [
|
|
6182
6464
|
api,
|
|
6183
6465
|
versionDialog,
|
|
@@ -6185,141 +6467,6 @@ window.__ModuleLoader__.load({
|
|
|
6185
6467
|
scanRepo,
|
|
6186
6468
|
shared
|
|
6187
6469
|
]);
|
|
6188
|
-
/** Toggle one repo preview row. */
|
|
6189
|
-
const toggleRepoSelected = (0, react.useCallback)((path, checked) => {
|
|
6190
|
-
setRepoSelected((previous) => {
|
|
6191
|
-
const next = new Set(previous);
|
|
6192
|
-
if (checked) next.add(path);
|
|
6193
|
-
else next.delete(path);
|
|
6194
|
-
return next;
|
|
6195
|
-
});
|
|
6196
|
-
}, []);
|
|
6197
|
-
/** Import every checked, non-existing repo skill (B方案:job+轮询+进度). */
|
|
6198
|
-
const importRepo = (0, react.useCallback)(async () => {
|
|
6199
|
-
if (repoDiscoverState.status !== "ready") return;
|
|
6200
|
-
setRepoImporting(true);
|
|
6201
|
-
setRepoResult(null);
|
|
6202
|
-
setImportJobId(null);
|
|
6203
|
-
shared.clearFail();
|
|
6204
|
-
let finalProgress = null;
|
|
6205
|
-
try {
|
|
6206
|
-
const created = await api.repoImport(repoDiscoverState.data.repo, [...repoSelected], repoDiscoverState.data.ref ?? void 0);
|
|
6207
|
-
setImportJobId(created.jobId);
|
|
6208
|
-
setRepoResult({
|
|
6209
|
-
ok: true,
|
|
6210
|
-
jobId: created.jobId,
|
|
6211
|
-
status: "running",
|
|
6212
|
-
total: created.total,
|
|
6213
|
-
done: 0,
|
|
6214
|
-
totalBytes: created.totalBytes,
|
|
6215
|
-
downloadedBytes: 0,
|
|
6216
|
-
imported: [],
|
|
6217
|
-
skipped: [],
|
|
6218
|
-
failed: []
|
|
6219
|
-
});
|
|
6220
|
-
pollAbortRef.current?.abort();
|
|
6221
|
-
pollAbortRef.current = new AbortController();
|
|
6222
|
-
const signal = pollAbortRef.current.signal;
|
|
6223
|
-
let attempt = 0;
|
|
6224
|
-
for (;;) {
|
|
6225
|
-
if (signal.aborted) break;
|
|
6226
|
-
const delay = Math.min(2e3, 800 + attempt * 200);
|
|
6227
|
-
await new Promise((r) => setTimeout(r, delay));
|
|
6228
|
-
if (signal.aborted) break;
|
|
6229
|
-
try {
|
|
6230
|
-
const progress = await api.repoImportProgress(created.jobId);
|
|
6231
|
-
setRepoResult(progress);
|
|
6232
|
-
finalProgress = progress;
|
|
6233
|
-
if (progress.status !== "running") break;
|
|
6234
|
-
attempt = 0;
|
|
6235
|
-
} catch (pollError) {
|
|
6236
|
-
if (errorMessage(pollError).includes("not found")) break;
|
|
6237
|
-
attempt += 1;
|
|
6238
|
-
if (attempt > 8) break;
|
|
6239
|
-
}
|
|
6240
|
-
}
|
|
6241
|
-
await Promise.all([
|
|
6242
|
-
reloadCatalog(),
|
|
6243
|
-
loadMarket(),
|
|
6244
|
-
reloadGroups(),
|
|
6245
|
-
reloadSources()
|
|
6246
|
-
]);
|
|
6247
|
-
} catch (error) {
|
|
6248
|
-
shared.fail(errorMessage(error));
|
|
6249
|
-
} finally {
|
|
6250
|
-
if (finalProgress !== null && (finalProgress.imported.length > 0 || finalProgress.skipped.length > 0)) {
|
|
6251
|
-
const doneNames = /* @__PURE__ */ new Set([...finalProgress.imported.map((r) => r.name), ...finalProgress.skipped.map((r) => r.name)]);
|
|
6252
|
-
const donePaths = new Set(repoDiscoverState.data.entries.filter((e) => doneNames.has(e.name)).map((e) => e.path));
|
|
6253
|
-
setRepoSelected((prev) => {
|
|
6254
|
-
const next = new Set(prev);
|
|
6255
|
-
for (const p of donePaths) next.delete(p);
|
|
6256
|
-
return next;
|
|
6257
|
-
});
|
|
6258
|
-
setRepoDiscoverState((prev) => {
|
|
6259
|
-
if (prev.status !== "ready") return prev;
|
|
6260
|
-
return {
|
|
6261
|
-
...prev,
|
|
6262
|
-
data: {
|
|
6263
|
-
...prev.data,
|
|
6264
|
-
entries: prev.data.entries.map((e) => doneNames.has(e.name) ? {
|
|
6265
|
-
...e,
|
|
6266
|
-
existing: true
|
|
6267
|
-
} : e)
|
|
6268
|
-
}
|
|
6269
|
-
};
|
|
6270
|
-
});
|
|
6271
|
-
}
|
|
6272
|
-
setRepoImporting(false);
|
|
6273
|
-
}
|
|
6274
|
-
}, [
|
|
6275
|
-
api,
|
|
6276
|
-
repoDiscoverState,
|
|
6277
|
-
repoSelected,
|
|
6278
|
-
reloadCatalog,
|
|
6279
|
-
loadMarket,
|
|
6280
|
-
reloadGroups,
|
|
6281
|
-
reloadSources,
|
|
6282
|
-
shared
|
|
6283
|
-
]);
|
|
6284
|
-
(0, react.useEffect)(() => {
|
|
6285
|
-
return () => {
|
|
6286
|
-
pollAbortRef.current?.abort();
|
|
6287
|
-
};
|
|
6288
|
-
}, []);
|
|
6289
|
-
/** 取消正在进行的导入(选项2:唯有取消才停) */
|
|
6290
|
-
const cancelImport = (0, react.useCallback)(async () => {
|
|
6291
|
-
if (importJobId === null) return;
|
|
6292
|
-
pollAbortRef.current?.abort();
|
|
6293
|
-
try {
|
|
6294
|
-
const res = await api.repoImportCancel(importJobId);
|
|
6295
|
-
try {
|
|
6296
|
-
const progress = await api.repoImportProgress(importJobId);
|
|
6297
|
-
setRepoResult(progress);
|
|
6298
|
-
} catch {
|
|
6299
|
-
setRepoResult((prev) => prev !== null ? {
|
|
6300
|
-
...prev,
|
|
6301
|
-
status: res.status
|
|
6302
|
-
} : prev);
|
|
6303
|
-
}
|
|
6304
|
-
} catch (error) {
|
|
6305
|
-
shared.fail(errorMessage(error));
|
|
6306
|
-
} finally {
|
|
6307
|
-
setRepoImporting(false);
|
|
6308
|
-
}
|
|
6309
|
-
}, [
|
|
6310
|
-
api,
|
|
6311
|
-
importJobId,
|
|
6312
|
-
shared
|
|
6313
|
-
]);
|
|
6314
|
-
/** 清空扫描结果(关闭归属卡片) */
|
|
6315
|
-
const clearScan = (0, react.useCallback)(() => {
|
|
6316
|
-
setRepoDiscoverState({ status: "idle" });
|
|
6317
|
-
setScanningRepo(null);
|
|
6318
|
-
setRepoResult(null);
|
|
6319
|
-
setRepoSelected(/* @__PURE__ */ new Set());
|
|
6320
|
-
setImportJobId(null);
|
|
6321
|
-
pollAbortRef.current?.abort();
|
|
6322
|
-
}, []);
|
|
6323
6470
|
/** 检查所有市场源的上游更新(服务端节流)。 */
|
|
6324
6471
|
const checkMarket = (0, react.useCallback)(async () => {
|
|
6325
6472
|
try {
|
|
@@ -6388,8 +6535,7 @@ window.__ModuleLoader__.load({
|
|
|
6388
6535
|
}, [api]),
|
|
6389
6536
|
syncMarketSource: (0, react.useCallback)(async (repo) => {
|
|
6390
6537
|
setSyncingMarket(repo);
|
|
6391
|
-
shared
|
|
6392
|
-
try {
|
|
6538
|
+
await runFlow(shared, async () => {
|
|
6393
6539
|
const result = await api.marketSync(repo);
|
|
6394
6540
|
setMarketSyncDialog({
|
|
6395
6541
|
repo: result.repo,
|
|
@@ -6398,11 +6544,7 @@ window.__ModuleLoader__.load({
|
|
|
6398
6544
|
selected: new Set(result.skills)
|
|
6399
6545
|
});
|
|
6400
6546
|
await loadMarket();
|
|
6401
|
-
}
|
|
6402
|
-
shared.fail(errorMessage(error));
|
|
6403
|
-
} finally {
|
|
6404
|
-
setSyncingMarket(null);
|
|
6405
|
-
}
|
|
6547
|
+
}, () => setSyncingMarket(null));
|
|
6406
6548
|
}, [
|
|
6407
6549
|
api,
|
|
6408
6550
|
loadMarket,
|
|
@@ -6412,8 +6554,7 @@ window.__ModuleLoader__.load({
|
|
|
6412
6554
|
if (marketSyncDialog === null) return;
|
|
6413
6555
|
const selected = [...marketSyncDialog.selected];
|
|
6414
6556
|
setSyncBusy(true);
|
|
6415
|
-
shared
|
|
6416
|
-
try {
|
|
6557
|
+
await runFlow(shared, async () => {
|
|
6417
6558
|
if (selected.length > 0) {
|
|
6418
6559
|
const result = await api.syncSource(marketSyncDialog.repo, selected);
|
|
6419
6560
|
if (result.failed.length > 0) shared.fail(result.failed.map((item) => item.name + ": " + item.error).join("\n"));
|
|
@@ -6425,11 +6566,7 @@ window.__ModuleLoader__.load({
|
|
|
6425
6566
|
reloadSources()
|
|
6426
6567
|
]);
|
|
6427
6568
|
checkMarket();
|
|
6428
|
-
}
|
|
6429
|
-
shared.fail(errorMessage(error));
|
|
6430
|
-
} finally {
|
|
6431
|
-
setSyncBusy(false);
|
|
6432
|
-
}
|
|
6569
|
+
}, () => setSyncBusy(false));
|
|
6433
6570
|
}, [
|
|
6434
6571
|
api,
|
|
6435
6572
|
marketSyncDialog,
|
|
@@ -6531,6 +6668,10 @@ window.__ModuleLoader__.load({
|
|
|
6531
6668
|
return next;
|
|
6532
6669
|
});
|
|
6533
6670
|
}, []);
|
|
6671
|
+
/** 整组折叠/展开:传 null 全部展开,传键列表全部折叠(视图侧自己算键)。 */
|
|
6672
|
+
const setAllGroupsCollapsed = (0, react.useCallback)((keys) => {
|
|
6673
|
+
setCollapsedGroups(keys === null ? /* @__PURE__ */ new Set() : new Set(keys));
|
|
6674
|
+
}, []);
|
|
6534
6675
|
const collapsePersonal = (0, react.useCallback)(() => {
|
|
6535
6676
|
setCollapsedGroups((previous) => new Set(previous).add("uncategorized-source"));
|
|
6536
6677
|
}, []);
|
|
@@ -6559,13 +6700,13 @@ window.__ModuleLoader__.load({
|
|
|
6559
6700
|
meta.loadConfig();
|
|
6560
6701
|
const fast = window.setInterval(() => {
|
|
6561
6702
|
catalogFlow.load();
|
|
6562
|
-
},
|
|
6703
|
+
}, POLL_MS);
|
|
6563
6704
|
const slow = window.setInterval(() => {
|
|
6564
6705
|
meta.loadUses();
|
|
6565
6706
|
groupFlow.loadGroups();
|
|
6566
6707
|
sourceFlow.loadSources();
|
|
6567
6708
|
meta.loadConfig();
|
|
6568
|
-
},
|
|
6709
|
+
}, SLOW_POLL_MS);
|
|
6569
6710
|
return () => {
|
|
6570
6711
|
window.clearInterval(fast);
|
|
6571
6712
|
window.clearInterval(slow);
|
|
@@ -6595,7 +6736,6 @@ window.__ModuleLoader__.load({
|
|
|
6595
6736
|
repoSelected: marketFlow.repoSelected,
|
|
6596
6737
|
repoImporting: marketFlow.repoImporting,
|
|
6597
6738
|
repoResult: marketFlow.repoResult,
|
|
6598
|
-
importJobId: marketFlow.importJobId,
|
|
6599
6739
|
search: catalogFlow.search,
|
|
6600
6740
|
workspace: catalogFlow.workspace,
|
|
6601
6741
|
detail: catalogFlow.detail,
|
|
@@ -6690,12 +6830,12 @@ window.__ModuleLoader__.load({
|
|
|
6690
6830
|
setVersionDialog: marketFlow.setVersionDialog,
|
|
6691
6831
|
toggleGroupCollapse,
|
|
6692
6832
|
toggleSubdivide,
|
|
6833
|
+
setAllGroupsCollapsed,
|
|
6693
6834
|
checkUpdate: meta.checkUpdate,
|
|
6694
6835
|
loadMarket: marketFlow.loadMarket,
|
|
6695
6836
|
openDetail: catalogFlow.openDetail,
|
|
6696
6837
|
toggle: catalogFlow.toggle,
|
|
6697
6838
|
enableDisabled: catalogFlow.enableDisabled,
|
|
6698
|
-
batchToggleNames: catalogFlow.batchToggleNames,
|
|
6699
6839
|
toggleGroup: groupFlow.toggleGroup,
|
|
6700
6840
|
resolveConflict: groupFlow.resolveConflict,
|
|
6701
6841
|
runConfirmed: sourceFlow.runConfirmed,
|
|
@@ -6717,7 +6857,6 @@ window.__ModuleLoader__.load({
|
|
|
6717
6857
|
deleteTag: groupFlow.deleteTag,
|
|
6718
6858
|
saveTag: groupFlow.saveTag,
|
|
6719
6859
|
reorderTags: groupFlow.reorderTags,
|
|
6720
|
-
reorderCollections: groupFlow.reorderCollections,
|
|
6721
6860
|
reorderSourceGroups: groupFlow.reorderSourceGroups,
|
|
6722
6861
|
addSource: marketFlow.addSource,
|
|
6723
6862
|
addMarketSource: marketFlow.addMarketSource,
|
|
@@ -6746,16 +6885,19 @@ window.__ModuleLoader__.load({
|
|
|
6746
6885
|
* detail inspection, and the new-skill scaffold form.
|
|
6747
6886
|
*
|
|
6748
6887
|
* Thin shell: state and flows live in useSkillHub, the tab contents live in
|
|
6749
|
-
* SourcesView / ScenesView / MarketView,
|
|
6750
|
-
* dialogs.tsx
|
|
6751
|
-
*
|
|
6752
|
-
* so the detail / tag-editor
|
|
6888
|
+
* SourcesView / ScenesView / MarketView, the dialog family lives in
|
|
6889
|
+
* dialogs.tsx, and their wiring lives in PanelDialogs.tsx. This component
|
|
6890
|
+
* owns only the shared chrome (header, banners, filter bar, shared sections)
|
|
6891
|
+
* and the view routing — and holds no hooks, so the detail / tag-editor
|
|
6892
|
+
* early returns are safe.
|
|
6753
6893
|
*/
|
|
6754
6894
|
function SkillHubPanel(props) {
|
|
6755
6895
|
const hub = useSkillHub(props.api);
|
|
6756
6896
|
/** 工作区输入草稿:回车才应用,避免每次按键都触发目录重拉。 */
|
|
6757
6897
|
const [workspaceDraft, setWorkspaceDraft] = (0, react.useState)("");
|
|
6758
|
-
|
|
6898
|
+
/** 「筛选」面板开合(来源 + 调用方式收进这里;搜索/排序/视图切换始终可见)。 */
|
|
6899
|
+
const [filtersOpen, setFiltersOpen] = (0, react.useState)(false);
|
|
6900
|
+
const { catalog, loading, loadError, successBanner, updateState, detail, detailLoading, showForm, formName, formDesc, formRoot, formBusy, formMessage, hubConfig, tab, skillView, sourceFilter, sortKey, search, workspace, setWorkspace, sourcesState, tagBusy, batchBusy, busyNames, normalized, origins, sourceOptions, filtered, conflictDialog, confirmDialog, deleteSkillDialog, deleteGroupDialog, confirmClearTrash, branchChoice, branchBusy, marketSyncDialog, syncBusy, editingTag, editName, membersDraft, editSearch, uses, groupsState, sourceCheck, checkingSource, syncingSource, showLegend, editMode, setLoadError, setSuccessBanner, setDetail, setShowForm, setFormName, setFormDesc, setFormRoot, setFormMessage, setTab, setSkillView, setSourceFilter, setSortKey, setSearch, setConflictDialog, setConfirmDialog, setDeleteSkillDialog, setDeleteGroupDialog, setConfirmClearTrash, setBranchChoice, setMarketSyncDialog, setEditingTag, setEditName, setMembersDraft, setEditSearch, setShowLegend, setEditMode, checkUpdate, loadMarket, checkSources, requestSync, requestDelete, restoreTrash, clearTrash, runDeleteSkill, runDeleteGroup, runConfirmed, resolveConflict, confirmBranchChoice, confirmMarketSync, create, saveTag, deleteTag, enableDisabled } = hub;
|
|
6759
6901
|
const { shortenedCount, fixingPaths, clearListFilters } = hub;
|
|
6760
6902
|
if (detail !== null) {
|
|
6761
6903
|
const disabledRecord = catalog?.disabled.find((record) => record.name === detail.name);
|
|
@@ -6768,7 +6910,6 @@ window.__ModuleLoader__.load({
|
|
|
6768
6910
|
sourceCheck,
|
|
6769
6911
|
checkingSource,
|
|
6770
6912
|
syncingSource,
|
|
6771
|
-
loading: detailLoading,
|
|
6772
6913
|
disabled: disabledRecord !== void 0,
|
|
6773
6914
|
onEnable: disabledRecord !== void 0 ? () => {
|
|
6774
6915
|
enableDisabled(disabledRecord).then(() => {
|
|
@@ -6815,6 +6956,8 @@ window.__ModuleLoader__.load({
|
|
|
6815
6956
|
saveTag(editingTag.id, editName, [...membersDraft]);
|
|
6816
6957
|
}
|
|
6817
6958
|
});
|
|
6959
|
+
/** 生效中的筛选条件数(来源 + 调用方式),显示在「筛选」按钮上。 */
|
|
6960
|
+
const activeFilterCount = (sourceFilter !== "all" ? 1 : 0) + (hub.invocationFilter !== "all" ? 1 : 0);
|
|
6818
6961
|
/** 检查结果的悬停提示:收敛到「检查更新」按钮上,不再占面板顶部横幅。 */
|
|
6819
6962
|
const updateTitle = (() => {
|
|
6820
6963
|
if (updateState.status === "checking") return tt("update.checking");
|
|
@@ -6832,6 +6975,7 @@ window.__ModuleLoader__.load({
|
|
|
6832
6975
|
})();
|
|
6833
6976
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6834
6977
|
className: panel_module_css_default.panel,
|
|
6978
|
+
"aria-busy": batchBusy || tagBusy,
|
|
6835
6979
|
children: [
|
|
6836
6980
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6837
6981
|
className: panel_module_css_default.header,
|
|
@@ -6875,22 +7019,35 @@ window.__ModuleLoader__.load({
|
|
|
6875
7019
|
}) : null,
|
|
6876
7020
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6877
7021
|
className: panel_module_css_default.actions,
|
|
6878
|
-
children: [
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
7022
|
+
children: [
|
|
7023
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7024
|
+
type: "button",
|
|
7025
|
+
className: panel_module_css_default.button + (editMode ? " " + panel_module_css_default.primary : ""),
|
|
7026
|
+
"aria-pressed": editMode,
|
|
7027
|
+
title: tt("edit.hint"),
|
|
7028
|
+
onClick: () => {
|
|
7029
|
+
setEditMode((value) => !value);
|
|
7030
|
+
},
|
|
7031
|
+
children: tt(editMode ? "edit.done" : "edit.start")
|
|
7032
|
+
}),
|
|
7033
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7034
|
+
type: "button",
|
|
7035
|
+
className: panel_module_css_default.button,
|
|
7036
|
+
disabled: updateState.status === "checking",
|
|
7037
|
+
title: updateTitle,
|
|
7038
|
+
onClick: () => {
|
|
7039
|
+
checkUpdate();
|
|
7040
|
+
},
|
|
7041
|
+
children: updateState.status === "checking" ? tt("update.checking") : tt("update.check")
|
|
7042
|
+
}),
|
|
7043
|
+
updateState.status === "ready" && updateState.data.updateAvailable && updateState.data.url !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
7044
|
+
className: panel_module_css_default.updateLink,
|
|
7045
|
+
href: updateState.data.url,
|
|
7046
|
+
target: "_blank",
|
|
7047
|
+
rel: "noreferrer",
|
|
7048
|
+
children: tt("update.newVersion", { version: updateState.data.latestVersion ?? "" })
|
|
7049
|
+
}) : null
|
|
7050
|
+
]
|
|
6894
7051
|
})
|
|
6895
7052
|
]
|
|
6896
7053
|
}),
|
|
@@ -7056,9 +7213,11 @@ window.__ModuleLoader__.load({
|
|
|
7056
7213
|
}) : null,
|
|
7057
7214
|
loadError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7058
7215
|
className: panel_module_css_default.errorBanner,
|
|
7216
|
+
role: "alert",
|
|
7059
7217
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: loadError }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7060
7218
|
type: "button",
|
|
7061
7219
|
className: panel_module_css_default.button,
|
|
7220
|
+
"aria-label": tt("err.dismiss"),
|
|
7062
7221
|
onClick: () => {
|
|
7063
7222
|
setLoadError(null);
|
|
7064
7223
|
},
|
|
@@ -7067,9 +7226,11 @@ window.__ModuleLoader__.load({
|
|
|
7067
7226
|
}) : null,
|
|
7068
7227
|
successBanner !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7069
7228
|
className: panel_module_css_default.successBanner,
|
|
7229
|
+
role: "status",
|
|
7070
7230
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: successBanner }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7071
7231
|
type: "button",
|
|
7072
7232
|
className: panel_module_css_default.button,
|
|
7233
|
+
"aria-label": tt("err.dismiss"),
|
|
7073
7234
|
onClick: () => {
|
|
7074
7235
|
setSuccessBanner(null);
|
|
7075
7236
|
},
|
|
@@ -7099,9 +7260,15 @@ window.__ModuleLoader__.load({
|
|
|
7099
7260
|
})
|
|
7100
7261
|
]
|
|
7101
7262
|
}) : null,
|
|
7102
|
-
loading ? /* @__PURE__ */ (0, react_jsx_runtime.
|
|
7103
|
-
className: panel_module_css_default.
|
|
7104
|
-
|
|
7263
|
+
loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7264
|
+
className: panel_module_css_default.skeleton,
|
|
7265
|
+
role: "status",
|
|
7266
|
+
"aria-label": tt("panel.loading"),
|
|
7267
|
+
children: [
|
|
7268
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: panel_module_css_default.skeletonRow }),
|
|
7269
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: panel_module_css_default.skeletonRow }),
|
|
7270
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: panel_module_css_default.skeletonRow })
|
|
7271
|
+
]
|
|
7105
7272
|
}) : null,
|
|
7106
7273
|
detailLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7107
7274
|
className: panel_module_css_default.empty,
|
|
@@ -7111,7 +7278,7 @@ window.__ModuleLoader__.load({
|
|
|
7111
7278
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7112
7279
|
className: panel_module_css_default.filterBar,
|
|
7113
7280
|
children: [
|
|
7114
|
-
tab === "sources" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
7281
|
+
tab === "sources" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7115
7282
|
className: panel_module_css_default.segmented,
|
|
7116
7283
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7117
7284
|
type: "button",
|
|
@@ -7128,20 +7295,7 @@ window.__ModuleLoader__.load({
|
|
|
7128
7295
|
},
|
|
7129
7296
|
children: tt("view.grouped")
|
|
7130
7297
|
})]
|
|
7131
|
-
})
|
|
7132
|
-
className: panel_module_css_default.select,
|
|
7133
|
-
value: sourceFilter,
|
|
7134
|
-
onChange: (event) => {
|
|
7135
|
-
setSourceFilter(event.target.value);
|
|
7136
|
-
},
|
|
7137
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7138
|
-
value: "all",
|
|
7139
|
-
children: tt("filter.allSources")
|
|
7140
|
-
}), sourceOptions.map((source) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7141
|
-
value: source,
|
|
7142
|
-
children: source === "private" ? tt("filter.private") : source
|
|
7143
|
-
}, source))]
|
|
7144
|
-
})] }) : null,
|
|
7298
|
+
}) : null,
|
|
7145
7299
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
7146
7300
|
className: panel_module_css_default.select,
|
|
7147
7301
|
value: sortKey,
|
|
@@ -7163,27 +7317,6 @@ window.__ModuleLoader__.load({
|
|
|
7163
7317
|
})
|
|
7164
7318
|
]
|
|
7165
7319
|
}),
|
|
7166
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
7167
|
-
className: panel_module_css_default.select,
|
|
7168
|
-
value: hub.invocationFilter,
|
|
7169
|
-
onChange: (event) => {
|
|
7170
|
-
hub.setInvocationFilter(event.target.value);
|
|
7171
|
-
},
|
|
7172
|
-
children: [
|
|
7173
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7174
|
-
value: "all",
|
|
7175
|
-
children: tt("filter.invocationAll")
|
|
7176
|
-
}),
|
|
7177
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7178
|
-
value: "model",
|
|
7179
|
-
children: tt("filter.modelOnly")
|
|
7180
|
-
}),
|
|
7181
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7182
|
-
value: "user",
|
|
7183
|
-
children: tt("filter.userOnly")
|
|
7184
|
-
})
|
|
7185
|
-
]
|
|
7186
|
-
}),
|
|
7187
7320
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
7188
7321
|
className: panel_module_css_default.search,
|
|
7189
7322
|
value: search,
|
|
@@ -7192,15 +7325,80 @@ window.__ModuleLoader__.load({
|
|
|
7192
7325
|
},
|
|
7193
7326
|
placeholder: tt("panel.search")
|
|
7194
7327
|
}),
|
|
7195
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
7328
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7196
7329
|
type: "button",
|
|
7197
|
-
className: panel_module_css_default.button + (
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7330
|
+
className: panel_module_css_default.button + (filtersOpen || activeFilterCount > 0 ? " " + panel_module_css_default.primary : ""),
|
|
7331
|
+
"aria-expanded": filtersOpen,
|
|
7332
|
+
"aria-controls": "skill-hub-filter-panel",
|
|
7333
|
+
onClick: () => {
|
|
7334
|
+
setFiltersOpen((value) => !value);
|
|
7335
|
+
},
|
|
7336
|
+
children: [tt("filter.title"), activeFilterCount > 0 ? " (" + activeFilterCount + ")" : ""]
|
|
7201
7337
|
})
|
|
7202
7338
|
]
|
|
7203
7339
|
}),
|
|
7340
|
+
filtersOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7341
|
+
className: panel_module_css_default.filterPanel,
|
|
7342
|
+
id: "skill-hub-filter-panel",
|
|
7343
|
+
children: [
|
|
7344
|
+
tab === "sources" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
7345
|
+
className: panel_module_css_default.filterField,
|
|
7346
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7347
|
+
className: panel_module_css_default.formLabel,
|
|
7348
|
+
children: tt("filter.source")
|
|
7349
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
7350
|
+
className: panel_module_css_default.select,
|
|
7351
|
+
value: sourceFilter,
|
|
7352
|
+
onChange: (event) => {
|
|
7353
|
+
setSourceFilter(event.target.value);
|
|
7354
|
+
},
|
|
7355
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7356
|
+
value: "all",
|
|
7357
|
+
children: tt("filter.allSources")
|
|
7358
|
+
}), sourceOptions.map((source) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7359
|
+
value: source,
|
|
7360
|
+
children: source === "private" ? tt("filter.private") : source
|
|
7361
|
+
}, source))]
|
|
7362
|
+
})]
|
|
7363
|
+
}) : null,
|
|
7364
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
7365
|
+
className: panel_module_css_default.filterField,
|
|
7366
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7367
|
+
className: panel_module_css_default.formLabel,
|
|
7368
|
+
children: tt("filter.invocation")
|
|
7369
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
7370
|
+
className: panel_module_css_default.select,
|
|
7371
|
+
value: hub.invocationFilter,
|
|
7372
|
+
onChange: (event) => {
|
|
7373
|
+
hub.setInvocationFilter(event.target.value);
|
|
7374
|
+
},
|
|
7375
|
+
children: [
|
|
7376
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7377
|
+
value: "all",
|
|
7378
|
+
children: tt("filter.invocationAll")
|
|
7379
|
+
}),
|
|
7380
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7381
|
+
value: "model",
|
|
7382
|
+
children: tt("filter.modelOnly")
|
|
7383
|
+
}),
|
|
7384
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7385
|
+
value: "user",
|
|
7386
|
+
children: tt("filter.userOnly")
|
|
7387
|
+
})
|
|
7388
|
+
]
|
|
7389
|
+
})]
|
|
7390
|
+
}),
|
|
7391
|
+
activeFilterCount > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7392
|
+
type: "button",
|
|
7393
|
+
className: panel_module_css_default.opBtn,
|
|
7394
|
+
onClick: () => {
|
|
7395
|
+
setSourceFilter("all");
|
|
7396
|
+
hub.setInvocationFilter("all");
|
|
7397
|
+
},
|
|
7398
|
+
children: tt("filter.clear")
|
|
7399
|
+
}) : null
|
|
7400
|
+
]
|
|
7401
|
+
}) : null,
|
|
7204
7402
|
catalog !== null && (filtered.length !== catalog.skills.length || hub.invocationFilter !== "all" || sourceFilter !== "all") ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7205
7403
|
className: panel_module_css_default.hintLine,
|
|
7206
7404
|
style: {
|
|
@@ -7305,130 +7503,37 @@ window.__ModuleLoader__.load({
|
|
|
7305
7503
|
}, entry.path))]
|
|
7306
7504
|
}) : null
|
|
7307
7505
|
] }) : null,
|
|
7308
|
-
|
|
7309
|
-
|
|
7506
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PanelDialogs, {
|
|
7507
|
+
conflictDialog,
|
|
7310
7508
|
tags: groupsState?.tags ?? [],
|
|
7311
7509
|
collections: groupsState?.collections ?? [],
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
setBranchChoice({
|
|
7340
|
-
...branchChoice,
|
|
7341
|
-
selected
|
|
7342
|
-
});
|
|
7343
|
-
},
|
|
7344
|
-
onCancel: () => {
|
|
7345
|
-
setBranchChoice(null);
|
|
7346
|
-
},
|
|
7347
|
-
onConfirm: () => {
|
|
7348
|
-
confirmBranchChoice();
|
|
7349
|
-
}
|
|
7350
|
-
}) : null,
|
|
7351
|
-
hub.versionDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionChoiceDialog, {
|
|
7352
|
-
choice: hub.versionDialog,
|
|
7353
|
-
busy: hub.versionBusy,
|
|
7354
|
-
onSelect: (selected) => {
|
|
7355
|
-
hub.setVersionDialog({
|
|
7356
|
-
...hub.versionDialog,
|
|
7357
|
-
selected
|
|
7358
|
-
});
|
|
7359
|
-
},
|
|
7360
|
-
onCustom: (custom) => {
|
|
7361
|
-
hub.setVersionDialog({
|
|
7362
|
-
...hub.versionDialog,
|
|
7363
|
-
custom
|
|
7364
|
-
});
|
|
7365
|
-
},
|
|
7366
|
-
onCancel: () => {
|
|
7367
|
-
hub.setVersionDialog(null);
|
|
7368
|
-
},
|
|
7369
|
-
onConfirm: () => {
|
|
7370
|
-
hub.confirmVersionDialog();
|
|
7371
|
-
}
|
|
7372
|
-
}) : null,
|
|
7373
|
-
marketSyncDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarketSyncDialog, {
|
|
7374
|
-
dialog: marketSyncDialog,
|
|
7375
|
-
busy: syncBusy,
|
|
7376
|
-
onToggle: (name, checked) => {
|
|
7377
|
-
const next = new Set(marketSyncDialog.selected);
|
|
7378
|
-
if (checked) next.add(name);
|
|
7379
|
-
else next.delete(name);
|
|
7380
|
-
setMarketSyncDialog({
|
|
7381
|
-
...marketSyncDialog,
|
|
7382
|
-
selected: next
|
|
7383
|
-
});
|
|
7384
|
-
},
|
|
7385
|
-
onCancel: () => {
|
|
7386
|
-
setMarketSyncDialog(null);
|
|
7387
|
-
},
|
|
7388
|
-
onConfirm: () => {
|
|
7389
|
-
confirmMarketSync();
|
|
7390
|
-
}
|
|
7391
|
-
}) : null,
|
|
7392
|
-
deleteSkillDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
|
|
7393
|
-
title: tt("delete.confirmTitle"),
|
|
7394
|
-
text: tt("delete.confirmText", { name: deleteSkillDialog }),
|
|
7395
|
-
confirmLabel: tt("delete.confirm"),
|
|
7396
|
-
danger: true,
|
|
7397
|
-
onCancel: () => {
|
|
7398
|
-
setDeleteSkillDialog(null);
|
|
7399
|
-
},
|
|
7400
|
-
onConfirm: () => {
|
|
7401
|
-
runDeleteSkill();
|
|
7402
|
-
}
|
|
7403
|
-
}) : null,
|
|
7404
|
-
deleteGroupDialog !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
|
|
7405
|
-
title: tt("source.deleteGroupTitle"),
|
|
7406
|
-
text: tt("source.deleteGroupText", {
|
|
7407
|
-
name: deleteGroupDialog.name,
|
|
7408
|
-
count: deleteGroupDialog.skillNames.length
|
|
7409
|
-
}),
|
|
7410
|
-
items: deleteGroupDialog.skillNames,
|
|
7411
|
-
confirmLabel: tt("source.deleteGroup"),
|
|
7412
|
-
danger: true,
|
|
7413
|
-
onCancel: () => {
|
|
7414
|
-
setDeleteGroupDialog(null);
|
|
7415
|
-
},
|
|
7416
|
-
onConfirm: () => {
|
|
7417
|
-
runDeleteGroup();
|
|
7418
|
-
}
|
|
7419
|
-
}) : null,
|
|
7420
|
-
confirmClearTrash ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmDialog, {
|
|
7421
|
-
title: tt("source.clearTrashConfirmTitle"),
|
|
7422
|
-
text: tt("source.clearTrashConfirmText"),
|
|
7423
|
-
confirmLabel: tt("source.clearTrashConfirm"),
|
|
7424
|
-
danger: true,
|
|
7425
|
-
onCancel: () => {
|
|
7426
|
-
setConfirmClearTrash(false);
|
|
7427
|
-
},
|
|
7428
|
-
onConfirm: () => {
|
|
7429
|
-
clearTrash();
|
|
7430
|
-
}
|
|
7431
|
-
}) : null
|
|
7510
|
+
setConflictDialog,
|
|
7511
|
+
resolveConflict,
|
|
7512
|
+
confirmDialog,
|
|
7513
|
+
setConfirmDialog,
|
|
7514
|
+
runConfirmed,
|
|
7515
|
+
branchChoice,
|
|
7516
|
+
branchBusy,
|
|
7517
|
+
setBranchChoice,
|
|
7518
|
+
confirmBranchChoice,
|
|
7519
|
+
versionDialog: hub.versionDialog,
|
|
7520
|
+
versionBusy: hub.versionBusy,
|
|
7521
|
+
setVersionDialog: hub.setVersionDialog,
|
|
7522
|
+
confirmVersionDialog: hub.confirmVersionDialog,
|
|
7523
|
+
marketSyncDialog,
|
|
7524
|
+
syncBusy,
|
|
7525
|
+
setMarketSyncDialog,
|
|
7526
|
+
confirmMarketSync,
|
|
7527
|
+
deleteSkillDialog,
|
|
7528
|
+
setDeleteSkillDialog,
|
|
7529
|
+
runDeleteSkill,
|
|
7530
|
+
deleteGroupDialog,
|
|
7531
|
+
setDeleteGroupDialog,
|
|
7532
|
+
runDeleteGroup,
|
|
7533
|
+
confirmClearTrash,
|
|
7534
|
+
setConfirmClearTrash,
|
|
7535
|
+
clearTrash
|
|
7536
|
+
})
|
|
7432
7537
|
]
|
|
7433
7538
|
});
|
|
7434
7539
|
}
|