dsh-mobile 0.5.0 → 0.5.1

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/lib/index.d.mts CHANGED
@@ -356,6 +356,8 @@ declare class JsonMobileAccessControlStore implements MobileAccessControlStore {
356
356
  private readonly file;
357
357
  private readonly initiallyEnabled;
358
358
  constructor(file: string, initiallyEnabled: boolean);
359
+ /** Avoid writing an absent already-disabled state without changing recovery of existing files. */
360
+ disableIfPresent(): Promise<void>;
359
361
  load(): Promise<MobileAccessControlState>;
360
362
  save(state: MobileAccessControlState): Promise<void>;
361
363
  }
package/lib/index.mjs CHANGED
@@ -1078,6 +1078,25 @@ var JsonMobileAccessControlStore = class {
1078
1078
  this.file = file;
1079
1079
  this.initiallyEnabled = initiallyEnabled;
1080
1080
  }
1081
+ /** Avoid writing an absent already-disabled state without changing recovery of existing files. */
1082
+ async disableIfPresent() {
1083
+ try {
1084
+ await lstat(this.file);
1085
+ } catch (error) {
1086
+ if (error.code === "ENOENT") {
1087
+ if (this.initiallyEnabled) await this.save({
1088
+ version: 1,
1089
+ enabled: false
1090
+ });
1091
+ return;
1092
+ }
1093
+ throw error;
1094
+ }
1095
+ await this.save({
1096
+ version: 1,
1097
+ enabled: false
1098
+ });
1099
+ }
1081
1100
  async load() {
1082
1101
  let stat;
1083
1102
  try {
@@ -9977,7 +9996,7 @@ function buildMobileGuide(state) {
9977
9996
  const scriptLine = state.hasCustomJs ? "存在(当前生效的自定义脚本)" : "不存在(无自定义脚本)";
9978
9997
  const extensionLines = state.extensions.length === 0 ? "(无)" : state.extensions.map((entry) => `- ${entry.id}(${entry.name} v${entry.version})`).join("\n");
9979
9998
  const failureLine = state.failedExtensionCount > 0 ? `注意:${state.failedExtensionCount} 个扩展的电脑端 host 激活失败,如改动相关扩展请先检查其 host.mjs 与 extension.json。` : "";
9980
- return `${`## 手机端当前状态(改名前必读,避免覆盖已有定制)
9999
+ return `${`## 手机端当前状态(改动前必读,避免覆盖已有定制)
9981
10000
 
9982
10001
  - 定制目录:${state.directory}(所有改动只允许在这里进行)
9983
10002
  - mobile.css:${styleLine}
@@ -10003,6 +10022,8 @@ const MOBILE_CUSTOMIZATION_GUIDE_BODY = `你在为用户定制 DSH Mobile 的手
10003
10022
  - $DSH_HOME/mobile-access/mobile.js:手机端脚本,用 window.dshMobile.register(({ root }) => { ... }) 把内容挂载到 root,返回清理函数
10004
10023
  - 保存后手机端几秒内自动应用,无需重启
10005
10024
 
10025
+ 动手前先读已有的定制文件。若要调整 DSH 自带的输入框、侧栏或设置等现有界面,先确认当前 DSH 版本与手机页面模式(专用移动页面或 ?frontend=stock),只读核对运行页面的 DOM、属性和样式;本机有同版本前端源码时可参考相应组件,没有源码时可查看已安装的客户端产物,不必下载源码。优先使用扩展 API、插槽和稳定的 data-* 标记,不凭猜测依赖构建类名。只读查看不改变前述写入范围。
10026
+
10006
10027
  2. 电脑端能力 —— 手机需要读电脑文件、执行命令或访问硬件时,创建扩展:
10007
10028
  - 目录:$DSH_HOME/mobile-access/extensions/<id>/,id 用小写字母数字和连字符(如 media-remote)
10008
10029
  - extension.json:{"schemaVersion":1,"id":"<id>","name":"显示名","version":"0.1.0","description":"说明"}
@@ -10019,6 +10040,7 @@ const MOBILE_CUSTOMIZATION_GUIDE_BODY = `你在为用户定制 DSH Mobile 的手
10019
10040
 
10020
10041
  完成前请自检:
10021
10042
  - 改动涉及 mobile.js 或扩展的 mobile.js / host.mjs 时,先做语法检查再保存(如 node --check <file>),确保没有语法错误
10043
+ - 改动 DSH 现有界面后尽可能在实际手机页面核对效果;无法观察运行页面时,明确告诉用户尚未实测
10022
10044
  - 创建或修改扩展后,确认 extension.json 的 schemaVersion 为 1、id 与目录名一致、且 id 只含小写字母数字和连字符
10023
10045
  - 扩展的 host.mjs 若在完成前无法激活,先修正而不是留下损坏的扩展
10024
10046
  - 完成后检查自己实际写入了哪些文件,向用户简要说明改了什么、手机端会有什么变化`;
@@ -13705,7 +13727,7 @@ async function apply(ctx, config) {
13705
13727
  const unregister = ctx.webServer.register(adminRoute);
13706
13728
  const disposeMobileCommand = ctx.commands.register({
13707
13729
  name: "mobile",
13708
- description: "按需求修改 DSH Mobile 的手机端界面或添加电脑端能力",
13730
+ description: "定制手机界面或添加电脑能力",
13709
13731
  input: { hint: "<要做什么>" },
13710
13732
  handler: async ({ agent, rawInput }) => {
13711
13733
  const task = rawInput.trim();
@@ -13751,10 +13773,7 @@ async function apply(ctx, config) {
13751
13773
  frp: frpStore,
13752
13774
  origin: originStore
13753
13775
  };
13754
- await Promise.all(Object.keys(stores).filter((provider) => provider !== remoteProviders.selected).map((provider) => stores[provider].save({
13755
- version: 1,
13756
- enabled: false
13757
- })));
13776
+ await Promise.all(Object.keys(stores).filter((provider) => provider !== remoteProviders.selected).map((provider) => stores[provider].disableIfPresent()));
13758
13777
  for (const provider of REMOTE_PROVIDERS) await remoteControllers[provider].initialize();
13759
13778
  const lanDiscovery = lanGateway?.discoveryStatus();
13760
13779
  if (lanDiscovery !== void 0 && !lanDiscovery.broadcast) logger.warn("broadcast discovery is unavailable (%s); mDNS is still published, so pair manually or free the UDP port", lanDiscovery.errorCode ?? "unknown_cause");