dsh-remote-plugin 0.6.10 → 0.6.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/public/index.html CHANGED
@@ -38,6 +38,12 @@
38
38
  </button>
39
39
  <div id="wb-panel" class="wb-panel hidden"></div>
40
40
  </div>
41
+ <div class="workspace-nav" id="workspace-nav">
42
+ <label for="session-workspace-filter" data-i18n="workspace.current">当前工作区</label>
43
+ <select id="session-workspace-filter" class="workspace-select" data-i18n-aria="workspace.select"></select>
44
+ <button id="session-workspace-files" class="mini-btn" type="button" data-i18n="workspace.files">查看文件</button>
45
+ <code id="session-workspace-path" class="workspace-path-scroll"></code>
46
+ </div>
41
47
  <div class="section-head">
42
48
  <span data-i18n="nav.sessions">会话</span>
43
49
  <div class="section-actions">
@@ -55,6 +61,10 @@
55
61
 
56
62
  <!-- 文件传输 -->
57
63
  <section id="view-files" class="view hidden">
64
+ <div class="fs-workspace-nav">
65
+ <label for="fs-workspace" data-i18n="fs.workspace">DSH 工作区</label>
66
+ <select id="fs-workspace" class="workspace-select" data-i18n-aria="workspace.select"></select>
67
+ </div>
58
68
  <div class="fs-head">
59
69
  <button id="fs-up" class="icon-btn" data-i18n-title="fs.up" data-i18n-aria="fs.up">‹</button>
60
70
  <div id="fs-path" class="fs-path" data-i18n="fs.loading">加载中…</div>
@@ -352,7 +362,7 @@
352
362
  <label class="switch"><input type="checkbox" id="opt-notify"><span class="slider"></span></label>
353
363
  </div>
354
364
  <div class="setting-row">
355
- <div><div class="setting-name" data-i18n="settings.peakRemindTitle">峰谷计费提醒</div><div class="setting-desc" data-i18n="settings.peakRemindDesc">每天 9:00 / 12:00 / 14:00 / 18:00 推送峰谷切换(App 内有效)</div></div>
365
+ <div><div class="setting-name" data-i18n="settings.peakRemindTitle">峰谷计费提醒</div><div class="setting-desc" data-i18n="settings.peakRemindDesc">工作日推送峰谷切换;周末全天谷时,仅 9:00 提醒一次(App 内有效)</div></div>
356
366
  <label class="switch"><input type="checkbox" id="opt-peak-remind"><span class="slider"></span></label>
357
367
  </div>
358
368
  <div class="setting-row">
@@ -365,7 +375,7 @@
365
375
  </div>
366
376
  <div class="setting-row">
367
377
  <div><div class="setting-name" data-i18n="settings.bgIntervalTitle">轮询间隔</div><div class="setting-desc" data-i18n="settings.bgIntervalDesc">灭屏后系统可能拉长间隔(Doze 平台限制)</div></div>
368
- <select id="bg-interval" style="padding:7px 9px;border-radius:10px;border:1px solid var(--dsr-line);background:var(--dsr-bg-2);color:var(--dsr-text);font:inherit">
378
+ <select id="bg-interval" class="setting-select">
369
379
  <option value="0.5" data-i18n="settings.bgInterval30s">30 秒</option>
370
380
  <option value="1" data-i18n="settings.bgInterval1m">1 分钟</option>
371
381
  <option value="5" data-i18n="settings.bgInterval5m">5 分钟</option>
@@ -458,6 +468,18 @@
458
468
  </button>
459
469
  </div>
460
470
 
471
+ <!-- 统一应用内选择抽屉:替代 Android WebView 的原生 select 弹窗 -->
472
+ <div id="custom-select-backdrop" class="sheet-backdrop custom-select-backdrop hidden"></div>
473
+ <div id="custom-select-sheet" class="sheet custom-select-sheet hidden" role="dialog" aria-modal="true" aria-labelledby="custom-select-title">
474
+ <div class="sheet-handle" aria-hidden="true"></div>
475
+ <div class="custom-select-head">
476
+ <div id="custom-select-title" class="sheet-title" data-i18n="select.choose">请选择</div>
477
+ <button id="custom-select-close" class="icon-btn" type="button" data-i18n-title="modal.close" data-i18n-aria="modal.close">×</button>
478
+ </div>
479
+ <div id="custom-select-options" class="custom-select-options" role="listbox"></div>
480
+ <button id="custom-select-cancel" class="btn subtle custom-select-cancel" type="button" data-i18n="select.cancel">取消</button>
481
+ </div>
482
+
461
483
  <nav class="bottom-nav" aria-label="主导航">
462
484
  <div class="nav-wave" aria-hidden="true">
463
485
  <svg viewBox="0 0 100 100" preserveAspectRatio="none">
@@ -547,6 +569,48 @@
547
569
  </div>
548
570
  </div>
549
571
 
572
+ <!-- 新会话工作区选择 -->
573
+ <div id="modal-new-session" class="modal hidden" role="dialog" aria-modal="true">
574
+ <div class="modal-card">
575
+ <div class="modal-title" data-i18n="newSession.title">新建会话</div>
576
+ <div class="modal-body">
577
+ <label class="field-label" for="new-session-workspace" data-i18n="newSession.workspace">选择工作区</label>
578
+ <select id="new-session-workspace" class="workspace-select full" data-i18n-aria="workspace.select"></select>
579
+ <div class="workspace-path-block">
580
+ <span data-i18n="newSession.path">工作区地址</span>
581
+ <code id="new-session-workspace-path" class="workspace-path-scroll"></code>
582
+ </div>
583
+ <div id="new-session-empty" class="empty hidden" data-i18n="newSession.noWorkspaces">还没有 DSH 工作区,请先新建工作区。</div>
584
+ </div>
585
+ <div class="modal-actions">
586
+ <button id="new-session-cancel" class="btn subtle" data-i18n="workspace.cancel">取消</button>
587
+ <button id="new-session-create" class="btn primary" data-i18n="newSession.create">创建会话</button>
588
+ </div>
589
+ </div>
590
+ </div>
591
+
592
+ <!-- 文本文件预览 -->
593
+ <div id="modal-file-preview" class="modal hidden" role="dialog" aria-modal="true">
594
+ <div class="modal-card file-preview-card">
595
+ <div class="file-preview-head">
596
+ <div class="modal-title" id="file-preview-title" data-i18n="fs.previewTitle">文件预览</div>
597
+ <button id="file-preview-close" class="icon-btn" data-i18n-title="modal.close" data-i18n-aria="modal.close">×</button>
598
+ </div>
599
+ <code id="file-preview-path" class="workspace-path-scroll file-preview-path"></code>
600
+ <div id="file-preview-tabs" class="file-preview-tabs hidden">
601
+ <button id="file-preview-source-tab" class="mini-btn current" type="button" data-i18n="fs.source">源码</button>
602
+ <button id="file-preview-rendered-tab" class="mini-btn" type="button" data-i18n="fs.preview">预览</button>
603
+ </div>
604
+ <div id="file-preview-loading" class="empty" data-i18n="fs.previewLoading">正在加载文件…</div>
605
+ <pre id="file-preview-source" class="file-preview-source hidden"></pre>
606
+ <div id="file-preview-rendered" class="md file-preview-rendered hidden"></div>
607
+ <div class="modal-actions">
608
+ <button id="file-preview-download" class="btn subtle" data-i18n="fs.download">下载</button>
609
+ <button id="file-preview-done" class="btn primary" data-i18n="modal.close">关闭</button>
610
+ </div>
611
+ </div>
612
+ </div>
613
+
550
614
  <div id="modal-archive" class="modal hidden" role="dialog" aria-modal="true">
551
615
  <div class="modal-card archive-modal-card">
552
616
  <div class="modal-title" data-i18n="session.archiveTitle">确认归档会话</div>
@@ -634,6 +698,12 @@
634
698
  <div class="announcement-kicker" data-i18n="announcement.label">公告</div>
635
699
  <div id="announcement-title" class="modal-title"></div>
636
700
  <div id="announcement-content" class="modal-body announcement-content"></div>
701
+ <div id="announcement-poll" class="announcement-poll hidden">
702
+ <div id="announcement-poll-question" class="announcement-poll-question"></div>
703
+ <div id="announcement-poll-options" class="announcement-poll-options" role="radiogroup"></div>
704
+ <div id="announcement-poll-status" class="announcement-poll-status hidden"></div>
705
+ <button id="announcement-poll-submit" class="btn primary" type="button" data-i18n="announcement.voteSubmit">提交投票</button>
706
+ </div>
637
707
  <a id="announcement-action" class="announcement-action hidden" target="_blank" rel="noopener"></a>
638
708
  <div class="modal-actions">
639
709
  <button id="announcement-later" class="btn subtle" data-i18n="announcement.later">稍后再看</button>
@@ -663,7 +733,7 @@
663
733
  'conn.reconnectIn': '重连中 {n}s', 'conn.offline': '离线', 'conn.failed': '连接失败',
664
734
  'conn.poll': '轮询', 'conn.pollTitle': '当前网络不支持实时推送,已降级为轮询(延迟数秒)',
665
735
  'conn.titleGroup': '{group} · {url}({ms})',
666
- 'common.refreshing': '刷新中…',
736
+ 'common.refreshing': '刷新中…', 'select.choose': '请选择', 'select.cancel': '取消',
667
737
  'nav.sessions': '会话', 'nav.files': '文件', 'nav.pending': '待办', 'nav.overview': '总览', 'nav.home': '主页', 'nav.stats': '统计', 'nav.settings': '设置',
668
738
  'overview.eyebrow': 'SYSTEM OVERVIEW', 'overview.title': '主页', 'overview.subtitle': '实时状态与需要你处理的事项',
669
739
  'overview.systemPulse': '系统链路', 'overview.nominal': '系统链路正常', 'overview.degraded': '部分链路需要关注', 'overview.offline': '连接已断开', 'overview.checking': '检查中…', 'overview.components': '{n}/4 个模块在线', 'overview.live': 'LIVE', 'overview.allLinked': '全部链路', 'overview.offlineCore': 'OFFLINE',
@@ -682,6 +752,8 @@
682
752
  'wb.unbound': '未绑定工作台', 'wb.bound': '绑定 {title}', 'wb.noProjects': '暂无项目', 'wb.noSessions': '暂无会话', 'wb.newSession': '新会话', 'wb.flatHidden': '工作台会话已收起({n} 个)', 'wb.archivedHidden': '------隐藏已归档会话------', 'wb.archivedShown': '------显示已归档会话------',
683
753
  'workspace.createTitle': '新建工作区', 'workspace.createDesc': '将在当前文件目录下创建文件夹,并自动打开新会话。', 'workspace.parent': '父目录', 'workspace.namePlaceholder': '例如:my-project', 'workspace.cancel': '取消', 'workspace.create': '创建并打开', 'workspace.nameRequired': '请输入工作区名称', 'workspace.exists': '该目录已存在', 'workspace.invalidName': '名称不能包含路径分隔符', 'workspace.createFailed': '创建工作区失败:{msg}', 'workspace.created': '工作区已创建', 'workspace.createdNoSession': '工作区已创建,但新会话未能打开',
684
754
  'workspace.createTitle': '新建工作区', 'workspace.createDesc': '将在当前文件目录下创建文件夹,并自动打开新会话。', 'workspace.parent': '父目录', 'workspace.namePlaceholder': '例如:my-project', 'workspace.cancel': '取消', 'workspace.create': '创建并打开', 'workspace.nameRequired': '请输入工作区名称', 'workspace.created': '工作区已创建', 'workspace.sessionFailed': '目录已创建,但新会话打开失败:{msg}',
755
+ 'workspace.current': '当前工作区', 'workspace.select': '选择工作区', 'workspace.all': '全部工作区', 'workspace.ungrouped': '未分组会话', 'workspace.files': '查看文件', 'workspace.allPath': '显示全部 DSH 工作区中的会话',
756
+ 'newSession.title': '新建会话', 'newSession.workspace': '选择工作区', 'newSession.path': '工作区地址', 'newSession.create': '创建会话', 'newSession.noWorkspaces': '还没有 DSH 工作区,请先新建工作区。', 'newSession.chooseWorkspace': '请先选择工作区',
685
757
  'sessions.running': '运行中', 'sessions.statRunning': '运行中', 'sessions.statPending': '待处理', 'sessions.statTotal': '会话总数',
686
758
  'sessions.sortLabel': '会话排序', 'sessions.sortTime': '按时间', 'sessions.sortWorkspace': '按工作区', 'sessions.workspace': '工作区', 'sessions.workspaceUnknown': '未指定工作区',
687
759
  'sessions.queueBadge': '队列 {n}', 'sessions.goalBadge': '目标·{phase}',
@@ -756,6 +828,7 @@
756
828
  'question.submitted': '已提交回答', 'question.stale': '提问已不在待处理状态', 'question.submitFailed': '回答提交失败:{msg}',
757
829
  'jobs.title': '后台任务', 'jobs.empty': '暂无后台任务',
758
830
  'fs.loading': '加载中…', 'fs.up': '返回上级', 'fs.newWorkspace': '新建工作区', 'fs.upload': '上传', 'fs.pause': '暂停', 'fs.resume': '继续', 'fs.cancel': '取消',
831
+ 'fs.workspace': 'DSH 工作区', 'fs.root': '文件根目录', 'fs.previewTitle': '文件预览', 'fs.previewLoading': '正在加载文件…', 'fs.previewFailed': '无法预览:{msg}', 'fs.previewUnsupported': '该文件类型暂不支持预览', 'fs.previewTooLarge': '文件超过 1 MB,请下载后查看', 'fs.source': '源码', 'fs.preview': '预览', 'fs.download': '下载',
759
832
  'fs.pullDown': '下拉刷新', 'fs.pullRelease': '松开刷新', 'fs.refreshing': '刷新中…',
760
833
  'fs.noToken': '未设置令牌', 'fs.goSettings': '请先到「设置」页粘贴网关令牌',
761
834
  'fs.notFound': '目录不存在', 'fs.forbidden': '路径不在允许范围内',
@@ -801,7 +874,7 @@
801
874
  'settings.notifyTitle': '通知', 'settings.notifyDesc': '收到审批/提问时推送', 'settings.announcementHistoryTitle': '历史公告', 'settings.announcementHistoryDesc': '查看以前收到的公告', 'settings.announcementHistory': '查看记录',
802
875
  'settings.testNotifyTitle': '测试通知', 'settings.testNotifyDesc': '立即排一条 3 秒后的本地通知,用于排查系统通知限制', 'settings.testNotify': '发送测试通知',
803
876
  'settings.testNotifySent': '测试通知已排定,3 秒后到达', 'settings.testNotifyFailed': '发送测试通知失败:{msg}', 'settings.testNotifyUnavailable': '测试通知仅在 App 内可用',
804
- 'settings.peakRemindTitle': '峰谷计费提醒', 'settings.peakRemindDesc': '每天 9:00 / 12:00 / 14:00 / 18:00 推送峰谷切换(App 内有效)',
877
+ 'settings.peakRemindTitle': '峰谷计费提醒', 'settings.peakRemindDesc': '工作日推送峰谷切换;周末全天谷时,仅 9:00 提醒一次(App 内有效)',
805
878
  'peakRemind.enterPeak': '已进入高峰计费时段', 'peakRemind.enterOff': '已进入空闲计费时段',
806
879
  'peakRemind.peak0912': '高峰 9:00-12:00', 'peakRemind.off1214': '空闲 12:00-14:00',
807
880
  'peakRemind.peak1418': '高峰 14:00-18:00', 'peakRemind.off1809': '空闲 18:00-次日 9:00',
@@ -851,6 +924,7 @@
851
924
  'modal.questionTitle': 'DSH 需要你回答', 'modal.later': '稍后', 'modal.submit': '提交',
852
925
  'modal.goalTitle': '目标控制', 'modal.close': '关闭', 'modal.updateGoal': '更新目标',
853
926
  'announcement.label': '公告', 'announcement.later': '稍后再看', 'announcement.gotIt': '知道了', 'announcement.open': '查看详情', 'announcement.historyLabel': '公告记录', 'announcement.historyTitle': '历史公告', 'announcement.historyEmpty': '暂无历史公告', 'announcement.close': '关闭', 'announcement.noDate': '未标注日期',
927
+ 'announcement.voteSubmit': '提交投票', 'announcement.voteChoose': '请先选择一项', 'announcement.voteThanks': '已投票:{option}', 'announcement.voteFailed': '投票失败:{msg}', 'announcement.voteNetworkError': '网络错误', 'announcement.voteAgainLater': '提交太频繁,请稍后再试', 'announcement.voteFromHistory': '参与投票',
854
928
  'modal.statsTitle': '本轮统计',
855
929
  'time.justNow': '刚刚', 'time.minAgo': ' 分钟前', 'time.hourAgo': ' 小时前'
856
930
  },
@@ -860,7 +934,7 @@
860
934
  'conn.reconnectIn': 'Reconnecting {n}s', 'conn.offline': 'Offline', 'conn.failed': 'Connection failed',
861
935
  'conn.poll': 'Polling', 'conn.pollTitle': 'Realtime push is unavailable on this network; degraded to polling (a few seconds delay)',
862
936
  'conn.titleGroup': '{group} · {url} ({ms})',
863
- 'common.refreshing': 'Refreshing…',
937
+ 'common.refreshing': 'Refreshing…', 'select.choose': 'Choose an option', 'select.cancel': 'Cancel',
864
938
  'nav.sessions': 'Sessions', 'nav.files': 'Files', 'nav.pending': 'Inbox', 'nav.overview': 'Overview', 'nav.home': 'Home', 'nav.stats': 'Stats', 'nav.settings': 'Settings',
865
939
  'overview.eyebrow': 'SYSTEM OVERVIEW', 'overview.title': 'Home', 'overview.subtitle': 'Live status and items needing your attention',
866
940
  'overview.systemPulse': 'System pulse', 'overview.nominal': 'System nominal', 'overview.degraded': 'Some links need attention', 'overview.offline': 'Connection offline', 'overview.checking': 'Checking…', 'overview.components': '{n}/4 components online', 'overview.live': 'LIVE', 'overview.allLinked': 'ALL LINKED', 'overview.offlineCore': 'OFFLINE',
@@ -879,6 +953,8 @@
879
953
  'wb.unbound': 'No workbench bound', 'wb.bound': 'Bound {title}', 'wb.noProjects': 'No projects', 'wb.noSessions': 'No sessions', 'wb.newSession': 'New session', 'wb.flatHidden': 'Workbench sessions folded ({n})', 'wb.archivedHidden': '------ Hide archived ------', 'wb.archivedShown': '------ Show archived ------',
880
954
  'workspace.createTitle': 'New workspace', 'workspace.createDesc': 'Create a folder in the current file directory and open a new session there.', 'workspace.parent': 'Parent folder', 'workspace.namePlaceholder': 'For example: my-project', 'workspace.cancel': 'Cancel', 'workspace.create': 'Create & open', 'workspace.nameRequired': 'Enter a workspace name', 'workspace.exists': 'That folder already exists', 'workspace.invalidName': 'The name cannot contain path separators', 'workspace.createFailed': 'Could not create workspace: {msg}', 'workspace.created': 'Workspace created', 'workspace.createdNoSession': 'Workspace created, but the new session could not be opened',
881
955
  'workspace.createTitle': 'New workspace', 'workspace.createDesc': 'Create a folder in the current file directory and open a new session there.', 'workspace.parent': 'Parent folder', 'workspace.namePlaceholder': 'For example: my-project', 'workspace.cancel': 'Cancel', 'workspace.create': 'Create & open', 'workspace.nameRequired': 'Enter a workspace name', 'workspace.created': 'Workspace created', 'workspace.sessionFailed': 'Folder created, but the new session could not be opened: {msg}',
956
+ 'workspace.current': 'Current workspace', 'workspace.select': 'Select workspace', 'workspace.all': 'All workspaces', 'workspace.ungrouped': 'Ungrouped sessions', 'workspace.files': 'View files', 'workspace.allPath': 'Showing sessions from every DSH workspace',
957
+ 'newSession.title': 'New session', 'newSession.workspace': 'Choose workspace', 'newSession.path': 'Workspace path', 'newSession.create': 'Create session', 'newSession.noWorkspaces': 'No DSH workspaces yet. Create a workspace first.', 'newSession.chooseWorkspace': 'Choose a workspace first',
882
958
  'sessions.running': 'Running', 'sessions.statRunning': 'Running', 'sessions.statPending': 'Pending', 'sessions.statTotal': 'Sessions',
883
959
  'sessions.sortLabel': 'Session sort', 'sessions.sortTime': 'By time', 'sessions.sortWorkspace': 'By workspace', 'sessions.workspace': 'Workspace', 'sessions.workspaceUnknown': 'No workspace',
884
960
  'sessions.queueBadge': 'Queue {n}', 'sessions.goalBadge': 'Goal·{phase}',
@@ -953,6 +1029,7 @@
953
1029
  'question.submitted': 'Answer submitted', 'question.stale': 'Question is no longer pending', 'question.submitFailed': 'Answer failed: {msg}',
954
1030
  'jobs.title': 'Background jobs', 'jobs.empty': 'No background jobs',
955
1031
  'fs.loading': 'Loading…', 'fs.up': 'Up one level', 'fs.newWorkspace': 'New workspace', 'fs.upload': 'Upload', 'fs.pause': 'Pause', 'fs.resume': 'Resume', 'fs.cancel': 'Cancel',
1032
+ 'fs.workspace': 'DSH workspace', 'fs.root': 'File root', 'fs.previewTitle': 'File preview', 'fs.previewLoading': 'Loading file…', 'fs.previewFailed': 'Could not preview: {msg}', 'fs.previewUnsupported': 'This file type cannot be previewed', 'fs.previewTooLarge': 'File is larger than 1 MB; download it to view', 'fs.source': 'Source', 'fs.preview': 'Preview', 'fs.download': 'Download',
956
1033
  'fs.pullDown': 'Pull to refresh', 'fs.pullRelease': 'Release to refresh', 'fs.refreshing': 'Refreshing…',
957
1034
  'fs.noToken': 'No token set', 'fs.goSettings': 'Go to Settings and paste the gateway token first',
958
1035
  'fs.notFound': 'Directory not found', 'fs.forbidden': 'Path is outside the allowed roots',
@@ -998,7 +1075,7 @@
998
1075
  'settings.notifyTitle': 'Notifications', 'settings.notifyDesc': 'Push on approvals / questions', 'settings.announcementHistoryTitle': 'Announcement history', 'settings.announcementHistoryDesc': 'Review announcements you received before', 'settings.announcementHistory': 'View history',
999
1076
  'settings.testNotifyTitle': 'Test notification', 'settings.testNotifyDesc': 'Schedule a local notification in 3 seconds to verify the notification pipeline', 'settings.testNotify': 'Send test notification',
1000
1077
  'settings.testNotifySent': 'Test notification scheduled, arriving in 3s', 'settings.testNotifyFailed': 'Failed to send test notification: {msg}', 'settings.testNotifyUnavailable': 'Test notification is only available in the app',
1001
- 'settings.peakRemindTitle': 'Peak/off-peak reminders', 'settings.peakRemindDesc': 'Push at 9:00 / 12:00 / 14:00 / 18:00 daily (in-app only)',
1078
+ 'settings.peakRemindTitle': 'Peak/off-peak reminders', 'settings.peakRemindDesc': 'Weekday transitions; weekends are off-peak all day with one reminder at 9:00 (app only)',
1002
1079
  'peakRemind.enterPeak': 'Peak pricing period started', 'peakRemind.enterOff': 'Off-peak pricing period started',
1003
1080
  'peakRemind.peak0912': 'Peak 9:00-12:00', 'peakRemind.off1214': 'Off-peak 12:00-14:00',
1004
1081
  'peakRemind.peak1418': 'Peak 14:00-18:00', 'peakRemind.off1809': 'Off-peak 18:00-9:00 next day',
@@ -1048,6 +1125,7 @@
1048
1125
  'modal.questionTitle': 'DSH needs your answer', 'modal.later': 'Later', 'modal.submit': 'Submit',
1049
1126
  'modal.goalTitle': 'Goal control', 'modal.close': 'Close', 'modal.updateGoal': 'Update goal',
1050
1127
  'announcement.label': 'Announcement', 'announcement.later': 'Later', 'announcement.gotIt': 'Got it', 'announcement.open': 'View details', 'announcement.historyLabel': 'Announcement archive', 'announcement.historyTitle': 'Announcement history', 'announcement.historyEmpty': 'No announcement history', 'announcement.close': 'Close', 'announcement.noDate': 'No date',
1128
+ 'announcement.voteSubmit': 'Submit vote', 'announcement.voteChoose': 'Choose an option first', 'announcement.voteThanks': 'Voted: {option}', 'announcement.voteFailed': 'Vote failed: {msg}', 'announcement.voteNetworkError': 'Network error', 'announcement.voteAgainLater': 'Too many submissions; try again later', 'announcement.voteFromHistory': 'Vote now',
1051
1129
  'modal.statsTitle': 'This round',
1052
1130
  'time.justNow': 'just now', 'time.minAgo': ' min ago', 'time.hourAgo': ' hr ago'
1053
1131
  }
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
2
+ <rect x=".75" y=".75" width="22.5" height="22.5" rx="5" fill="#F6F9FF" stroke="#0F1724" stroke-opacity=".14"/>
3
+ <path d="M10 6l4 4 4-4m-4 4 4 4" fill="none" stroke="#4F7FEF" stroke-width="2.8" stroke-linecap="square" stroke-linejoin="miter"/>
4
+ <path d="M6 10l4 4-4 4m4-4 4 4" fill="none" stroke="#8A64D8" stroke-width="2.8" stroke-linecap="square" stroke-linejoin="miter"/>
5
+ </svg>
package/public/styles.css CHANGED
@@ -136,6 +136,24 @@ a.mini-btn { text-decoration: none; display: inline-flex; align-items: center; }
136
136
  }
137
137
  .session-sort:focus { border-color: var(--dsr-accent-line); color: var(--dsr-text); }
138
138
  .section-head.small { margin-top: 6px; }
139
+ .workspace-nav, .fs-workspace-nav {
140
+ display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; align-items: center;
141
+ margin: 10px 0; padding: 10px; background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: var(--dsr-radius);
142
+ }
143
+ .workspace-nav > label, .fs-workspace-nav > label, .field-label { color: var(--dsr-muted); font-size: 12px; font-weight: 600; }
144
+ .workspace-select {
145
+ min-width: 0; width: 100%; height: 34px; padding: 0 9px; border-radius: 9px;
146
+ color: var(--dsr-text); background: var(--dsr-bg-2); border: 1px solid var(--dsr-line); font: inherit; font-size: 12.5px; outline: none;
147
+ }
148
+ .workspace-select:focus { border-color: var(--dsr-accent-line); }
149
+ .workspace-select.full { margin: 7px 0 10px; }
150
+ .workspace-path-scroll {
151
+ display: block; min-width: 0; overflow-x: auto; overflow-y: hidden; white-space: nowrap;
152
+ scrollbar-width: thin; color: var(--dsr-text); background: var(--dsr-bg-2); border: 1px solid var(--dsr-line); border-radius: 9px;
153
+ padding: 7px 9px; font-size: 11.5px; user-select: text;
154
+ }
155
+ .workspace-nav > .workspace-path-scroll { grid-column: 1 / -1; }
156
+ .workspace-path-block { display: grid; gap: 6px; margin-top: 2px; color: var(--dsr-muted); font-size: 12px; }
139
157
 
140
158
  /* ---------- Token 统计(移动端) ---------- */
141
159
  .stats-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@@ -570,6 +588,7 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
570
588
 
571
589
  /* ---------- 文件传输 ---------- */
572
590
  .fs-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
591
+ .fs-workspace-nav { grid-template-columns: auto minmax(0, 1fr); margin-top: 0; }
573
592
  .fs-path {
574
593
  flex: 1 1 150px; min-width: 0; font-size: 12.5px; color: var(--dsr-muted);
575
594
  background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 10px;
@@ -611,6 +630,19 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
611
630
  }
612
631
  .fs-sub { font-size: 12px; color: var(--dsr-muted); margin-top: 1px; }
613
632
  .fs-arrow { flex-shrink: 0; color: var(--dsr-muted); font-size: 18px; }
633
+ .file-preview-card { max-width: 760px; height: min(82vh, 760px); display: flex; flex-direction: column; overflow: hidden; }
634
+ .file-preview-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
635
+ .file-preview-head .modal-title { margin-bottom: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
636
+ .file-preview-path { margin: 10px 0; flex-shrink: 0; }
637
+ .file-preview-tabs { display: flex; gap: 7px; margin-bottom: 8px; flex-shrink: 0; }
638
+ .file-preview-tabs .current { border-color: var(--dsr-accent-line); color: var(--dsr-accent-strong); background: var(--dsr-accent-soft); }
639
+ .file-preview-source, .file-preview-rendered {
640
+ flex: 1; min-height: 0; overflow: auto; margin: 0; padding: 12px; border-radius: 10px;
641
+ color: var(--dsr-text); background: var(--dsr-panel); border: 1px solid var(--dsr-line); font-size: 12.5px; line-height: 1.55;
642
+ }
643
+ .file-preview-source { white-space: pre; tab-size: 2; }
644
+ .file-preview-rendered { overflow-wrap: anywhere; }
645
+ .file-preview-card > .modal-actions { flex-shrink: 0; }
614
646
 
615
647
  /* ---------- 设置 ---------- */
616
648
  .settings-group {
@@ -775,6 +807,45 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
775
807
  @keyframes sheet-fade { from { opacity: 0 } to { opacity: 1 } }
776
808
  @keyframes sheet-up { from { transform: translateY(24px); opacity: .6 } to { transform: translateY(0); opacity: 1 } }
777
809
 
810
+ /* ---------- 应用内选择抽屉 ---------- */
811
+ .custom-select-native {
812
+ position: fixed !important; left: -10000px !important; width: 1px !important; height: 1px !important;
813
+ opacity: 0 !important; pointer-events: none !important;
814
+ }
815
+ .custom-select-trigger {
816
+ min-width: 0; height: 34px; display: flex; align-items: center; justify-content: space-between; gap: 8px;
817
+ padding: 0 10px; border: 1px solid var(--dsr-line); border-radius: 9px;
818
+ color: var(--dsr-text); background: var(--dsr-bg-2); font: inherit; font-size: 12.5px;
819
+ text-align: left; cursor: pointer; outline: none;
820
+ }
821
+ .custom-select-trigger::after { content: '⌄'; flex: 0 0 auto; color: var(--dsr-muted); font-size: 14px; transform: translateY(-1px); }
822
+ .custom-select-trigger:focus-visible { border-color: var(--dsr-accent-line); box-shadow: 0 0 0 2px var(--dsr-accent-soft); }
823
+ .custom-select-trigger:disabled { opacity: .48; cursor: default; }
824
+ .custom-select-trigger-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
825
+ .workspace-select-trigger { width: 100%; }
826
+ .workspace-select-trigger.full { margin: 7px 0 10px; }
827
+ .session-sort-trigger { height: 30px; max-width: 112px; color: var(--dsr-muted); background: var(--dsr-panel); font-size: 11px; }
828
+ .setting-select-trigger { min-width: 112px; max-width: 145px; }
829
+ .custom-select-backdrop { z-index: 79; }
830
+ .custom-select-sheet { z-index: 80; max-height: min(72vh, 620px); overflow: hidden; display: flex; flex-direction: column; }
831
+ .custom-select-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
832
+ .custom-select-head .sheet-title { min-width: 0; margin: 0; padding-bottom: 8px; }
833
+ .custom-select-head .icon-btn { width: 34px; height: 34px; flex: 0 0 auto; }
834
+ .custom-select-options { min-height: 48px; overflow-y: auto; overscroll-behavior: contain; display: grid; gap: 5px; padding: 2px 0 8px; }
835
+ .custom-select-option {
836
+ width: 100%; min-height: 52px; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 10px;
837
+ padding: 9px 11px; border: 1px solid transparent; border-radius: 13px;
838
+ color: var(--dsr-text); background: transparent; font: inherit; text-align: left; cursor: pointer;
839
+ }
840
+ .custom-select-option:focus-visible, .custom-select-option:active { background: var(--dsr-panel); border-color: var(--dsr-line); outline: none; }
841
+ .custom-select-option.current { background: var(--dsr-accent-soft); border-color: var(--dsr-accent-line); }
842
+ .custom-select-option:disabled { opacity: .45; cursor: default; }
843
+ .custom-select-option-copy { min-width: 0; display: grid; gap: 3px; }
844
+ .custom-select-option-name { font-size: 14px; font-weight: 650; overflow-wrap: anywhere; }
845
+ .custom-select-option-path { color: var(--dsr-muted); font-size: 11.5px; line-height: 1.45; overflow-wrap: anywhere; }
846
+ .custom-select-option-check { width: 24px; color: var(--dsr-accent-strong); font-size: 18px; font-weight: 800; text-align: center; }
847
+ .custom-select-cancel { flex: 0 0 auto; width: 100%; margin-top: 2px; }
848
+
778
849
  /* 写反馈弹层 */
779
850
  .fb-chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
780
851
  .fb-chip {
@@ -827,6 +898,16 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
827
898
  .announcement-card { border-top: 3px solid var(--dsr-accent); }
828
899
  .announcement-kicker { color: var(--dsr-accent-strong); font-size: 12px; font-weight: 700; letter-spacing: .04em; margin-bottom: 6px; }
829
900
  .announcement-content { line-height: 1.7; overflow-wrap: anywhere; word-break: break-word; }
901
+ .announcement-poll { display: grid; gap: 10px; margin-top: 14px; padding: 12px; border: 1px solid var(--dsr-line); border-radius: 12px; background: var(--dsr-panel); }
902
+ .announcement-poll-question { font-size: 14px; font-weight: 700; line-height: 1.5; }
903
+ .announcement-poll-options { display: grid; gap: 7px; }
904
+ .announcement-poll-option { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 9px; align-items: start; padding: 10px; border: 1px solid var(--dsr-line); border-radius: 10px; background: var(--dsr-bg-2); cursor: pointer; }
905
+ .announcement-poll-option:has(input:checked) { border-color: var(--dsr-accent-line); background: var(--dsr-accent-soft); }
906
+ .announcement-poll-option input { margin-top: 3px; accent-color: var(--dsr-accent); }
907
+ .announcement-poll-option strong { display: block; font-size: 13px; line-height: 1.45; }
908
+ .announcement-poll-option small { display: block; margin-top: 2px; color: var(--dsr-muted); font-size: 11.5px; line-height: 1.45; }
909
+ .announcement-poll-status { color: var(--dsr-accent-strong); font-size: 12.5px; font-weight: 650; }
910
+ .announcement-poll > .btn { justify-self: stretch; }
830
911
  .announcement-action { display: inline-block; margin-top: 12px; color: var(--dsr-accent-strong); font-size: 13px; font-weight: 600; text-decoration: none; }
831
912
  .announcement-action:hover { text-decoration: underline; }
832
913
  .announcement-history-card { max-width: 520px; }
@@ -857,6 +938,11 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
857
938
  .topbar-right .topbar-btn.conn-badge { max-width: 72px; padding-left: 8px; padding-right: 8px; overflow: hidden; text-overflow: ellipsis; }
858
939
  .setting-row { align-items: flex-start; flex-wrap: wrap; }
859
940
  .setting-row > .setting-actions { width: 100%; justify-content: flex-end; }
941
+ .workspace-nav { grid-template-columns: minmax(0, 1fr) auto; }
942
+ .workspace-nav > label { grid-column: 1 / -1; }
943
+ .workspace-nav > .workspace-path-scroll { grid-column: 1 / -1; }
944
+ .fs-workspace-nav { grid-template-columns: 1fr; }
945
+ .file-preview-card { height: 88vh; padding: 13px; }
860
946
  }
861
947
  .theme-panel-list { display: flex; flex-direction: column; gap: 8px; }
862
948
  .theme-option {
package/public/theme.js CHANGED
@@ -27,9 +27,17 @@
27
27
  if (meta && bg) meta.setAttribute('content', bg)
28
28
  }
29
29
 
30
+ function announce(t) {
31
+ window.dispatchEvent(new CustomEvent('dsh-theme-change', { detail: { theme: t } }))
32
+ if (window.parent !== window) {
33
+ window.parent.postMessage({ source: 'dsh-remote-theme', type: 'change', theme: t }, location.origin)
34
+ }
35
+ }
36
+
30
37
  function applyAttr(t) {
31
38
  document.documentElement.setAttribute('data-theme', t)
32
39
  syncMeta()
40
+ announce(t)
33
41
  }
34
42
 
35
43
  function applyCurrent() {
@@ -39,9 +47,8 @@
39
47
 
40
48
  function set(t) {
41
49
  if (!VALID.includes(t)) t = get()
42
- document.documentElement.setAttribute('data-theme', t)
43
50
  store.set(KEY, t)
44
- syncMeta()
51
+ applyAttr(t)
45
52
  return t
46
53
  }
47
54
 
@@ -1,10 +1,14 @@
1
1
  {
2
- "version": "0.6.10",
2
+ "version": "0.6.11",
3
3
  "apkUrl": "dsh-remote.apk",
4
- "sha256": "1aa45a7edcadbbfc5285d30308e6abf2fac7c7eaaf4ad6cf831df1a06a4f48b9",
5
- "releasedAt": "2026-08-23T08:13:20.716Z",
6
- "notes": "0.6.10 正式版:修复 DSH/网关重启后事件通道不自动恢复、启动阶段网卡读取异常、同源状态误报、双通道总览卡在 3/4、图片后实时回复不可见及子代理重复;新增完整用户链路与重启生命周期测试;公网反馈切换到安全的 HTTPS 临时入口并加强来源 IP 防伪造、节流与隐私保护。",
4
+ "sha256": "674a5929f051b0c6bce67d703a2ca90a1048542f04c3d13534654b7f6f17b641",
5
+ "releasedAt": "2026-08-23T10:44:30.082Z",
6
+ "notes": "0.6.11 正式版:新增按 DSH 工作区筛选、切换和创建会话,文件页支持切换工作区并直接预览常见文本与 Markdown;新增投票公告及隐私化汇总;统一手机端应用内选择抽屉;周末全天按谷时并修复重复峰谷提醒;插件侧栏图标采用亮色背景并随插件自身四套皮肤切换配色;加强网关安装、连接与故障排查引导。",
7
7
  "history": [
8
+ {
9
+ "version": "0.6.11",
10
+ "notes": "0.6.11 正式版:新增按 DSH 工作区筛选、切换和创建会话,文件页支持切换工作区并直接预览常见文本与 Markdown;新增投票公告及隐私化汇总;统一手机端应用内选择抽屉;周末全天按谷时并修复重复峰谷提醒;插件侧栏图标采用亮色背景并随插件自身四套皮肤切换配色;加强网关安装、连接与故障排查引导。"
11
+ },
8
12
  {
9
13
  "version": "0.6.10",
10
14
  "notes": "0.6.10 正式版:修复 DSH/网关重启后事件通道不自动恢复、启动阶段网卡读取异常、同源状态误报、双通道总览卡在 3/4、图片后实时回复不可见及子代理重复;新增完整用户链路与重启生命周期测试;公网反馈切换到安全的 HTTPS 临时入口并加强来源 IP 防伪造、节流与隐私保护。"
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.6.10"
2
+ "version": "0.6.11"
3
3
  }