pinokiod 6.0.46 → 6.0.48
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/package.json +1 -1
- package/server/lib/desktop_event_router.js +137 -2
- package/server/public/layout.js +34 -0
- package/server/views/app.ejs +241 -3
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ const path = require("path")
|
|
|
5
5
|
|
|
6
6
|
const DESKTOP_EVENT_NAME_PATTERN = /^[a-z0-9][a-z0-9:_-]{0,127}$/
|
|
7
7
|
const WORKSPACE_PATH_PATTERNS = [
|
|
8
|
+
/^\/pinokio\/([^/?#]+)/i,
|
|
8
9
|
/^\/p\/([^/?#]+)/i,
|
|
9
10
|
/^\/api\/([^/?#]+)/i,
|
|
10
11
|
/^\/_api\/([^/?#]+)/i,
|
|
@@ -100,7 +101,134 @@ const extractWorkspaceFromUrl = (rawUrl) => {
|
|
|
100
101
|
return extractWorkspaceFromPathname(parsedUrl.pathname)
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
const
|
|
104
|
+
const toHttpHostKey = (rawUrl) => {
|
|
105
|
+
if (typeof rawUrl !== "string") {
|
|
106
|
+
return null
|
|
107
|
+
}
|
|
108
|
+
const value = rawUrl.trim()
|
|
109
|
+
if (!value) {
|
|
110
|
+
return null
|
|
111
|
+
}
|
|
112
|
+
let parsed
|
|
113
|
+
try {
|
|
114
|
+
parsed = /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(value)
|
|
115
|
+
? new URL(value)
|
|
116
|
+
: new URL(value, "http://localhost")
|
|
117
|
+
} catch (_) {
|
|
118
|
+
return null
|
|
119
|
+
}
|
|
120
|
+
const protocol = parsed.protocol || ""
|
|
121
|
+
if (protocol !== "http:" && protocol !== "https:") {
|
|
122
|
+
return null
|
|
123
|
+
}
|
|
124
|
+
const host = (parsed.host || "").trim().toLowerCase()
|
|
125
|
+
return host || null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const collectUrlLikeValues = (value, out = new Set(), depth = 0) => {
|
|
129
|
+
if (depth > 4 || value === null || value === undefined) {
|
|
130
|
+
return out
|
|
131
|
+
}
|
|
132
|
+
if (typeof value === "string") {
|
|
133
|
+
const trimmed = value.trim()
|
|
134
|
+
if (trimmed) {
|
|
135
|
+
out.add(trimmed)
|
|
136
|
+
}
|
|
137
|
+
return out
|
|
138
|
+
}
|
|
139
|
+
if (Array.isArray(value)) {
|
|
140
|
+
for (const entry of value) {
|
|
141
|
+
collectUrlLikeValues(entry, out, depth + 1)
|
|
142
|
+
}
|
|
143
|
+
return out
|
|
144
|
+
}
|
|
145
|
+
if (typeof value === "object") {
|
|
146
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
147
|
+
if (!key) {
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
150
|
+
if (typeof entry === "string" && /url/i.test(key)) {
|
|
151
|
+
const trimmed = entry.trim()
|
|
152
|
+
if (trimmed) {
|
|
153
|
+
out.add(trimmed)
|
|
154
|
+
}
|
|
155
|
+
continue
|
|
156
|
+
}
|
|
157
|
+
if (typeof entry === "object" && entry !== null) {
|
|
158
|
+
collectUrlLikeValues(entry, out, depth + 1)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return out
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const resolveWorkspaceFromRunningScripts = (kernel, context = {}) => {
|
|
166
|
+
if (!kernel || !kernel.info || typeof kernel.info.scriptsByApi !== "function") {
|
|
167
|
+
return null
|
|
168
|
+
}
|
|
169
|
+
const contextHosts = new Set()
|
|
170
|
+
const contextUrlCandidates = [
|
|
171
|
+
context.frameUrl,
|
|
172
|
+
context.pageUrl,
|
|
173
|
+
context.currentUrl,
|
|
174
|
+
context.sourceUrl,
|
|
175
|
+
context.referrerUrl,
|
|
176
|
+
context.topUrl,
|
|
177
|
+
context.destinationUrl,
|
|
178
|
+
context.url,
|
|
179
|
+
]
|
|
180
|
+
for (const candidate of contextUrlCandidates) {
|
|
181
|
+
const hostKey = toHttpHostKey(candidate)
|
|
182
|
+
if (hostKey) {
|
|
183
|
+
contextHosts.add(hostKey)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (contextHosts.size === 0) {
|
|
187
|
+
return null
|
|
188
|
+
}
|
|
189
|
+
let scriptsByApi
|
|
190
|
+
try {
|
|
191
|
+
scriptsByApi = kernel.info.scriptsByApi()
|
|
192
|
+
} catch (_) {
|
|
193
|
+
return null
|
|
194
|
+
}
|
|
195
|
+
if (!scriptsByApi || typeof scriptsByApi !== "object") {
|
|
196
|
+
return null
|
|
197
|
+
}
|
|
198
|
+
const matches = new Set()
|
|
199
|
+
for (const [workspace, entries] of Object.entries(scriptsByApi)) {
|
|
200
|
+
if (!workspace || !Array.isArray(entries)) {
|
|
201
|
+
continue
|
|
202
|
+
}
|
|
203
|
+
const normalizedWorkspace = sanitizeDesktopWorkspaceName(workspace)
|
|
204
|
+
if (!normalizedWorkspace) {
|
|
205
|
+
continue
|
|
206
|
+
}
|
|
207
|
+
let matched = false
|
|
208
|
+
for (const entry of entries) {
|
|
209
|
+
const urlValues = collectUrlLikeValues(entry, new Set())
|
|
210
|
+
for (const value of urlValues) {
|
|
211
|
+
const hostKey = toHttpHostKey(value)
|
|
212
|
+
if (hostKey && contextHosts.has(hostKey)) {
|
|
213
|
+
matched = true
|
|
214
|
+
break
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (matched) {
|
|
218
|
+
break
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (matched) {
|
|
222
|
+
matches.add(normalizedWorkspace)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (matches.size === 1) {
|
|
226
|
+
return [...matches][0]
|
|
227
|
+
}
|
|
228
|
+
return null
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const resolveDesktopEventWorkspace = async (context = {}, kernel = null) => {
|
|
104
232
|
const explicitCandidates = [
|
|
105
233
|
context.workspace,
|
|
106
234
|
context.app,
|
|
@@ -114,11 +242,14 @@ const resolveDesktopEventWorkspace = async (context = {}) => {
|
|
|
114
242
|
}
|
|
115
243
|
}
|
|
116
244
|
const urlCandidates = [
|
|
245
|
+
context.frameUrl,
|
|
117
246
|
context.pageUrl,
|
|
118
247
|
context.url,
|
|
119
248
|
context.currentUrl,
|
|
120
249
|
context.sourceUrl,
|
|
121
250
|
context.referrerUrl,
|
|
251
|
+
context.topUrl,
|
|
252
|
+
context.destinationUrl,
|
|
122
253
|
]
|
|
123
254
|
for (const candidate of urlCandidates) {
|
|
124
255
|
const workspaceName = extractWorkspaceFromUrl(candidate)
|
|
@@ -126,6 +257,10 @@ const resolveDesktopEventWorkspace = async (context = {}) => {
|
|
|
126
257
|
return workspaceName
|
|
127
258
|
}
|
|
128
259
|
}
|
|
260
|
+
const workspaceByHost = resolveWorkspaceFromRunningScripts(kernel, context)
|
|
261
|
+
if (workspaceByHost) {
|
|
262
|
+
return workspaceByHost
|
|
263
|
+
}
|
|
129
264
|
return null
|
|
130
265
|
}
|
|
131
266
|
|
|
@@ -195,7 +330,7 @@ const buildDesktopEventQueryParams = (eventName, payload) => {
|
|
|
195
330
|
}
|
|
196
331
|
|
|
197
332
|
const resolveDesktopEventHandler = async ({ kernel, eventName, payload, context = {} }) => {
|
|
198
|
-
const workspace = await resolveDesktopEventWorkspace(context)
|
|
333
|
+
const workspace = await resolveDesktopEventWorkspace(context, kernel)
|
|
199
334
|
if (!workspace) {
|
|
200
335
|
return { matched: false, reason: "workspace_not_resolved" }
|
|
201
336
|
}
|
package/server/public/layout.js
CHANGED
|
@@ -479,6 +479,27 @@
|
|
|
479
479
|
});
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
+
function relayDesktopEventLaunch(payload, excludedSource = null) {
|
|
483
|
+
if (!payload || typeof payload !== 'object' || payload.e !== 'pinokio:desktop-event-launch') {
|
|
484
|
+
return 0;
|
|
485
|
+
}
|
|
486
|
+
let relayed = 0;
|
|
487
|
+
leafElements.forEach((entry) => {
|
|
488
|
+
const targetWindow = entry && entry.iframe ? entry.iframe.contentWindow : null;
|
|
489
|
+
if (!targetWindow) {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
if (excludedSource && targetWindow === excludedSource) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
try {
|
|
496
|
+
targetWindow.postMessage(payload, '*');
|
|
497
|
+
relayed += 1;
|
|
498
|
+
} catch (_) {}
|
|
499
|
+
});
|
|
500
|
+
return relayed;
|
|
501
|
+
}
|
|
502
|
+
|
|
482
503
|
let activeResize = null;
|
|
483
504
|
|
|
484
505
|
function beginResize(splitId, pointerEvent) {
|
|
@@ -665,6 +686,10 @@
|
|
|
665
686
|
if (!event || !event.data || typeof event.data !== 'object') {
|
|
666
687
|
return;
|
|
667
688
|
}
|
|
689
|
+
if (event.data.e === 'pinokio:desktop-event-launch') {
|
|
690
|
+
relayDesktopEventLaunch(event.data, event.source || null);
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
668
693
|
if (event.data.e === 'layout-state-request') {
|
|
669
694
|
let frameEntry = null;
|
|
670
695
|
let frameId = null;
|
|
@@ -770,6 +795,15 @@
|
|
|
770
795
|
|
|
771
796
|
initLayout();
|
|
772
797
|
window.addEventListener('message', onMessage);
|
|
798
|
+
window.addEventListener('pinokio:desktop-event-launch', (event) => {
|
|
799
|
+
const detail = event && event.detail && typeof event.detail === 'object'
|
|
800
|
+
? event.detail
|
|
801
|
+
: null;
|
|
802
|
+
if (!detail || detail.e !== 'pinokio:desktop-event-launch') {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
relayDesktopEventLaunch(detail, null);
|
|
806
|
+
});
|
|
773
807
|
window.addEventListener('resize', onResize);
|
|
774
808
|
window.addEventListener('pinokio:viewport-change', onResize);
|
|
775
809
|
|
package/server/views/app.ejs
CHANGED
|
@@ -7422,6 +7422,12 @@ const rerenderMenuSection = (container, html) => {
|
|
|
7422
7422
|
//if (String(port) === "<%=port%>" || /https:\/\/pinokio\..*localhost/.test(origin)) {
|
|
7423
7423
|
//if (String(port) === "<%=port%>") {
|
|
7424
7424
|
if (event.data) {
|
|
7425
|
+
if (event.data.e === "pinokio:desktop-event-launch") {
|
|
7426
|
+
return
|
|
7427
|
+
}
|
|
7428
|
+
if (event.data.e === "pinokio:desktop-event") {
|
|
7429
|
+
return
|
|
7430
|
+
}
|
|
7425
7431
|
if (event.data.action) {
|
|
7426
7432
|
if (event.data.action.type === "newtab") {
|
|
7427
7433
|
addTab(event.data.action.url)
|
|
@@ -7437,18 +7443,23 @@ const rerenderMenuSection = (container, html) => {
|
|
|
7437
7443
|
}
|
|
7438
7444
|
}
|
|
7439
7445
|
} else if (event.data.launch) {
|
|
7440
|
-
const
|
|
7446
|
+
const launchPayload = event.data.launch
|
|
7447
|
+
const rawName = launchPayload && typeof launchPayload.name === "string" ? launchPayload.name : ""
|
|
7448
|
+
const launchHref = launchPayload && typeof launchPayload.href === "string" ? launchPayload.href : ""
|
|
7449
|
+
if (!rawName || !launchHref) {
|
|
7450
|
+
return
|
|
7451
|
+
}
|
|
7441
7452
|
const escapedSelector = escapeTargetSelector(rawName)
|
|
7442
7453
|
if (escapedSelector) {
|
|
7443
7454
|
global_selector = `.frame-link[target="${escapedSelector}"]`
|
|
7444
7455
|
} else {
|
|
7445
7456
|
global_selector = null
|
|
7446
7457
|
}
|
|
7447
|
-
|
|
7458
|
+
const frameExists = Array.from(document.querySelectorAll("main.browserview iframe")).some((frame) => {
|
|
7448
7459
|
return frame.name === rawName
|
|
7449
7460
|
})
|
|
7450
7461
|
if (!frameExists) {
|
|
7451
|
-
create_iframe(rawName,
|
|
7462
|
+
create_iframe(rawName, launchHref)
|
|
7452
7463
|
}
|
|
7453
7464
|
refresh()
|
|
7454
7465
|
} else if (event.data.type === "shell-session-id") {
|
|
@@ -11876,6 +11887,19 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
11876
11887
|
}
|
|
11877
11888
|
})
|
|
11878
11889
|
|
|
11890
|
+
const openDesktopEvent = (launch) => {
|
|
11891
|
+
if (!launch || typeof launch !== "object") {
|
|
11892
|
+
return false
|
|
11893
|
+
}
|
|
11894
|
+
const rawUrl = typeof launch.url === "string" ? launch.url : ""
|
|
11895
|
+
if (!rawUrl) {
|
|
11896
|
+
return false
|
|
11897
|
+
}
|
|
11898
|
+
return openWithUrl(rawUrl, {
|
|
11899
|
+
workspaceCwd: resolveWorkspaceCwd(launch)
|
|
11900
|
+
})
|
|
11901
|
+
}
|
|
11902
|
+
|
|
11879
11903
|
if (resizer) {
|
|
11880
11904
|
let isResizing = false
|
|
11881
11905
|
let pointerId = null
|
|
@@ -11952,11 +11976,225 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
11952
11976
|
openWithAgent,
|
|
11953
11977
|
openPicker,
|
|
11954
11978
|
openWithUrl,
|
|
11979
|
+
openDesktopEvent,
|
|
11955
11980
|
close: () => setOpen(false),
|
|
11956
11981
|
isOpen: () => open
|
|
11957
11982
|
}
|
|
11958
11983
|
})();
|
|
11959
11984
|
|
|
11985
|
+
(function() {
|
|
11986
|
+
const normalizeLaunchUrl = (rawUrl) => {
|
|
11987
|
+
if (typeof rawUrl !== "string" || !rawUrl.trim()) {
|
|
11988
|
+
return null
|
|
11989
|
+
}
|
|
11990
|
+
let parsed
|
|
11991
|
+
try {
|
|
11992
|
+
parsed = new URL(rawUrl, window.location.origin)
|
|
11993
|
+
} catch (_) {
|
|
11994
|
+
return null
|
|
11995
|
+
}
|
|
11996
|
+
if (parsed.origin !== window.location.origin) {
|
|
11997
|
+
return null
|
|
11998
|
+
}
|
|
11999
|
+
return `${parsed.pathname}${parsed.search}${parsed.hash}`
|
|
12000
|
+
}
|
|
12001
|
+
|
|
12002
|
+
const isTrustedOrigin = (origin) => {
|
|
12003
|
+
if (!origin) {
|
|
12004
|
+
return true
|
|
12005
|
+
}
|
|
12006
|
+
let parsed
|
|
12007
|
+
try {
|
|
12008
|
+
parsed = new URL(origin)
|
|
12009
|
+
} catch (_) {
|
|
12010
|
+
return false
|
|
12011
|
+
}
|
|
12012
|
+
const originPort = parsed.port || "80"
|
|
12013
|
+
const currentPort = window.location.port || "80"
|
|
12014
|
+
if (String(originPort) === String(currentPort)) {
|
|
12015
|
+
return true
|
|
12016
|
+
}
|
|
12017
|
+
return /https:\/\/.*pinokio\..*(localhost|co)/.test(origin)
|
|
12018
|
+
}
|
|
12019
|
+
|
|
12020
|
+
const escapeText = (value) => String(value || "")
|
|
12021
|
+
.replace(/&/g, "&")
|
|
12022
|
+
.replace(/</g, "<")
|
|
12023
|
+
.replace(/>/g, ">")
|
|
12024
|
+
.replace(/"/g, """)
|
|
12025
|
+
.replace(/'/g, "'")
|
|
12026
|
+
|
|
12027
|
+
let overlayEl = null
|
|
12028
|
+
let overlayEscHandler = null
|
|
12029
|
+
|
|
12030
|
+
const closeOverlay = () => {
|
|
12031
|
+
if (overlayEscHandler) {
|
|
12032
|
+
document.removeEventListener("keydown", overlayEscHandler)
|
|
12033
|
+
overlayEscHandler = null
|
|
12034
|
+
}
|
|
12035
|
+
if (overlayEl && overlayEl.parentNode) {
|
|
12036
|
+
overlayEl.parentNode.removeChild(overlayEl)
|
|
12037
|
+
}
|
|
12038
|
+
overlayEl = null
|
|
12039
|
+
}
|
|
12040
|
+
|
|
12041
|
+
const openOverlay = (launch) => {
|
|
12042
|
+
if (!launch || typeof launch !== "object") {
|
|
12043
|
+
return false
|
|
12044
|
+
}
|
|
12045
|
+
const normalizedUrl = normalizeLaunchUrl(launch.url)
|
|
12046
|
+
if (!normalizedUrl) {
|
|
12047
|
+
return false
|
|
12048
|
+
}
|
|
12049
|
+
closeOverlay()
|
|
12050
|
+
const ui = launch.ui && typeof launch.ui === "object" ? launch.ui : {}
|
|
12051
|
+
const title = typeof ui.title === "string" && ui.title.trim()
|
|
12052
|
+
? ui.title.trim()
|
|
12053
|
+
: "Task"
|
|
12054
|
+
const overlay = document.createElement("div")
|
|
12055
|
+
overlay.className = "pinokio-custom-terminal-overlay pinokio-desktop-event-overlay"
|
|
12056
|
+
overlay.innerHTML = `
|
|
12057
|
+
<div class="pinokio-custom-terminal-modal">
|
|
12058
|
+
<div class="pinokio-custom-terminal-header">
|
|
12059
|
+
<h3>${escapeText(title)}</h3>
|
|
12060
|
+
<button class="pinokio-custom-terminal-close" aria-label="Close">×</button>
|
|
12061
|
+
</div>
|
|
12062
|
+
<div class="pinokio-custom-terminal-body">
|
|
12063
|
+
<iframe src="${escapeText(normalizedUrl)}" frameborder="0" allow="fullscreen *;" allowfullscreen></iframe>
|
|
12064
|
+
</div>
|
|
12065
|
+
</div>
|
|
12066
|
+
`
|
|
12067
|
+
const closeBtn = overlay.querySelector(".pinokio-custom-terminal-close")
|
|
12068
|
+
if (closeBtn) {
|
|
12069
|
+
closeBtn.addEventListener("click", closeOverlay)
|
|
12070
|
+
}
|
|
12071
|
+
overlay.addEventListener("click", (event) => {
|
|
12072
|
+
if (event.target === overlay) {
|
|
12073
|
+
closeOverlay()
|
|
12074
|
+
}
|
|
12075
|
+
})
|
|
12076
|
+
overlayEscHandler = (event) => {
|
|
12077
|
+
if (event.key === "Escape") {
|
|
12078
|
+
closeOverlay()
|
|
12079
|
+
}
|
|
12080
|
+
}
|
|
12081
|
+
document.addEventListener("keydown", overlayEscHandler)
|
|
12082
|
+
document.body.appendChild(overlay)
|
|
12083
|
+
overlayEl = overlay
|
|
12084
|
+
return true
|
|
12085
|
+
}
|
|
12086
|
+
|
|
12087
|
+
const openSidebar = (launch) => {
|
|
12088
|
+
const drawer = window.PinokioAskAiDrawer
|
|
12089
|
+
if (!drawer || typeof drawer.openDesktopEvent !== "function") {
|
|
12090
|
+
return false
|
|
12091
|
+
}
|
|
12092
|
+
closeOverlay()
|
|
12093
|
+
return drawer.openDesktopEvent(launch)
|
|
12094
|
+
}
|
|
12095
|
+
|
|
12096
|
+
const handleDesktopLaunch = (envelope) => {
|
|
12097
|
+
const launch = envelope && typeof envelope === "object" && envelope.launch && typeof envelope.launch === "object"
|
|
12098
|
+
? envelope.launch
|
|
12099
|
+
: envelope
|
|
12100
|
+
if (!launch || typeof launch !== "object") {
|
|
12101
|
+
return false
|
|
12102
|
+
}
|
|
12103
|
+
const ui = launch.ui && typeof launch.ui === "object" ? launch.ui : {}
|
|
12104
|
+
const mode = typeof ui.mode === "string" ? ui.mode.trim().toLowerCase() : "sidebar"
|
|
12105
|
+
if (mode === "overlay") {
|
|
12106
|
+
return openOverlay(launch)
|
|
12107
|
+
}
|
|
12108
|
+
if (mode === "sidebar") {
|
|
12109
|
+
const opened = openSidebar(launch)
|
|
12110
|
+
if (opened) {
|
|
12111
|
+
return true
|
|
12112
|
+
}
|
|
12113
|
+
return openOverlay(launch)
|
|
12114
|
+
}
|
|
12115
|
+
return false
|
|
12116
|
+
}
|
|
12117
|
+
|
|
12118
|
+
const dispatchDesktopEvent = async (envelope) => {
|
|
12119
|
+
if (!envelope || typeof envelope !== "object") {
|
|
12120
|
+
return null
|
|
12121
|
+
}
|
|
12122
|
+
const eventName = typeof envelope.event === "string" ? envelope.event.trim() : ""
|
|
12123
|
+
if (!eventName) {
|
|
12124
|
+
return null
|
|
12125
|
+
}
|
|
12126
|
+
const payload = envelope.payload && typeof envelope.payload === "object"
|
|
12127
|
+
? envelope.payload
|
|
12128
|
+
: {}
|
|
12129
|
+
const context = envelope.context && typeof envelope.context === "object"
|
|
12130
|
+
? { ...envelope.context }
|
|
12131
|
+
: {}
|
|
12132
|
+
if (!context.pageUrl) {
|
|
12133
|
+
context.pageUrl = window.location.href
|
|
12134
|
+
}
|
|
12135
|
+
if (!context.currentUrl) {
|
|
12136
|
+
context.currentUrl = window.location.href
|
|
12137
|
+
}
|
|
12138
|
+
if (!context.referrerUrl && document.referrer) {
|
|
12139
|
+
context.referrerUrl = document.referrer
|
|
12140
|
+
}
|
|
12141
|
+
const response = await fetch("/pinokio/desktop/event", {
|
|
12142
|
+
method: "POST",
|
|
12143
|
+
headers: {
|
|
12144
|
+
"Content-Type": "application/json"
|
|
12145
|
+
},
|
|
12146
|
+
body: JSON.stringify({ event: eventName, payload, context })
|
|
12147
|
+
})
|
|
12148
|
+
if (!response.ok) {
|
|
12149
|
+
return null
|
|
12150
|
+
}
|
|
12151
|
+
return response.json().catch(() => null)
|
|
12152
|
+
}
|
|
12153
|
+
|
|
12154
|
+
window.addEventListener("message", (event) => {
|
|
12155
|
+
if (!event || !event.data || typeof event.data !== "object") {
|
|
12156
|
+
return
|
|
12157
|
+
}
|
|
12158
|
+
if (event.data.e !== "pinokio:desktop-event") {
|
|
12159
|
+
return
|
|
12160
|
+
}
|
|
12161
|
+
dispatchDesktopEvent(event.data).then((result) => {
|
|
12162
|
+
if (!result || !result.ok || !result.matched || !result.launch || !result.launch.url) {
|
|
12163
|
+
return
|
|
12164
|
+
}
|
|
12165
|
+
window.postMessage({ e: "pinokio:desktop-event-launch", launch: result.launch }, "*")
|
|
12166
|
+
}).catch(() => {})
|
|
12167
|
+
})
|
|
12168
|
+
|
|
12169
|
+
window.addEventListener("pinokio:desktop-event-launch", (event) => {
|
|
12170
|
+
handleDesktopLaunch(event && event.detail ? event.detail : null)
|
|
12171
|
+
})
|
|
12172
|
+
|
|
12173
|
+
window.addEventListener("message", (event) => {
|
|
12174
|
+
if (!event || !event.data || typeof event.data !== "object") {
|
|
12175
|
+
return
|
|
12176
|
+
}
|
|
12177
|
+
if (event.data.e !== "pinokio:desktop-event-launch") {
|
|
12178
|
+
return
|
|
12179
|
+
}
|
|
12180
|
+
if (!isTrustedOrigin(event.origin)) {
|
|
12181
|
+
return
|
|
12182
|
+
}
|
|
12183
|
+
handleDesktopLaunch(event.data)
|
|
12184
|
+
})
|
|
12185
|
+
|
|
12186
|
+
window.PinokioDesktopEventUi = {
|
|
12187
|
+
open: (launch) => handleDesktopLaunch(launch),
|
|
12188
|
+
closeOverlay,
|
|
12189
|
+
closeSidebar: () => {
|
|
12190
|
+
const drawer = window.PinokioAskAiDrawer
|
|
12191
|
+
if (drawer && typeof drawer.close === "function") {
|
|
12192
|
+
drawer.close()
|
|
12193
|
+
}
|
|
12194
|
+
}
|
|
12195
|
+
}
|
|
12196
|
+
})();
|
|
12197
|
+
|
|
11960
12198
|
(function() {
|
|
11961
12199
|
const drawer = document.getElementById("community-drawer")
|
|
11962
12200
|
if (!drawer) {
|