@velor/remote-mouse 6.4.8

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.
Files changed (316) hide show
  1. package/.artifacts/screenshots/remote-mobile-config.png +0 -0
  2. package/.artifacts/screenshots/remote-mobile-home.png +0 -0
  3. package/.artifacts/screenshots/remote-mobile-preferences.png +0 -0
  4. package/.artifacts/screenshots/remote-mobile-server-info.png +0 -0
  5. package/.artifacts/screenshots/remote-mobile-vlc.png +0 -0
  6. package/.env.example +93 -0
  7. package/README.md +370 -0
  8. package/bin/remote-mouse.js +19 -0
  9. package/client/core/dom.js +148 -0
  10. package/client/core/init-socket-io.js +117 -0
  11. package/client/core/socket-emit.js +6 -0
  12. package/client/core/window-events.js +23 -0
  13. package/client/i18n/apply-page-translations.js +18 -0
  14. package/client/i18n/constants.js +3 -0
  15. package/client/i18n/core.js +40 -0
  16. package/client/i18n/locale-registry.js +77 -0
  17. package/client/i18n/locales/de.js +227 -0
  18. package/client/i18n/locales/en.js +389 -0
  19. package/client/i18n/locales/es.js +228 -0
  20. package/client/i18n/locales/fr.js +389 -0
  21. package/client/i18n/locales/it.js +227 -0
  22. package/client/i18n/locales/ja.js +227 -0
  23. package/client/i18n/locales/pt.js +227 -0
  24. package/client/i18n/locales/ru.js +240 -0
  25. package/client/i18n/locales/zh.js +227 -0
  26. package/client/preferences/constants.js +15 -0
  27. package/client/preferences/effects.js +24 -0
  28. package/client/preferences/load.js +19 -0
  29. package/client/preferences/render.js +26 -0
  30. package/client/preferences/rows.js +78 -0
  31. package/client/preferences/state.js +29 -0
  32. package/client/preview/create-preview-frame-receiver.js +13 -0
  33. package/client/preview/draw.js +77 -0
  34. package/client/preview/parse-preview-frame.js +39 -0
  35. package/client/preview/preview-stream.js +152 -0
  36. package/client/services/app-state/appStateKeys.js +30 -0
  37. package/client/services/app-state/createAppStateService.js +216 -0
  38. package/client/services/app-state/createPersistStoreService.js +122 -0
  39. package/client/services/app-state/createStateStoreService.js +64 -0
  40. package/client/services/app-state/localStorageBinding.js +26 -0
  41. package/client/services/app-state/normalizers.js +74 -0
  42. package/client/services/app-state/resolveEffectiveStateValue.js +58 -0
  43. package/client/services/app-state/stateDefinitions.js +107 -0
  44. package/client/services/backend/createBackendService.js +55 -0
  45. package/client/services/config/ConfigView.js +45 -0
  46. package/client/services/config/createClientConfigService.js +122 -0
  47. package/client/services/config/defaultClientConfig.js +22 -0
  48. package/client/services/createServicesContainer.js +48 -0
  49. package/client/services/createServicesRegistry.js +26 -0
  50. package/client/services/i18n/createI18nService.js +86 -0
  51. package/client/services/notifications/createNotificationService.js +56 -0
  52. package/client/services/pubsub/createPubSubService.js +20 -0
  53. package/client/services/remotes/createRemotesService.js +20 -0
  54. package/client/services/transport/createSocketIoTransportService.js +50 -0
  55. package/client/touch/bindTouchPassthrough.js +94 -0
  56. package/client/touch/createTouchList.js +18 -0
  57. package/client/touch/dispatchSyntheticTouch.js +20 -0
  58. package/client/touch/gesture-zone.js +28 -0
  59. package/client/touch/throttle.js +46 -0
  60. package/client/touch/touch-handlers.js +193 -0
  61. package/client/touch/touchpad.js +231 -0
  62. package/client/ui/config/page.js +840 -0
  63. package/client/ui/main/applyRemoteVisibilityState.js +60 -0
  64. package/client/ui/main/bind-client-notifications.js +3 -0
  65. package/client/ui/main/bindings/bindAccordion.js +121 -0
  66. package/client/ui/main/bindings/bindActionButtons.js +13 -0
  67. package/client/ui/main/bindings/bindAdminDrawer.js +137 -0
  68. package/client/ui/main/bindings/bindAdminRemoteButtons.js +77 -0
  69. package/client/ui/main/bindings/bindAdminVersion.js +27 -0
  70. package/client/ui/main/bindings/bindBrowserRemoteButtons.js +119 -0
  71. package/client/ui/main/bindings/bindRemoteAccordion.js +23 -0
  72. package/client/ui/main/bindings/bindSamsungRemoteButtons.js +320 -0
  73. package/client/ui/main/bindings/bindSystemRemoteButtons.js +41 -0
  74. package/client/ui/main/bindings/bindVlcRemoteButtons.js +64 -0
  75. package/client/ui/main/canvas-ui.js +33 -0
  76. package/client/ui/main/connection-overlay.js +57 -0
  77. package/client/ui/main/init-ui.js +54 -0
  78. package/client/ui/main/keyboard-panel.js +271 -0
  79. package/client/ui/main/mouse-buttons.js +94 -0
  80. package/client/ui/main/page.js +21 -0
  81. package/client/ui/notifications/show-toast.js +48 -0
  82. package/client/ui/preferences/bindPreferenceSwitchers.js +49 -0
  83. package/client/ui/preferences/page.js +61 -0
  84. package/client/ui/preferences/switchers.js +200 -0
  85. package/index.js +9 -0
  86. package/package.json +41 -0
  87. package/public/admin-config.css +447 -0
  88. package/public/admin-config.html +63 -0
  89. package/public/apple-touch-icon.png +0 -0
  90. package/public/brave-icon.svg +13 -0
  91. package/public/favicon.svg +30 -0
  92. package/public/icon-192.png +0 -0
  93. package/public/icon-512.png +0 -0
  94. package/public/index.html +246 -0
  95. package/public/manifest.webmanifest +45 -0
  96. package/public/preferences.html +55 -0
  97. package/public/server-info.html +574 -0
  98. package/public/styles.css +1042 -0
  99. package/public/sw.js +103 -0
  100. package/scripts/codex-commit.sh +112 -0
  101. package/scripts/generate-mobile-screenshots.mjs +244 -0
  102. package/scripts/install-linux.sh +633 -0
  103. package/scripts/install-windows.ps1 +369 -0
  104. package/server/application/createApplicationLifecycle.js +15 -0
  105. package/server/application/logger.js +216 -0
  106. package/server/application/shutdown.js +81 -0
  107. package/server/application/start.js +95 -0
  108. package/server/application/state.js +19 -0
  109. package/server/connection/api/admin-actions.router.js +65 -0
  110. package/server/connection/api/admin-configs.router.js +165 -0
  111. package/server/connection/api/admin-remotes.router.js +61 -0
  112. package/server/connection/api/admin-subs.router.js +49 -0
  113. package/server/connection/api/client.router.js +15 -0
  114. package/server/connection/api/configs.js +96 -0
  115. package/server/connection/api/qr-page.handler.js +17 -0
  116. package/server/connection/api/remotes.router.js +30 -0
  117. package/server/connection/api/server-info.router.js +149 -0
  118. package/server/connection/api/session.middleware.js +93 -0
  119. package/server/connection/api/unauthorized-response.js +73 -0
  120. package/server/connection/socket/createConnectionRegistrar.js +23 -0
  121. package/server/connection/socket/createSocketSessionAuthMiddleware.js +49 -0
  122. package/server/connection/socket/socket-action-responder.js +12 -0
  123. package/server/connection/socket/socket.timestamp-middleware.js +51 -0
  124. package/server/index.js +12 -0
  125. package/server/init/bootstrapApi.js +87 -0
  126. package/server/init/bootstrapSocket.js +79 -0
  127. package/server/init/createAdminApiRouter.js +22 -0
  128. package/server/init/createAdminUiRouter.js +21 -0
  129. package/server/init/createSocketActionRegistrars.js +52 -0
  130. package/server/init/observers/startConfigObserver.js +51 -0
  131. package/server/init/observers/startDisplaySizeObserver.js +55 -0
  132. package/server/init/observers/startNotificationObserver.js +49 -0
  133. package/server/init/observers/startQrOverlayHoverObserver.js +89 -0
  134. package/server/init/observers/startQrOverlayRefreshObserver.js +53 -0
  135. package/server/os/darwin/app.js +45 -0
  136. package/server/os/darwin/applescript.js +51 -0
  137. package/server/os/darwin/cliSocket.js +53 -0
  138. package/server/os/darwin/url.js +9 -0
  139. package/server/os/darwin/window.js +10 -0
  140. package/server/os/linux/app.js +120 -0
  141. package/server/os/linux/cliSocket.js +53 -0
  142. package/server/os/linux/process.js +69 -0
  143. package/server/os/linux/screen.js +58 -0
  144. package/server/os/linux/systemd.js +139 -0
  145. package/server/os/linux/url.js +17 -0
  146. package/server/os/linux/windows.js +144 -0
  147. package/server/os/win32/app.js +66 -0
  148. package/server/os/win32/cliSocket.js +15 -0
  149. package/server/os/win32/powershell.js +70 -0
  150. package/server/os/win32/process.js +20 -0
  151. package/server/os/win32/service.js +95 -0
  152. package/server/os/win32/url.js +9 -0
  153. package/server/os/win32/window.js +10 -0
  154. package/server/remotes/admin/createAdminEventGuardMiddleware.js +29 -0
  155. package/server/remotes/admin/createForceUpdateCheckAction.js +39 -0
  156. package/server/remotes/admin/createInstallUpdateAction.js +64 -0
  157. package/server/remotes/admin/createOpenQrBrowserAction.js +63 -0
  158. package/server/remotes/admin/createOpenServerInfoBrowserAction.js +58 -0
  159. package/server/remotes/admin/createRestartServiceAction.js +20 -0
  160. package/server/remotes/admin/createRotateEntryTokenAction.js +43 -0
  161. package/server/remotes/admin/createToggleQrOverlayAction.js +38 -0
  162. package/server/remotes/admin/index.js +32 -0
  163. package/server/remotes/admin/notifyIfRestarted.js +102 -0
  164. package/server/remotes/admin/registrar.js +94 -0
  165. package/server/remotes/browser/actions/createFocusOrLaunchBrowserAction.js +22 -0
  166. package/server/remotes/browser/actions/openUrlOnHost.js +3 -0
  167. package/server/remotes/browser/browserCatalog.js +70 -0
  168. package/server/remotes/browser/index.js +15 -0
  169. package/server/remotes/browser/listBrowsersOnHost.js +23 -0
  170. package/server/remotes/browser/registrar.js +29 -0
  171. package/server/remotes/browser/spec.js +18 -0
  172. package/server/remotes/browser/state.js +5 -0
  173. package/server/remotes/input/registrar.js +39 -0
  174. package/server/remotes/preview/bgraToRgbaBuffer.js +20 -0
  175. package/server/remotes/preview/captureAroundCursor.js +19 -0
  176. package/server/remotes/preview/createPreviewStreamer.js +85 -0
  177. package/server/remotes/preview/registrar.js +34 -0
  178. package/server/remotes/samsung/createSamsungCommandService.js +203 -0
  179. package/server/remotes/samsung/createSamsungRemote.js +26 -0
  180. package/server/remotes/samsung/createSamsungRemoteGetter.js +46 -0
  181. package/server/remotes/samsung/createSamsungTvGetter.js +102 -0
  182. package/server/remotes/samsung/device-config.js +122 -0
  183. package/server/remotes/samsung/registrar.js +59 -0
  184. package/server/remotes/samsung/utils.js +56 -0
  185. package/server/remotes/vlc/index.js +39 -0
  186. package/server/remotes/vlc/registrar.js +94 -0
  187. package/server/remotes/vlc/spec.js +15 -0
  188. package/server/remotes/vlc/state.js +5 -0
  189. package/server/remotes/window/index.js +6 -0
  190. package/server/remotes/window/registrar.js +28 -0
  191. package/server/services/application/createApplicationDaemonService.js +144 -0
  192. package/server/services/application/getDaemonServiceAdapter.js +56 -0
  193. package/server/services/application/utils.js +29 -0
  194. package/server/services/config/bootstrapConfig.js +38 -0
  195. package/server/services/config/configPaths.js +42 -0
  196. package/server/services/config/configSchema.js +297 -0
  197. package/server/services/config/configService.js +89 -0
  198. package/server/services/config/defaultConfig.js +137 -0
  199. package/server/services/config/envConfig.js +49 -0
  200. package/server/services/config/index.js +9 -0
  201. package/server/services/config/logConfig.js +54 -0
  202. package/server/services/config/system-config.js +44 -0
  203. package/server/services/createServicesContainer.js +94 -0
  204. package/server/services/createServicesRegistry.js +48 -0
  205. package/server/services/input/createInputController.js +17 -0
  206. package/server/services/input/createKeyboardController.js +146 -0
  207. package/server/services/input/createMouseController.js +182 -0
  208. package/server/services/notifier/createClientNotifier.js +23 -0
  209. package/server/services/notifier/createHostNotifier.js +41 -0
  210. package/server/services/notifier/createNotifier.js +13 -0
  211. package/server/services/notifier/createNotifierComposite.js +122 -0
  212. package/server/services/notifier/handleOpenQrBrowserEvent.js +40 -0
  213. package/server/services/notifier/handleOpenServerInfoBrowserEvent.js +40 -0
  214. package/server/services/notifier/handleRestartServiceEvent.js +37 -0
  215. package/server/services/notifier/handleRotateEntryTokenEvent.js +42 -0
  216. package/server/services/notifier/handleSessionEvent.js +24 -0
  217. package/server/services/notifier/handleToggleQrOverlayEvent.js +21 -0
  218. package/server/services/notifier/host-notifier/createLinuxHostNotifier.js +23 -0
  219. package/server/services/notifier/host-notifier/createNodeNotifierHostNotifier.js +24 -0
  220. package/server/services/notifier/host-notifier/index.js +11 -0
  221. package/server/services/notifier/mapper/handleForceUpdateCheckEvent.js +24 -0
  222. package/server/services/notifier/mapper/handleInstallUpdateEvent.js +53 -0
  223. package/server/services/notifier/mapper/handleSocketEvent.js +40 -0
  224. package/server/services/notifier/mapper/handleUpdateManagerEvent.js +24 -0
  225. package/server/services/notifier/mapper/notify.js +7 -0
  226. package/server/services/os/index.js +23 -0
  227. package/server/services/os/platforms/createFallbackAdapter.js +31 -0
  228. package/server/services/os/platforms/darwin/app.js +6 -0
  229. package/server/services/os/platforms/darwin/index.js +21 -0
  230. package/server/services/os/platforms/darwin/scripts.js +4 -0
  231. package/server/services/os/platforms/darwin/url.js +1 -0
  232. package/server/services/os/platforms/darwin/window.js +4 -0
  233. package/server/services/os/platforms/linux/app.js +6 -0
  234. package/server/services/os/platforms/linux/index.js +33 -0
  235. package/server/services/os/platforms/linux/url.js +1 -0
  236. package/server/services/os/platforms/linux/windows.js +11 -0
  237. package/server/services/os/platforms/win32/app.js +6 -0
  238. package/server/services/os/platforms/win32/index.js +21 -0
  239. package/server/services/os/platforms/win32/overlay.js +6 -0
  240. package/server/services/os/platforms/win32/powershell.js +4 -0
  241. package/server/services/os/platforms/win32/url.js +1 -0
  242. package/server/services/os/platforms/win32/window.js +4 -0
  243. package/server/services/os/shared.js +2 -0
  244. package/server/services/overlay/createNoopOverlay.js +13 -0
  245. package/server/services/overlay/createQrOverlay.js +27 -0
  246. package/server/services/overlay/createQrOverlayWin32.js +158 -0
  247. package/server/services/overlay/createQrOverlayYad.js +178 -0
  248. package/server/services/overlay/renderQrPage.js +82 -0
  249. package/server/services/persistence/createConfigDao.js +106 -0
  250. package/server/services/persistence/createDatabaseProvider.js +23 -0
  251. package/server/services/persistence/createEntryTokenDao.js +140 -0
  252. package/server/services/persistence/createRestartLogDao.js +210 -0
  253. package/server/services/persistence/index.js +19 -0
  254. package/server/services/pubsub/createEventStore.js +54 -0
  255. package/server/services/pubsub/createPubSub.js +89 -0
  256. package/server/services/pubsub/createServiceEvents.js +29 -0
  257. package/server/services/pubsub/serviceEventConstants.js +39 -0
  258. package/server/services/remotes/createRemotes.js +25 -0
  259. package/server/services/server/createHttpsServer.js +12 -0
  260. package/server/services/server/createServer.js +66 -0
  261. package/server/services/sse/createSseService.js +96 -0
  262. package/server/services/sse/utils.js +7 -0
  263. package/server/services/system/createSystemService.js +170 -0
  264. package/server/services/system/getNetworkInfo.js +18 -0
  265. package/server/services/system/getScreenInfo.js +32 -0
  266. package/server/services/system/listNetworkInterfaces.js +27 -0
  267. package/server/services/task-manager/createTaskManager.js +68 -0
  268. package/server/services/task-runner/createTaskRunner.js +114 -0
  269. package/server/services/token-manager/createTokenManager.js +244 -0
  270. package/server/services/token-manager/token-format.js +7 -0
  271. package/server/services/token-manager/token-store-utils.js +8 -0
  272. package/server/services/update-manager/CommandUpdateSource.js +70 -0
  273. package/server/services/update-manager/NpmUpdateSource.js +34 -0
  274. package/server/services/update-manager/buildNpmGlobalUpdateCommand.js +15 -0
  275. package/server/services/update-manager/chooseUpdateCheckSource.js +20 -0
  276. package/server/services/update-manager/chooseUpdateInstallSource.js +5 -0
  277. package/server/services/update-manager/createUpdateManager.js +109 -0
  278. package/server/services/update-manager/resolveInstallUpdateCommand.js +42 -0
  279. package/server/term/cli/executeLocalServiceCommand.js +42 -0
  280. package/server/term/cli/getCliSocketPath.js +5 -0
  281. package/server/term/cli/parseCliArgs.js +110 -0
  282. package/server/term/cli/printCliResult.js +18 -0
  283. package/server/term/cli/runCliCmd.js +50 -0
  284. package/server/term/cli/sendCliCommand.js +76 -0
  285. package/server/term/cliSocket.js +29 -0
  286. package/server/term/srv/commands/configCommand.js +84 -0
  287. package/server/term/srv/commands/helpCommand.js +6 -0
  288. package/server/term/srv/commands/infoCommand.js +7 -0
  289. package/server/term/srv/commands/openQrCommand.js +7 -0
  290. package/server/term/srv/commands/samsungDetectCommand.js +52 -0
  291. package/server/term/srv/commands/serviceCommand.js +25 -0
  292. package/server/term/srv/commands/systemConfigCommand.js +7 -0
  293. package/server/term/srv/commands/tasksCommand.js +24 -0
  294. package/server/term/srv/commands/tokensCommand.js +15 -0
  295. package/server/term/srv/executeCliCommand.js +44 -0
  296. package/server/term/srv/executeCliRequest.js +38 -0
  297. package/server/term/srv/startCliServer.js +140 -0
  298. package/server/utils/createRandomToken.js +11 -0
  299. package/server/utils/env.js +155 -0
  300. package/server/utils/git.js +13 -0
  301. package/server/utils/http.js +7 -0
  302. package/server/utils/network.js +45 -0
  303. package/server/utils/paths.js +10 -0
  304. package/server/utils/process.js +57 -0
  305. package/server/utils/robot.js +11 -0
  306. package/server/utils/semver.js +33 -0
  307. package/server/utils/truncateText.js +7 -0
  308. package/utils/createLazy.js +13 -0
  309. package/utils/functional.js +48 -0
  310. package/utils/math.js +26 -0
  311. package/utils/notificationSettings.js +61 -0
  312. package/utils/object.utils.js +79 -0
  313. package/utils/predicates.js +17 -0
  314. package/utils/remoteCommands.js +40 -0
  315. package/utils/sync.js +3 -0
  316. package/velor-remote-mouse-6.4.8.tgz +0 -0
@@ -0,0 +1,200 @@
1
+ import {localeRegistry} from '../../i18n/locale-registry.js';
2
+
3
+ function applySwitcherLabelStyle(label) {
4
+ label.style.fontSize = '12px';
5
+ label.style.color = 'var(--muted)';
6
+ }
7
+
8
+ function applySwitcherSelectStyle(select) {
9
+ select.style.fontSize = '12px';
10
+ select.style.borderRadius = '8px';
11
+ select.style.padding = '3px 8px';
12
+ select.style.border = '1px solid var(--border, rgba(255, 255, 255, 0.16))';
13
+ select.style.background = 'var(--panel-strong, rgba(255, 255, 255, 0.08))';
14
+ select.style.color = 'var(--text)';
15
+ }
16
+
17
+ function ensureSwitcherRoot({
18
+ rootSelector,
19
+ rootDatasetKey,
20
+ labelDatasetKey,
21
+ selectDatasetKey,
22
+ hostSelectors,
23
+ }) {
24
+ const host = hostSelectors
25
+ .map((selector) => document.querySelector(selector))
26
+ .find(Boolean);
27
+
28
+ let root = document.querySelector(rootSelector);
29
+ if (!root) {
30
+ root = document.createElement('div');
31
+ root.dataset[rootDatasetKey] = 'true';
32
+ root.style.display = 'flex';
33
+ root.style.alignItems = 'center';
34
+ root.style.gap = '6px';
35
+
36
+ const label = document.createElement('span');
37
+ label.dataset[labelDatasetKey] = 'true';
38
+ applySwitcherLabelStyle(label);
39
+
40
+ const select = document.createElement('select');
41
+ select.dataset[selectDatasetKey] = 'true';
42
+ applySwitcherSelectStyle(select);
43
+
44
+ root.append(label, select);
45
+ (host || document.body).appendChild(root);
46
+ }
47
+
48
+ return root;
49
+ }
50
+
51
+ export function mountLanguageSwitcher({locale, t, onChange}) {
52
+ const root = ensureSwitcherRoot({
53
+ rootSelector: '[data-language-switcher]',
54
+ rootDatasetKey: 'languageSwitcher',
55
+ labelDatasetKey: 'languageLabel',
56
+ selectDatasetKey: 'languageSelect',
57
+ hostSelectors: ['[data-client-prefs-host]', '[data-language-switcher-host]'],
58
+ });
59
+
60
+ const select = root.querySelector('[data-language-select]');
61
+ if (select && select.options.length === 0) {
62
+ for (const nextLocale of Object.keys(localeRegistry)) {
63
+ const option = document.createElement('option');
64
+ option.value = nextLocale;
65
+ option.textContent = localeRegistry[nextLocale].label;
66
+ select.appendChild(option);
67
+ }
68
+
69
+ if (typeof onChange === 'function') {
70
+ select.addEventListener('change', () => {
71
+ void onChange(select.value);
72
+ });
73
+ }
74
+ }
75
+
76
+ if (select) {
77
+ select.value = locale;
78
+ select.setAttribute('aria-label', t('common.language'));
79
+ }
80
+
81
+ const label = root.querySelector('[data-language-label]');
82
+ if (label) {
83
+ label.textContent = t('common.languageShort');
84
+ }
85
+ }
86
+
87
+ export function mountThemeSwitcher({theme, t, onChange}) {
88
+ const root = ensureSwitcherRoot({
89
+ rootSelector: '[data-theme-switcher]',
90
+ rootDatasetKey: 'themeSwitcher',
91
+ labelDatasetKey: 'themeLabel',
92
+ selectDatasetKey: 'themeSelect',
93
+ hostSelectors: ['[data-client-prefs-host]', '[data-language-switcher-host]'],
94
+ });
95
+
96
+ const select = root.querySelector('[data-theme-select]');
97
+ if (select && select.options.length === 0) {
98
+ for (const nextTheme of ['dark', 'light']) {
99
+ const option = document.createElement('option');
100
+ option.value = nextTheme;
101
+ select.appendChild(option);
102
+ }
103
+
104
+ if (typeof onChange === 'function') {
105
+ select.addEventListener('change', () => {
106
+ onChange(select.value);
107
+ });
108
+ }
109
+ }
110
+
111
+ if (select) {
112
+ select.value = theme;
113
+ select.setAttribute('aria-label', t('common.theme'));
114
+ for (const option of select.options) {
115
+ option.textContent = t(`common.theme.${option.value}`);
116
+ }
117
+ }
118
+
119
+ const label = root.querySelector('[data-theme-label]');
120
+ if (label) {
121
+ label.textContent = t('common.themeShort');
122
+ }
123
+ }
124
+
125
+ export function mountHandednessSwitcher({handedness, t, onChange}) {
126
+ const root = ensureSwitcherRoot({
127
+ rootSelector: '[data-handedness-switcher]',
128
+ rootDatasetKey: 'handednessSwitcher',
129
+ labelDatasetKey: 'handednessLabel',
130
+ selectDatasetKey: 'handednessSelect',
131
+ hostSelectors: ['[data-client-prefs-host]', '[data-language-switcher-host]'],
132
+ });
133
+
134
+ const select = root.querySelector('[data-handedness-select]');
135
+ if (select && select.options.length === 0) {
136
+ for (const nextHandedness of ['right', 'left']) {
137
+ const option = document.createElement('option');
138
+ option.value = nextHandedness;
139
+ select.appendChild(option);
140
+ }
141
+
142
+ if (typeof onChange === 'function') {
143
+ select.addEventListener('change', () => {
144
+ onChange(select.value);
145
+ });
146
+ }
147
+ }
148
+
149
+ if (select) {
150
+ select.value = handedness;
151
+ select.setAttribute('aria-label', t('common.handedness'));
152
+ for (const option of select.options) {
153
+ option.textContent = t(`common.handedness.${option.value}`);
154
+ }
155
+ }
156
+
157
+ const label = root.querySelector('[data-handedness-label]');
158
+ if (label) {
159
+ label.textContent = t('common.handednessShort');
160
+ }
161
+ }
162
+
163
+ export function mountRemoteAutoHideSwitcher({enabled, t, onChange}) {
164
+ const root = ensureSwitcherRoot({
165
+ rootSelector: '[data-remote-auto-hide-switcher]',
166
+ rootDatasetKey: 'remoteAutoHideSwitcher',
167
+ labelDatasetKey: 'remoteAutoHideLabel',
168
+ selectDatasetKey: 'remoteAutoHideSelect',
169
+ hostSelectors: ['[data-remote-auto-hide-host]', '[data-client-prefs-host]', '[data-language-switcher-host]'],
170
+ });
171
+
172
+ const select = root.querySelector('[data-remote-auto-hide-select]');
173
+ if (select && select.options.length === 0) {
174
+ for (const [value, key] of [['true', 'common.enabled'], ['false', 'common.disabled']]) {
175
+ const option = document.createElement('option');
176
+ option.value = value;
177
+ option.dataset.i18nKey = key;
178
+ select.appendChild(option);
179
+ }
180
+
181
+ if (typeof onChange === 'function') {
182
+ select.addEventListener('change', () => {
183
+ onChange(select.value === 'true');
184
+ });
185
+ }
186
+ }
187
+
188
+ if (select) {
189
+ select.value = enabled ? 'true' : 'false';
190
+ select.setAttribute('aria-label', t('common.remoteAutoHide'));
191
+ for (const option of select.options) {
192
+ option.textContent = t(option.dataset.i18nKey);
193
+ }
194
+ }
195
+
196
+ const label = root.querySelector('[data-remote-auto-hide-label]');
197
+ if (label) {
198
+ label.textContent = t('common.remoteAutoHideShort');
199
+ }
200
+ }
package/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { startServer } from './server/index.js';
2
+ import { createLogger } from './server/application/logger.js';
3
+
4
+ const log = createLogger('bootstrap');
5
+
6
+ startServer().catch((error) => {
7
+ log.error({ err: error }, 'Erreur au démarrage');
8
+ process.exit(1);
9
+ });
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@velor/remote-mouse",
3
+ "version": "6.4.8",
4
+ "type": "module",
5
+ "description": "Remote mouse and keyboard with mobile client",
6
+ "main": "index.js",
7
+ "bin": {
8
+ "remote-mouse": "./bin/remote-mouse.js"
9
+ },
10
+ "scripts": {
11
+ "start": "node index.js",
12
+ "dev": "node index.js",
13
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest --runInBand --coverage",
14
+ "test:install": "NODE_OPTIONS=--experimental-vm-modules jest test/unit/install-scripts.test.js --runInBand",
15
+ "test:install:integration": "node test/integration/install/run-linux-install.mjs",
16
+ "test:all": "npm test && npm run test:e2e",
17
+ "test:e2e": "playwright test",
18
+ "screenshots:mobile": "node scripts/generate-mobile-screenshots.mjs",
19
+ "commit:codex": "bash scripts/codex-commit.sh"
20
+ },
21
+ "dependencies": {
22
+ "@hurdlegroup/robotjs": "^0.12.3",
23
+ "better-sqlite3": "^12.8.0",
24
+ "cookie-parser": "^1.4.7",
25
+ "dotenv": "^17.3.1",
26
+ "express": "^4.21.2",
27
+ "node-notifier": "^10.0.1",
28
+ "pino": "^9.5.0",
29
+ "pino-pretty": "^13.0.0",
30
+ "qrcode": "^1.5.4",
31
+ "qrcode-terminal": "^0.12.0",
32
+ "samsung-tv-remote": "^3.0.4",
33
+ "socket.io": "^4.8.1",
34
+ "yargs": "^15.4.1"
35
+ },
36
+ "devDependencies": {
37
+ "@playwright/test": "^1.59.1",
38
+ "jest": "^30.3.0",
39
+ "sinon": "^21.0.3"
40
+ }
41
+ }
@@ -0,0 +1,447 @@
1
+ :root {
2
+ color-scheme: dark;
3
+ --bg: #11161a;
4
+ --bg-soft: #192127;
5
+ --panel: rgba(21, 29, 35, 0.84);
6
+ --panel-strong: rgba(31, 43, 51, 0.96);
7
+ --border: rgba(174, 212, 226, 0.16);
8
+ --text: #eef5f8;
9
+ --muted: #9bb2bd;
10
+ --accent: #80e3ff;
11
+ --accent-2: #ffd27b;
12
+ --danger: #ff8f8f;
13
+ }
14
+
15
+ html[data-theme="light"] {
16
+ color-scheme: light;
17
+ --bg: #eef4f7;
18
+ --bg-soft: #dde8ee;
19
+ --panel: rgba(255, 255, 255, 0.9);
20
+ --panel-strong: rgba(244, 249, 252, 0.98);
21
+ --border: rgba(32, 75, 97, 0.14);
22
+ --text: #18303a;
23
+ --muted: #5e7886;
24
+ --accent: #0a8ab8;
25
+ --accent-2: #b67d17;
26
+ --danger: #c25a5a;
27
+ }
28
+
29
+ * {
30
+ box-sizing: border-box;
31
+ }
32
+
33
+ html,
34
+ body {
35
+ margin: 0;
36
+ min-height: 100%;
37
+ background:
38
+ radial-gradient(circle at top left, rgba(62, 98, 120, 0.28), transparent 32%),
39
+ linear-gradient(180deg, #0d1215, #12191e 55%, #0f1519);
40
+ color: var(--text);
41
+ font-family: system-ui, -apple-system, Segoe UI, sans-serif;
42
+ }
43
+
44
+ body {
45
+ padding: 20px;
46
+ }
47
+
48
+ .page-toolbar {
49
+ width: min(1200px, 100%);
50
+ margin: 0 auto 12px;
51
+ display: flex;
52
+ justify-content: flex-end;
53
+ }
54
+
55
+ .page-toolbar-actions {
56
+ display: flex;
57
+ gap: 10px;
58
+ align-items: center;
59
+ }
60
+
61
+ .page-toolbar-actions[data-client-prefs-host] {
62
+ display: grid;
63
+ gap: 12px;
64
+ justify-items: stretch;
65
+ }
66
+
67
+ .page-toolbar-actions[data-client-prefs-host] > div,
68
+ .page-toolbar-actions[data-remote-auto-hide-host] > div {
69
+ display: grid !important;
70
+ grid-template-columns: minmax(110px, 140px) minmax(0, 1fr);
71
+ gap: 10px !important;
72
+ align-items: center !important;
73
+ }
74
+
75
+ .preferences-remotes-settings {
76
+ display: grid;
77
+ gap: 12px;
78
+ justify-items: stretch;
79
+ }
80
+
81
+ .preferences-section-separator {
82
+ width: 100%;
83
+ height: 1px;
84
+ margin: -4px 0 0;
85
+ border: 0;
86
+ background: var(--border);
87
+ }
88
+
89
+ .preferences-remotes-list {
90
+ display: grid;
91
+ gap: 12px;
92
+ }
93
+
94
+ .preferences-remote-row {
95
+ display: grid;
96
+ grid-template-columns: minmax(110px, 140px) minmax(0, 1fr);
97
+ gap: 10px;
98
+ align-items: center !important;
99
+ }
100
+
101
+ .preferences-remote-label {
102
+ color: var(--muted);
103
+ font-size: 12px;
104
+ font-weight: 400;
105
+ }
106
+
107
+ .preferences-remote-select {
108
+ width: 100%;
109
+ font: inherit;
110
+ font-size: 12px;
111
+ border-radius: 8px;
112
+ min-height: 0;
113
+ padding: 3px 8px;
114
+ border: 1px solid var(--border);
115
+ background: var(--panel-strong);
116
+ color: var(--text);
117
+ }
118
+
119
+ .config-page {
120
+ width: min(1200px, 100%);
121
+ margin: 0 auto;
122
+ display: grid;
123
+ gap: 18px;
124
+ }
125
+
126
+ .config-hero,
127
+ .status-bar,
128
+ .config-section {
129
+ border: 1px solid var(--border);
130
+ background: var(--panel);
131
+ backdrop-filter: blur(10px);
132
+ border-radius: 22px;
133
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.24);
134
+ }
135
+
136
+ html[data-theme="light"] .config-hero,
137
+ html[data-theme="light"] .status-bar,
138
+ html[data-theme="light"] .config-section {
139
+ box-shadow: 0 18px 44px rgba(73, 111, 130, 0.14);
140
+ }
141
+
142
+ .config-hero {
143
+ padding: 22px;
144
+ display: grid;
145
+ gap: 16px;
146
+ grid-template-columns: minmax(0, 1fr) auto;
147
+ align-items: end;
148
+ }
149
+
150
+ .eyebrow,
151
+ .section-key {
152
+ margin: 0 0 8px;
153
+ color: var(--accent);
154
+ font-size: 0.76rem;
155
+ text-transform: uppercase;
156
+ letter-spacing: 0.12em;
157
+ }
158
+
159
+ .config-hero h1,
160
+ .config-section h2 {
161
+ margin: 0;
162
+ line-height: 1.05;
163
+ }
164
+
165
+ .hero-copy,
166
+ .section-description,
167
+ #config-status {
168
+ margin: 0;
169
+ color: var(--muted);
170
+ line-height: 1.5;
171
+ }
172
+
173
+ .hero-actions {
174
+ display: flex;
175
+ flex-wrap: wrap;
176
+ justify-content: flex-end;
177
+ gap: 10px;
178
+ }
179
+
180
+ button,
181
+ .secondary-link {
182
+ appearance: none;
183
+ border: 1px solid rgba(128, 227, 255, 0.22);
184
+ border-radius: 999px;
185
+ min-height: 44px;
186
+ padding: 0 16px;
187
+ color: var(--text);
188
+ background: linear-gradient(180deg, rgba(43, 77, 92, 0.92), rgba(28, 50, 60, 0.98));
189
+ font: inherit;
190
+ font-weight: 650;
191
+ text-decoration: none;
192
+ display: inline-flex;
193
+ align-items: center;
194
+ justify-content: center;
195
+ cursor: pointer;
196
+ }
197
+
198
+ .secondary-link {
199
+ background: rgba(21, 29, 35, 0.5);
200
+ }
201
+
202
+ html[data-theme="light"] button,
203
+ html[data-theme="light"] .secondary-link {
204
+ color: var(--text);
205
+ border-color: rgba(10, 138, 184, 0.18);
206
+ background: linear-gradient(180deg, rgba(208, 231, 240, 0.96), rgba(191, 220, 231, 0.98));
207
+ }
208
+
209
+ html[data-theme="light"] .secondary-link {
210
+ background: rgba(255, 255, 255, 0.72);
211
+ }
212
+
213
+ button:disabled {
214
+ opacity: 0.6;
215
+ cursor: progress;
216
+ }
217
+
218
+ button[hidden] {
219
+ display: none !important;
220
+ }
221
+
222
+ .status-bar {
223
+ padding: 14px 18px;
224
+ }
225
+
226
+ .config-grid {
227
+ display: grid;
228
+ gap: 18px;
229
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
230
+ }
231
+
232
+ .config-section {
233
+ padding: 18px;
234
+ display: grid;
235
+ gap: 18px;
236
+ align-content: start;
237
+ }
238
+
239
+ .section-header {
240
+ position: relative;
241
+ }
242
+
243
+ .section-heading {
244
+ position: relative;
245
+ padding-right: 86px;
246
+ }
247
+
248
+ .section-heading-copy {
249
+ display: grid;
250
+ gap: 6px;
251
+ }
252
+
253
+ .section-toggle {
254
+ position: absolute;
255
+ top: 0;
256
+ right: 0;
257
+ min-width: 74px;
258
+ min-height: 24px;
259
+ height: 24px;
260
+ padding: 0 8px;
261
+ border-radius: 999px;
262
+ background: rgba(21, 29, 35, 0.5);
263
+ font-size: 0.72rem;
264
+ line-height: 1;
265
+ display: inline-flex;
266
+ align-items: center;
267
+ justify-content: center;
268
+ }
269
+
270
+ .config-section.is-collapsed .section-fields {
271
+ display: none;
272
+ }
273
+
274
+ .section-fields {
275
+ display: grid;
276
+ gap: 12px;
277
+ }
278
+
279
+ .section-actions {
280
+ display: flex;
281
+ justify-content: flex-end;
282
+ }
283
+
284
+ .notifications-matrix {
285
+ overflow-x: auto;
286
+ }
287
+
288
+ .notifications-table {
289
+ width: 100%;
290
+ border-collapse: collapse;
291
+ border-spacing: 0;
292
+ background: var(--panel-strong);
293
+ border: 1px solid rgba(255, 255, 255, 0.08);
294
+ border-radius: 16px;
295
+ overflow: hidden;
296
+ }
297
+
298
+ .notifications-table th,
299
+ .notifications-table td {
300
+ padding: 12px 14px;
301
+ text-align: left;
302
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
303
+ }
304
+
305
+ .notifications-table tbody tr:last-child td {
306
+ border-bottom: none;
307
+ }
308
+
309
+ .notifications-table th {
310
+ color: var(--muted);
311
+ font-size: 0.82rem;
312
+ text-transform: uppercase;
313
+ letter-spacing: 0.06em;
314
+ }
315
+
316
+ .notifications-table-label {
317
+ min-width: 220px;
318
+ font-weight: 600;
319
+ }
320
+
321
+ .notifications-table-toggle {
322
+ width: 96px;
323
+ text-align: center;
324
+ }
325
+
326
+ .notifications-table-toggle input {
327
+ width: 20px;
328
+ height: 20px;
329
+ }
330
+
331
+ .section-action-button {
332
+ min-height: 36px;
333
+ padding: 0 12px;
334
+ font-size: 0.82rem;
335
+ }
336
+
337
+ .field-card {
338
+ display: grid;
339
+ gap: 10px;
340
+ padding: 14px;
341
+ border-radius: 16px;
342
+ border: 1px solid rgba(255, 255, 255, 0.08);
343
+ background: var(--panel-strong);
344
+ }
345
+
346
+ .field-header {
347
+ display: grid;
348
+ gap: 4px;
349
+ }
350
+
351
+ .field-label {
352
+ font-weight: 700;
353
+ }
354
+
355
+ .field-path {
356
+ color: var(--muted);
357
+ font-size: 0.82rem;
358
+ }
359
+
360
+ .field-control {
361
+ display: grid;
362
+ }
363
+
364
+ .field-body {
365
+ display: grid;
366
+ grid-template-columns: minmax(0, 1fr) auto;
367
+ gap: 10px;
368
+ align-items: center;
369
+ }
370
+
371
+ .field-control input[type="text"],
372
+ .field-control input[type="number"],
373
+ .field-control select {
374
+ width: 100%;
375
+ min-height: 44px;
376
+ border-radius: 12px;
377
+ border: 1px solid rgba(255, 255, 255, 0.1);
378
+ background: rgba(7, 12, 15, 0.7);
379
+ color: var(--text);
380
+ padding: 0 12px;
381
+ font: inherit;
382
+ }
383
+
384
+ .field-control input:disabled,
385
+ .field-control select:disabled,
386
+ .toggle-row:has(input:disabled) {
387
+ opacity: 0.55;
388
+ cursor: not-allowed;
389
+ }
390
+
391
+ .field-reset {
392
+ min-height: 44px;
393
+ padding: 0 14px;
394
+ border-radius: 12px;
395
+ }
396
+
397
+ .toggle-row {
398
+ display: flex;
399
+ align-items: center;
400
+ justify-content: space-between;
401
+ gap: 12px;
402
+ min-height: 44px;
403
+ padding: 0 12px;
404
+ border-radius: 12px;
405
+ background: rgba(7, 12, 15, 0.7);
406
+ border: 1px solid rgba(255, 255, 255, 0.1);
407
+ }
408
+
409
+ .toggle-row input {
410
+ width: 20px;
411
+ height: 20px;
412
+ }
413
+
414
+ .status-success {
415
+ color: var(--accent);
416
+ }
417
+
418
+ .status-error {
419
+ color: var(--danger);
420
+ }
421
+
422
+ .status-pending {
423
+ color: var(--accent-2);
424
+ }
425
+
426
+ @media (max-width: 760px) {
427
+ body {
428
+ padding: 12px;
429
+ }
430
+
431
+ .config-hero {
432
+ grid-template-columns: 1fr;
433
+ align-items: start;
434
+ }
435
+
436
+ .hero-actions {
437
+ justify-content: stretch;
438
+ }
439
+
440
+ .hero-actions > * {
441
+ flex: 1 1 100%;
442
+ }
443
+
444
+ .field-body {
445
+ grid-template-columns: 1fr;
446
+ }
447
+ }