livedesk 0.1.407 → 0.1.409
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/client/package.json +5 -5
- package/electron/electron-builder.mac-arm64.yml +3 -0
- package/electron/electron-builder.mac-x64.yml +3 -0
- package/electron/electron-builder.win.yml +3 -0
- package/electron/icon.icns +0 -0
- package/electron/icon.ico +0 -0
- package/electron/icon.png +0 -0
- package/electron/icon.svg +11 -0
- package/electron/main.mjs +11 -9
- package/electron/tray.ico +0 -0
- package/electron/tray.png +0 -0
- package/hub/src/mode4-atlas-sizing.js +32 -0
- package/hub/src/mode4-atlas-worker.js +14 -7
- package/hub/src/server.js +19 -10
- package/package.json +6 -6
- package/web/dist/apple-touch-icon.png +0 -0
- package/web/dist/assets/{index-B2NcHxhD.css → index-CZw2jLf-.css} +1 -1
- package/web/dist/assets/{index-CGClXphd.js → index-CmEDMI47.js} +1 -1
- package/web/dist/favicon.ico +0 -0
- package/web/dist/favicon.svg +11 -0
- package/web/dist/index.html +6 -2
package/client/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livedesk/client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.174",
|
|
4
4
|
"description": "LiveDesk local remote client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"ws": "^8.18.3"
|
|
40
40
|
},
|
|
41
41
|
"optionalDependencies": {
|
|
42
|
-
"@livedesk/fast-linux-x64": "0.1.
|
|
43
|
-
"@livedesk/fast-osx-arm64": "0.1.
|
|
44
|
-
"@livedesk/fast-osx-x64": "0.1.
|
|
45
|
-
"@livedesk/fast-win-x64": "0.1.
|
|
42
|
+
"@livedesk/fast-linux-x64": "0.1.380",
|
|
43
|
+
"@livedesk/fast-osx-arm64": "0.1.380",
|
|
44
|
+
"@livedesk/fast-osx-x64": "0.1.380",
|
|
45
|
+
"@livedesk/fast-win-x64": "0.1.380"
|
|
46
46
|
},
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public"
|
|
@@ -16,10 +16,13 @@ asarUnpack:
|
|
|
16
16
|
- bin/**
|
|
17
17
|
- bootstrap/**
|
|
18
18
|
- client/**
|
|
19
|
+
- electron/icon.*
|
|
20
|
+
- electron/tray.*
|
|
19
21
|
- hub/**
|
|
20
22
|
- runtime-core/**
|
|
21
23
|
- web/**
|
|
22
24
|
mac:
|
|
25
|
+
icon: packages/livedesk/electron/icon.icns
|
|
23
26
|
category: public.app-category.utilities
|
|
24
27
|
target:
|
|
25
28
|
- target: dmg
|
|
@@ -16,10 +16,13 @@ asarUnpack:
|
|
|
16
16
|
- bin/**
|
|
17
17
|
- bootstrap/**
|
|
18
18
|
- client/**
|
|
19
|
+
- electron/icon.*
|
|
20
|
+
- electron/tray.*
|
|
19
21
|
- hub/**
|
|
20
22
|
- runtime-core/**
|
|
21
23
|
- web/**
|
|
22
24
|
mac:
|
|
25
|
+
icon: packages/livedesk/electron/icon.icns
|
|
23
26
|
category: public.app-category.utilities
|
|
24
27
|
target:
|
|
25
28
|
- target: dmg
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024" fill="none">
|
|
2
|
+
<rect x="24" y="24" width="976" height="976" rx="220" fill="#111827"/>
|
|
3
|
+
<g transform="translate(192 192) scale(22.8571428571)">
|
|
4
|
+
<rect x="2.5" y="4" width="14" height="9" rx="1.5" stroke="#F8FAFC" stroke-width="1.7" opacity="0.42"/>
|
|
5
|
+
<path d="M7 16v1.5h5" stroke="#F8FAFC" stroke-width="1.7" stroke-linecap="round" opacity="0.42"/>
|
|
6
|
+
<rect x="10.5" y="2.5" width="14" height="9" rx="1.5" stroke="#F8FAFC" stroke-width="1.7" opacity="0.62"/>
|
|
7
|
+
<path d="M15 14.5V16h5" stroke="#F8FAFC" stroke-width="1.7" stroke-linecap="round" opacity="0.62"/>
|
|
8
|
+
<rect x="6.5" y="8.5" width="15" height="10" rx="1.7" fill="#F8FAFC" fill-opacity="0.12" stroke="#F8FAFC" stroke-width="1.9"/>
|
|
9
|
+
<path d="M12 21v1.5H9.5M16 21v1.5h2.5M9.5 22.5h9" stroke="#F8FAFC" stroke-width="1.9" stroke-linecap="round"/>
|
|
10
|
+
</g>
|
|
11
|
+
</svg>
|
package/electron/main.mjs
CHANGED
|
@@ -69,7 +69,7 @@ let productUpdates = null;
|
|
|
69
69
|
let pendingOAuth = null;
|
|
70
70
|
let pendingProtocolUrl = '';
|
|
71
71
|
let runtimeLogoutPromise = null;
|
|
72
|
-
const
|
|
72
|
+
const FALLBACK_ICON_DATA_URL = `data:image/svg+xml;charset=utf-8,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none"><rect x="1" y="1" width="30" height="30" rx="7" fill="#111827"/><g transform="translate(5 5) scale(.785714)"><rect x="2.5" y="4" width="14" height="9" rx="1.5" stroke="#F8FAFC" stroke-width="1.7" opacity=".42"/><path d="M7 16v1.5h5" stroke="#F8FAFC" stroke-width="1.7" stroke-linecap="round" opacity=".42"/><rect x="10.5" y="2.5" width="14" height="9" rx="1.5" stroke="#F8FAFC" stroke-width="1.7" opacity=".62"/><path d="M15 14.5V16h5" stroke="#F8FAFC" stroke-width="1.7" stroke-linecap="round" opacity=".62"/><rect x="6.5" y="8.5" width="15" height="10" rx="1.7" fill="#F8FAFC" fill-opacity=".12" stroke="#F8FAFC" stroke-width="1.9"/><path d="M12 21v1.5H9.5M16 21v1.5h2.5M9.5 22.5h9" stroke="#F8FAFC" stroke-width="1.9" stroke-linecap="round"/></g></svg>')}`;
|
|
73
73
|
|
|
74
74
|
function mask(value) {
|
|
75
75
|
return String(value ?? '')
|
|
@@ -595,14 +595,16 @@ function showWindow() {
|
|
|
595
595
|
mainWindow.focus();
|
|
596
596
|
}
|
|
597
597
|
|
|
598
|
-
function createMainWindow() {
|
|
599
|
-
|
|
598
|
+
function createMainWindow() {
|
|
599
|
+
const iconPath = appResource('electron', 'icon.png');
|
|
600
|
+
mainWindow = new BrowserWindow({
|
|
600
601
|
width: 1440,
|
|
601
602
|
height: 960,
|
|
602
603
|
minWidth: 1080,
|
|
603
|
-
minHeight: 720,
|
|
604
|
-
show: false,
|
|
605
|
-
title: APP_NAME,
|
|
604
|
+
minHeight: 720,
|
|
605
|
+
show: false,
|
|
606
|
+
title: APP_NAME,
|
|
607
|
+
icon: existsSync(iconPath) ? iconPath : nativeImage.createFromDataURL(FALLBACK_ICON_DATA_URL),
|
|
606
608
|
webPreferences: {
|
|
607
609
|
preload: appResource('electron', 'preload.cjs'),
|
|
608
610
|
contextIsolation: true,
|
|
@@ -707,9 +709,9 @@ function registerIpc() {
|
|
|
707
709
|
handle('updates:install', () => productUpdates?.install() || Promise.resolve({ state: 'unavailable' }));
|
|
708
710
|
}
|
|
709
711
|
|
|
710
|
-
function createTray() {
|
|
711
|
-
const iconPath = appResource('electron', 'tray.ico');
|
|
712
|
-
tray = new Tray(existsSync(iconPath) ? iconPath : nativeImage.createFromDataURL(
|
|
712
|
+
function createTray() {
|
|
713
|
+
const iconPath = appResource('electron', process.platform === 'win32' ? 'tray.ico' : 'tray.png');
|
|
714
|
+
tray = new Tray(existsSync(iconPath) ? iconPath : nativeImage.createFromDataURL(FALLBACK_ICON_DATA_URL));
|
|
713
715
|
const menu = Menu.buildFromTemplate([
|
|
714
716
|
{ label: 'Show LiveDesk', click: showWindow },
|
|
715
717
|
{ label: 'Restart runtime', click: restartRuntimeProcess },
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const TILE_PRESETS = Object.freeze([
|
|
2
|
+
Object.freeze({ width: 320, height: 180 }),
|
|
3
|
+
Object.freeze({ width: 480, height: 270 }),
|
|
4
|
+
Object.freeze({ width: 640, height: 360 })
|
|
5
|
+
]);
|
|
6
|
+
|
|
7
|
+
export function resolveMode4AtlasTileSize(options = {}) {
|
|
8
|
+
const deviceCount = Math.max(1, Math.floor(Number(options.deviceCount) || 1));
|
|
9
|
+
const atlasWidth = Math.max(640, Math.floor(Number(options.atlasWidth) || 1920));
|
|
10
|
+
const atlasHeight = Math.max(360, Math.floor(Number(options.atlasHeight) || 1080));
|
|
11
|
+
const requestedWidth = Number(options.requestedWidth) || 320;
|
|
12
|
+
const requestedHeight = Number(options.requestedHeight) || 180;
|
|
13
|
+
const columns = Math.max(1, Math.ceil(Math.sqrt(deviceCount)));
|
|
14
|
+
const rows = Math.max(1, Math.ceil(deviceCount / columns));
|
|
15
|
+
const requestedPresetIndex = requestedWidth >= 640 || requestedHeight >= 360
|
|
16
|
+
? 2
|
|
17
|
+
: requestedWidth >= 480 || requestedHeight >= 270
|
|
18
|
+
? 1
|
|
19
|
+
: 0;
|
|
20
|
+
const supportedCandidates = TILE_PRESETS.slice(0, requestedPresetIndex + 1).reverse();
|
|
21
|
+
const selected = supportedCandidates.find(candidate => (
|
|
22
|
+
candidate.width * columns <= atlasWidth
|
|
23
|
+
&& candidate.height * rows <= atlasHeight
|
|
24
|
+
)) || TILE_PRESETS[0];
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
width: selected.width,
|
|
28
|
+
height: selected.height,
|
|
29
|
+
columns,
|
|
30
|
+
rows
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -4,6 +4,7 @@ import { spawn } from 'node:child_process';
|
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
5
5
|
import { existsSync } from 'node:fs';
|
|
6
6
|
import { decodeLzo1xBlock } from './lzo1x.js';
|
|
7
|
+
import { resolveMode4AtlasTileSize } from './mode4-atlas-sizing.js';
|
|
7
8
|
|
|
8
9
|
const require = createRequire(import.meta.url);
|
|
9
10
|
const DEFAULT_WIDTH = 1920;
|
|
@@ -11,8 +12,8 @@ const DEFAULT_HEIGHT = 1080;
|
|
|
11
12
|
const DEFAULT_FPS = 20;
|
|
12
13
|
const MAX_DEVICES = 100;
|
|
13
14
|
const FRAME_POOL_SIZE = 3;
|
|
14
|
-
const MAX_TILE_WIDTH =
|
|
15
|
-
const MAX_TILE_HEIGHT =
|
|
15
|
+
const MAX_TILE_WIDTH = 640;
|
|
16
|
+
const MAX_TILE_HEIGHT = 360;
|
|
16
17
|
|
|
17
18
|
const rgb565Red = new Uint8Array(65_536);
|
|
18
19
|
const rgb565Green = new Uint8Array(65_536);
|
|
@@ -59,12 +60,18 @@ function normalizeConfig(value) {
|
|
|
59
60
|
.map(item => String(item || '').trim()).filter(Boolean))].slice(0, MAX_DEVICES);
|
|
60
61
|
const maxWidth = clamp(value?.width, 640, 3840, DEFAULT_WIDTH);
|
|
61
62
|
const maxHeight = clamp(value?.height, 360, 2160, DEFAULT_HEIGHT);
|
|
62
|
-
const sharpTiles = Number(value?.tileWidth) >= 480 || Number(value?.tileHeight) >= 270;
|
|
63
|
-
const sourceTileWidth = sharpTiles ? 480 : 320;
|
|
64
|
-
const sourceTileHeight = sharpTiles ? 270 : 180;
|
|
65
63
|
const count = Math.max(1, deviceIds.length);
|
|
66
|
-
const
|
|
67
|
-
|
|
64
|
+
const tileSize = resolveMode4AtlasTileSize({
|
|
65
|
+
requestedWidth: value?.tileWidth,
|
|
66
|
+
requestedHeight: value?.tileHeight,
|
|
67
|
+
deviceCount: count,
|
|
68
|
+
atlasWidth: maxWidth,
|
|
69
|
+
atlasHeight: maxHeight
|
|
70
|
+
});
|
|
71
|
+
const columns = tileSize.columns;
|
|
72
|
+
const rows = tileSize.rows;
|
|
73
|
+
const sourceTileWidth = tileSize.width;
|
|
74
|
+
const sourceTileHeight = tileSize.height;
|
|
68
75
|
const tileWidth = Math.max(2, Math.min(sourceTileWidth, Math.floor(maxWidth / columns))) & ~1;
|
|
69
76
|
const tileHeight = Math.max(2, Math.min(sourceTileHeight, Math.floor(maxHeight / rows))) & ~1;
|
|
70
77
|
return {
|
package/hub/src/server.js
CHANGED
|
@@ -8,8 +8,9 @@ import { dirname, resolve } from 'node:path';
|
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import os from 'node:os';
|
|
10
10
|
import { WebSocketServer } from 'ws';
|
|
11
|
-
import { createRemoteHub } from './remote-hub.js';
|
|
11
|
+
import { createRemoteHub } from './remote-hub.js';
|
|
12
12
|
import { buildMode4AtlasSessionKey, Mode4AtlasPool, planMode4AtlasInputTransitions } from './mode4-atlas-pool.js';
|
|
13
|
+
import { resolveMode4AtlasTileSize } from './mode4-atlas-sizing.js';
|
|
13
14
|
import { createHubFilesystem } from './filesystem/hub-filesystem.js';
|
|
14
15
|
import { createHubTransferJobs } from './filesystem/transfer-jobs.js';
|
|
15
16
|
import { createHubSharedFolders } from './filesystem/shared-folders.js';
|
|
@@ -2287,13 +2288,21 @@ function sendMode4AtlasFrame(ws, output) {
|
|
|
2287
2288
|
}
|
|
2288
2289
|
|
|
2289
2290
|
function configureMode4Atlas(ws, payload = {}) {
|
|
2290
|
-
const deviceIds = normalizeDeviceIds(payload.deviceIds ?? payload.devices ?? payload.deviceId).slice(0, 100);
|
|
2291
|
-
const captureDeviceIds = normalizeDeviceIds(payload.captureDeviceIds ?? payload.inputDeviceIds ?? deviceIds)
|
|
2292
|
-
.filter(deviceId => deviceIds.includes(deviceId));
|
|
2293
|
-
const monitorSelections = normalizeMonitorSelections(payload.monitorSelections);
|
|
2294
|
-
const
|
|
2295
|
-
const
|
|
2296
|
-
const
|
|
2291
|
+
const deviceIds = normalizeDeviceIds(payload.deviceIds ?? payload.devices ?? payload.deviceId).slice(0, 100);
|
|
2292
|
+
const captureDeviceIds = normalizeDeviceIds(payload.captureDeviceIds ?? payload.inputDeviceIds ?? deviceIds)
|
|
2293
|
+
.filter(deviceId => deviceIds.includes(deviceId));
|
|
2294
|
+
const monitorSelections = normalizeMonitorSelections(payload.monitorSelections);
|
|
2295
|
+
const width = clampNumber(payload.width, 640, 3840, 1920);
|
|
2296
|
+
const height = clampNumber(payload.height, 360, 2160, 1080);
|
|
2297
|
+
const tileSize = resolveMode4AtlasTileSize({
|
|
2298
|
+
requestedWidth: payload.tileWidth,
|
|
2299
|
+
requestedHeight: payload.tileHeight,
|
|
2300
|
+
deviceCount: deviceIds.length,
|
|
2301
|
+
atlasWidth: width,
|
|
2302
|
+
atlasHeight: height
|
|
2303
|
+
});
|
|
2304
|
+
const tileWidth = tileSize.width;
|
|
2305
|
+
const tileHeight = tileSize.height;
|
|
2297
2306
|
const previousInputDeviceIds = ws.liveDeskAtlasInputDeviceIds instanceof Set
|
|
2298
2307
|
? new Set(ws.liveDeskAtlasInputDeviceIds)
|
|
2299
2308
|
: new Set();
|
|
@@ -2304,8 +2313,8 @@ function configureMode4Atlas(ws, payload = {}) {
|
|
|
2304
2313
|
// every layout device ingestible lets a paused/reused input retain its
|
|
2305
2314
|
// latest tile while only the changed device restarts capture.
|
|
2306
2315
|
inputDeviceIds: deviceIds,
|
|
2307
|
-
width
|
|
2308
|
-
height
|
|
2316
|
+
width,
|
|
2317
|
+
height,
|
|
2309
2318
|
tileWidth,
|
|
2310
2319
|
tileHeight,
|
|
2311
2320
|
fps: clampNumber(payload.fps, 1, 30, 20),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livedesk",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"livedeskClientVersion": "0.1.
|
|
3
|
+
"version": "0.1.409",
|
|
4
|
+
"livedeskClientVersion": "0.1.174",
|
|
5
5
|
"buildFlavor": "production",
|
|
6
6
|
"description": "LiveDesk Hub and client launcher",
|
|
7
7
|
"type": "module",
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
"ws": "^8.18.3"
|
|
50
50
|
},
|
|
51
51
|
"optionalDependencies": {
|
|
52
|
-
"@livedesk/fast-linux-x64": "0.1.
|
|
53
|
-
"@livedesk/fast-osx-arm64": "0.1.
|
|
54
|
-
"@livedesk/fast-osx-x64": "0.1.
|
|
55
|
-
"@livedesk/fast-win-x64": "0.1.
|
|
52
|
+
"@livedesk/fast-linux-x64": "0.1.380",
|
|
53
|
+
"@livedesk/fast-osx-arm64": "0.1.380",
|
|
54
|
+
"@livedesk/fast-osx-x64": "0.1.380",
|
|
55
|
+
"@livedesk/fast-win-x64": "0.1.380"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|
|
Binary file
|