@ohmykreee/dsh-remote-control 0.0.0-stage → 1.0.3
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/AGENTS.md +556 -0
- package/INSTALLATION.md +310 -0
- package/LICENSE +21 -0
- package/README.md +195 -2
- package/client.js +3 -0
- package/components.json +20 -0
- package/cordis.patch.yml +3 -0
- package/docs/README.en.md +196 -0
- package/docs/screenshots/en/overview.png +0 -0
- package/docs/screenshots/en/question.png +0 -0
- package/docs/screenshots/zh/overview.png +0 -0
- package/docs/screenshots/zh/question.png +0 -0
- package/icon.svg +24 -0
- package/index.js +2 -0
- package/lib/account.js +1 -0
- package/lib/app-mapping.js +1 -0
- package/lib/i18n.js +1 -0
- package/lib/media-enrich.js +1 -0
- package/lib/notifications.js +1 -0
- package/lib/performance.js +1 -0
- package/lib/platform/index.js +1 -0
- package/lib/probe-adapter.js +1 -0
- package/lib/probe-daemon.js +1 -0
- package/lib/probe.js +1 -0
- package/lib/qr.js +1 -0
- package/lib/runtime.js +1 -0
- package/lib/service.js +1 -0
- package/lib/sessions.js +1 -0
- package/lib/settings.js +1 -0
- package/lib/types.js +1 -0
- package/lib/util.js +1 -0
- package/lib/weather.js +1 -0
- package/lib/ws.js +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +118 -4
- package/scripts/browser-shot.mjs +217 -0
- package/scripts/build-dsh.mjs +228 -0
- package/scripts/build-rust.mjs +319 -0
- package/scripts/build-web.mjs +17 -0
- package/scripts/check-npm-package.mjs +322 -0
- package/scripts/mock-preview.py +574 -0
- package/scripts/screenshot-compose.py +89 -0
- package/scripts/screenshot-device.sh +75 -0
- package/src/dsh/client/api.ts +68 -0
- package/src/dsh/client/i18n.ts +573 -0
- package/src/dsh/client/icons.ts +56 -0
- package/src/dsh/client/index.ts +95 -0
- package/src/dsh/client/logic.ts +310 -0
- package/src/dsh/client/panel.ts +483 -0
- package/src/dsh/client/sections/apps.ts +40 -0
- package/src/dsh/client/sections/balance.ts +38 -0
- package/src/dsh/client/sections/connection.ts +97 -0
- package/src/dsh/client/sections/notifications.ts +43 -0
- package/src/dsh/client/sections/pomodoro.ts +184 -0
- package/src/dsh/client/sections/preferences.ts +138 -0
- package/src/dsh/client/sections/system.ts +120 -0
- package/src/dsh/client/sections/weather.ts +276 -0
- package/src/dsh/client/styles.ts +1119 -0
- package/src/dsh/client/types.ts +366 -0
- package/src/dsh/client/ui.ts +142 -0
- package/src/dsh/index.ts +108 -0
- package/src/dsh/lib/account.ts +520 -0
- package/src/dsh/lib/app-mapping.ts +366 -0
- package/src/dsh/lib/i18n.ts +82 -0
- package/src/dsh/lib/media-enrich.ts +202 -0
- package/src/dsh/lib/notifications.ts +322 -0
- package/src/dsh/lib/performance.ts +279 -0
- package/src/dsh/lib/platform/index.ts +43 -0
- package/src/dsh/lib/probe-adapter.ts +275 -0
- package/src/dsh/lib/probe-daemon.ts +359 -0
- package/src/dsh/lib/probe.ts +395 -0
- package/src/dsh/lib/qr.ts +42 -0
- package/src/dsh/lib/runtime.ts +126 -0
- package/src/dsh/lib/service.ts +1645 -0
- package/src/dsh/lib/sessions.ts +907 -0
- package/src/dsh/lib/settings.ts +468 -0
- package/src/dsh/lib/types.ts +231 -0
- package/src/dsh/lib/util.ts +115 -0
- package/src/dsh/lib/weather.ts +532 -0
- package/src/dsh/lib/ws.ts +328 -0
- package/src/dsh/types/qrcode-generator.d.ts +16 -0
- package/src/rust/Cargo.lock +1431 -0
- package/src/rust/Cargo.toml +68 -0
- package/src/rust/src/cli.rs +233 -0
- package/src/rust/src/daemon.rs +140 -0
- package/src/rust/src/location/linux.rs +118 -0
- package/src/rust/src/location/macos.rs +26 -0
- package/src/rust/src/location/mod.rs +170 -0
- package/src/rust/src/location/windows.rs +205 -0
- package/src/rust/src/main.rs +42 -0
- package/src/rust/src/media/catalog.rs +454 -0
- package/src/rust/src/media/linux.rs +350 -0
- package/src/rust/src/media/macos/accessibility.rs +59 -0
- package/src/rust/src/media/macos.rs +366 -0
- package/src/rust/src/media/mod.rs +298 -0
- package/src/rust/src/media/vendor/apple_music.rs +90 -0
- package/src/rust/src/media/vendor/common.rs +186 -0
- package/src/rust/src/media/vendor/kugou.rs +52 -0
- package/src/rust/src/media/vendor/kuwo.rs +49 -0
- package/src/rust/src/media/vendor/mod.rs +75 -0
- package/src/rust/src/media/vendor/netease.rs +1715 -0
- package/src/rust/src/media/vendor/qishui.rs +36 -0
- package/src/rust/src/media/vendor/qqmusic.rs +33 -0
- package/src/rust/src/media/vendor/spotify.rs +46 -0
- package/src/rust/src/media/vendor/wesing.rs +39 -0
- package/src/rust/src/media/vendor/youtube_music.rs +49 -0
- package/src/rust/src/media/windows/accessibility.rs +85 -0
- package/src/rust/src/media/windows/audio.rs +116 -0
- package/src/rust/src/media/windows/private.rs +291 -0
- package/src/rust/src/media/windows.rs +775 -0
- package/src/rust/src/notifications/linux.rs +276 -0
- package/src/rust/src/notifications/macos.rs +382 -0
- package/src/rust/src/notifications/mod.rs +244 -0
- package/src/rust/src/notifications/windows.rs +565 -0
- package/src/rust/src/perf/common.rs +109 -0
- package/src/rust/src/perf/linux.rs +282 -0
- package/src/rust/src/perf/macos.rs +28 -0
- package/src/rust/src/perf/mod.rs +157 -0
- package/src/rust/src/perf/windows.rs +981 -0
- package/src/rust/src/util.rs +360 -0
- package/src/rust/src/volume/linux.rs +195 -0
- package/src/rust/src/volume/macos.rs +54 -0
- package/src/rust/src/volume/mod.rs +116 -0
- package/src/rust/src/volume/windows.rs +75 -0
- package/src/rust/tests/cli.rs +79 -0
- package/src/rust/tests/daemon.rs +107 -0
- package/src/svelte/App.svelte +385 -0
- package/src/svelte/index.html +18 -0
- package/src/svelte/lib/billing.svelte.ts +228 -0
- package/src/svelte/lib/components/BalanceCard.svelte +173 -0
- package/src/svelte/lib/components/ClockCard.svelte +183 -0
- package/src/svelte/lib/components/CountdownCard.svelte +261 -0
- package/src/svelte/lib/components/CpuMemoryCard.svelte +238 -0
- package/src/svelte/lib/components/EmptyState.svelte +34 -0
- package/src/svelte/lib/components/GpuCard.svelte +245 -0
- package/src/svelte/lib/components/HomePage.svelte +34 -0
- package/src/svelte/lib/components/MusicControls.svelte +256 -0
- package/src/svelte/lib/components/MusicCover.svelte +88 -0
- package/src/svelte/lib/components/MusicPage.svelte +116 -0
- package/src/svelte/lib/components/NotificationsCard.svelte +109 -0
- package/src/svelte/lib/components/Panel.svelte +22 -0
- package/src/svelte/lib/components/PerformancePage.svelte +55 -0
- package/src/svelte/lib/components/PomodoroCard.svelte +250 -0
- package/src/svelte/lib/components/QuestionSheet.svelte +354 -0
- package/src/svelte/lib/components/RadialGauge.svelte +99 -0
- package/src/svelte/lib/components/Rail.svelte +217 -0
- package/src/svelte/lib/components/SectionHeader.svelte +40 -0
- package/src/svelte/lib/components/SeekBar.svelte +421 -0
- package/src/svelte/lib/components/SessionList.svelte +364 -0
- package/src/svelte/lib/components/SessionStats.svelte +98 -0
- package/src/svelte/lib/components/SessionsPage.svelte +61 -0
- package/src/svelte/lib/components/SpendCard.svelte +105 -0
- package/src/svelte/lib/components/ThermalCard.svelte +249 -0
- package/src/svelte/lib/components/Toast.svelte +32 -0
- package/src/svelte/lib/components/WeatherIcon.svelte +40 -0
- package/src/svelte/lib/components/WeatherPanel.svelte +420 -0
- package/src/svelte/lib/components/ui/alert/alert-action.svelte +20 -0
- package/src/svelte/lib/components/ui/alert/alert-description.svelte +23 -0
- package/src/svelte/lib/components/ui/alert/alert-title.svelte +23 -0
- package/src/svelte/lib/components/ui/alert/alert.svelte +43 -0
- package/src/svelte/lib/components/ui/alert/index.ts +17 -0
- package/src/svelte/lib/components/ui/avatar/avatar-badge.svelte +26 -0
- package/src/svelte/lib/components/ui/avatar/avatar-fallback.svelte +20 -0
- package/src/svelte/lib/components/ui/avatar/avatar-group-count.svelte +23 -0
- package/src/svelte/lib/components/ui/avatar/avatar-group.svelte +23 -0
- package/src/svelte/lib/components/ui/avatar/avatar-image.svelte +17 -0
- package/src/svelte/lib/components/ui/avatar/avatar.svelte +26 -0
- package/src/svelte/lib/components/ui/avatar/index.ts +22 -0
- package/src/svelte/lib/components/ui/badge/badge.svelte +49 -0
- package/src/svelte/lib/components/ui/badge/index.ts +2 -0
- package/src/svelte/lib/components/ui/button/button.svelte +82 -0
- package/src/svelte/lib/components/ui/button/index.ts +17 -0
- package/src/svelte/lib/components/ui/card/card-action.svelte +23 -0
- package/src/svelte/lib/components/ui/card/card-content.svelte +20 -0
- package/src/svelte/lib/components/ui/card/card-description.svelte +20 -0
- package/src/svelte/lib/components/ui/card/card-footer.svelte +20 -0
- package/src/svelte/lib/components/ui/card/card-header.svelte +23 -0
- package/src/svelte/lib/components/ui/card/card-title.svelte +20 -0
- package/src/svelte/lib/components/ui/card/card.svelte +22 -0
- package/src/svelte/lib/components/ui/card/index.ts +25 -0
- package/src/svelte/lib/components/ui/dialog/dialog-close.svelte +11 -0
- package/src/svelte/lib/components/ui/dialog/dialog-content.svelte +48 -0
- package/src/svelte/lib/components/ui/dialog/dialog-description.svelte +17 -0
- package/src/svelte/lib/components/ui/dialog/dialog-footer.svelte +32 -0
- package/src/svelte/lib/components/ui/dialog/dialog-header.svelte +20 -0
- package/src/svelte/lib/components/ui/dialog/dialog-overlay.svelte +17 -0
- package/src/svelte/lib/components/ui/dialog/dialog-portal.svelte +7 -0
- package/src/svelte/lib/components/ui/dialog/dialog-title.svelte +17 -0
- package/src/svelte/lib/components/ui/dialog/dialog-trigger.svelte +11 -0
- package/src/svelte/lib/components/ui/dialog/dialog.svelte +7 -0
- package/src/svelte/lib/components/ui/dialog/index.ts +34 -0
- package/src/svelte/lib/components/ui/empty/empty-content.svelte +23 -0
- package/src/svelte/lib/components/ui/empty/empty-description.svelte +23 -0
- package/src/svelte/lib/components/ui/empty/empty-header.svelte +20 -0
- package/src/svelte/lib/components/ui/empty/empty-media.svelte +41 -0
- package/src/svelte/lib/components/ui/empty/empty-title.svelte +20 -0
- package/src/svelte/lib/components/ui/empty/empty.svelte +23 -0
- package/src/svelte/lib/components/ui/empty/index.ts +22 -0
- package/src/svelte/lib/components/ui/input/index.ts +7 -0
- package/src/svelte/lib/components/ui/input/input.svelte +48 -0
- package/src/svelte/lib/components/ui/progress/index.ts +7 -0
- package/src/svelte/lib/components/ui/progress/progress.svelte +27 -0
- package/src/svelte/lib/components/ui/scroll-area/index.ts +10 -0
- package/src/svelte/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte +30 -0
- package/src/svelte/lib/components/ui/scroll-area/scroll-area.svelte +43 -0
- package/src/svelte/lib/components/ui/separator/index.ts +7 -0
- package/src/svelte/lib/components/ui/separator/separator.svelte +21 -0
- package/src/svelte/lib/components/ui/sheet/index.ts +34 -0
- package/src/svelte/lib/components/ui/sheet/sheet-close.svelte +7 -0
- package/src/svelte/lib/components/ui/sheet/sheet-content.svelte +55 -0
- package/src/svelte/lib/components/ui/sheet/sheet-description.svelte +17 -0
- package/src/svelte/lib/components/ui/sheet/sheet-footer.svelte +20 -0
- package/src/svelte/lib/components/ui/sheet/sheet-header.svelte +20 -0
- package/src/svelte/lib/components/ui/sheet/sheet-overlay.svelte +20 -0
- package/src/svelte/lib/components/ui/sheet/sheet-portal.svelte +7 -0
- package/src/svelte/lib/components/ui/sheet/sheet-title.svelte +17 -0
- package/src/svelte/lib/components/ui/sheet/sheet-trigger.svelte +7 -0
- package/src/svelte/lib/components/ui/sheet/sheet.svelte +7 -0
- package/src/svelte/lib/components/ui/skeleton/index.ts +7 -0
- package/src/svelte/lib/components/ui/skeleton/skeleton.svelte +17 -0
- package/src/svelte/lib/components/ui/slider/index.ts +7 -0
- package/src/svelte/lib/components/ui/slider/slider.svelte +52 -0
- package/src/svelte/lib/components/ui/tooltip/index.ts +19 -0
- package/src/svelte/lib/components/ui/tooltip/tooltip-content.svelte +51 -0
- package/src/svelte/lib/components/ui/tooltip/tooltip-portal.svelte +7 -0
- package/src/svelte/lib/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/src/svelte/lib/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/src/svelte/lib/components/ui/tooltip/tooltip.svelte +7 -0
- package/src/svelte/lib/countdown.svelte.ts +252 -0
- package/src/svelte/lib/format.ts +199 -0
- package/src/svelte/lib/i18n.svelte.ts +583 -0
- package/src/svelte/lib/media.ts +32 -0
- package/src/svelte/lib/pages.ts +18 -0
- package/src/svelte/lib/pomodoro.svelte.ts +223 -0
- package/src/svelte/lib/session-tree.ts +80 -0
- package/src/svelte/lib/state.svelte.ts +359 -0
- package/src/svelte/lib/timer-alarm.svelte.ts +319 -0
- package/src/svelte/lib/types.ts +306 -0
- package/src/svelte/lib/utils.ts +8 -0
- package/src/svelte/lib/weather.ts +84 -0
- package/src/svelte/lib/ws.ts +104 -0
- package/src/svelte/main.ts +13 -0
- package/src/svelte/styles/global.css +315 -0
- package/src/svelte/vite-env.d.ts +12 -0
- package/static/fonts/LICENSE.txt +287 -0
- package/static/icon.svg +24 -0
- package/static/manifest.webmanifest +18 -0
- package/svelte.config.js +5 -0
- package/tsconfig.dsh-client.json +18 -0
- package/tsconfig.dsh.json +21 -0
- package/tsconfig.json +20 -0
- package/vite.config.js +31 -0
- package/web/assets/index-DLdSfnJ3.css +1 -0
- package/web/assets/index-YNE8X0Uy.js +6 -0
- package/web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/web/assets/jetbrains-mono-cyrillic-ext-wght-normal-EocZY2iu.woff2 +0 -0
- package/web/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/web/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/web/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/web/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/web/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/web/assets/noto-sans-sc-100-wght-normal-DluiXYzi.woff2 +0 -0
- package/web/assets/noto-sans-sc-101-wght-normal-CPkZHnw0.woff2 +0 -0
- package/web/assets/noto-sans-sc-102-wght-normal-gzIulUH6.woff2 +0 -0
- package/web/assets/noto-sans-sc-103-wght-normal-CJfSBxFo.woff2 +0 -0
- package/web/assets/noto-sans-sc-104-wght-normal-B3QMglgE.woff2 +0 -0
- package/web/assets/noto-sans-sc-105-wght-normal-xXh_OMfk.woff2 +0 -0
- package/web/assets/noto-sans-sc-106-wght-normal-B9n3jMjP.woff2 +0 -0
- package/web/assets/noto-sans-sc-107-wght-normal-D7fvVprN.woff2 +0 -0
- package/web/assets/noto-sans-sc-108-wght-normal-J0_LhxVo.woff2 +0 -0
- package/web/assets/noto-sans-sc-109-wght-normal-Dsp-De_0.woff2 +0 -0
- package/web/assets/noto-sans-sc-110-wght-normal-DE_6NUrb.woff2 +0 -0
- package/web/assets/noto-sans-sc-111-wght-normal-C4S-TlTn.woff2 +0 -0
- package/web/assets/noto-sans-sc-112-wght-normal-BcFuP3w6.woff2 +0 -0
- package/web/assets/noto-sans-sc-113-wght-normal-Dk932kmj.woff2 +0 -0
- package/web/assets/noto-sans-sc-114-wght-normal-CO_5Xo-i.woff2 +0 -0
- package/web/assets/noto-sans-sc-115-wght-normal-BWy07H14.woff2 +0 -0
- package/web/assets/noto-sans-sc-116-wght-normal-B4HVAfHo.woff2 +0 -0
- package/web/assets/noto-sans-sc-117-wght-normal-siZzFqgK.woff2 +0 -0
- package/web/assets/noto-sans-sc-118-wght-normal-xhBB7f6V.woff2 +0 -0
- package/web/assets/noto-sans-sc-119-wght-normal-Ck_g2FGz.woff2 +0 -0
- package/web/assets/noto-sans-sc-21-wght-normal-D0x9-yBt.woff2 +0 -0
- package/web/assets/noto-sans-sc-22-wght-normal-BBUVTShg.woff2 +0 -0
- package/web/assets/noto-sans-sc-23-wght-normal-Du1oYWkE.woff2 +0 -0
- package/web/assets/noto-sans-sc-24-wght-normal-CmWjJ0gt.woff2 +0 -0
- package/web/assets/noto-sans-sc-25-wght-normal-BFHiqilg.woff2 +0 -0
- package/web/assets/noto-sans-sc-26-wght-normal-C0sF2Z2f.woff2 +0 -0
- package/web/assets/noto-sans-sc-27-wght-normal-COFdrquJ.woff2 +0 -0
- package/web/assets/noto-sans-sc-28-wght-normal-DMgdNu1o.woff2 +0 -0
- package/web/assets/noto-sans-sc-29-wght-normal-Cmq8em30.woff2 +0 -0
- package/web/assets/noto-sans-sc-30-wght-normal-CZWqZ3yU.woff2 +0 -0
- package/web/assets/noto-sans-sc-31-wght-normal-Wfi_lutW.woff2 +0 -0
- package/web/assets/noto-sans-sc-32-wght-normal-BRJQ4PY5.woff2 +0 -0
- package/web/assets/noto-sans-sc-33-wght-normal-CUVQXNAJ.woff2 +0 -0
- package/web/assets/noto-sans-sc-34-wght-normal-Bspba0wC.woff2 +0 -0
- package/web/assets/noto-sans-sc-35-wght-normal-K8fX_YPG.woff2 +0 -0
- package/web/assets/noto-sans-sc-36-wght-normal-CkITyjoT.woff2 +0 -0
- package/web/assets/noto-sans-sc-37-wght-normal-WCZ2zfEe.woff2 +0 -0
- package/web/assets/noto-sans-sc-38-wght-normal-DeM7CUce.woff2 +0 -0
- package/web/assets/noto-sans-sc-39-wght-normal-BMZNLWQU.woff2 +0 -0
- package/web/assets/noto-sans-sc-4-wght-normal-AR5bdDjz.woff2 +0 -0
- package/web/assets/noto-sans-sc-40-wght-normal-BQ5xpS5j.woff2 +0 -0
- package/web/assets/noto-sans-sc-41-wght-normal-Hthm7FFi.woff2 +0 -0
- package/web/assets/noto-sans-sc-42-wght-normal-eaS2gKds.woff2 +0 -0
- package/web/assets/noto-sans-sc-43-wght-normal-o-T53XXV.woff2 +0 -0
- package/web/assets/noto-sans-sc-44-wght-normal-BJH5J4Ez.woff2 +0 -0
- package/web/assets/noto-sans-sc-45-wght-normal-BKuxSCOJ.woff2 +0 -0
- package/web/assets/noto-sans-sc-46-wght-normal-BR_5Mu6e.woff2 +0 -0
- package/web/assets/noto-sans-sc-47-wght-normal-CyY7gKNX.woff2 +0 -0
- package/web/assets/noto-sans-sc-48-wght-normal-BNMfTR6k.woff2 +0 -0
- package/web/assets/noto-sans-sc-49-wght-normal-DX-0y7wg.woff2 +0 -0
- package/web/assets/noto-sans-sc-5-wght-normal-CfWugllB.woff2 +0 -0
- package/web/assets/noto-sans-sc-50-wght-normal-DAOGW-Dr.woff2 +0 -0
- package/web/assets/noto-sans-sc-51-wght-normal-BlFLOjcP.woff2 +0 -0
- package/web/assets/noto-sans-sc-52-wght-normal-OZjrybnw.woff2 +0 -0
- package/web/assets/noto-sans-sc-53-wght-normal-CwyWNT6x.woff2 +0 -0
- package/web/assets/noto-sans-sc-54-wght-normal-DM0nRe18.woff2 +0 -0
- package/web/assets/noto-sans-sc-55-wght-normal-DBK2wUOR.woff2 +0 -0
- package/web/assets/noto-sans-sc-56-wght-normal-C-VKK1LS.woff2 +0 -0
- package/web/assets/noto-sans-sc-57-wght-normal-Cdbfh5kq.woff2 +0 -0
- package/web/assets/noto-sans-sc-58-wght-normal-CflMKARZ.woff2 +0 -0
- package/web/assets/noto-sans-sc-59-wght-normal-BS4Kwzxx.woff2 +0 -0
- package/web/assets/noto-sans-sc-6-wght-normal-ChnZIQfQ.woff2 +0 -0
- package/web/assets/noto-sans-sc-60-wght-normal-B7QOYsXJ.woff2 +0 -0
- package/web/assets/noto-sans-sc-61-wght-normal-C8JjQS7w.woff2 +0 -0
- package/web/assets/noto-sans-sc-62-wght-normal-bS4wq1Gg.woff2 +0 -0
- package/web/assets/noto-sans-sc-63-wght-normal-BJr8P-OB.woff2 +0 -0
- package/web/assets/noto-sans-sc-64-wght-normal-DVB11t7j.woff2 +0 -0
- package/web/assets/noto-sans-sc-65-wght-normal-DMPCXBvK.woff2 +0 -0
- package/web/assets/noto-sans-sc-66-wght-normal-BobaG10V.woff2 +0 -0
- package/web/assets/noto-sans-sc-67-wght-normal-Dzk7WhCR.woff2 +0 -0
- package/web/assets/noto-sans-sc-68-wght-normal-DGbCD9xu.woff2 +0 -0
- package/web/assets/noto-sans-sc-69-wght-normal-Ctrv1EqA.woff2 +0 -0
- package/web/assets/noto-sans-sc-70-wght-normal-RgTO941D.woff2 +0 -0
- package/web/assets/noto-sans-sc-71-wght-normal-D9sG-CWv.woff2 +0 -0
- package/web/assets/noto-sans-sc-72-wght-normal-C4oWy3ul.woff2 +0 -0
- package/web/assets/noto-sans-sc-73-wght-normal-B1ZoOTgM.woff2 +0 -0
- package/web/assets/noto-sans-sc-74-wght-normal-F7dH_rZJ.woff2 +0 -0
- package/web/assets/noto-sans-sc-75-wght-normal-Cp2wp4si.woff2 +0 -0
- package/web/assets/noto-sans-sc-76-wght-normal-B494D7xS.woff2 +0 -0
- package/web/assets/noto-sans-sc-77-wght-normal-B3MVY9Ax.woff2 +0 -0
- package/web/assets/noto-sans-sc-78-wght-normal-5jX7iNMC.woff2 +0 -0
- package/web/assets/noto-sans-sc-79-wght-normal-BIoZy8fr.woff2 +0 -0
- package/web/assets/noto-sans-sc-80-wght-normal-Bje1Fxy1.woff2 +0 -0
- package/web/assets/noto-sans-sc-81-wght-normal-B2NN7Qi3.woff2 +0 -0
- package/web/assets/noto-sans-sc-82-wght-normal-CUggNZi4.woff2 +0 -0
- package/web/assets/noto-sans-sc-83-wght-normal-99rD8YO-.woff2 +0 -0
- package/web/assets/noto-sans-sc-84-wght-normal-zMBmUocm.woff2 +0 -0
- package/web/assets/noto-sans-sc-85-wght-normal-CjI3qdxG.woff2 +0 -0
- package/web/assets/noto-sans-sc-86-wght-normal-BHY8TVEH.woff2 +0 -0
- package/web/assets/noto-sans-sc-87-wght-normal-DioZSHnU.woff2 +0 -0
- package/web/assets/noto-sans-sc-88-wght-normal-BXYxwf2t.woff2 +0 -0
- package/web/assets/noto-sans-sc-89-wght-normal-ClMFrFaL.woff2 +0 -0
- package/web/assets/noto-sans-sc-90-wght-normal-BnOlPreP.woff2 +0 -0
- package/web/assets/noto-sans-sc-91-wght-normal-DTr9RQcS.woff2 +0 -0
- package/web/assets/noto-sans-sc-97-wght-normal-9u6Aiav-.woff2 +0 -0
- package/web/assets/noto-sans-sc-98-wght-normal-BR-H2C0V.woff2 +0 -0
- package/web/assets/noto-sans-sc-99-wght-normal-BI6XPoxp.woff2 +0 -0
- package/web/assets/noto-sans-sc-cyrillic-wght-normal-BGmsQlw-.woff2 +0 -0
- package/web/assets/noto-sans-sc-latin-ext-wght-normal-DuJTpTg_.woff2 +0 -0
- package/web/assets/noto-sans-sc-latin-wght-normal-DDW8mKAR.woff2 +0 -0
- package/web/assets/noto-sans-sc-vietnamese-wght-normal-Bi3ATJ76.woff2 +0 -0
- package/web/fonts/LICENSE.txt +287 -0
- package/web/icon.svg +24 -0
- package/web/index.html +19 -0
- package/web/manifest.webmanifest +18 -0
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dictionaries and locale plumbing for the remote-control page.
|
|
3
|
+
*
|
|
4
|
+
* Each shipped language is one flat key -> text object so a new language can be
|
|
5
|
+
* added by appending another object to {@link DICTS}; no key needs to be
|
|
6
|
+
* declared twice. English is the terminal fallback for every missing key.
|
|
7
|
+
*
|
|
8
|
+
* "Follow DSH" resolves against the DSH locale service: an exact match with a
|
|
9
|
+
* shipped language wins, anything else (ja, zh-CN, an unknown language pack)
|
|
10
|
+
* falls back to English instead of borrowing an unrelated dictionary.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { useEffect, useState } from 'react';
|
|
14
|
+
import type { LocaleService, Translator } from './types.js';
|
|
15
|
+
|
|
16
|
+
export const NS = 'dsh-remote-control';
|
|
17
|
+
|
|
18
|
+
/** Plugin language preference: follow DSH, or force one shipped language. */
|
|
19
|
+
export type PluginLanguage = 'dsh' | 'zh' | 'en';
|
|
20
|
+
|
|
21
|
+
/** Languages the plugin ships dictionaries for. */
|
|
22
|
+
export type LocaleCode = 'zh' | 'en';
|
|
23
|
+
|
|
24
|
+
export const SUPPORTED_LOCALES: readonly LocaleCode[] = ['zh', 'en'];
|
|
25
|
+
|
|
26
|
+
export const zh: Record<string, string> = {
|
|
27
|
+
title: '远程控制台',
|
|
28
|
+
kicker: 'REMOTE CONSOLE',
|
|
29
|
+
heading: '远程控制台',
|
|
30
|
+
subtitle: '手机控制台的连接、显示与偏好设置。',
|
|
31
|
+
running: '运行中',
|
|
32
|
+
stopped: '未运行',
|
|
33
|
+
refresh: '刷新',
|
|
34
|
+
save: '保存',
|
|
35
|
+
saved: '已保存',
|
|
36
|
+
error: '操作失败',
|
|
37
|
+
loading: '正在读取设置…',
|
|
38
|
+
pairing: '扫码连接',
|
|
39
|
+
pairingHint: '手机与电脑连接同一个局域网,扫描二维码即可打开。',
|
|
40
|
+
open: '在电脑上打开',
|
|
41
|
+
copy: '复制链接',
|
|
42
|
+
copied: '已复制',
|
|
43
|
+
connection: '连接',
|
|
44
|
+
menuPlugin: '偏好设置',
|
|
45
|
+
menuNetwork: '开放网卡',
|
|
46
|
+
menuAccess: '访问验证',
|
|
47
|
+
menuTheme: '主题与页面',
|
|
48
|
+
menuTls: 'HTTPS 证书',
|
|
49
|
+
menuWeather: '天气设置',
|
|
50
|
+
menuBalance: '余额显示',
|
|
51
|
+
menuNotifications: '通知设置',
|
|
52
|
+
menuSystem: '系统信息',
|
|
53
|
+
menuStatus: '服务状态',
|
|
54
|
+
menuClients: '已连接设备',
|
|
55
|
+
menuDiagnostics: '诊断信息',
|
|
56
|
+
network: '开放网卡',
|
|
57
|
+
networkHint: '只有勾选网卡所在网段的设备可以访问控制台。',
|
|
58
|
+
pluginHint: '手机端的访问方式、温度单位、主题、页面顺序与 HTTPS 证书;修改后点击保存设置生效。',
|
|
59
|
+
access: '访问验证',
|
|
60
|
+
accessHint: '开启后,手机首次打开需要扫描带验证令牌的链接。',
|
|
61
|
+
token: '链接验证',
|
|
62
|
+
rotate: '刷新验证',
|
|
63
|
+
rotateHint: '刷新后已连接设备会断开,需要重新扫码。',
|
|
64
|
+
theme: '主题与页面',
|
|
65
|
+
themeHint: '选择手机控制台跟随 DSH 主题,或固定亮暗模式。',
|
|
66
|
+
temperatureUnit: '温度单位',
|
|
67
|
+
temperatureUnitHint: '手机端天气和性能页使用的温度显示单位。',
|
|
68
|
+
celsius: '摄氏度 (°C)',
|
|
69
|
+
fahrenheit: '华氏度 (°F)',
|
|
70
|
+
followDsh: '跟随 DSH',
|
|
71
|
+
language: '插件语言',
|
|
72
|
+
languageHint: '选择界面语言;没有对应翻译时使用英语。',
|
|
73
|
+
languageFollowDsh: '跟随 DSH',
|
|
74
|
+
light: '浅色',
|
|
75
|
+
dark: '深色',
|
|
76
|
+
pageOrder: '页面顺序',
|
|
77
|
+
pageOrderHint: '拖拽调整手机端的页面顺序;关闭的页面不会显示。',
|
|
78
|
+
tls: 'HTTPS 证书',
|
|
79
|
+
tlsHint: '可选。填写证书和私钥文件路径后启用 HTTPS;保存后连接会短暂中断。',
|
|
80
|
+
certPath: '证书路径',
|
|
81
|
+
keyPath: '私钥路径',
|
|
82
|
+
saveTls: '保存证书配置',
|
|
83
|
+
tlsOn: 'HTTPS 已启用',
|
|
84
|
+
tlsOff: 'HTTPS 未启用',
|
|
85
|
+
tlsError: '证书无效,当前仍使用 HTTP',
|
|
86
|
+
weather: '天气设置',
|
|
87
|
+
weatherHint: '自动定位优先使用本机位置;手动位置可搜索城市,选中后自动填入经纬度。',
|
|
88
|
+
forecastDisplay: '天气卡片显示',
|
|
89
|
+
hourly: '小时天气',
|
|
90
|
+
daily: '7 天天气',
|
|
91
|
+
saveSettings: '保存设置',
|
|
92
|
+
pagePerformance: '性能',
|
|
93
|
+
auto: '本机位置',
|
|
94
|
+
manual: '手动位置',
|
|
95
|
+
locationName: '位置名称',
|
|
96
|
+
latitude: '纬度',
|
|
97
|
+
longitude: '经度',
|
|
98
|
+
saveLocation: '保存位置',
|
|
99
|
+
citySearchPlaceholder: '输入城市名搜索',
|
|
100
|
+
citySearchHint: '输入城市名后从下拉结果中选择,纬度和经度会自动填入;也可以直接编辑坐标。',
|
|
101
|
+
locationAutoHint: '本机位置模式下坐标由系统定位提供,切换到「手动位置」后可搜索或填写城市与坐标。',
|
|
102
|
+
citySearching: '正在搜索…',
|
|
103
|
+
cityNoResults: '没有找到匹配的城市',
|
|
104
|
+
citySearchFailed: '城市搜索失败,请稍后重试',
|
|
105
|
+
citySearchUnavailable: '城市搜索暂不可用,请重启 DSH 后重试',
|
|
106
|
+
balance: '余额显示',
|
|
107
|
+
balanceHint: '选择本周或最近 7 天作为消耗统计窗口。',
|
|
108
|
+
calendar: '本周',
|
|
109
|
+
rolling: '最近 7 天',
|
|
110
|
+
lowThreshold: '低余额提醒线',
|
|
111
|
+
lowThresholdHint: '低于这个金额时,手机端余额会显示为红色。留空关闭提醒。',
|
|
112
|
+
thresholdPlaceholder: '例如:5',
|
|
113
|
+
saveThreshold: '保存提醒线',
|
|
114
|
+
notifications: '通知设置',
|
|
115
|
+
notificationsHint: '所有应用默认接收通知;取消勾选的应用不会显示在手机端。',
|
|
116
|
+
allApps: '全部显示',
|
|
117
|
+
limit: '显示数量',
|
|
118
|
+
noApps: '还没有记录到通知应用。',
|
|
119
|
+
status: '服务状态',
|
|
120
|
+
statusHint: '当前系统服务能力。',
|
|
121
|
+
clients: '已连接设备',
|
|
122
|
+
clientsHint: '正在访问控制台的手机或浏览器。',
|
|
123
|
+
noClients: '当前没有已连接设备。',
|
|
124
|
+
disconnect: '断开',
|
|
125
|
+
diagnostics: '诊断信息',
|
|
126
|
+
pluginVersion: '插件版本',
|
|
127
|
+
protocol: '连接方式',
|
|
128
|
+
profileName: 'Profile',
|
|
129
|
+
notificationsStatus: '通知',
|
|
130
|
+
mediaStatus: '媒体',
|
|
131
|
+
volumeStatus: '音量',
|
|
132
|
+
weatherStatus: '天气',
|
|
133
|
+
healthy: '正常',
|
|
134
|
+
unavailable: '不可用',
|
|
135
|
+
checking: '待检测',
|
|
136
|
+
pageHome: '首页',
|
|
137
|
+
pageSessions: '会话',
|
|
138
|
+
pageMusic: '音乐',
|
|
139
|
+
moveUp: '上移',
|
|
140
|
+
moveDown: '下移',
|
|
141
|
+
noWebServer: '远程控制台页面暂不可用,请重启 DSH 后重试。',
|
|
142
|
+
serviceRunning: '服务运行中',
|
|
143
|
+
serviceStopped: '服务未运行',
|
|
144
|
+
menuPomodoro: '番茄钟/倒计时',
|
|
145
|
+
connectionHint: '扫码配对、可访问的网卡、访问验证与 HTTPS 证书。',
|
|
146
|
+
preferencesHint: '手机端的温度单位、主题、页面顺序与导航栏位置;修改后点击保存设置生效。',
|
|
147
|
+
navPosition: '导航栏位置',
|
|
148
|
+
navPositionHint: '选择手机控制台导航栏停靠在屏幕的哪一侧。',
|
|
149
|
+
navLeft: '左侧',
|
|
150
|
+
navRight: '右侧',
|
|
151
|
+
navTop: '上方',
|
|
152
|
+
navBottom: '下方',
|
|
153
|
+
pomodoro: '番茄钟/倒计时',
|
|
154
|
+
pomodoroHint: '手机端番茄钟与倒计时的启用、时长、预设与提示音;两者只能开启一个。',
|
|
155
|
+
pomodoroEnable: '启用番茄钟',
|
|
156
|
+
pomodoroEnableHint: '启用后,时钟下方会出现番茄钟卡片,并可设置专注与休息时长;启用倒计时会关闭番茄钟。',
|
|
157
|
+
pomodoroFocus: '专注时长(分钟)',
|
|
158
|
+
pomodoroBreak: '休息时长(分钟)',
|
|
159
|
+
pomodoroDurations: '专注与休息',
|
|
160
|
+
pomodoroDurationHint: '分钟数支持 2 位小数,超出允许范围时会自动调整。',
|
|
161
|
+
pomodoroSound: '提示音文件',
|
|
162
|
+
pomodoroSoundSection: '提示音',
|
|
163
|
+
pomodoroSoundHint: '番茄钟和倒计时结束时使用;留空则使用内置的轻柔提示音,也可以填写本机音频文件路径或 http(s) 链接。',
|
|
164
|
+
pomodoroSoundPlaceholder: '例如:D:\\sounds\\chime.mp3',
|
|
165
|
+
pomodoroLoop: '循环响铃直到停止',
|
|
166
|
+
pomodoroLoopHint: '开启后,时间到的提示音会循环播放,直到在手机端点击「停止响铃」才停止;关闭时只播放一次。',
|
|
167
|
+
countdown: '倒计时',
|
|
168
|
+
countdownHint: '最多可添加 5 个快速预设,按「分」「秒」填写,秒数会自动进位到分钟。',
|
|
169
|
+
countdownPresets: '倒计时预设',
|
|
170
|
+
countdownEnable: '启用倒计时',
|
|
171
|
+
countdownEnableHint: '启用后,时钟下方会出现倒计时卡片;与番茄钟互斥,开启此项会关闭番茄钟。',
|
|
172
|
+
countdownPreset1: '预设 1',
|
|
173
|
+
countdownPreset2: '预设 2',
|
|
174
|
+
countdownPreset3: '预设 3',
|
|
175
|
+
countdownPreset4: '预设 4',
|
|
176
|
+
countdownPreset5: '预设 5',
|
|
177
|
+
countdownPresetLimitHint: '最多 5 个',
|
|
178
|
+
addPreset: '添加预设',
|
|
179
|
+
removePreset: '删除',
|
|
180
|
+
peakValley: '显示梁文峰 / 梁文谷',
|
|
181
|
+
peakValleyHint: '在余额卡片右上角显示当前计费时段:工作日 9:00–12:00、14:00–18:00 为高峰;其余时间、周末与节假日为低谷,价格为高峰的一半。',
|
|
182
|
+
menuAppMapping: '软件映射',
|
|
183
|
+
appMapping: '软件映射',
|
|
184
|
+
appMappingHint: '通知和音乐中显示的应用名称;修改后立即保存。',
|
|
185
|
+
sourceNotification: '通知',
|
|
186
|
+
sourceMusic: '音乐',
|
|
187
|
+
resetName: '恢复默认',
|
|
188
|
+
locationPermission: '定位权限',
|
|
189
|
+
locationPermissionHint: 'Windows 定位需要系统隐私授权。点击下面的按钮申请定位权限;如果被拒绝,会自动打开系统「位置」设置页。开启「位置服务」和「允许桌面应用访问你的位置」后重试即可。',
|
|
190
|
+
locationRequest: '请求定位权限',
|
|
191
|
+
locationRequesting: '正在请求…',
|
|
192
|
+
locationAllowed: '定位权限已授予,天气会自动使用本机位置。',
|
|
193
|
+
locationPrivacyDenied: '系统拒绝了定位权限,已打开「位置」设置页;请开启「位置服务」和「允许桌面应用访问你的位置」后重试。',
|
|
194
|
+
locationLowIntegrity: '定位权限被系统拒绝,请按安装文档修复后重试。',
|
|
195
|
+
locationUnspecified: '系统还没有授予定位权限,已打开设置页,请手动开启后重试。',
|
|
196
|
+
locationFailed: '定位权限请求失败,请稍后重试。',
|
|
197
|
+
locationStatus: '当前状态',
|
|
198
|
+
accessAllowed: '已授权',
|
|
199
|
+
accessDenied: '已拒绝',
|
|
200
|
+
accessUnspecified: '未授权',
|
|
201
|
+
accessUnknown: '未知',
|
|
202
|
+
pushQuestions: '推送问询',
|
|
203
|
+
pushQuestionsHint: '开启后,等待回答的会话会显示完整问题与选项,可直接在手机上回复。',
|
|
204
|
+
tlsEnable: '启用 HTTPS',
|
|
205
|
+
weatherPageHint: '手机端天气的位置来源、显示方式与定位权限。',
|
|
206
|
+
weatherSource: '天气位置',
|
|
207
|
+
forecastDisplayHint: '选择天气卡片展示小时预报还是 7 天预报。',
|
|
208
|
+
balancePageHint: '手机端余额卡片的统计窗口、低余额提醒与峰谷标记。',
|
|
209
|
+
balanceSpend: '消耗统计',
|
|
210
|
+
peakValleyBlock: '梁文峰/谷标记',
|
|
211
|
+
peakValleyToggle: '显示峰谷标记',
|
|
212
|
+
notificationsPageHint: '手机端通知卡片的推送、可见应用与显示数量。',
|
|
213
|
+
notificationApps: '通知应用',
|
|
214
|
+
pushQuestionsToggle: '允许远程回答',
|
|
215
|
+
limitDisplay: '显示数量',
|
|
216
|
+
limitField: '数量',
|
|
217
|
+
notificationLimitHint: '手机端通知卡片最多显示的通知数量(1–20)。',
|
|
218
|
+
appsPageHint: '手机端通知和音乐里显示的应用名称;修改后立即保存。',
|
|
219
|
+
appNamesBlock: '应用名称',
|
|
220
|
+
systemPageHint: '服务运行状态、系统能力、已连接设备与诊断信息。',
|
|
221
|
+
diagnosticsHint: '插件/探针版本、协议、Profile 与运行时信息。',
|
|
222
|
+
performanceStatus: '性能',
|
|
223
|
+
locationCapability: '定位',
|
|
224
|
+
runtime: '系统能力',
|
|
225
|
+
runtimeHint: '原生探针与 Node.js 运行时的版本、平台和平台后端。',
|
|
226
|
+
probeVersion: '探针版本',
|
|
227
|
+
probeBackends: '平台后端',
|
|
228
|
+
probeBinary: '探针路径',
|
|
229
|
+
probeMissing: '探针不可用',
|
|
230
|
+
nodeVersion: 'Node.js 版本',
|
|
231
|
+
nodeV8: 'V8 版本',
|
|
232
|
+
nodeMemory: '内存占用',
|
|
233
|
+
nodePlatform: '平台',
|
|
234
|
+
backendMedia: '媒体',
|
|
235
|
+
backendVolume: '音量',
|
|
236
|
+
backendPerformance: '性能',
|
|
237
|
+
backendNotifications: '通知',
|
|
238
|
+
backendLocation: '定位',
|
|
239
|
+
device: '设备',
|
|
240
|
+
durationSeconds: '秒',
|
|
241
|
+
durationMinutes: '分钟',
|
|
242
|
+
durationHours: '小时',
|
|
243
|
+
durationDays: '天',
|
|
244
|
+
keepOneApp: '至少保留一个通知应用',
|
|
245
|
+
keepOnePage: '至少保留一个页面',
|
|
246
|
+
tlsPathsRequired: '请先填写证书和私钥路径',
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
export const en: Record<string, string> = {
|
|
250
|
+
title: 'Remote control',
|
|
251
|
+
kicker: 'REMOTE CONSOLE',
|
|
252
|
+
heading: 'Remote control',
|
|
253
|
+
subtitle: 'Connection, display, and preferences for the phone console.',
|
|
254
|
+
running: 'Running',
|
|
255
|
+
stopped: 'Stopped',
|
|
256
|
+
refresh: 'Refresh',
|
|
257
|
+
save: 'Save',
|
|
258
|
+
saved: 'Saved',
|
|
259
|
+
error: 'Action failed',
|
|
260
|
+
loading: 'Reading settings…',
|
|
261
|
+
pairing: 'Scan to connect',
|
|
262
|
+
pairingHint: 'Connect the phone to the same LAN and scan the QR code.',
|
|
263
|
+
open: 'Open on this computer',
|
|
264
|
+
copy: 'Copy link',
|
|
265
|
+
copied: 'Copied',
|
|
266
|
+
connection: 'Connection',
|
|
267
|
+
menuPlugin: 'Preferences',
|
|
268
|
+
menuNetwork: 'Open interfaces',
|
|
269
|
+
menuAccess: 'Access verification',
|
|
270
|
+
menuTheme: 'Theme & pages',
|
|
271
|
+
menuTls: 'HTTPS certificate',
|
|
272
|
+
menuWeather: 'Weather',
|
|
273
|
+
menuBalance: 'Balance display',
|
|
274
|
+
menuNotifications: 'Notifications',
|
|
275
|
+
menuSystem: 'System information',
|
|
276
|
+
menuStatus: 'Service status',
|
|
277
|
+
menuClients: 'Connected devices',
|
|
278
|
+
menuDiagnostics: 'Diagnostics',
|
|
279
|
+
network: 'Open network interfaces',
|
|
280
|
+
networkHint: 'Only devices on the checked interface subnets can access the console.',
|
|
281
|
+
pluginHint: 'Access, temperature unit, theme, page order, and HTTPS for the phone console; changes apply after Save.',
|
|
282
|
+
access: 'Access verification',
|
|
283
|
+
accessHint: 'When enabled, the first open requires the pairing link.',
|
|
284
|
+
token: 'Link verification',
|
|
285
|
+
rotate: 'Refresh verification',
|
|
286
|
+
rotateHint: 'Rotating disconnects existing devices; scan again to reconnect.',
|
|
287
|
+
theme: 'Theme & pages',
|
|
288
|
+
themeHint: 'Follow DSH, or force light or dark mode on the phone console.',
|
|
289
|
+
temperatureUnit: 'Temperature unit',
|
|
290
|
+
temperatureUnitHint: 'Temperature unit used by the phone weather and performance pages.',
|
|
291
|
+
celsius: 'Celsius (°C)',
|
|
292
|
+
fahrenheit: 'Fahrenheit (°F)',
|
|
293
|
+
followDsh: 'Follow DSH',
|
|
294
|
+
language: 'Plugin language',
|
|
295
|
+
languageHint: 'Interface language. English is used when a translation is missing.',
|
|
296
|
+
languageFollowDsh: 'Follow DSH',
|
|
297
|
+
light: 'Light',
|
|
298
|
+
dark: 'Dark',
|
|
299
|
+
pageOrder: 'Page order',
|
|
300
|
+
pageOrderHint: 'Drag to reorder the phone pages; disabled pages are hidden.',
|
|
301
|
+
tls: 'HTTPS certificate',
|
|
302
|
+
tlsHint: 'Optional. Provide certificate and private-key file paths, then enable HTTPS. Saving briefly drops connections.',
|
|
303
|
+
certPath: 'Certificate path',
|
|
304
|
+
keyPath: 'Private key path',
|
|
305
|
+
saveTls: 'Save certificate',
|
|
306
|
+
tlsOn: 'HTTPS is enabled',
|
|
307
|
+
tlsOff: 'HTTPS is not enabled',
|
|
308
|
+
tlsError: 'The certificate is invalid; still using HTTP',
|
|
309
|
+
weather: 'Weather',
|
|
310
|
+
weatherHint: 'Automatic location uses this computer first; Manual location lets you search for a city and fills the coordinates when you pick one.',
|
|
311
|
+
forecastDisplay: 'Weather card',
|
|
312
|
+
hourly: 'Hourly',
|
|
313
|
+
daily: '7-day',
|
|
314
|
+
saveSettings: 'Save settings',
|
|
315
|
+
pagePerformance: 'Performance',
|
|
316
|
+
auto: 'This computer',
|
|
317
|
+
manual: 'Manual location',
|
|
318
|
+
locationName: 'Location name',
|
|
319
|
+
latitude: 'Latitude',
|
|
320
|
+
longitude: 'Longitude',
|
|
321
|
+
saveLocation: 'Save location',
|
|
322
|
+
citySearchPlaceholder: 'Search for a city',
|
|
323
|
+
citySearchHint: 'Type a city and pick a suggestion to fill latitude and longitude automatically; you can also edit the coordinates directly.',
|
|
324
|
+
locationAutoHint: 'This-computer mode uses the system location; switch to Manual location to search or enter a city and coordinates.',
|
|
325
|
+
citySearching: 'Searching…',
|
|
326
|
+
cityNoResults: 'No matching city found',
|
|
327
|
+
citySearchFailed: 'City search failed; try again later',
|
|
328
|
+
citySearchUnavailable: 'City search is unavailable; restart DSH and retry',
|
|
329
|
+
balance: 'Balance display',
|
|
330
|
+
balanceHint: 'Choose this week or the last 7 days as the spend window.',
|
|
331
|
+
calendar: 'This week',
|
|
332
|
+
rolling: 'Last 7 days',
|
|
333
|
+
lowThreshold: 'Low-balance threshold',
|
|
334
|
+
lowThresholdHint: 'Below this amount the phone balance turns red. Leave empty to disable the alert.',
|
|
335
|
+
thresholdPlaceholder: 'e.g. 5',
|
|
336
|
+
saveThreshold: 'Save threshold',
|
|
337
|
+
notifications: 'Notifications',
|
|
338
|
+
notificationsHint: 'Every app is included by default; unchecked apps are hidden on the phone.',
|
|
339
|
+
allApps: 'Select all',
|
|
340
|
+
limit: 'Display limit',
|
|
341
|
+
noApps: 'No notification apps recorded yet.',
|
|
342
|
+
status: 'Service status',
|
|
343
|
+
statusHint: 'Capabilities of the current system service.',
|
|
344
|
+
clients: 'Connected devices',
|
|
345
|
+
clientsHint: 'Phones or browsers currently viewing the console.',
|
|
346
|
+
noClients: 'No devices are connected.',
|
|
347
|
+
disconnect: 'Disconnect',
|
|
348
|
+
diagnostics: 'Diagnostics',
|
|
349
|
+
pluginVersion: 'Plugin version',
|
|
350
|
+
protocol: 'Transport',
|
|
351
|
+
profileName: 'Profile',
|
|
352
|
+
notificationsStatus: 'Notifications',
|
|
353
|
+
mediaStatus: 'Media',
|
|
354
|
+
volumeStatus: 'Volume',
|
|
355
|
+
weatherStatus: 'Weather',
|
|
356
|
+
healthy: 'Healthy',
|
|
357
|
+
unavailable: 'Unavailable',
|
|
358
|
+
checking: 'Checking',
|
|
359
|
+
pageHome: 'Home',
|
|
360
|
+
pageSessions: 'Sessions',
|
|
361
|
+
pageMusic: 'Music',
|
|
362
|
+
moveUp: 'Move up',
|
|
363
|
+
moveDown: 'Move down',
|
|
364
|
+
noWebServer: 'The console page is unavailable; restart DSH and retry.',
|
|
365
|
+
serviceRunning: 'Service running',
|
|
366
|
+
serviceStopped: 'Service stopped',
|
|
367
|
+
menuPomodoro: 'Pomodoro / countdown',
|
|
368
|
+
connectionHint: 'Pairing, reachable interfaces, access verification, and the HTTPS certificate.',
|
|
369
|
+
preferencesHint: 'Temperature unit, theme, page order, and navigation placement for the phone console; save to apply.',
|
|
370
|
+
navPosition: 'Navigation bar',
|
|
371
|
+
navPositionHint: 'Choose where the phone navigation bar sits.',
|
|
372
|
+
navLeft: 'Left',
|
|
373
|
+
navRight: 'Right',
|
|
374
|
+
navTop: 'Top',
|
|
375
|
+
navBottom: 'Bottom',
|
|
376
|
+
pomodoro: 'Pomodoro / countdown',
|
|
377
|
+
pomodoroHint: 'Enable and configure the phone pomodoro and countdown; only one can be on.',
|
|
378
|
+
pomodoroEnable: 'Enable pomodoro',
|
|
379
|
+
pomodoroEnableHint: 'Show a pomodoro card below the clock and set focus and break lengths. Enabling the countdown turns the pomodoro off.',
|
|
380
|
+
pomodoroFocus: 'Focus minutes',
|
|
381
|
+
pomodoroBreak: 'Break minutes',
|
|
382
|
+
pomodoroDurations: 'Focus and break',
|
|
383
|
+
pomodoroDurationHint: 'Minutes accept two decimals and adjust to the allowed range automatically.',
|
|
384
|
+
pomodoroSound: 'Alert sound file',
|
|
385
|
+
pomodoroSoundSection: 'Alert sound',
|
|
386
|
+
pomodoroSoundHint: 'Used when the pomodoro or countdown ends. Leave empty for the built-in gentle chime, or use a local audio file path or http(s) URL.',
|
|
387
|
+
pomodoroSoundPlaceholder: 'e.g. D:\\sounds\\chime.mp3',
|
|
388
|
+
pomodoroLoop: 'Loop until stopped',
|
|
389
|
+
pomodoroLoopHint: 'When enabled, the end-of-timer sound repeats until you click Stop ringing on the phone. When disabled, it plays once.',
|
|
390
|
+
countdown: 'Countdown',
|
|
391
|
+
countdownHint: 'Add up to five quick presets in minutes and seconds; seconds carry into minutes automatically.',
|
|
392
|
+
countdownPresets: 'Countdown presets',
|
|
393
|
+
countdownEnable: 'Enable countdown',
|
|
394
|
+
countdownEnableHint: 'Show a countdown card below the clock. The pomodoro and countdown are mutually exclusive; enabling this turns the pomodoro off.',
|
|
395
|
+
countdownPreset1: 'Preset 1',
|
|
396
|
+
countdownPreset2: 'Preset 2',
|
|
397
|
+
countdownPreset3: 'Preset 3',
|
|
398
|
+
countdownPreset4: 'Preset 4',
|
|
399
|
+
countdownPreset5: 'Preset 5',
|
|
400
|
+
countdownPresetLimitHint: 'Up to 5',
|
|
401
|
+
addPreset: 'Add preset',
|
|
402
|
+
removePreset: 'Remove',
|
|
403
|
+
peakValley: 'Show peak / valley',
|
|
404
|
+
peakValleyHint: 'Show the current billing period in the balance card header: weekdays 09:00–12:00 and 14:00–18:00 are peak; other times, weekends and holidays are off-peak at half the peak price.',
|
|
405
|
+
menuAppMapping: 'App names',
|
|
406
|
+
appMapping: 'App names',
|
|
407
|
+
appMappingHint: 'App names shown in notifications and music; changes save immediately.',
|
|
408
|
+
sourceNotification: 'Notification',
|
|
409
|
+
sourceMusic: 'Music',
|
|
410
|
+
resetName: 'Reset',
|
|
411
|
+
locationPermission: 'Location permission',
|
|
412
|
+
locationPermissionHint: 'Windows location access needs a privacy grant. The button asks for permission; when it is denied, the system Location settings page opens. Enable "Location services" and "Let desktop apps access your location", then retry.',
|
|
413
|
+
locationRequest: 'Request location access',
|
|
414
|
+
locationRequesting: 'Requesting…',
|
|
415
|
+
locationAllowed: 'Location access granted; weather will use this computer position.',
|
|
416
|
+
locationPrivacyDenied: 'Windows denied location access and the Settings page was opened; enable "Location services" and "Let desktop apps access your location", then retry.',
|
|
417
|
+
locationLowIntegrity: 'Location access was denied by the system. Follow the installation guide to fix it, then retry.',
|
|
418
|
+
locationUnspecified: 'Location access has not been granted yet; the Settings page was opened.',
|
|
419
|
+
locationFailed: 'The location permission request failed; try again later.',
|
|
420
|
+
locationStatus: 'Current status',
|
|
421
|
+
accessAllowed: 'Allowed',
|
|
422
|
+
accessDenied: 'Denied',
|
|
423
|
+
accessUnspecified: 'Not granted',
|
|
424
|
+
accessUnknown: 'Unknown',
|
|
425
|
+
pushQuestions: 'Push inquiries',
|
|
426
|
+
pushQuestionsHint: 'When enabled, sessions waiting for an answer show the full questions and options, and you can reply from the phone.',
|
|
427
|
+
tlsEnable: 'Enable HTTPS',
|
|
428
|
+
weatherPageHint: 'Location source, display mode, and location permission for the phone weather page.',
|
|
429
|
+
weatherSource: 'Weather location',
|
|
430
|
+
forecastDisplayHint: 'Choose hourly or 7-day forecast for the weather card.',
|
|
431
|
+
balancePageHint: 'Spend window, low-balance alert, and peak/off-peak marker for the phone balance card.',
|
|
432
|
+
balanceSpend: 'Spend window',
|
|
433
|
+
peakValleyBlock: 'Peak / off-peak marker',
|
|
434
|
+
peakValleyToggle: 'Show peak/off-peak marker',
|
|
435
|
+
notificationsPageHint: 'Push questions, visible apps, and display limit for phone notifications.',
|
|
436
|
+
notificationApps: 'Notification apps',
|
|
437
|
+
pushQuestionsToggle: 'Allow remote answers',
|
|
438
|
+
limitDisplay: 'Display limit',
|
|
439
|
+
limitField: 'Count',
|
|
440
|
+
notificationLimitHint: 'Maximum number of notifications shown on the phone card (1–20).',
|
|
441
|
+
appsPageHint: 'App names shown in phone notifications and media; changes save immediately.',
|
|
442
|
+
appNamesBlock: 'App names',
|
|
443
|
+
systemPageHint: 'Service status, system capabilities, connected devices, and diagnostics.',
|
|
444
|
+
diagnosticsHint: 'Plugin/probe versions, transport, profile, and runtime details.',
|
|
445
|
+
performanceStatus: 'Performance',
|
|
446
|
+
locationCapability: 'Location',
|
|
447
|
+
runtime: 'System capabilities',
|
|
448
|
+
runtimeHint: 'Versions, platforms, and platform backends of the native probe and the Node.js runtime.',
|
|
449
|
+
probeVersion: 'Probe version',
|
|
450
|
+
probeBackends: 'Platform backends',
|
|
451
|
+
probeBinary: 'Probe path',
|
|
452
|
+
probeMissing: 'Probe unavailable',
|
|
453
|
+
nodeVersion: 'Node.js version',
|
|
454
|
+
nodeV8: 'V8 version',
|
|
455
|
+
nodeMemory: 'Memory',
|
|
456
|
+
nodePlatform: 'Platform',
|
|
457
|
+
backendMedia: 'Media',
|
|
458
|
+
backendVolume: 'Volume',
|
|
459
|
+
backendPerformance: 'Performance',
|
|
460
|
+
backendNotifications: 'Notifications',
|
|
461
|
+
backendLocation: 'Location',
|
|
462
|
+
device: 'Device',
|
|
463
|
+
durationSeconds: 'sec',
|
|
464
|
+
durationMinutes: 'min',
|
|
465
|
+
durationHours: 'h',
|
|
466
|
+
durationDays: 'd',
|
|
467
|
+
keepOneApp: 'Keep at least one notification app',
|
|
468
|
+
keepOnePage: 'Keep at least one page',
|
|
469
|
+
tlsPathsRequired: 'Fill in the certificate and private key paths first',
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
/** Every shipped dictionary, keyed by locale code. */
|
|
473
|
+
export const DICTS: Record<LocaleCode, Record<string, string>> = { zh, en };
|
|
474
|
+
|
|
475
|
+
let localeService: LocaleService | null = null;
|
|
476
|
+
let preference: PluginLanguage = 'dsh';
|
|
477
|
+
const listeners = new Set<() => void>();
|
|
478
|
+
|
|
479
|
+
/** Remember the host locale service so the panel can follow its locale. */
|
|
480
|
+
export function configureLocale(service: LocaleService): void {
|
|
481
|
+
localeService = service;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/** Active DSH locale id, or an empty string before the service is ready. */
|
|
485
|
+
export function dshLocaleId(): string {
|
|
486
|
+
try {
|
|
487
|
+
const snapshot = localeService?.getLocale?.() ?? localeService?.getSnapshot?.();
|
|
488
|
+
return String(snapshot?.active || '');
|
|
489
|
+
} catch {
|
|
490
|
+
return '';
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Resolve a preference plus the current DSH locale into a shipped language.
|
|
496
|
+
* Following DSH requires an exact locale-id match; the fallback is English.
|
|
497
|
+
*/
|
|
498
|
+
export function resolveLocale(preferenceValue: PluginLanguage, dshLocale: string): LocaleCode {
|
|
499
|
+
if (preferenceValue === 'zh' || preferenceValue === 'en') return preferenceValue;
|
|
500
|
+
const requested = String(dshLocale || '').trim().toLowerCase();
|
|
501
|
+
const exact = SUPPORTED_LOCALES.find((id) => id === requested);
|
|
502
|
+
return exact ?? 'en';
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/** Language currently used to render the panel. */
|
|
506
|
+
export function currentLocale(): LocaleCode {
|
|
507
|
+
return resolveLocale(preference, dshLocaleId());
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/** Remember the saved plugin language and repaint bound panels. */
|
|
511
|
+
export function setPluginLanguage(value: unknown): void {
|
|
512
|
+
const next: PluginLanguage = value === 'zh' || value === 'en' ? value : 'dsh';
|
|
513
|
+
if (next === preference) return;
|
|
514
|
+
preference = next;
|
|
515
|
+
notifyLanguage();
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/** Current preference (not the resolved language). */
|
|
519
|
+
export function getPluginLanguage(): PluginLanguage {
|
|
520
|
+
return preference;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/** Notify panels when the plugin language preference changes. */
|
|
524
|
+
export function subscribePluginLanguage(listener: () => void): () => void {
|
|
525
|
+
listeners.add(listener);
|
|
526
|
+
return () => {
|
|
527
|
+
listeners.delete(listener);
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function notifyLanguage(): void {
|
|
532
|
+
for (const listener of [...listeners]) {
|
|
533
|
+
try {
|
|
534
|
+
listener();
|
|
535
|
+
} catch {
|
|
536
|
+
/* one broken panel must not stop the others */
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/** Bundled dictionary lookup through the active language, then English. */
|
|
542
|
+
export function fallbackTranslate(key: string): string {
|
|
543
|
+
const dict = DICTS[currentLocale()];
|
|
544
|
+
return dict[key] ?? en[key] ?? key;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/** Translate one key with the plugin language preference applied. */
|
|
548
|
+
export function translate(key: string): string {
|
|
549
|
+
return fallbackTranslate(key);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* React hook that re-renders the panel when DSH changes locale or the saved
|
|
554
|
+
* plugin language changes. The translator reads the current state on every
|
|
555
|
+
* call, so only a version tick is needed here.
|
|
556
|
+
*/
|
|
557
|
+
export function useTranslator(): Translator {
|
|
558
|
+
const [, setVersion] = useState(0);
|
|
559
|
+
useEffect(() => {
|
|
560
|
+
const bump = (): void => setVersion((value) => value + 1);
|
|
561
|
+
const offLanguage = subscribePluginLanguage(bump);
|
|
562
|
+
const offLocale = localeService?.subscribe?.(bump);
|
|
563
|
+
return () => {
|
|
564
|
+
offLanguage();
|
|
565
|
+
try {
|
|
566
|
+
offLocale?.();
|
|
567
|
+
} catch {
|
|
568
|
+
/* ignore a disposed locale service */
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
}, []);
|
|
572
|
+
return translate;
|
|
573
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Small inline SVGs: the sidebar launcher and the section navigation icons. */
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
const h = React.createElement;
|
|
6
|
+
|
|
7
|
+
export interface PanelIconProps {
|
|
8
|
+
size?: number;
|
|
9
|
+
active?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface MenuIconProps {
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Sidebar launcher glyph: a phone beside a broadcast signal. */
|
|
17
|
+
export function PanelIcon({ size = 20, active = false }: PanelIconProps): React.ReactElement {
|
|
18
|
+
return h('svg', {
|
|
19
|
+
width: size,
|
|
20
|
+
height: size,
|
|
21
|
+
viewBox: '0 0 24 24',
|
|
22
|
+
fill: 'none',
|
|
23
|
+
'aria-hidden': true,
|
|
24
|
+
style: { display: 'block', color: active ? 'var(--dsw-alias-brand-primary)' : 'currentColor' },
|
|
25
|
+
},
|
|
26
|
+
h('rect', { x: 4.2, y: 2.8, width: 15.6, height: 18.4, rx: 4, stroke: 'currentColor', strokeWidth: 1.7 }),
|
|
27
|
+
h('path', { d: 'M9.3 18.1h5.4', stroke: 'currentColor', strokeWidth: 1.7, strokeLinecap: 'round' }),
|
|
28
|
+
h('circle', { cx: 12, cy: 10.5, r: 3.5, stroke: 'currentColor', strokeWidth: 1.7 }),
|
|
29
|
+
h('path', {
|
|
30
|
+
d: 'M2.6 8.2c-1 1.1-1.5 2.3-1.5 3.6 0 1.4.5 2.6 1.5 3.7M21.4 8.2c1 1.1 1.5 2.3 1.5 3.6 0 1.4-.5 2.6-1.5 3.7',
|
|
31
|
+
stroke: 'currentColor',
|
|
32
|
+
strokeWidth: 1.5,
|
|
33
|
+
strokeLinecap: 'round',
|
|
34
|
+
opacity: 0.7,
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const MENU_ICONS: Record<string, string> = {
|
|
39
|
+
link: '<path d="M9.5 14.5 14.5 9.5M7.1 16.9a3.5 3.5 0 0 1 0-5l2.1-2.1M16.9 7.1a3.5 3.5 0 0 1 0 5l-2.1 2.1" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>',
|
|
40
|
+
sliders: '<path d="M4 7h10M18 7h2M4 17h2M10 17h10" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/><circle cx="16" cy="7" r="2.4" stroke="currentColor" stroke-width="1.7"/><circle cx="8" cy="17" r="2.4" stroke="currentColor" stroke-width="1.7"/>',
|
|
41
|
+
cloud: '<path d="M6.5 18h10.2a4.3 4.3 0 0 0 .7-8.5A5.5 5.5 0 0 0 7 8.6 4.7 4.7 0 0 0 6.5 18Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/>',
|
|
42
|
+
wallet: '<rect x="3.5" y="6" width="17" height="13" rx="3" stroke="currentColor" stroke-width="1.7"/><path d="M3.5 10h17M16 14.5h2" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>',
|
|
43
|
+
bell: '<path d="M6 10a6 6 0 0 1 12 0c0 5 2 6 2 6H4s2-1 2-6ZM10 20h4" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
44
|
+
apps: '<rect x="3.5" y="3.5" width="7.2" height="7.2" rx="1.8" stroke="currentColor" stroke-width="1.7"/><rect x="13.3" y="3.5" width="7.2" height="7.2" rx="1.8" stroke="currentColor" stroke-width="1.7"/><rect x="3.5" y="13.3" width="7.2" height="7.2" rx="1.8" stroke="currentColor" stroke-width="1.7"/><rect x="13.3" y="13.3" width="7.2" height="7.2" rx="1.8" stroke="currentColor" stroke-width="1.7"/>',
|
|
45
|
+
timer: '<circle cx="12" cy="13.5" r="7" stroke="currentColor" stroke-width="1.7"/><path d="M12 9.5v4l2.8 1.7M9 2.8h6M12 2.8v2.2M18.8 6.2l1.5-1.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
46
|
+
info: '<circle cx="12" cy="12" r="8.5" stroke="currentColor" stroke-width="1.7"/><path d="M12 11v6M12 7.2v.2" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export function MenuIcon({ name }: MenuIconProps): React.ReactElement {
|
|
50
|
+
return h('svg', {
|
|
51
|
+
viewBox: '0 0 24 24',
|
|
52
|
+
fill: 'none',
|
|
53
|
+
'aria-hidden': true,
|
|
54
|
+
dangerouslySetInnerHTML: { __html: MENU_ICONS[name] || MENU_ICONS.info },
|
|
55
|
+
});
|
|
56
|
+
}
|