@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,320 @@
1
+ import {emitWithTimestamp} from '../../../core/socket-emit.js';
2
+ import {
3
+ REMOTE_EVENT_SAMSUNG_ENTER,
4
+ REMOTE_EVENT_SAMSUNG_INPUT,
5
+ REMOTE_EVENT_SAMSUNG_MUTE,
6
+ REMOTE_EVENT_SAMSUNG_OFF,
7
+ REMOTE_EVENT_SAMSUNG_ON,
8
+ REMOTE_EVENT_SAMSUNG_PC_INPUT,
9
+ REMOTE_EVENT_SAMSUNG_VOL_DOWN,
10
+ REMOTE_EVENT_SAMSUNG_VOL_UP
11
+ } from '../../../../utils/remoteCommands.js';
12
+ import { bindTouchPassthrough } from '../../../touch/bindTouchPassthrough.js';
13
+
14
+ const VOLUME_REPEAT_HOLD_DELAY_MS = 1000;
15
+ const VOLUME_REPEAT_INTERVAL_MS = 170;
16
+ const VOLUME_REPEAT_MOVE_CANCEL_THRESHOLD_PX = 10;
17
+
18
+ function getPointerDistance(startPoint, event) {
19
+ if (!startPoint) {
20
+ return 0;
21
+ }
22
+
23
+ const dx = Number(event.clientX || 0) - startPoint.clientX;
24
+ const dy = Number(event.clientY || 0) - startPoint.clientY;
25
+ return Math.hypot(dx, dy);
26
+ }
27
+
28
+ function getTouchDistance(startPoint, touch) {
29
+ if (!startPoint || !touch) {
30
+ return 0;
31
+ }
32
+
33
+ const dx = Number(touch.clientX || 0) - startPoint.clientX;
34
+ const dy = Number(touch.clientY || 0) - startPoint.clientY;
35
+ return Math.hypot(dx, dy);
36
+ }
37
+
38
+ export function bindRepeatingButton(button, emitAction, {
39
+ holdDelayMs = VOLUME_REPEAT_HOLD_DELAY_MS,
40
+ repeatIntervalMs = VOLUME_REPEAT_INTERVAL_MS,
41
+ moveCancelThresholdPx = VOLUME_REPEAT_MOVE_CANCEL_THRESHOLD_PX,
42
+ } = {}) {
43
+ if (!button || typeof emitAction !== 'function') {
44
+ return;
45
+ }
46
+
47
+ let isPressed = false;
48
+ let pointerPressHandled = false;
49
+ let activePointerId = null;
50
+ let activeTouchId = null;
51
+ let startPoint = null;
52
+ let holdTimer = null;
53
+ let repeatTimer = null;
54
+ let suppressClickTimer = null;
55
+
56
+ const clearTimers = () => {
57
+ if (holdTimer) {
58
+ window.clearTimeout(holdTimer);
59
+ holdTimer = null;
60
+ }
61
+ if (repeatTimer) {
62
+ window.clearInterval(repeatTimer);
63
+ repeatTimer = null;
64
+ }
65
+ if (suppressClickTimer) {
66
+ window.clearTimeout(suppressClickTimer);
67
+ suppressClickTimer = null;
68
+ }
69
+ };
70
+
71
+ const startPress = () => {
72
+ if (isPressed || button.disabled || button.hidden) {
73
+ return;
74
+ }
75
+
76
+ isPressed = true;
77
+ emitAction();
78
+ holdTimer = window.setTimeout(() => {
79
+ emitAction();
80
+ repeatTimer = window.setInterval(emitAction, repeatIntervalMs);
81
+ }, holdDelayMs);
82
+ };
83
+
84
+ const stopPress = () => {
85
+ if (!isPressed) {
86
+ return;
87
+ }
88
+
89
+ isPressed = false;
90
+ activePointerId = null;
91
+ activeTouchId = null;
92
+ startPoint = null;
93
+ if (holdTimer) {
94
+ window.clearTimeout(holdTimer);
95
+ holdTimer = null;
96
+ }
97
+ if (repeatTimer) {
98
+ window.clearInterval(repeatTimer);
99
+ repeatTimer = null;
100
+ }
101
+ suppressClickTimer = window.setTimeout(() => {
102
+ pointerPressHandled = false;
103
+ suppressClickTimer = null;
104
+ }, 500);
105
+ };
106
+
107
+ button.addEventListener('pointerdown', (event) => {
108
+ if (event.button !== undefined && event.button !== 0) {
109
+ return;
110
+ }
111
+
112
+ pointerPressHandled = true;
113
+ activePointerId = event.pointerId;
114
+ startPoint = {
115
+ clientX: Number(event.clientX || 0),
116
+ clientY: Number(event.clientY || 0),
117
+ };
118
+ event.preventDefault();
119
+ button.setPointerCapture?.(event.pointerId);
120
+ startPress();
121
+ });
122
+
123
+ button.addEventListener('touchstart', (event) => {
124
+ if (event.changedTouches?.length !== 1) {
125
+ return;
126
+ }
127
+
128
+ const touch = event.changedTouches[0];
129
+ activeTouchId = touch.identifier;
130
+ startPoint = {
131
+ clientX: Number(touch.clientX || 0),
132
+ clientY: Number(touch.clientY || 0),
133
+ };
134
+ }, {passive: true});
135
+
136
+ button.addEventListener('pointermove', (event) => {
137
+ if (!isPressed || event.pointerId !== activePointerId) {
138
+ return;
139
+ }
140
+
141
+ if (getPointerDistance(startPoint, event) >= moveCancelThresholdPx) {
142
+ stopPress();
143
+ }
144
+ });
145
+
146
+ button.addEventListener('touchmove', (event) => {
147
+ if (!isPressed || activeTouchId === null) {
148
+ return;
149
+ }
150
+
151
+ const touch = Array.from(event.changedTouches || [])
152
+ .find((entry) => entry.identifier === activeTouchId);
153
+ if (getTouchDistance(startPoint, touch) >= moveCancelThresholdPx) {
154
+ stopPress();
155
+ }
156
+ }, {passive: true});
157
+
158
+ button.addEventListener('pointerup', (event) => {
159
+ event.preventDefault();
160
+ button.releasePointerCapture?.(event.pointerId);
161
+ stopPress();
162
+ });
163
+
164
+ button.addEventListener('pointercancel', stopPress);
165
+ button.addEventListener('lostpointercapture', stopPress);
166
+ button.addEventListener('mouseleave', stopPress);
167
+ window.addEventListener('blur', stopPress);
168
+ document.addEventListener('visibilitychange', () => {
169
+ if (document.hidden) {
170
+ stopPress();
171
+ }
172
+ });
173
+
174
+ button.addEventListener('click', (event) => {
175
+ if (pointerPressHandled) {
176
+ pointerPressHandled = false;
177
+ if (suppressClickTimer) {
178
+ window.clearTimeout(suppressClickTimer);
179
+ suppressClickTimer = null;
180
+ }
181
+ event.preventDefault();
182
+ return;
183
+ }
184
+
185
+ emitAction();
186
+ });
187
+ }
188
+
189
+ export function bindSamsungRemoteButtons(services, dom) {
190
+ const socket = services.getTransport();
191
+ const clientConfig = services.getClientConfig();
192
+ const getConfigView = services.getConfigView;
193
+ const appState = services.getAppState();
194
+ const backend = services.getBackend();
195
+ const touchpad = dom.remotes.mouse.touchpad;
196
+ const {
197
+ root,
198
+ btnSamsungOn,
199
+ btnSamsungOff,
200
+ btnSamsungVolUp,
201
+ btnSamsungVolDown,
202
+ btnSamsungMute,
203
+ btnSamsungInput,
204
+ btnSamsungEnter,
205
+ btnSamsungPcInput,
206
+ } = dom.remotes.samsung;
207
+ bindTouchPassthrough([
208
+ btnSamsungOn,
209
+ btnSamsungOff,
210
+ btnSamsungVolUp,
211
+ btnSamsungVolDown,
212
+ btnSamsungMute,
213
+ btnSamsungInput,
214
+ btnSamsungEnter,
215
+ btnSamsungPcInput,
216
+ ], touchpad);
217
+
218
+ const requiresOnButtons = Array.from(root?.querySelectorAll('[data-samsung-requires-on="true"]') || []);
219
+ let samsungStatusInterval = null;
220
+ let currentSamsungPowerState = 'unknown';
221
+ let expeditedPollTimers = [];
222
+ const emit = (eventName) => () => emitWithTimestamp(socket, eventName);
223
+ const emitSamsungOn = emit(REMOTE_EVENT_SAMSUNG_ON);
224
+ const emitSamsungOff = emit(REMOTE_EVENT_SAMSUNG_OFF);
225
+
226
+ const clearExpeditedSamsungPolling = () => {
227
+ for (const timer of expeditedPollTimers) {
228
+ clearTimeout(timer);
229
+ }
230
+ expeditedPollTimers = [];
231
+ };
232
+
233
+ const applySamsungPowerState = (powerState) => {
234
+ currentSamsungPowerState = powerState || 'unknown';
235
+ console.debug('[samsung-remote] apply power state', {
236
+ powerState: currentSamsungPowerState,
237
+ });
238
+ const isOn = powerState === 'on' || powerState === 'unknown';
239
+ for (const button of requiresOnButtons) {
240
+ button.hidden = !isOn;
241
+ }
242
+ };
243
+
244
+ const refreshSamsungPowerState = async () => {
245
+ const samsungConfig = getConfigView().getSamsungConfig();
246
+ const locallyVisible = appState.get('effective.remote.samsung.visible');
247
+ if (!root || !samsungConfig.enabled || !locallyVisible) {
248
+ applySamsungPowerState('off');
249
+ return;
250
+ }
251
+
252
+ try {
253
+ console.debug('[samsung-remote] refresh power state');
254
+ const payload = await backend.getSamsungStatus();
255
+ console.debug('[samsung-remote] status payload', payload);
256
+ applySamsungPowerState(payload?.power || 'unknown');
257
+ } catch (_error) {
258
+ console.debug('[samsung-remote] status fetch failed');
259
+ applySamsungPowerState('unknown');
260
+ }
261
+ };
262
+
263
+ const startExpeditedSamsungPolling = (targetPowerState) => {
264
+ console.debug('[samsung-remote] start expedited polling', {targetPowerState});
265
+ clearExpeditedSamsungPolling();
266
+ const delaysMs = [0, 350, 900, 1800, 3200, 5200];
267
+
268
+ expeditedPollTimers = delaysMs.map((delayMs) => window.setTimeout(async () => {
269
+ await refreshSamsungPowerState();
270
+ if (currentSamsungPowerState === targetPowerState) {
271
+ clearExpeditedSamsungPolling();
272
+ }
273
+ }, delayMs));
274
+ };
275
+
276
+ const ensureSamsungStatusPolling = () => {
277
+ if (samsungStatusInterval) {
278
+ return;
279
+ }
280
+ samsungStatusInterval = window.setInterval(() => {
281
+ void refreshSamsungPowerState();
282
+ }, 4000);
283
+ };
284
+
285
+ const syncSamsungVisibility = () => {
286
+ if (!root) {
287
+ return;
288
+ }
289
+ const samsungConfig = getConfigView().getSamsungConfig();
290
+ const locallyVisible = appState.get('effective.remote.samsung.visible');
291
+ root.hidden = !samsungConfig.enabled || !locallyVisible;
292
+ if (root.hidden) {
293
+ clearExpeditedSamsungPolling();
294
+ applySamsungPowerState('off');
295
+ } else {
296
+ void refreshSamsungPowerState();
297
+ }
298
+ };
299
+
300
+ btnSamsungOn.addEventListener('click', () => {
301
+ console.debug('[samsung-remote] click on');
302
+ emitSamsungOn();
303
+ startExpeditedSamsungPolling('on');
304
+ });
305
+ btnSamsungOff.addEventListener('click', () => {
306
+ console.debug('[samsung-remote] click off');
307
+ emitSamsungOff();
308
+ startExpeditedSamsungPolling('off');
309
+ });
310
+ bindRepeatingButton(btnSamsungVolUp, emit(REMOTE_EVENT_SAMSUNG_VOL_UP));
311
+ bindRepeatingButton(btnSamsungVolDown, emit(REMOTE_EVENT_SAMSUNG_VOL_DOWN));
312
+ btnSamsungMute.addEventListener('click', emit(REMOTE_EVENT_SAMSUNG_MUTE));
313
+ btnSamsungInput.addEventListener('click', emit(REMOTE_EVENT_SAMSUNG_INPUT));
314
+ btnSamsungEnter.addEventListener('click', emit(REMOTE_EVENT_SAMSUNG_ENTER));
315
+ btnSamsungPcInput.addEventListener('click', emit(REMOTE_EVENT_SAMSUNG_PC_INPUT));
316
+ syncSamsungVisibility();
317
+ ensureSamsungStatusPolling();
318
+ clientConfig.onChange(syncSamsungVisibility);
319
+ appState.subscribeProperty('effective.remote.samsung.visible', syncSamsungVisibility);
320
+ }
@@ -0,0 +1,41 @@
1
+ import { emitWithTimestamp } from '../../../core/socket-emit.js';
2
+ import { bindTouchPassthrough } from '../../../touch/bindTouchPassthrough.js';
3
+ import {
4
+ REMOTE_EVENT_KEYBOARD_KEY,
5
+ REMOTE_EVENT_WINDOW_CLOSE,
6
+ REMOTE_EVENT_WINDOW_TOGGLE_MAXIMIZE,
7
+ } from '../../../../utils/remoteCommands.js';
8
+
9
+ export function bindSystemRemoteButtons(services, dom) {
10
+ const socket = services.getTransport();
11
+ const touchpad = dom.remotes.mouse.touchpad;
12
+ const {
13
+ btnSystemShowDesktop,
14
+ btnSystemWindowLeft,
15
+ btnSystemWindowRight,
16
+ btnSystemStartMenu,
17
+ btnSystemWindowToggle,
18
+ btnSystemWindowClose,
19
+ } = dom.remotes.system;
20
+ const buttons = [
21
+ btnSystemShowDesktop,
22
+ btnSystemWindowLeft,
23
+ btnSystemWindowRight,
24
+ btnSystemStartMenu,
25
+ btnSystemWindowToggle,
26
+ btnSystemWindowClose,
27
+ ].filter(Boolean);
28
+
29
+ const emitKey = (payload = {}) => () => emitWithTimestamp(socket, REMOTE_EVENT_KEYBOARD_KEY, payload);
30
+ const emitWindowToggle = () => emitWithTimestamp(socket, REMOTE_EVENT_WINDOW_TOGGLE_MAXIMIZE);
31
+ const emitWindowClose = () => emitWithTimestamp(socket, REMOTE_EVENT_WINDOW_CLOSE);
32
+
33
+ bindTouchPassthrough(buttons, touchpad);
34
+
35
+ btnSystemShowDesktop?.addEventListener('click', emitKey({ key: 'd', modifiers: ['command'] }));
36
+ btnSystemWindowLeft?.addEventListener('click', emitKey({ key: 'tab', modifiers: ['alt', 'shift'] }));
37
+ btnSystemWindowRight?.addEventListener('click', emitKey({ key: 'tab', modifiers: ['alt'] }));
38
+ btnSystemStartMenu?.addEventListener('click', emitKey({ key: 'command' }));
39
+ btnSystemWindowToggle?.addEventListener('click', emitWindowToggle);
40
+ btnSystemWindowClose?.addEventListener('click', emitWindowClose);
41
+ }
@@ -0,0 +1,64 @@
1
+ import { emitWithTimestamp } from '../../../core/socket-emit.js';
2
+ import { bindTouchPassthrough } from '../../../touch/bindTouchPassthrough.js';
3
+ import {
4
+ REMOTE_EVENT_VLC_COMMAND,
5
+ REMOTE_EVENT_VLC_OPEN,
6
+ REMOTE_EVENT_VLC_WINDOW_CLOSE,
7
+ REMOTE_EVENT_VLC_WINDOW_TOGGLE,
8
+ } from '../../../../utils/remoteCommands.js';
9
+
10
+ export function bindVlcRemoteButtons(services, dom) {
11
+ const socket = services.getTransport();
12
+ const touchpad = dom.remotes.mouse.touchpad;
13
+ const {
14
+ btnVlcOpen,
15
+ btnVlcWindowToggle,
16
+ btnVlcWindowClose,
17
+ btnVlcPrevious,
18
+ btnVlcPlayPause,
19
+ btnVlcNext,
20
+ btnVlcSeekBackward,
21
+ btnVlcStop,
22
+ btnVlcSeekForward,
23
+ btnVlcVolumeDown,
24
+ btnVlcMute,
25
+ btnVlcVolumeUp,
26
+ btnVlcFullscreen,
27
+ } = dom.remotes.vlc;
28
+ const buttons = [
29
+ btnVlcOpen,
30
+ btnVlcWindowToggle,
31
+ btnVlcWindowClose,
32
+ btnVlcPrevious,
33
+ btnVlcPlayPause,
34
+ btnVlcNext,
35
+ btnVlcSeekBackward,
36
+ btnVlcStop,
37
+ btnVlcSeekForward,
38
+ btnVlcVolumeDown,
39
+ btnVlcMute,
40
+ btnVlcVolumeUp,
41
+ btnVlcFullscreen,
42
+ ].filter(Boolean);
43
+
44
+ const emitCommand = (action) => () => emitWithTimestamp(socket, REMOTE_EVENT_VLC_COMMAND, { action });
45
+ const emitOpen = () => emitWithTimestamp(socket, REMOTE_EVENT_VLC_OPEN);
46
+ const emitWindowToggle = () => emitWithTimestamp(socket, REMOTE_EVENT_VLC_WINDOW_TOGGLE);
47
+ const emitWindowClose = () => emitWithTimestamp(socket, REMOTE_EVENT_VLC_WINDOW_CLOSE);
48
+
49
+ bindTouchPassthrough(buttons, touchpad);
50
+
51
+ btnVlcOpen?.addEventListener('click', emitOpen);
52
+ btnVlcWindowToggle?.addEventListener('click', emitWindowToggle);
53
+ btnVlcWindowClose?.addEventListener('click', emitWindowClose);
54
+ btnVlcPrevious?.addEventListener('click', emitCommand('previous'));
55
+ btnVlcPlayPause?.addEventListener('click', emitCommand('play-pause'));
56
+ btnVlcNext?.addEventListener('click', emitCommand('next'));
57
+ btnVlcSeekBackward?.addEventListener('click', emitCommand('seek-backward'));
58
+ btnVlcStop?.addEventListener('click', emitCommand('stop'));
59
+ btnVlcSeekForward?.addEventListener('click', emitCommand('seek-forward'));
60
+ btnVlcVolumeDown?.addEventListener('click', emitCommand('volume-down'));
61
+ btnVlcMute?.addEventListener('click', emitCommand('mute'));
62
+ btnVlcVolumeUp?.addEventListener('click', emitCommand('volume-up'));
63
+ btnVlcFullscreen?.addEventListener('click', emitCommand('fullscreen'));
64
+ }
@@ -0,0 +1,33 @@
1
+ import { getScrollZoneLayout } from '../../touch/gesture-zone.js';
2
+ import {APP_STATE_HANDEDNESS} from '../../services/app-state/createAppStateService.js';
3
+
4
+ export function createCanvasUI(touchpad, appState) {
5
+ const ctx = touchpad.getContext('2d');
6
+
7
+ function drawHint() {
8
+ const width = touchpad.clientWidth;
9
+ const height = touchpad.clientHeight;
10
+
11
+ ctx.clearRect(0, 0, width, height);
12
+ }
13
+
14
+ function resize() {
15
+ const ratio = window.devicePixelRatio || 1;
16
+ const rect = touchpad.getBoundingClientRect();
17
+ touchpad.width = Math.round(rect.width * ratio);
18
+ touchpad.height = Math.round(rect.height * ratio);
19
+ ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
20
+
21
+ const layout = getScrollZoneLayout(touchpad.clientWidth, touchpad.clientHeight, appState.get(APP_STATE_HANDEDNESS));
22
+ document.documentElement.style.setProperty('--scroll-zone-width', `${layout.width}px`);
23
+ document.documentElement.style.setProperty('--scroll-zone-edge-gap', `${layout.edgeGap}px`);
24
+
25
+ drawHint();
26
+ }
27
+
28
+ appState.subscribeProperty(APP_STATE_HANDEDNESS, () => {
29
+ resize();
30
+ });
31
+
32
+ return { resize };
33
+ }
@@ -0,0 +1,57 @@
1
+ export function bindConnectionOverlay(services, dom) {
2
+ const socket = services.getTransport();
3
+ const i18n = services.getI18n();
4
+ const overlay = dom.connectionOverlay;
5
+
6
+ if (!overlay) {
7
+ return;
8
+ }
9
+
10
+ const titleEl = overlay.querySelector('[data-connection-title]');
11
+ const messageEl = overlay.querySelector('[data-connection-message]');
12
+
13
+ function setContent(title, message) {
14
+ if (titleEl) {
15
+ titleEl.textContent = title;
16
+ }
17
+ if (messageEl) {
18
+ messageEl.textContent = message;
19
+ }
20
+ }
21
+
22
+ function update() {
23
+ const {t} = i18n.getI18n();
24
+ const connected = socket.connected;
25
+ if (!connected) {
26
+ setContent(t('main.connectionUnavailableTitle'), t('main.connectionWaiting'));
27
+ }
28
+ overlay.classList.toggle('hidden', connected);
29
+ }
30
+
31
+ function handleConnectError(error) {
32
+ const {t} = i18n.getI18n();
33
+ const isUnauthorized = error?.message === 'unauthorized'
34
+ || error?.data?.code === 'ENTRY_TOKEN_INVALID';
35
+
36
+ if (isUnauthorized) {
37
+ setContent(
38
+ t('main.connectionExpiredTitle'),
39
+ t('main.connectionExpiredMessage')
40
+ );
41
+ overlay.classList.remove('hidden');
42
+ return;
43
+ }
44
+
45
+ update();
46
+ }
47
+
48
+ socket.on('connect', update);
49
+ socket.on('disconnect', update);
50
+ socket.on('reconnect', update);
51
+ socket.on('connect_error', handleConnectError);
52
+ i18n.onChange(() => {
53
+ update();
54
+ });
55
+
56
+ update();
57
+ }
@@ -0,0 +1,54 @@
1
+ import { getDom } from '../../core/dom.js';
2
+ import { createCanvasUI } from './canvas-ui.js';
3
+ import { bindTouchpad } from '../../touch/touchpad.js';
4
+ import { bindKeyboardPanel } from './keyboard-panel.js';
5
+ import { bindMouseButtons } from './mouse-buttons.js';
6
+ import { bindActionButtons } from './bindings/bindActionButtons.js';
7
+ import { bindConnectionOverlay } from './connection-overlay.js';
8
+ import { bindPreviewStream } from '../../preview/preview-stream.js';
9
+ import { bindClientNotifications } from './bind-client-notifications.js';
10
+ import { bindAdminDrawer } from './bindings/bindAdminDrawer.js';
11
+ import { bindAdminVersion } from './bindings/bindAdminVersion.js';
12
+ import { bindRemoteAccordion } from './bindings/bindRemoteAccordion.js';
13
+ import {applyRemoteVisibilityState} from './applyRemoteVisibilityState.js';
14
+
15
+ export function initUi(services) {
16
+
17
+ services.getI18n().translateRoot(document);
18
+
19
+ const dom = getDom();
20
+ const {remotes} = dom;
21
+ const canvasUI = createCanvasUI(remotes.mouse.touchpad, services.getAppState());
22
+ bindRemoteAccordion(services, dom);
23
+
24
+ const syncRemoteVisibilityState = () => applyRemoteVisibilityState({
25
+ services,
26
+ dom,
27
+ });
28
+
29
+ bindPreviewStream(services, dom);
30
+ bindTouchpad(services, dom);
31
+ bindKeyboardPanel(services, dom);
32
+ bindMouseButtons(services, dom);
33
+ bindActionButtons(services, dom);
34
+ bindConnectionOverlay(services, dom);
35
+ bindClientNotifications(services, dom);
36
+ bindAdminDrawer(services, dom);
37
+ bindAdminVersion(services, dom);
38
+
39
+ for (const key of [
40
+ 'effective.remote.browser.visible',
41
+ 'effective.remote.keyboard.visible',
42
+ 'effective.remote.vlc.visible',
43
+ 'effective.remote.samsung.visible',
44
+ 'effective.remote.preview.visible',
45
+ ]) {
46
+ services.getAppState().subscribeProperty(key, syncRemoteVisibilityState);
47
+ }
48
+
49
+ syncRemoteVisibilityState();
50
+
51
+ window.addEventListener('resize', canvasUI.resize);
52
+
53
+ canvasUI.resize();
54
+ }