dshmarket 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/client.js +555 -73
- package/client/client.js.map +1 -1
- package/data/registry-snapshot.json +9180 -3442
- package/lib/backup.js +309 -0
- package/lib/dsh-cli.js +52 -9
- package/lib/http.js +2 -2
- package/lib/routes.js +164 -1
- package/lib/types/backup.d.ts +57 -0
- package/lib/types/dsh-cli.d.ts +12 -0
- package/lib/types/http.d.ts +1 -1
- package/package.json +1 -1
- package/src/backup.ts +311 -0
- package/src/client/Market.module.css +16 -0
- package/src/client/MarketSection.tsx +235 -9
- package/src/client/locales.ts +50 -0
- package/src/client/market-data.ts +107 -0
- package/src/dsh-cli.ts +60 -10
- package/src/http.ts +2 -2
- package/src/routes.ts +161 -1
package/client/client.js
CHANGED
|
@@ -90,6 +90,31 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
90
90
|
marketUpdate: "市场有新版本,升级",
|
|
91
91
|
updateAll: "全部更新",
|
|
92
92
|
tabThemes: "主题",
|
|
93
|
+
tabBackup: "备份与恢复",
|
|
94
|
+
backupLocal: "本地文件",
|
|
95
|
+
backupDownload: "导出备份",
|
|
96
|
+
backupImport: "导入并预览",
|
|
97
|
+
backupHint: "仅包含插件清单和 profile 配置,不包含 node_modules;恢复会按清单重新安装插件。",
|
|
98
|
+
webdav: "WebDAV",
|
|
99
|
+
webdavPreset: "服务商预设",
|
|
100
|
+
webdavUrl: "备份文件 URL",
|
|
101
|
+
webdavUser: "用户名(可选)",
|
|
102
|
+
webdavPassword: "密码(可选)",
|
|
103
|
+
webdavUpload: "上传备份",
|
|
104
|
+
webdavRestore: "从 WebDAV 恢复",
|
|
105
|
+
autoBackup: "每天自动备份(打开市场时)",
|
|
106
|
+
webdavNote: "WebDAV 地址与用户名仅保存在当前浏览器;密码只存于服务端,每次会话需重新输入。",
|
|
107
|
+
localOnly: "WebDAV 地址和凭证仅保存在当前浏览器。",
|
|
108
|
+
credsWarning: "注意:备份包含配置与可能含密钥的文件(config.toml、.env 等)。下载件会原样导出,上传 WebDAV 前请确认目标可信。",
|
|
109
|
+
backupWorking: "处理中…",
|
|
110
|
+
backupDone: "备份已上传",
|
|
111
|
+
restoreDone: "恢复完成,请重启 DeepSeek Harness",
|
|
112
|
+
restorePartial: "恢复已继续完成,但以下插件安装失败:",
|
|
113
|
+
restoreConfirm: "恢复将覆盖当前 profile 配置并重新安装插件,确定继续吗?",
|
|
114
|
+
restorePreviewDone: "备份已导入,请在“已安装”中确认后开始恢复",
|
|
115
|
+
restoreMissing: "备份中有 {0} 个插件尚未安装",
|
|
116
|
+
restoreStart: "开始恢复",
|
|
117
|
+
notInstalled: "未安装",
|
|
93
118
|
themeApply: "使用",
|
|
94
119
|
themeActive: "使用中",
|
|
95
120
|
themeEmpty: "目录里暂时还没有主题,敬请期待",
|
|
@@ -192,6 +217,31 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
192
217
|
marketUpdate: "Market update available — upgrade",
|
|
193
218
|
updateAll: "Update all",
|
|
194
219
|
tabThemes: "Themes",
|
|
220
|
+
tabBackup: "Backup & Restore",
|
|
221
|
+
backupLocal: "Local file",
|
|
222
|
+
backupDownload: "Export backup",
|
|
223
|
+
backupImport: "Import and preview",
|
|
224
|
+
backupHint: "Includes the plugin list and profile configuration, never node_modules. Restore reinstalls plugins from the list.",
|
|
225
|
+
webdav: "WebDAV",
|
|
226
|
+
webdavPreset: "Provider preset",
|
|
227
|
+
webdavUrl: "Backup file URL",
|
|
228
|
+
webdavUser: "Username (optional)",
|
|
229
|
+
webdavPassword: "Password (optional)",
|
|
230
|
+
webdavUpload: "Upload backup",
|
|
231
|
+
webdavRestore: "Restore from WebDAV",
|
|
232
|
+
autoBackup: "Back up daily (when the market opens)",
|
|
233
|
+
webdavNote: "The WebDAV URL and username stay in this browser only; the password is kept server-side and must be re-entered each session.",
|
|
234
|
+
localOnly: "The WebDAV URL and credentials stay in this browser only.",
|
|
235
|
+
credsWarning: "Heads up: backups include profile configuration and files that may hold secrets (config.toml, .env, …). Local exports are unmodified, so only upload to a WebDAV target you trust.",
|
|
236
|
+
backupWorking: "Working…",
|
|
237
|
+
backupDone: "Backup uploaded",
|
|
238
|
+
restoreDone: "Restore complete — restart DeepSeek Harness",
|
|
239
|
+
restorePartial: "Restore continued, but these plugins failed to install:",
|
|
240
|
+
restoreConfirm: "Restore will overwrite this profile configuration and reinstall plugins. Continue?",
|
|
241
|
+
restorePreviewDone: "Backup imported. Review Installed, then start restore.",
|
|
242
|
+
restoreMissing: "{0} plugins from this backup are not installed",
|
|
243
|
+
restoreStart: "Start restore",
|
|
244
|
+
notInstalled: "Not installed",
|
|
195
245
|
themeApply: "Use",
|
|
196
246
|
themeActive: "Active",
|
|
197
247
|
themeEmpty: "No more theme plugins in the catalog yet — stay tuned",
|
|
@@ -404,6 +454,97 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
404
454
|
pick(["--dsw-alias-label-primary"]) || (dark ? "#e5e7eb" : "#1f2328")
|
|
405
455
|
];
|
|
406
456
|
}
|
|
457
|
+
/**
|
|
458
|
+
* Image hosts screenshots may load from (#61) — GitHub's own hosting only.
|
|
459
|
+
* Any other host is dropped BEFORE an <img> is created: a screenshot URL is
|
|
460
|
+
* a request carrying the user's IP, so registry data and README content are
|
|
461
|
+
* both treated as untrusted here, matching the upstream build gate.
|
|
462
|
+
*/
|
|
463
|
+
const SCREENSHOT_HOSTS = /* @__PURE__ */ new Set([
|
|
464
|
+
"raw.githubusercontent.com",
|
|
465
|
+
"user-images.githubusercontent.com",
|
|
466
|
+
"camo.githubusercontent.com",
|
|
467
|
+
"github.com"
|
|
468
|
+
]);
|
|
469
|
+
const MAX_SCREENSHOTS = 6;
|
|
470
|
+
/** Keep only https URLs on allowlisted image hosts; SVG dropped (logos/badges). */
|
|
471
|
+
function safeScreenshots(urls) {
|
|
472
|
+
if (!Array.isArray(urls)) return [];
|
|
473
|
+
const safe = [];
|
|
474
|
+
for (const value of urls) {
|
|
475
|
+
if (typeof value !== "string") continue;
|
|
476
|
+
let parsed = null;
|
|
477
|
+
try {
|
|
478
|
+
parsed = new URL(value);
|
|
479
|
+
} catch {
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
if (parsed.protocol !== "https:" || !SCREENSHOT_HOSTS.has(parsed.hostname)) continue;
|
|
483
|
+
if (/\.svg$/i.test(parsed.pathname)) continue;
|
|
484
|
+
if (!safe.includes(value)) safe.push(value);
|
|
485
|
+
if (safe.length >= MAX_SCREENSHOTS) break;
|
|
486
|
+
}
|
|
487
|
+
return safe;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Image URLs extracted from a repo README, in document order — the fallback
|
|
491
|
+
* when an entry has no curated screenshots (#61). Markdown and <img> forms;
|
|
492
|
+
* relative paths resolve against the README's directory on
|
|
493
|
+
* raw.githubusercontent.com; badges fall out naturally (shields.io etc. are
|
|
494
|
+
* not allowlisted) and SVG is skipped as logo/badge noise.
|
|
495
|
+
*/
|
|
496
|
+
function extractReadmeImages(markdown, owner, repo, subpath) {
|
|
497
|
+
const base = `https://raw.githubusercontent.com/${owner}/${repo}/HEAD/${subpath === null ? "" : subpath + "/"}`;
|
|
498
|
+
const found = [];
|
|
499
|
+
const push = (raw) => {
|
|
500
|
+
const src = raw.trim().replace(/^<|>$/g, "");
|
|
501
|
+
if (src === "" || src.startsWith("data:")) return;
|
|
502
|
+
let absolute;
|
|
503
|
+
if (/^https?:\/\//i.test(src)) absolute = src;
|
|
504
|
+
else if (src.startsWith("/")) absolute = `https://raw.githubusercontent.com/${owner}/${repo}/HEAD${src}`;
|
|
505
|
+
else try {
|
|
506
|
+
absolute = new URL(src, base).href;
|
|
507
|
+
} catch {
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
found.push(absolute);
|
|
511
|
+
};
|
|
512
|
+
for (const m of markdown.matchAll(/!\[[^\]]*\]\(\s*([^)\s]+)(?:\s+"[^"]*")?\s*\)|<img[^>]*\ssrc=["']([^"']+)["']/gi)) push(m[1] ?? m[2]);
|
|
513
|
+
return safeScreenshots(found);
|
|
514
|
+
}
|
|
515
|
+
const readmeShotsCache = /* @__PURE__ */ new Map();
|
|
516
|
+
/**
|
|
517
|
+
* Screenshots for a plugin: the registry's curated list when present,
|
|
518
|
+
* otherwise lazily extracted from the repo README. Only ever called AFTER
|
|
519
|
+
* the user opens the detail dialog — browsing the list must make zero
|
|
520
|
+
* external requests. Failures resolve to [] (silent degradation).
|
|
521
|
+
*/
|
|
522
|
+
function pluginScreenshots(plugin) {
|
|
523
|
+
const curated = safeScreenshots(plugin.screenshots);
|
|
524
|
+
if (curated.length > 0) return Promise.resolve(curated);
|
|
525
|
+
const m = /^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\/tree\/[^/]+\/(.+?))?\/?$/.exec(plugin.url);
|
|
526
|
+
if (m === null) return Promise.resolve([]);
|
|
527
|
+
const [, owner, repo, subpath = null] = m;
|
|
528
|
+
const cacheKey = plugin.url;
|
|
529
|
+
const cached = readmeShotsCache.get(cacheKey);
|
|
530
|
+
if (cached !== void 0) return cached;
|
|
531
|
+
const fetchReadme = async (path) => {
|
|
532
|
+
try {
|
|
533
|
+
const res = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/${path === null ? "" : path + "/"}README.md`);
|
|
534
|
+
return res.ok ? await res.text() : null;
|
|
535
|
+
} catch {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
const task = (async () => {
|
|
540
|
+
const sub = subpath === null ? null : await fetchReadme(subpath);
|
|
541
|
+
if (sub !== null) return extractReadmeImages(sub, owner, repo, subpath);
|
|
542
|
+
const root = await fetchReadme(null);
|
|
543
|
+
return root === null ? [] : extractReadmeImages(root, owner, repo, null);
|
|
544
|
+
})().catch(() => []);
|
|
545
|
+
readmeShotsCache.set(cacheKey, task);
|
|
546
|
+
return task;
|
|
547
|
+
}
|
|
407
548
|
//#endregion
|
|
408
549
|
//#region src/client/InstallToast.tsx
|
|
409
550
|
/**
|
|
@@ -432,7 +573,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
432
573
|
}
|
|
433
574
|
//#endregion
|
|
434
575
|
//#region \0dsh-css:/home/runner/work/dsh-market/dsh-market/src/client/Market.module.css.mjs
|
|
435
|
-
const css = ".eGUBIq_root{min-width:0;height:100%;color:var(--dsw-alias-label-primary,#1f2328);flex-direction:column;display:flex;position:relative}.eGUBIq_head{flex-direction:column;gap:12px;padding:4px 4px 12px;display:flex}.eGUBIq_title{margin:0;font-size:16px;font-weight:500;line-height:24px}.eGUBIq_sub{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:0;font-size:14px;line-height:22px}.eGUBIq_searchInline{flex-shrink:0;width:200px;margin-bottom:6px}.eGUBIq_tabs{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-end;gap:2px;display:flex}.eGUBIq_tab{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;padding:7px 12px;font-size:13px}.eGUBIq_tab.eGUBIq_on{color:var(--dsw-alias-brand-primary,#4f6ef7);border-bottom-color:var(--dsw-alias-brand-primary,#4f6ef7);font-weight:600}.eGUBIq_restart{background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;align-items:center;gap:8px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_body{flex:1;padding:12px 4px 24px;overflow-x:hidden;overflow-y:auto}.eGUBIq_cats{z-index:5;background:var(--dsw-alias-bg-layer-2,#f7f8fa);margin:-12px -4px 2px;padding:12px 4px 4px;position:sticky;top:-13px}.eGUBIq_catsRow{align-items:flex-start;gap:8px;display:flex;position:relative}.eGUBIq_filterWrap{flex-shrink:0;position:relative}.eGUBIq_filterBtn{border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font:inherit;cursor:pointer;white-space:nowrap;border-radius:8px;align-items:center;gap:5px;padding:5px 11px;font-size:12px;line-height:18px;display:flex}.eGUBIq_filterBtn:hover,.eGUBIq_filterBtnOn{color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_filterPanel{z-index:30;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:10px;flex-direction:column;gap:10px;width:250px;padding:8px;display:flex;position:absolute;top:calc(100% + 6px);right:0;box-shadow:0 8px 28px #00000024}.eGUBIq_filterGroup{flex-direction:column;gap:2px;display:flex}.eGUBIq_filterTitle{color:var(--dsw-alias-label-secondary,#6b7280);padding:4px 8px 2px;font-size:11px;font-weight:600}.eGUBIq_filterOption{cursor:pointer;color:var(--dsw-alias-label-primary,#1f2328);border-radius:6px;align-items:center;gap:8px;padding:5px 8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_filterOption:hover{background:var(--dsw-alias-bg-layer-2,#f3f4f6)}.eGUBIq_filterOption input{margin:0}.eGUBIq_star{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_top{z-index:20;border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);width:38px;height:38px;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;border-radius:99px;font-size:16px;position:absolute;bottom:18px;right:18px;box-shadow:0 4px 14px #0000001f}.eGUBIq_top:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_tag{border:1px solid var(--dsw-alias-border-l3,#d9dde3);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:4px;flex-shrink:0;padding:1px 6px;font-size:11px;line-height:16px}.eGUBIq_okState{color:var(--dsw-alias-state-success-primary,#16a34a);white-space:nowrap;font-size:12px;font-weight:600}.eGUBIq_dangerBtn.eGUBIq_dangerBtn{border-color:var(--dsw-alias-state-error-primary,#dc2626);color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_dangerArmed.eGUBIq_dangerArmed{background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_warnBtn.eGUBIq_warnBtn{background:var(--dsw-alias-state-warn-primary,#ea580c);color:#fff}.eGUBIq_catsWrap{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_catsCollapsed{max-height:62px;overflow:hidden}.eGUBIq_catsToggle.eGUBIq_catsToggle{height:26px;min-height:26px;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_cmdDetails{margin:0}.eGUBIq_cmdSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.eGUBIq_cmdSummary::-webkit-details-marker{display:none}.eGUBIq_cmdSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.eGUBIq_cmdDetails[open]>.eGUBIq_cmdSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.eGUBIq_cmdSummary:hover{color:var(--dsw-alias-label-primary,#1f2328)}.eGUBIq_cmd{background:var(--dsw-alias-bg-layer-2,#f3f4f6);word-break:break-all;border-radius:6px;margin:8px 0 0;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:18px}.eGUBIq_warnLine{color:var(--dsw-alias-state-warn-primary,#b45309);margin:0;font-size:12px;font-weight:600;line-height:18px}.eGUBIq_modalNote{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:12px 0 0;font-size:12px;line-height:18px}.eGUBIq_grid{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;display:grid}.eGUBIq_sect{color:var(--dsw-alias-label-secondary,#6b7280);margin:14px 2px 8px;font-size:12px;font-weight:600}.eGUBIq_sect:first-child{margin-top:2px}.eGUBIq_swatches{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;gap:0;height:34px;display:flex;overflow:hidden}.eGUBIq_themesGrid{margin-bottom:12px}.eGUBIq_swatches i{flex:1}.eGUBIq_card{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.eGUBIq_row1{align-items:center;gap:10px;min-width:0;display:flex}.eGUBIq_av{color:#fff;object-fit:cover;background:var(--dsw-alias-bg-layer-2,#f3f4f6);border-radius:8px;flex-shrink:0;place-items:center;width:32px;height:32px;font-size:14px;font-weight:700;display:grid}.eGUBIq_nm{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:500;line-height:22px;overflow:hidden}.eGUBIq_owner{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_desc{color:var(--dsw-alias-label-tertiary,#8b93a1);min-height:36px;margin:0;font-size:12px;line-height:18px}.eGUBIq_foot{align-items:center;gap:8px;margin-top:auto;display:flex}.eGUBIq_grow{flex:1}.eGUBIq_titleRow{align-items:center;gap:10px;display:flex}.eGUBIq_descTight{min-height:0}.eGUBIq_src{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px;text-decoration:none}.eGUBIq_src:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_dot{vertical-align:2px;margin-left:5px}.eGUBIq_act{flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px;font-size:11px;display:flex}.eGUBIq_actLive{color:var(--dsw-alias-state-success-primary,#16a34a);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWarn{color:var(--dsw-alias-state-warn-primary,#b45309);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actBroken{color:var(--dsw-alias-state-error-primary,#dc2626);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWhy{margin:0}.eGUBIq_actWhy summary{cursor:pointer;color:var(--dsw-alias-label-secondary,#6b7280);font-size:11px}.eGUBIq_loading{color:var(--dsw-alias-label-secondary,#9ca3af);flex-direction:column;align-items:center;gap:12px;padding:48px;font-size:13px;display:flex}.eGUBIq_spin{border:3px solid var(--dsw-alias-border-l1,#e5e7eb);border-top-color:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;width:22px;height:22px;animation:.8s linear infinite eGUBIq_sp}@keyframes eGUBIq_sp{to{transform:rotate(360deg)}}.eGUBIq_progress{background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:8px;flex-wrap:wrap;align-items:center;gap:9px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_bar{background:var(--dsw-alias-border-l1,#e5e7eb);border-radius:99px;width:100%;height:4px;overflow:hidden}.eGUBIq_barFill{background:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;height:100%;transition:width .6s}.eGUBIq_barWave{width:30%;animation:1.2s ease-in-out infinite eGUBIq_dshmSlide}@keyframes eGUBIq_dshmSlide{0%{margin-left:-30%}to{margin-left:100%}}.eGUBIq_irow .eGUBIq_progress{margin-top:8px}.eGUBIq_progress .eGUBIq_spin{border-width:2px;flex-shrink:0;width:14px;height:14px}.eGUBIq_progress code{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_empty{color:var(--dsw-alias-label-secondary,#9ca3af);text-align:center;padding:32px;font-size:13px}.eGUBIq_err{color:var(--dsw-alias-state-error-primary,#dc2626);white-space:pre-wrap;word-break:break-all;margin:8px 0;font-size:12px}.eGUBIq_irow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;align-items:center;gap:10px;margin-bottom:8px;padding:12px 14px;display:flex}.eGUBIq_irow>.eGUBIq_src,.eGUBIq_irow>.eGUBIq_owner,.eGUBIq_dangerBtn.eGUBIq_dangerBtn,.eGUBIq_warnBtn.eGUBIq_warnBtn,.eGUBIq_dangerArmed.eGUBIq_dangerArmed{white-space:nowrap;flex-shrink:0}.eGUBIq_spec{color:var(--dsw-alias-label-secondary,#9ca3af);font-family:ui-monospace,Menlo,monospace;font-size:11px}.eGUBIq_staleAction{margin-top:8px}.eGUBIq_pct{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;font-size:11px;font-weight:600}.eGUBIq_cancelBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;white-space:nowrap;border-radius:6px;flex-shrink:0;padding:2px 10px;font-size:11px;line-height:16px}.eGUBIq_cancelBtn:hover{color:var(--dsw-alias-state-error-primary,#dc2626);border-color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_pager{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:16px 0 4px;display:flex}.eGUBIq_pagerPages{flex-wrap:wrap;flex:1;justify-content:center;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_pagerSize{flex-shrink:0;align-items:center;gap:4px;display:flex}.eGUBIq_sizeLabel{color:var(--dsw-alias-label-secondary,#6b7280);font-size:12px}.eGUBIq_sizeBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;border-radius:6px;padding:3px 8px;font-size:12px;line-height:18px}.eGUBIq_sizeBtn:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_sizeOn{background:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;font-weight:600}.eGUBIq_pageBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;border-radius:6px;min-width:28px;padding:4px 10px;font-size:12px;line-height:18px}.eGUBIq_pageBtn:hover:not(:disabled){color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_pageBtn:disabled{opacity:.45;cursor:default}.eGUBIq_pageOn{background:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;font-weight:600}.eGUBIq_pageEllipsis{color:var(--dsw-alias-label-secondary,#9ca3af);padding:0 2px;font-size:12px}.eGUBIq_pageInfo{color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;font-size:12px}";
|
|
576
|
+
const css = ".eGUBIq_root{min-width:0;height:100%;color:var(--dsw-alias-label-primary,#1f2328);flex-direction:column;display:flex;position:relative}.eGUBIq_head{flex-direction:column;gap:12px;padding:4px 4px 12px;display:flex}.eGUBIq_title{margin:0;font-size:16px;font-weight:500;line-height:24px}.eGUBIq_sub{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:0;font-size:14px;line-height:22px}.eGUBIq_searchInline{flex-shrink:0;width:200px;margin-bottom:6px}.eGUBIq_tabs{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-end;gap:2px;display:flex}.eGUBIq_tab{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;padding:7px 12px;font-size:13px}.eGUBIq_tab.eGUBIq_on{color:var(--dsw-alias-brand-primary,#4f6ef7);border-bottom-color:var(--dsw-alias-brand-primary,#4f6ef7);font-weight:600}.eGUBIq_restart{background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;align-items:center;gap:8px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_body{flex:1;padding:12px 4px 24px;overflow-x:hidden;overflow-y:auto}.eGUBIq_cats{z-index:5;background:var(--dsw-alias-bg-layer-2,#f7f8fa);margin:-12px -4px 2px;padding:12px 4px 4px;position:sticky;top:-13px}.eGUBIq_catsRow{align-items:flex-start;gap:8px;display:flex;position:relative}.eGUBIq_filterWrap{flex-shrink:0;position:relative}.eGUBIq_filterBtn{border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font:inherit;cursor:pointer;white-space:nowrap;border-radius:8px;align-items:center;gap:5px;padding:5px 11px;font-size:12px;line-height:18px;display:flex}.eGUBIq_filterBtn:hover,.eGUBIq_filterBtnOn{color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_filterPanel{z-index:30;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:10px;flex-direction:column;gap:10px;width:250px;padding:8px;display:flex;position:absolute;top:calc(100% + 6px);right:0;box-shadow:0 8px 28px #00000024}.eGUBIq_filterGroup{flex-direction:column;gap:2px;display:flex}.eGUBIq_filterTitle{color:var(--dsw-alias-label-secondary,#6b7280);padding:4px 8px 2px;font-size:11px;font-weight:600}.eGUBIq_filterOption{cursor:pointer;color:var(--dsw-alias-label-primary,#1f2328);border-radius:6px;align-items:center;gap:8px;padding:5px 8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_filterOption:hover{background:var(--dsw-alias-bg-layer-2,#f3f4f6)}.eGUBIq_filterOption input{margin:0}.eGUBIq_star{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_top{z-index:20;border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);width:38px;height:38px;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;border-radius:99px;font-size:16px;position:absolute;bottom:18px;right:18px;box-shadow:0 4px 14px #0000001f}.eGUBIq_top:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_tag{border:1px solid var(--dsw-alias-border-l3,#d9dde3);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:4px;flex-shrink:0;padding:1px 6px;font-size:11px;line-height:16px}.eGUBIq_okState{color:var(--dsw-alias-state-success-primary,#16a34a);white-space:nowrap;font-size:12px;font-weight:600}.eGUBIq_dangerBtn.eGUBIq_dangerBtn{border-color:var(--dsw-alias-state-error-primary,#dc2626);color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_dangerArmed.eGUBIq_dangerArmed{background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_warnBtn.eGUBIq_warnBtn{background:var(--dsw-alias-state-warn-primary,#ea580c);color:#fff}.eGUBIq_catsWrap{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_catsCollapsed{max-height:62px;overflow:hidden}.eGUBIq_catsToggle.eGUBIq_catsToggle{height:26px;min-height:26px;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_shots{-webkit-overflow-scrolling:touch;scrollbar-width:thin;gap:8px;margin:0 0 8px;padding:2px 0 6px;display:flex;overflow-x:auto}.eGUBIq_shot{object-fit:cover;border:1px solid var(--dsw-alias-border-default,#e5e7eb);background:var(--dsw-alias-bg-layer-2,#f3f4f6);border-radius:8px;flex:none;max-width:260px;height:150px}.eGUBIq_cmdDetails{margin:0}.eGUBIq_cmdSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.eGUBIq_cmdSummary::-webkit-details-marker{display:none}.eGUBIq_cmdSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.eGUBIq_cmdDetails[open]>.eGUBIq_cmdSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.eGUBIq_cmdSummary:hover{color:var(--dsw-alias-label-primary,#1f2328)}.eGUBIq_cmd{background:var(--dsw-alias-bg-layer-2,#f3f4f6);word-break:break-all;border-radius:6px;margin:8px 0 0;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:18px}.eGUBIq_warnLine{color:var(--dsw-alias-state-warn-primary,#b45309);margin:0;font-size:12px;font-weight:600;line-height:18px}.eGUBIq_modalNote{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:12px 0 0;font-size:12px;line-height:18px}.eGUBIq_grid{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;display:grid}.eGUBIq_sect{color:var(--dsw-alias-label-secondary,#6b7280);margin:14px 2px 8px;font-size:12px;font-weight:600}.eGUBIq_sect:first-child{margin-top:2px}.eGUBIq_swatches{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;gap:0;height:34px;display:flex;overflow:hidden}.eGUBIq_themesGrid{margin-bottom:12px}.eGUBIq_swatches i{flex:1}.eGUBIq_card{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.eGUBIq_row1{align-items:center;gap:10px;min-width:0;display:flex}.eGUBIq_av{color:#fff;object-fit:cover;background:var(--dsw-alias-bg-layer-2,#f3f4f6);border-radius:8px;flex-shrink:0;place-items:center;width:32px;height:32px;font-size:14px;font-weight:700;display:grid}.eGUBIq_nm{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:500;line-height:22px;overflow:hidden}.eGUBIq_owner{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_desc{color:var(--dsw-alias-label-tertiary,#8b93a1);min-height:36px;margin:0;font-size:12px;line-height:18px}.eGUBIq_foot{align-items:center;gap:8px;margin-top:auto;display:flex}.eGUBIq_grow{flex:1}.eGUBIq_titleRow{align-items:center;gap:10px;display:flex}.eGUBIq_descTight{min-height:0}.eGUBIq_src{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px;text-decoration:none}.eGUBIq_src:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_dot{vertical-align:2px;margin-left:5px}.eGUBIq_act{flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px;font-size:11px;display:flex}.eGUBIq_actLive{color:var(--dsw-alias-state-success-primary,#16a34a);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWarn{color:var(--dsw-alias-state-warn-primary,#b45309);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actBroken{color:var(--dsw-alias-state-error-primary,#dc2626);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWhy{margin:0}.eGUBIq_actWhy summary{cursor:pointer;color:var(--dsw-alias-label-secondary,#6b7280);font-size:11px}.eGUBIq_loading{color:var(--dsw-alias-label-secondary,#9ca3af);flex-direction:column;align-items:center;gap:12px;padding:48px;font-size:13px;display:flex}.eGUBIq_spin{border:3px solid var(--dsw-alias-border-l1,#e5e7eb);border-top-color:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;width:22px;height:22px;animation:.8s linear infinite eGUBIq_sp}@keyframes eGUBIq_sp{to{transform:rotate(360deg)}}.eGUBIq_progress{background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:8px;flex-wrap:wrap;align-items:center;gap:9px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_bar{background:var(--dsw-alias-border-l1,#e5e7eb);border-radius:99px;width:100%;height:4px;overflow:hidden}.eGUBIq_barFill{background:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;height:100%;transition:width .6s}.eGUBIq_barWave{width:30%;animation:1.2s ease-in-out infinite eGUBIq_dshmSlide}@keyframes eGUBIq_dshmSlide{0%{margin-left:-30%}to{margin-left:100%}}.eGUBIq_irow .eGUBIq_progress{margin-top:8px}.eGUBIq_progress .eGUBIq_spin{border-width:2px;flex-shrink:0;width:14px;height:14px}.eGUBIq_progress code{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_empty{color:var(--dsw-alias-label-secondary,#9ca3af);text-align:center;padding:32px;font-size:13px}.eGUBIq_err{color:var(--dsw-alias-state-error-primary,#dc2626);white-space:pre-wrap;word-break:break-all;margin:8px 0;font-size:12px}.eGUBIq_irow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;align-items:center;gap:10px;margin-bottom:8px;padding:12px 14px;display:flex}.eGUBIq_irowMissing{filter:grayscale();opacity:.5}.eGUBIq_irow>.eGUBIq_src,.eGUBIq_irow>.eGUBIq_owner,.eGUBIq_dangerBtn.eGUBIq_dangerBtn,.eGUBIq_warnBtn.eGUBIq_warnBtn,.eGUBIq_dangerArmed.eGUBIq_dangerArmed{white-space:nowrap;flex-shrink:0}.eGUBIq_spec{color:var(--dsw-alias-label-secondary,#9ca3af);font-family:ui-monospace,Menlo,monospace;font-size:11px}.eGUBIq_staleAction{margin-top:8px}.eGUBIq_pct{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;font-size:11px;font-weight:600}.eGUBIq_cancelBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;white-space:nowrap;border-radius:6px;flex-shrink:0;padding:2px 10px;font-size:11px;line-height:16px}.eGUBIq_cancelBtn:hover{color:var(--dsw-alias-state-error-primary,#dc2626);border-color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_pager{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:16px 0 4px;display:flex}.eGUBIq_pagerPages{flex-wrap:wrap;flex:1;justify-content:center;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_pagerSize{flex-shrink:0;align-items:center;gap:4px;display:flex}.eGUBIq_sizeLabel{color:var(--dsw-alias-label-secondary,#6b7280);font-size:12px}.eGUBIq_sizeBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;border-radius:6px;padding:3px 8px;font-size:12px;line-height:18px}.eGUBIq_sizeBtn:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_sizeOn{background:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;font-weight:600}.eGUBIq_pageBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;border-radius:6px;min-width:28px;padding:4px 10px;font-size:12px;line-height:18px}.eGUBIq_pageBtn:hover:not(:disabled){color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_pageBtn:disabled{opacity:.45;cursor:default}.eGUBIq_pageOn{background:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;font-weight:600}.eGUBIq_pageEllipsis{color:var(--dsw-alias-label-secondary,#9ca3af);padding:0 2px;font-size:12px}.eGUBIq_pageInfo{color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;font-size:12px}.eGUBIq_backupGrid{grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px;display:grid}.eGUBIq_backupCard{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:10px;padding:16px;display:flex}.eGUBIq_backupCard h3{margin:0;font-size:14px}.eGUBIq_backupCard p{color:var(--dsw-alias-label-secondary,#6b7280);margin:0;font-size:12px;line-height:18px}.eGUBIq_backupActions{flex-wrap:wrap;gap:8px;display:flex}.eGUBIq_backupButton{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);color:var(--dsw-alias-label-primary,#1f2328);cursor:pointer;border-radius:6px;align-items:center;padding:4px 10px;font-size:12px;line-height:18px;text-decoration:none;display:inline-flex;position:relative}.eGUBIq_backupButton[aria-disabled=true]{opacity:.5;pointer-events:none}.eGUBIq_backupButton input{opacity:0;width:1px;height:1px;position:absolute}.eGUBIq_backupPrimary{background:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff}.eGUBIq_backupInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);width:100%;color:var(--dsw-alias-label-primary,#1f2328);font:inherit;border-radius:8px;padding:7px 9px;font-size:12px}.eGUBIq_backupCheck{cursor:pointer;align-items:center;gap:6px;font-size:12px;display:flex}.eGUBIq_backupWarn{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-state-warn-primary,#b45309)!important}.eGUBIq_backupMessage{color:var(--dsw-alias-label-secondary,#6b7280);grid-column:1/-1;font-size:12px}";
|
|
436
577
|
const tagId = "dshmarket/Market.module.css";
|
|
437
578
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
438
579
|
const tag = document.createElement("style");
|
|
@@ -442,86 +583,98 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
442
583
|
document.head.appendChild(tag);
|
|
443
584
|
}
|
|
444
585
|
var Market_module_css_default = {
|
|
445
|
-
"swatches": "eGUBIq_swatches",
|
|
446
|
-
"body": "eGUBIq_body",
|
|
447
|
-
"okState": "eGUBIq_okState",
|
|
448
|
-
"empty": "eGUBIq_empty",
|
|
449
|
-
"desc": "eGUBIq_desc",
|
|
450
|
-
"modalNote": "eGUBIq_modalNote",
|
|
451
|
-
"dangerArmed": "eGUBIq_dangerArmed",
|
|
452
|
-
"sizeOn": "eGUBIq_sizeOn",
|
|
453
|
-
"filterTitle": "eGUBIq_filterTitle",
|
|
454
|
-
"warnLine": "eGUBIq_warnLine",
|
|
455
586
|
"actLive": "eGUBIq_actLive",
|
|
456
|
-
"
|
|
587
|
+
"okState": "eGUBIq_okState",
|
|
588
|
+
"filterWrap": "eGUBIq_filterWrap",
|
|
457
589
|
"foot": "eGUBIq_foot",
|
|
458
|
-
"
|
|
459
|
-
"
|
|
460
|
-
"
|
|
461
|
-
"
|
|
462
|
-
"
|
|
463
|
-
"
|
|
464
|
-
"
|
|
590
|
+
"tab": "eGUBIq_tab",
|
|
591
|
+
"tabs": "eGUBIq_tabs",
|
|
592
|
+
"loading": "eGUBIq_loading",
|
|
593
|
+
"barFill": "eGUBIq_barFill",
|
|
594
|
+
"searchInline": "eGUBIq_searchInline",
|
|
595
|
+
"pageBtn": "eGUBIq_pageBtn",
|
|
596
|
+
"sub": "eGUBIq_sub",
|
|
465
597
|
"tag": "eGUBIq_tag",
|
|
598
|
+
"backupGrid": "eGUBIq_backupGrid",
|
|
599
|
+
"dangerBtn": "eGUBIq_dangerBtn",
|
|
600
|
+
"barWave": "eGUBIq_barWave",
|
|
601
|
+
"pct": "eGUBIq_pct",
|
|
602
|
+
"filterPanel": "eGUBIq_filterPanel",
|
|
603
|
+
"filterTitle": "eGUBIq_filterTitle",
|
|
604
|
+
"desc": "eGUBIq_desc",
|
|
605
|
+
"actWarn": "eGUBIq_actWarn",
|
|
606
|
+
"sizeLabel": "eGUBIq_sizeLabel",
|
|
607
|
+
"sp": "eGUBIq_sp",
|
|
608
|
+
"sizeBtn": "eGUBIq_sizeBtn",
|
|
609
|
+
"backupCard": "eGUBIq_backupCard",
|
|
466
610
|
"head": "eGUBIq_head",
|
|
467
|
-
"
|
|
468
|
-
"
|
|
611
|
+
"src": "eGUBIq_src",
|
|
612
|
+
"empty": "eGUBIq_empty",
|
|
613
|
+
"on": "eGUBIq_on",
|
|
614
|
+
"av": "eGUBIq_av",
|
|
615
|
+
"pager": "eGUBIq_pager",
|
|
616
|
+
"backupButton": "eGUBIq_backupButton",
|
|
617
|
+
"backupInput": "eGUBIq_backupInput",
|
|
618
|
+
"swatches": "eGUBIq_swatches",
|
|
619
|
+
"sect": "eGUBIq_sect",
|
|
469
620
|
"filterBtn": "eGUBIq_filterBtn",
|
|
470
621
|
"catsWrap": "eGUBIq_catsWrap",
|
|
471
|
-
"
|
|
622
|
+
"root": "eGUBIq_root",
|
|
623
|
+
"top": "eGUBIq_top",
|
|
472
624
|
"title": "eGUBIq_title",
|
|
473
|
-
"
|
|
474
|
-
"nm": "eGUBIq_nm",
|
|
475
|
-
"pager": "eGUBIq_pager",
|
|
625
|
+
"backupCheck": "eGUBIq_backupCheck",
|
|
476
626
|
"irow": "eGUBIq_irow",
|
|
477
|
-
"
|
|
478
|
-
"
|
|
479
|
-
"
|
|
480
|
-
"
|
|
627
|
+
"filterOption": "eGUBIq_filterOption",
|
|
628
|
+
"grow": "eGUBIq_grow",
|
|
629
|
+
"cancelBtn": "eGUBIq_cancelBtn",
|
|
630
|
+
"pagerSize": "eGUBIq_pagerSize",
|
|
631
|
+
"modalNote": "eGUBIq_modalNote",
|
|
632
|
+
"dshmSlide": "eGUBIq_dshmSlide",
|
|
633
|
+
"filterGroup": "eGUBIq_filterGroup",
|
|
634
|
+
"card": "eGUBIq_card",
|
|
481
635
|
"catsCollapsed": "eGUBIq_catsCollapsed",
|
|
482
|
-
"
|
|
636
|
+
"body": "eGUBIq_body",
|
|
637
|
+
"cmdSummary": "eGUBIq_cmdSummary",
|
|
483
638
|
"actWhy": "eGUBIq_actWhy",
|
|
484
|
-
"src": "eGUBIq_src",
|
|
485
|
-
"card": "eGUBIq_card",
|
|
486
639
|
"star": "eGUBIq_star",
|
|
487
|
-
"
|
|
488
|
-
"
|
|
489
|
-
"
|
|
490
|
-
"
|
|
491
|
-
"
|
|
492
|
-
"
|
|
493
|
-
"
|
|
494
|
-
"sizeBtn": "eGUBIq_sizeBtn",
|
|
495
|
-
"root": "eGUBIq_root",
|
|
496
|
-
"filterWrap": "eGUBIq_filterWrap",
|
|
497
|
-
"pagerPages": "eGUBIq_pagerPages",
|
|
498
|
-
"row1": "eGUBIq_row1",
|
|
499
|
-
"owner": "eGUBIq_owner",
|
|
640
|
+
"cats": "eGUBIq_cats",
|
|
641
|
+
"bar": "eGUBIq_bar",
|
|
642
|
+
"irowMissing": "eGUBIq_irowMissing",
|
|
643
|
+
"sizeOn": "eGUBIq_sizeOn",
|
|
644
|
+
"backupPrimary": "eGUBIq_backupPrimary",
|
|
645
|
+
"backupActions": "eGUBIq_backupActions",
|
|
646
|
+
"nm": "eGUBIq_nm",
|
|
500
647
|
"warnBtn": "eGUBIq_warnBtn",
|
|
501
|
-
"
|
|
502
|
-
"
|
|
503
|
-
"barFill": "eGUBIq_barFill",
|
|
648
|
+
"pageEllipsis": "eGUBIq_pageEllipsis",
|
|
649
|
+
"warnLine": "eGUBIq_warnLine",
|
|
504
650
|
"spec": "eGUBIq_spec",
|
|
505
|
-
"
|
|
506
|
-
"
|
|
507
|
-
"sub": "eGUBIq_sub",
|
|
508
|
-
"restart": "eGUBIq_restart",
|
|
651
|
+
"staleAction": "eGUBIq_staleAction",
|
|
652
|
+
"grid": "eGUBIq_grid",
|
|
509
653
|
"descTight": "eGUBIq_descTight",
|
|
510
|
-
"progress": "eGUBIq_progress",
|
|
511
|
-
"cmd": "eGUBIq_cmd",
|
|
512
|
-
"bar": "eGUBIq_bar",
|
|
513
|
-
"cancelBtn": "eGUBIq_cancelBtn",
|
|
514
|
-
"sect": "eGUBIq_sect",
|
|
515
|
-
"spin": "eGUBIq_spin",
|
|
516
|
-
"filterPanel": "eGUBIq_filterPanel",
|
|
517
654
|
"dot": "eGUBIq_dot",
|
|
655
|
+
"shot": "eGUBIq_shot",
|
|
656
|
+
"backupMessage": "eGUBIq_backupMessage",
|
|
657
|
+
"filterBtnOn": "eGUBIq_filterBtnOn",
|
|
658
|
+
"cmdDetails": "eGUBIq_cmdDetails",
|
|
659
|
+
"pageOn": "eGUBIq_pageOn",
|
|
660
|
+
"restart": "eGUBIq_restart",
|
|
661
|
+
"backupWarn": "eGUBIq_backupWarn",
|
|
662
|
+
"themesGrid": "eGUBIq_themesGrid",
|
|
663
|
+
"owner": "eGUBIq_owner",
|
|
664
|
+
"pageInfo": "eGUBIq_pageInfo",
|
|
518
665
|
"catsRow": "eGUBIq_catsRow",
|
|
519
|
-
"
|
|
520
|
-
"
|
|
521
|
-
"
|
|
522
|
-
"
|
|
523
|
-
"
|
|
524
|
-
"
|
|
666
|
+
"act": "eGUBIq_act",
|
|
667
|
+
"catsToggle": "eGUBIq_catsToggle",
|
|
668
|
+
"spin": "eGUBIq_spin",
|
|
669
|
+
"progress": "eGUBIq_progress",
|
|
670
|
+
"err": "eGUBIq_err",
|
|
671
|
+
"pagerPages": "eGUBIq_pagerPages",
|
|
672
|
+
"dangerArmed": "eGUBIq_dangerArmed",
|
|
673
|
+
"shots": "eGUBIq_shots",
|
|
674
|
+
"row1": "eGUBIq_row1",
|
|
675
|
+
"titleRow": "eGUBIq_titleRow",
|
|
676
|
+
"actBroken": "eGUBIq_actBroken",
|
|
677
|
+
"cmd": "eGUBIq_cmd"
|
|
525
678
|
};
|
|
526
679
|
//#endregion
|
|
527
680
|
//#region src/client/MarketSection.tsx
|
|
@@ -579,6 +732,41 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
579
732
|
});
|
|
580
733
|
}
|
|
581
734
|
/**
|
|
735
|
+
* AppStore-style screenshot strip in the install detail dialog (#61).
|
|
736
|
+
* Curated registry screenshots win; otherwise images are extracted from the
|
|
737
|
+
* repo README. Requests start only once the dialog opens; failures — no
|
|
738
|
+
* README, no images, broken links — degrade to rendering nothing at all.
|
|
739
|
+
*/
|
|
740
|
+
function ScreenshotStrip({ plugin }) {
|
|
741
|
+
const [shots, setShots] = (0, react.useState)([]);
|
|
742
|
+
const [broken, setBroken] = (0, react.useState)([]);
|
|
743
|
+
(0, react.useEffect)(() => {
|
|
744
|
+
let live = true;
|
|
745
|
+
setShots([]);
|
|
746
|
+
setBroken([]);
|
|
747
|
+
pluginScreenshots(plugin).then((list) => {
|
|
748
|
+
if (live) setShots(list);
|
|
749
|
+
});
|
|
750
|
+
return () => {
|
|
751
|
+
live = false;
|
|
752
|
+
};
|
|
753
|
+
}, [plugin]);
|
|
754
|
+
const visible = shots.filter((src) => !broken.includes(src));
|
|
755
|
+
if (visible.length === 0) return null;
|
|
756
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
757
|
+
className: Market_module_css_default.shots,
|
|
758
|
+
children: visible.map((src) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
759
|
+
className: Market_module_css_default.shot,
|
|
760
|
+
src,
|
|
761
|
+
alt: "",
|
|
762
|
+
loading: "lazy",
|
|
763
|
+
decoding: "async",
|
|
764
|
+
referrerPolicy: "no-referrer",
|
|
765
|
+
onError: () => setBroken((prev) => prev.includes(src) ? prev : prev.concat(src))
|
|
766
|
+
}, src))
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
582
770
|
* Official-style market glyph: the shared block-grid brand mark converted to
|
|
583
771
|
* the official monochrome icon form (16×16, fill="currentColor") so it
|
|
584
772
|
* follows the active theme. Mirrors the settings-nav glyph used for the
|
|
@@ -617,6 +805,38 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
617
805
|
96
|
|
618
806
|
];
|
|
619
807
|
const DEFAULT_PAGE_SIZE = 24;
|
|
808
|
+
const WEBDAV_STORAGE_KEY = "dshm-webdav";
|
|
809
|
+
function savedWebdav() {
|
|
810
|
+
try {
|
|
811
|
+
const value = JSON.parse(localStorage.getItem(WEBDAV_STORAGE_KEY) ?? "{}");
|
|
812
|
+
return {
|
|
813
|
+
url: typeof value.url === "string" ? value.url : "",
|
|
814
|
+
username: typeof value.username === "string" ? value.username : "",
|
|
815
|
+
password: "",
|
|
816
|
+
auto: value.auto === true
|
|
817
|
+
};
|
|
818
|
+
} catch {
|
|
819
|
+
return {
|
|
820
|
+
url: "",
|
|
821
|
+
username: "",
|
|
822
|
+
password: "",
|
|
823
|
+
auto: false
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
function backupDependencies(value) {
|
|
828
|
+
if (value === null || typeof value !== "object") throw new Error("invalid backup");
|
|
829
|
+
const backup = value;
|
|
830
|
+
if (backup.format !== "dsh-profile-backup" || backup.version !== .2) throw new Error("unsupported backup format");
|
|
831
|
+
const files = backup.files;
|
|
832
|
+
if (!Array.isArray(files)) throw new Error("unsupported backup format");
|
|
833
|
+
const manifest = files.find((file) => file !== null && typeof file === "object" && file.path === "package.json");
|
|
834
|
+
if (manifest?.json === null || typeof manifest?.json !== "object" || Array.isArray(manifest.json)) throw new Error("backup package.json is invalid");
|
|
835
|
+
const dependencies = manifest.json.dependencies;
|
|
836
|
+
if (dependencies === null || typeof dependencies !== "object" || Array.isArray(dependencies)) return {};
|
|
837
|
+
if (!Object.values(dependencies).every((spec) => typeof spec === "string")) throw new Error("backup dependencies are invalid");
|
|
838
|
+
return dependencies;
|
|
839
|
+
}
|
|
620
840
|
/** Sort field choices in the filter panel. */
|
|
621
841
|
const SORT_FIELD_OPTIONS = [{
|
|
622
842
|
key: "stars",
|
|
@@ -656,6 +876,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
656
876
|
];
|
|
657
877
|
function MarketSection(props) {
|
|
658
878
|
const t = props.t;
|
|
879
|
+
const initialWebdav = (0, react.useMemo)(savedWebdav, []);
|
|
659
880
|
const localeSnap = (0, react.useSyncExternalStore)((cb) => props.locale.subscribe(cb), () => props.locale.getSnapshot());
|
|
660
881
|
const lang = String(localeSnap.active).toLowerCase().startsWith("zh") ? "zh" : "en";
|
|
661
882
|
const themeSnap = (0, react.useSyncExternalStore)(props.themeStore.subscribe, props.themeStore.getSnapshot);
|
|
@@ -666,6 +887,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
666
887
|
cachedInstalled = value;
|
|
667
888
|
setInstalledState(value);
|
|
668
889
|
}, []);
|
|
890
|
+
const [installedFiles, setInstalledFiles] = (0, react.useState)([]);
|
|
669
891
|
const [skins, setSkins] = (0, react.useState)([]);
|
|
670
892
|
const [tab, setTab] = (0, react.useState)(() => {
|
|
671
893
|
const saved = sessionStorage.getItem("dshm-tab");
|
|
@@ -720,6 +942,15 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
720
942
|
const [restartEnabled, setRestartEnabled] = (0, react.useState)(false);
|
|
721
943
|
const [restarting, setRestarting] = (0, react.useState)(false);
|
|
722
944
|
const [showTop, setShowTop] = (0, react.useState)(false);
|
|
945
|
+
const [backupBusy, setBackupBusy] = (0, react.useState)(false);
|
|
946
|
+
const [backupMessage, setBackupMessage] = (0, react.useState)(null);
|
|
947
|
+
const [backupRestored, setBackupRestored] = (0, react.useState)(false);
|
|
948
|
+
const [pendingBackup, setPendingBackup] = (0, react.useState)(null);
|
|
949
|
+
const [pendingDependencies, setPendingDependencies] = (0, react.useState)({});
|
|
950
|
+
const [webdavUrl, setWebdavUrl] = (0, react.useState)(initialWebdav.url);
|
|
951
|
+
const [webdavUser, setWebdavUser] = (0, react.useState)(initialWebdav.username);
|
|
952
|
+
const [webdavPassword, setWebdavPassword] = (0, react.useState)(initialWebdav.password);
|
|
953
|
+
const [autoBackup, setAutoBackup] = (0, react.useState)(initialWebdav.auto);
|
|
723
954
|
const bodyRef = (0, react.useRef)(null);
|
|
724
955
|
const [sortField, setSortField] = (0, react.useState)("stars");
|
|
725
956
|
const [sortDir, setSortDir] = (0, react.useState)("desc");
|
|
@@ -734,6 +965,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
734
965
|
const refreshInstalled = (0, react.useCallback)((force) => {
|
|
735
966
|
fetch("/dsh-market/installed", { cache: "no-store" }).then((res) => res.json()).then((body) => {
|
|
736
967
|
setInstalled(body.installed || {});
|
|
968
|
+
setInstalledFiles(Array.isArray(body.present) ? body.present : Object.keys(body.installed || {}));
|
|
737
969
|
setSkins(body.live || []);
|
|
738
970
|
if (body.activation && typeof body.activation === "object") setActivations(body.activation);
|
|
739
971
|
}).catch(() => {});
|
|
@@ -1144,7 +1376,100 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
1144
1376
|
};
|
|
1145
1377
|
next();
|
|
1146
1378
|
}, [updatableNames, doUpdate]);
|
|
1147
|
-
const
|
|
1379
|
+
const finishRestore = (0, react.useCallback)((body) => {
|
|
1380
|
+
const errors = Array.isArray(body.errors) ? body.errors : [];
|
|
1381
|
+
if (errors.length > 0) window.alert(`${t("restorePartial")}\n\n${errors.map((item) => `${String(item.name)}: ${String(item.error)}`).join("\n")}`);
|
|
1382
|
+
setBackupRestored(true);
|
|
1383
|
+
setBackupMessage(t("restoreDone"));
|
|
1384
|
+
if (errors.length === 0) {
|
|
1385
|
+
setPendingBackup(null);
|
|
1386
|
+
setPendingDependencies({});
|
|
1387
|
+
}
|
|
1388
|
+
refreshInstalled(true);
|
|
1389
|
+
}, [refreshInstalled, t]);
|
|
1390
|
+
const previewBackup = (0, react.useCallback)((backup) => {
|
|
1391
|
+
const dependencies = backupDependencies(backup);
|
|
1392
|
+
setPendingBackup(backup);
|
|
1393
|
+
setPendingDependencies(dependencies);
|
|
1394
|
+
setBackupMessage(t("restorePreviewDone"));
|
|
1395
|
+
setTab("installed");
|
|
1396
|
+
}, [t]);
|
|
1397
|
+
const restoreBackup = (0, react.useCallback)(() => {
|
|
1398
|
+
if (pendingBackup === null) return Promise.resolve();
|
|
1399
|
+
if (!window.confirm(t("restoreConfirm"))) return Promise.resolve();
|
|
1400
|
+
setBackupBusy(true);
|
|
1401
|
+
setBackupMessage(null);
|
|
1402
|
+
return fetch("/dsh-market/restore", {
|
|
1403
|
+
method: "POST",
|
|
1404
|
+
headers: { "content-type": "application/json" },
|
|
1405
|
+
body: JSON.stringify({ backup: pendingBackup })
|
|
1406
|
+
}).then(async (response) => {
|
|
1407
|
+
const body = await response.json();
|
|
1408
|
+
if (!response.ok) throw new Error(String(body.error || "restore failed"));
|
|
1409
|
+
finishRestore(body);
|
|
1410
|
+
}).catch((error) => setBackupMessage(String(error))).finally(() => setBackupBusy(false));
|
|
1411
|
+
}, [
|
|
1412
|
+
finishRestore,
|
|
1413
|
+
pendingBackup,
|
|
1414
|
+
t
|
|
1415
|
+
]);
|
|
1416
|
+
const runWebdav = (0, react.useCallback)((action) => {
|
|
1417
|
+
if (webdavUrl.trim() === "") return;
|
|
1418
|
+
setBackupBusy(true);
|
|
1419
|
+
setBackupMessage(null);
|
|
1420
|
+
fetch("/dsh-market/webdav", {
|
|
1421
|
+
method: "POST",
|
|
1422
|
+
headers: { "content-type": "application/json" },
|
|
1423
|
+
body: JSON.stringify({
|
|
1424
|
+
action,
|
|
1425
|
+
url: webdavUrl.trim(),
|
|
1426
|
+
username: webdavUser,
|
|
1427
|
+
password: webdavPassword
|
|
1428
|
+
})
|
|
1429
|
+
}).then(async (response) => {
|
|
1430
|
+
const body = await response.json();
|
|
1431
|
+
if (!response.ok) throw new Error(String(body.error || "WebDAV failed"));
|
|
1432
|
+
if (action === "restore") previewBackup(body.backup);
|
|
1433
|
+
if (action === "backup") {
|
|
1434
|
+
try {
|
|
1435
|
+
localStorage.setItem("dshm-webdav-last", String(Date.now()));
|
|
1436
|
+
} catch {}
|
|
1437
|
+
setBackupMessage(t("backupDone"));
|
|
1438
|
+
}
|
|
1439
|
+
}).catch((error) => setBackupMessage(String(error))).finally(() => setBackupBusy(false));
|
|
1440
|
+
}, [
|
|
1441
|
+
previewBackup,
|
|
1442
|
+
t,
|
|
1443
|
+
webdavPassword,
|
|
1444
|
+
webdavUrl,
|
|
1445
|
+
webdavUser
|
|
1446
|
+
]);
|
|
1447
|
+
(0, react.useEffect)(() => {
|
|
1448
|
+
try {
|
|
1449
|
+
localStorage.setItem(WEBDAV_STORAGE_KEY, JSON.stringify({
|
|
1450
|
+
url: webdavUrl,
|
|
1451
|
+
username: webdavUser,
|
|
1452
|
+
auto: autoBackup
|
|
1453
|
+
}));
|
|
1454
|
+
} catch {}
|
|
1455
|
+
if (!autoBackup || webdavUrl.trim() === "") return;
|
|
1456
|
+
let last = 0;
|
|
1457
|
+
try {
|
|
1458
|
+
last = Number(localStorage.getItem("dshm-webdav-last")) || 0;
|
|
1459
|
+
} catch {}
|
|
1460
|
+
if (Date.now() - last >= 864e5) runWebdav("backup");
|
|
1461
|
+
}, [
|
|
1462
|
+
autoBackup,
|
|
1463
|
+
runWebdav,
|
|
1464
|
+
webdavUrl,
|
|
1465
|
+
webdavUser
|
|
1466
|
+
]);
|
|
1467
|
+
const pendingRestart = doneUrls.length + updatedNames.length + removedCount + (backupRestored ? 1 : 0);
|
|
1468
|
+
const displayedInstalled = pendingBackup === null ? installed : {
|
|
1469
|
+
...pendingDependencies,
|
|
1470
|
+
...installed
|
|
1471
|
+
};
|
|
1472
|
+
const missingRestoreCount = Object.keys(pendingDependencies).filter((name) => !installedFiles.includes(name)).length;
|
|
1148
1473
|
const hasUpdates = Object.keys(installed).some((name) => !updatedNames.includes(name) && updates[name] && updates[name].updateAvailable);
|
|
1149
1474
|
/** Live status line: structured phase, or the human-line fallback. */
|
|
1150
1475
|
const phasePart = progressPhase != null ? phaseLabel(progressPhase, t) + (progressCurrent !== null ? " · " + progressCurrent : "") + (progressDone > 0 ? " · " + t("packagesDone").replace("{0}", String(progressDone)) : "") : progressLine || t("progressHint");
|
|
@@ -1491,8 +1816,13 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
1491
1816
|
className: Market_module_css_default.dot
|
|
1492
1817
|
})]
|
|
1493
1818
|
}),
|
|
1819
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1820
|
+
className: tab === "backup" ? `${Market_module_css_default.tab} ${Market_module_css_default.on}` : Market_module_css_default.tab,
|
|
1821
|
+
onClick: () => setTab("backup"),
|
|
1822
|
+
children: t("tabBackup")
|
|
1823
|
+
}),
|
|
1494
1824
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: Market_module_css_default.grow }),
|
|
1495
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
1825
|
+
tab !== "backup" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
1496
1826
|
className: Market_module_css_default.searchInline,
|
|
1497
1827
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 14 }),
|
|
1498
1828
|
placeholder: t("searchPh"),
|
|
@@ -1518,6 +1848,23 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
1518
1848
|
})
|
|
1519
1849
|
]
|
|
1520
1850
|
}),
|
|
1851
|
+
tab === "installed" && pendingBackup !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1852
|
+
className: Market_module_css_default.restart,
|
|
1853
|
+
children: [
|
|
1854
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "↺" }),
|
|
1855
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1856
|
+
className: Market_module_css_default.grow,
|
|
1857
|
+
children: t("restoreMissing").replace("{0}", String(missingRestoreCount))
|
|
1858
|
+
}),
|
|
1859
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1860
|
+
variant: "primary",
|
|
1861
|
+
size: "sm",
|
|
1862
|
+
disabled: backupBusy,
|
|
1863
|
+
onClick: restoreBackup,
|
|
1864
|
+
children: backupBusy ? t("backupWorking") : t("restoreStart")
|
|
1865
|
+
})
|
|
1866
|
+
]
|
|
1867
|
+
}),
|
|
1521
1868
|
hotUrls.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1522
1869
|
className: Market_module_css_default.restart,
|
|
1523
1870
|
children: [
|
|
@@ -1631,7 +1978,137 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
1631
1978
|
className: Market_module_css_default.body,
|
|
1632
1979
|
ref: bodyRef,
|
|
1633
1980
|
onScroll: (e) => setShowTop(e.currentTarget.scrollTop > 400),
|
|
1634
|
-
children: tab === "
|
|
1981
|
+
children: tab === "backup" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1982
|
+
className: Market_module_css_default.backupGrid,
|
|
1983
|
+
children: [
|
|
1984
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1985
|
+
className: Market_module_css_default.backupCard,
|
|
1986
|
+
children: [
|
|
1987
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("backupLocal") }),
|
|
1988
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("backupHint") }),
|
|
1989
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1990
|
+
className: Market_module_css_default.backupWarn,
|
|
1991
|
+
children: t("credsWarning")
|
|
1992
|
+
}),
|
|
1993
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1994
|
+
className: Market_module_css_default.backupActions,
|
|
1995
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
1996
|
+
className: `${Market_module_css_default.backupButton} ${Market_module_css_default.backupPrimary}`,
|
|
1997
|
+
href: "/dsh-market/backup",
|
|
1998
|
+
download: true,
|
|
1999
|
+
"aria-disabled": backupBusy,
|
|
2000
|
+
children: t("backupDownload")
|
|
2001
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2002
|
+
className: Market_module_css_default.backupButton,
|
|
2003
|
+
"aria-disabled": backupBusy,
|
|
2004
|
+
children: [backupBusy ? t("backupWorking") : t("backupImport"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2005
|
+
type: "file",
|
|
2006
|
+
accept: "application/json,.json",
|
|
2007
|
+
disabled: backupBusy,
|
|
2008
|
+
onChange: (event) => {
|
|
2009
|
+
const file = event.currentTarget.files?.[0];
|
|
2010
|
+
event.currentTarget.value = "";
|
|
2011
|
+
if (file !== void 0) file.text().then((text) => previewBackup(JSON.parse(text))).catch((error) => setBackupMessage(String(error)));
|
|
2012
|
+
}
|
|
2013
|
+
})]
|
|
2014
|
+
})]
|
|
2015
|
+
})
|
|
2016
|
+
]
|
|
2017
|
+
}),
|
|
2018
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2019
|
+
className: Market_module_css_default.backupCard,
|
|
2020
|
+
children: [
|
|
2021
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("webdav") }),
|
|
2022
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
2023
|
+
className: Market_module_css_default.backupInput,
|
|
2024
|
+
"aria-label": t("webdavPreset"),
|
|
2025
|
+
defaultValue: "",
|
|
2026
|
+
onChange: (event) => {
|
|
2027
|
+
const urls = {
|
|
2028
|
+
jianguoyun: "https://dav.jianguoyun.com/dav/dsh-profile-backup.json",
|
|
2029
|
+
koofr: "https://app.koofr.net/dav/Koofr/dsh-profile-backup.json",
|
|
2030
|
+
nextcloud: "https://nextcloud.example/remote.php/dav/files/USERNAME/dsh-profile-backup.json"
|
|
2031
|
+
};
|
|
2032
|
+
if (urls[event.target.value] !== void 0) setWebdavUrl(urls[event.target.value]);
|
|
2033
|
+
},
|
|
2034
|
+
children: [
|
|
2035
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2036
|
+
value: "",
|
|
2037
|
+
children: t("webdavPreset")
|
|
2038
|
+
}),
|
|
2039
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2040
|
+
value: "jianguoyun",
|
|
2041
|
+
children: "坚果云 / Nutstore"
|
|
2042
|
+
}),
|
|
2043
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2044
|
+
value: "koofr",
|
|
2045
|
+
children: "Koofr"
|
|
2046
|
+
}),
|
|
2047
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2048
|
+
value: "nextcloud",
|
|
2049
|
+
children: "Nextcloud"
|
|
2050
|
+
})
|
|
2051
|
+
]
|
|
2052
|
+
}),
|
|
2053
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2054
|
+
className: Market_module_css_default.backupInput,
|
|
2055
|
+
type: "url",
|
|
2056
|
+
value: webdavUrl,
|
|
2057
|
+
placeholder: t("webdavUrl"),
|
|
2058
|
+
onChange: (e) => setWebdavUrl(e.target.value)
|
|
2059
|
+
}),
|
|
2060
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2061
|
+
className: Market_module_css_default.backupInput,
|
|
2062
|
+
autoComplete: "username",
|
|
2063
|
+
value: webdavUser,
|
|
2064
|
+
placeholder: t("webdavUser"),
|
|
2065
|
+
onChange: (e) => setWebdavUser(e.target.value)
|
|
2066
|
+
}),
|
|
2067
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2068
|
+
className: Market_module_css_default.backupInput,
|
|
2069
|
+
type: "password",
|
|
2070
|
+
autoComplete: "current-password",
|
|
2071
|
+
value: webdavPassword,
|
|
2072
|
+
placeholder: t("webdavPassword"),
|
|
2073
|
+
onChange: (e) => setWebdavPassword(e.target.value)
|
|
2074
|
+
}),
|
|
2075
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2076
|
+
className: Market_module_css_default.backupActions,
|
|
2077
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2078
|
+
variant: "primary",
|
|
2079
|
+
size: "sm",
|
|
2080
|
+
disabled: backupBusy || webdavUrl.trim() === "",
|
|
2081
|
+
onClick: () => runWebdav("backup"),
|
|
2082
|
+
children: backupBusy ? t("backupWorking") : t("webdavUpload")
|
|
2083
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2084
|
+
variant: "outline",
|
|
2085
|
+
size: "sm",
|
|
2086
|
+
disabled: backupBusy || webdavUrl.trim() === "",
|
|
2087
|
+
onClick: () => runWebdav("restore"),
|
|
2088
|
+
children: t("webdavRestore")
|
|
2089
|
+
})]
|
|
2090
|
+
}),
|
|
2091
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2092
|
+
className: Market_module_css_default.backupCheck,
|
|
2093
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2094
|
+
type: "checkbox",
|
|
2095
|
+
checked: autoBackup,
|
|
2096
|
+
onChange: (e) => setAutoBackup(e.target.checked)
|
|
2097
|
+
}), t("autoBackup")]
|
|
2098
|
+
}),
|
|
2099
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("webdavNote") }),
|
|
2100
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2101
|
+
className: Market_module_css_default.backupWarn,
|
|
2102
|
+
children: t("credsWarning")
|
|
2103
|
+
})
|
|
2104
|
+
]
|
|
2105
|
+
}),
|
|
2106
|
+
backupMessage !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2107
|
+
className: Market_module_css_default.backupMessage,
|
|
2108
|
+
children: backupMessage
|
|
2109
|
+
})
|
|
2110
|
+
]
|
|
2111
|
+
}) : tab === "discover" ? loadError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1635
2112
|
className: Market_module_css_default.empty,
|
|
1636
2113
|
children: t("loadFail")
|
|
1637
2114
|
}) : data === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -1812,10 +2289,11 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
1812
2289
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1813
2290
|
className: Market_module_css_default.grid,
|
|
1814
2291
|
children: themePlugins$1.map(themePluginCard)
|
|
1815
|
-
})] }) : Object.keys(
|
|
2292
|
+
})] }) : Object.keys(displayedInstalled).length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1816
2293
|
className: Market_module_css_default.empty,
|
|
1817
2294
|
children: t("installedEmpty")
|
|
1818
|
-
}) : Object.entries(
|
|
2295
|
+
}) : Object.entries(displayedInstalled).map(([name, spec]) => {
|
|
2296
|
+
const missing = pendingBackup !== null && !installedFiles.includes(name);
|
|
1819
2297
|
const entry = data === null ? void 0 : entryForDep(data.plugins, name, String(spec));
|
|
1820
2298
|
const status = updates[name];
|
|
1821
2299
|
const act = activations[name];
|
|
@@ -1825,7 +2303,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
1825
2303
|
const ghSpec = /^github:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:#|$)/.exec(specText);
|
|
1826
2304
|
const repoUrl = entry !== void 0 ? entry.url : ghSpec !== null ? "https://github.com/" + ghSpec[1] : null;
|
|
1827
2305
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1828
|
-
className: Market_module_css_default.irow,
|
|
2306
|
+
className: missing ? `${Market_module_css_default.irow} ${Market_module_css_default.irowMissing}` : Market_module_css_default.irow,
|
|
1829
2307
|
children: [
|
|
1830
2308
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1831
2309
|
style: { minWidth: 0 },
|
|
@@ -1906,7 +2384,10 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
1906
2384
|
rel: "noreferrer",
|
|
1907
2385
|
children: t("readme")
|
|
1908
2386
|
}),
|
|
1909
|
-
|
|
2387
|
+
missing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2388
|
+
className: Market_module_css_default.owner,
|
|
2389
|
+
children: t("notInstalled")
|
|
2390
|
+
}) : updatedNames.includes(name) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1910
2391
|
className: Market_module_css_default.okState,
|
|
1911
2392
|
children: act?.state === "live" ? t("updatedLive") : t("updated")
|
|
1912
2393
|
}) : updatingName === name ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
@@ -1929,7 +2410,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
1929
2410
|
className: Market_module_css_default.owner,
|
|
1930
2411
|
children: t("upToDate")
|
|
1931
2412
|
}),
|
|
1932
|
-
name !== "dsh-market" && name !== "dshmarket" && (removingName === name ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2413
|
+
!missing && name !== "dsh-market" && name !== "dshmarket" && (removingName === name ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1933
2414
|
variant: "outline",
|
|
1934
2415
|
size: "sm",
|
|
1935
2416
|
className: Market_module_css_default.dangerBtn,
|
|
@@ -1981,6 +2462,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
1981
2462
|
children: t("confirm")
|
|
1982
2463
|
})] }),
|
|
1983
2464
|
children: [
|
|
2465
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScreenshotStrip, { plugin: confirming }),
|
|
1984
2466
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
1985
2467
|
className: Market_module_css_default.cmdDetails,
|
|
1986
2468
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
|