livedesk 0.1.554 → 0.1.562
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/bin/livedesk-client.js +19 -16
- package/client/src/runtime/packaged-executable-path.js +23 -0
- package/electron/electron-builder.linux-x64.yml +8 -6
- package/electron/electron-builder.mac-arm64.yml +8 -6
- package/electron/electron-builder.mac-x64.yml +8 -6
- package/electron/electron-builder.win-dev.yml +9 -0
- package/electron/electron-builder.win.yml +8 -6
- package/electron/main.mjs +40 -19
- package/electron/oauth-pkce.mjs +11 -8
- package/electron/recurring-update-owner.mjs +98 -0
- package/electron/update-manager.mjs +43 -22
- package/hub/src/remote-hub.js +34 -8
- package/package.json +7 -8
- package/runtime-core/src/auth-config.js +1 -1
- package/web/dist/_headers +19 -2
- package/web/dist/assets/{index-bwoEoZuf.css → index-eImKb97V.css} +1 -1
- package/web/dist/desktop-auth-callback.html +133 -0
- package/web/dist/desktop-auth-callback.js +109 -0
- package/web/dist/index.html +2 -2
- package/web/dist/livedesk-build-evidence.json +28 -18
- package/web/dist/sw.js +1 -1
- /package/web/dist/assets/{index-Bzov0Sti.js → index-Dox-U5dj.js} +0 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<meta name="referrer" content="no-referrer" />
|
|
7
|
+
<meta
|
|
8
|
+
http-equiv="Content-Security-Policy"
|
|
9
|
+
content="default-src 'none'; script-src 'self'; style-src 'unsafe-inline'; img-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'"
|
|
10
|
+
/>
|
|
11
|
+
<title>LiveDesk</title>
|
|
12
|
+
<style>
|
|
13
|
+
:root {
|
|
14
|
+
color-scheme: light;
|
|
15
|
+
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
16
|
+
color: #152039;
|
|
17
|
+
background: #f3f7fb;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
* { box-sizing: border-box; }
|
|
21
|
+
|
|
22
|
+
body {
|
|
23
|
+
min-height: 100vh;
|
|
24
|
+
margin: 0;
|
|
25
|
+
display: grid;
|
|
26
|
+
place-items: center;
|
|
27
|
+
padding: 24px;
|
|
28
|
+
background:
|
|
29
|
+
radial-gradient(circle at 50% 18%, rgba(48, 205, 193, 0.14), transparent 34%),
|
|
30
|
+
linear-gradient(150deg, #f8fbff 0%, #edf4fb 100%);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
main {
|
|
34
|
+
width: min(520px, 100%);
|
|
35
|
+
padding: 48px 42px 40px;
|
|
36
|
+
text-align: center;
|
|
37
|
+
background: rgba(255, 255, 255, 0.96);
|
|
38
|
+
border: 1px solid rgba(143, 160, 185, 0.2);
|
|
39
|
+
border-radius: 28px;
|
|
40
|
+
box-shadow: 0 24px 70px rgba(32, 55, 88, 0.14);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.mark {
|
|
44
|
+
width: 70px;
|
|
45
|
+
height: 70px;
|
|
46
|
+
margin: 0 auto 22px;
|
|
47
|
+
display: grid;
|
|
48
|
+
place-items: center;
|
|
49
|
+
border-radius: 22px;
|
|
50
|
+
color: white;
|
|
51
|
+
background: linear-gradient(145deg, #21bcae, #3188f3);
|
|
52
|
+
box-shadow: 0 14px 32px rgba(40, 151, 204, 0.28);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.mark svg { width: 38px; height: 38px; }
|
|
56
|
+
|
|
57
|
+
.eyebrow {
|
|
58
|
+
margin: 0 0 11px;
|
|
59
|
+
color: #63718b;
|
|
60
|
+
font-size: 12px;
|
|
61
|
+
font-weight: 800;
|
|
62
|
+
letter-spacing: 0.16em;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
h1 {
|
|
66
|
+
margin: 0;
|
|
67
|
+
font-size: clamp(28px, 6vw, 36px);
|
|
68
|
+
line-height: 1.18;
|
|
69
|
+
letter-spacing: -0.035em;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.message {
|
|
73
|
+
margin: 17px auto 0;
|
|
74
|
+
color: #52617c;
|
|
75
|
+
font-size: 17px;
|
|
76
|
+
line-height: 1.65;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
button {
|
|
80
|
+
width: 100%;
|
|
81
|
+
margin-top: 30px;
|
|
82
|
+
padding: 15px 20px;
|
|
83
|
+
border: 0;
|
|
84
|
+
border-radius: 14px;
|
|
85
|
+
color: white;
|
|
86
|
+
background: #176ee8;
|
|
87
|
+
font: inherit;
|
|
88
|
+
font-weight: 750;
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
box-shadow: 0 10px 22px rgba(23, 110, 232, 0.24);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
button:hover { background: #0e60d3; }
|
|
94
|
+
button:focus-visible { outline: 3px solid rgba(23, 110, 232, 0.28); outline-offset: 3px; }
|
|
95
|
+
button[hidden] { display: none; }
|
|
96
|
+
|
|
97
|
+
.note {
|
|
98
|
+
margin: 17px 0 0;
|
|
99
|
+
color: #8792a6;
|
|
100
|
+
font-size: 13px;
|
|
101
|
+
line-height: 1.55;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
body[data-state="error"] .mark {
|
|
105
|
+
background: linear-gradient(145deg, #f1a83c, #eb6a54);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
body[data-state="invalid"] .mark {
|
|
109
|
+
background: linear-gradient(145deg, #8190a8, #63718b);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@media (max-width: 520px) {
|
|
113
|
+
main { padding: 40px 24px 34px; border-radius: 22px; }
|
|
114
|
+
h1 { font-size: 26px; }
|
|
115
|
+
}
|
|
116
|
+
</style>
|
|
117
|
+
<script type="module" src="/desktop-auth-callback.js"></script>
|
|
118
|
+
</head>
|
|
119
|
+
<body>
|
|
120
|
+
<main aria-labelledby="auth-title">
|
|
121
|
+
<div class="mark" aria-hidden="true">
|
|
122
|
+
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
123
|
+
<path d="M8 25h7l4-11 8 23 5-15 3 3h5" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
|
|
124
|
+
</svg>
|
|
125
|
+
</div>
|
|
126
|
+
<p class="eyebrow" data-auth-eyebrow>LIVE DESK</p>
|
|
127
|
+
<h1 id="auth-title" data-auth-title>Returning to LiveDesk</h1>
|
|
128
|
+
<p class="message" data-auth-message>Please wait while LiveDesk opens.</p>
|
|
129
|
+
<button type="button" data-auth-open>Open LiveDesk</button>
|
|
130
|
+
<p class="note" data-auth-note>If the app does not open automatically, use the button above.</p>
|
|
131
|
+
</main>
|
|
132
|
+
</body>
|
|
133
|
+
</html>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export const DESKTOP_AUTH_CALLBACK_URL = 'livedesk://auth/callback';
|
|
2
|
+
|
|
3
|
+
const FORWARDED_PARAMETER_NAMES = Object.freeze([
|
|
4
|
+
'code',
|
|
5
|
+
'state',
|
|
6
|
+
'error',
|
|
7
|
+
'error_description'
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
export function buildDesktopAuthCallbackUrl(search = '') {
|
|
11
|
+
const source = new URLSearchParams(String(search || '').replace(/^\?/, ''));
|
|
12
|
+
const forwarded = new URLSearchParams();
|
|
13
|
+
for (const name of FORWARDED_PARAMETER_NAMES) {
|
|
14
|
+
const value = source.get(name);
|
|
15
|
+
if (value) forwarded.set(name, value);
|
|
16
|
+
}
|
|
17
|
+
if (!forwarded.has('code') && !forwarded.has('error')) return '';
|
|
18
|
+
return `${DESKTOP_AUTH_CALLBACK_URL}?${forwarded.toString()}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function localPreviewRequested(location) {
|
|
22
|
+
const hostname = String(location?.hostname || '').toLowerCase();
|
|
23
|
+
if (hostname !== 'localhost' && hostname !== '127.0.0.1') return false;
|
|
24
|
+
return new URLSearchParams(location.search).get('preview') === '1';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function setPageState(state, language) {
|
|
28
|
+
const korean = String(language || '').toLowerCase().startsWith('ko');
|
|
29
|
+
const copy = {
|
|
30
|
+
success: korean
|
|
31
|
+
? {
|
|
32
|
+
eyebrow: 'LIVE DESK',
|
|
33
|
+
title: '로그인이 완료되었습니다',
|
|
34
|
+
message: 'LiveDesk 앱으로 돌아가세요. 이 탭은 닫아도 됩니다.',
|
|
35
|
+
button: 'LiveDesk 열기',
|
|
36
|
+
note: '앱이 자동으로 열리지 않으면 위 버튼을 눌러주세요.'
|
|
37
|
+
}
|
|
38
|
+
: {
|
|
39
|
+
eyebrow: 'LIVE DESK',
|
|
40
|
+
title: 'Sign-in complete',
|
|
41
|
+
message: 'Return to the LiveDesk app. You can close this tab.',
|
|
42
|
+
button: 'Open LiveDesk',
|
|
43
|
+
note: 'If the app did not open automatically, use the button above.'
|
|
44
|
+
},
|
|
45
|
+
error: korean
|
|
46
|
+
? {
|
|
47
|
+
eyebrow: 'LIVE DESK',
|
|
48
|
+
title: '로그인을 완료하지 못했습니다',
|
|
49
|
+
message: 'LiveDesk 앱으로 돌아가 다시 시도해주세요.',
|
|
50
|
+
button: 'LiveDesk 열기',
|
|
51
|
+
note: '계정을 선택하지 않았거나 인증 요청이 취소되었습니다.'
|
|
52
|
+
}
|
|
53
|
+
: {
|
|
54
|
+
eyebrow: 'LIVE DESK',
|
|
55
|
+
title: 'Sign-in was not completed',
|
|
56
|
+
message: 'Return to the LiveDesk app and try again.',
|
|
57
|
+
button: 'Open LiveDesk',
|
|
58
|
+
note: 'The account selection or authorization request may have been cancelled.'
|
|
59
|
+
},
|
|
60
|
+
invalid: korean
|
|
61
|
+
? {
|
|
62
|
+
eyebrow: 'LIVE DESK',
|
|
63
|
+
title: '로그인 정보가 없습니다',
|
|
64
|
+
message: 'LiveDesk 앱에서 로그인을 다시 시작해주세요.',
|
|
65
|
+
button: '',
|
|
66
|
+
note: '이 페이지는 LiveDesk 로그인 뒤에 자동으로 열립니다.'
|
|
67
|
+
}
|
|
68
|
+
: {
|
|
69
|
+
eyebrow: 'LIVE DESK',
|
|
70
|
+
title: 'No sign-in information found',
|
|
71
|
+
message: 'Start sign-in again from the LiveDesk app.',
|
|
72
|
+
button: '',
|
|
73
|
+
note: 'This page opens automatically after LiveDesk sign-in.'
|
|
74
|
+
}
|
|
75
|
+
}[state];
|
|
76
|
+
|
|
77
|
+
document.documentElement.lang = korean ? 'ko' : 'en';
|
|
78
|
+
document.title = `${copy.title} · LiveDesk`;
|
|
79
|
+
document.body.dataset.state = state;
|
|
80
|
+
document.querySelector('[data-auth-eyebrow]').textContent = copy.eyebrow;
|
|
81
|
+
document.querySelector('[data-auth-title]').textContent = copy.title;
|
|
82
|
+
document.querySelector('[data-auth-message]').textContent = copy.message;
|
|
83
|
+
document.querySelector('[data-auth-note]').textContent = copy.note;
|
|
84
|
+
const button = document.querySelector('[data-auth-open]');
|
|
85
|
+
button.textContent = copy.button;
|
|
86
|
+
button.hidden = !copy.button;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function startDesktopAuthCallback() {
|
|
90
|
+
const callbackUrl = buildDesktopAuthCallbackUrl(window.location.search);
|
|
91
|
+
const source = new URLSearchParams(window.location.search);
|
|
92
|
+
const state = source.has('error') ? 'error' : callbackUrl ? 'success' : 'invalid';
|
|
93
|
+
const preview = localPreviewRequested(window.location);
|
|
94
|
+
|
|
95
|
+
setPageState(state, navigator.language);
|
|
96
|
+
|
|
97
|
+
// Remove the one-time authorization code from browser history before the
|
|
98
|
+
// custom protocol is opened. The code remains only in this page's memory.
|
|
99
|
+
window.history.replaceState({}, document.title, window.location.pathname);
|
|
100
|
+
|
|
101
|
+
const button = document.querySelector('[data-auth-open]');
|
|
102
|
+
if (!callbackUrl) return;
|
|
103
|
+
button.addEventListener('click', () => window.location.assign(callbackUrl));
|
|
104
|
+
if (!preview) window.setTimeout(() => window.location.assign(callbackUrl), 150);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
108
|
+
startDesktopAuthCallback();
|
|
109
|
+
}
|
package/web/dist/index.html
CHANGED
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
<link rel="icon" href="/favicon.ico" sizes="any" />
|
|
14
14
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
|
15
15
|
<title>LiveDesk</title>
|
|
16
|
-
<script type="module" crossorigin src="/assets/index-
|
|
16
|
+
<script type="module" crossorigin src="/assets/index-Dox-U5dj.js"></script>
|
|
17
17
|
<link rel="modulepreload" crossorigin href="/assets/icons-Bna5_o78.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="/assets/react-DYqrNwY4.js">
|
|
19
19
|
<link rel="modulepreload" crossorigin href="/assets/supabase-C7qjtLN3.js">
|
|
20
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
20
|
+
<link rel="stylesheet" crossorigin href="/assets/index-eImKb97V.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
|
23
23
|
<div id="root"></div>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"kind": "livedesk-production-web-source-evidence",
|
|
4
|
-
"generatedAt": "2026-08-
|
|
5
|
-
"pwaRelease": "0.1.
|
|
6
|
-
"sourceHash": "
|
|
7
|
-
"sourceFileCount":
|
|
8
|
-
"sourceBytes":
|
|
4
|
+
"generatedAt": "2026-08-15T02:43:25.514Z",
|
|
5
|
+
"pwaRelease": "0.1.562",
|
|
6
|
+
"sourceHash": "0b615bb5eb789e05ff3a86a258e7306f522e87bff3338493d55b1a3997b6a15f",
|
|
7
|
+
"sourceFileCount": 142,
|
|
8
|
+
"sourceBytes": 2243671,
|
|
9
9
|
"viteEnvironmentHash": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
|
|
10
|
-
"outputHash": "
|
|
11
|
-
"outputFileCount":
|
|
12
|
-
"outputBytes":
|
|
10
|
+
"outputHash": "05a71220ece6eba07ac2102bb6ad863463b1e26e9f68cae83fbc35bf0968031e",
|
|
11
|
+
"outputFileCount": 18,
|
|
12
|
+
"outputBytes": 1629538,
|
|
13
13
|
"outputManifest": [
|
|
14
14
|
{
|
|
15
15
|
"path": "_headers",
|
|
16
|
-
"bytes":
|
|
17
|
-
"sha256": "
|
|
16
|
+
"bytes": 1138,
|
|
17
|
+
"sha256": "f16ea7d42c6507ced51cb910f743ac90ef77fa2ebe1b62c0cec6e835c0369ae5"
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"path": "app.webmanifest",
|
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
"sha256": "4f25c62e468deac2fea9a62517ab10021fe45164734669a8e399e15c7504bf75"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
|
-
"path": "assets/index-
|
|
36
|
-
"bytes": 332348,
|
|
37
|
-
"sha256": "82a36db0ebf602718191f2a73db917af2f9812d80fba88e53e820e28495a00a8"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"path": "assets/index-Bzov0Sti.js",
|
|
35
|
+
"path": "assets/index-Dox-U5dj.js",
|
|
41
36
|
"bytes": 996930,
|
|
42
37
|
"sha256": "f80422cd493d49248018595a669d07d2de1542c5ecc53d6818678b3cc550465b"
|
|
43
38
|
},
|
|
39
|
+
{
|
|
40
|
+
"path": "assets/index-eImKb97V.css",
|
|
41
|
+
"bytes": 332358,
|
|
42
|
+
"sha256": "8ed54009a9db63b816b83ddd56c73e8a1defd094e52558b4f7153d4359fb1ce8"
|
|
43
|
+
},
|
|
44
44
|
{
|
|
45
45
|
"path": "assets/react-DYqrNwY4.js",
|
|
46
46
|
"bytes": 3654,
|
|
@@ -51,6 +51,16 @@
|
|
|
51
51
|
"bytes": 210756,
|
|
52
52
|
"sha256": "35040fe06fc7d7d25c730105638388ca6400835dac8caff268cf553d6639b886"
|
|
53
53
|
},
|
|
54
|
+
{
|
|
55
|
+
"path": "desktop-auth-callback.html",
|
|
56
|
+
"bytes": 3960,
|
|
57
|
+
"sha256": "0a15094ff4721e18744a16559e6815cdd302a5852070bd589ef123225699e7f3"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"path": "desktop-auth-callback.js",
|
|
61
|
+
"bytes": 4376,
|
|
62
|
+
"sha256": "3bd12ad98fe9606e23b4d0b112a88891a0fba76c6150e437f121b915c3f9216c"
|
|
63
|
+
},
|
|
54
64
|
{
|
|
55
65
|
"path": "favicon.ico",
|
|
56
66
|
"bytes": 9960,
|
|
@@ -64,7 +74,7 @@
|
|
|
64
74
|
{
|
|
65
75
|
"path": "index.html",
|
|
66
76
|
"bytes": 1251,
|
|
67
|
-
"sha256": "
|
|
77
|
+
"sha256": "bec24ff39bc381a117024c121c11a939b2715861e68eb4f5e83d44fb028f82a5"
|
|
68
78
|
},
|
|
69
79
|
{
|
|
70
80
|
"path": "offline.html",
|
|
@@ -89,7 +99,7 @@
|
|
|
89
99
|
{
|
|
90
100
|
"path": "sw.js",
|
|
91
101
|
"bytes": 1309,
|
|
92
|
-
"sha256": "
|
|
102
|
+
"sha256": "1e1af2a05a70a8f898dd51b7513564bec691d299de451145ccb5ca3b0148331d"
|
|
93
103
|
}
|
|
94
104
|
]
|
|
95
105
|
}
|
package/web/dist/sw.js
CHANGED
|
File without changes
|