pinokiod 8.0.79 → 8.0.80
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/index.js +5 -2
- package/server/views/app.ejs +240 -40
- package/test/launch-settings-ui.test.js +37 -5
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -1870,8 +1870,10 @@ class Server {
|
|
|
1870
1870
|
}
|
|
1871
1871
|
return ""
|
|
1872
1872
|
}
|
|
1873
|
+
const launcherPath = this.kernel.path("api", name)
|
|
1874
|
+
const launcherDisplayPath = this.formatLogsDisplayPath(launcherPath)
|
|
1873
1875
|
const launcherRemote = this.kernel.api && typeof this.kernel.api.parentGitURI === "function"
|
|
1874
|
-
? (this.kernel.api.parentGitURI(
|
|
1876
|
+
? (this.kernel.api.parentGitURI(launcherPath) || "")
|
|
1875
1877
|
: ""
|
|
1876
1878
|
const launcherRemoteUrl = buildGitRemoteWebUrl(launcherRemote)
|
|
1877
1879
|
|
|
@@ -1926,7 +1928,8 @@ class Server {
|
|
|
1926
1928
|
dev_link,
|
|
1927
1929
|
// repos,
|
|
1928
1930
|
current_urls,
|
|
1929
|
-
path:
|
|
1931
|
+
path: launcherPath,
|
|
1932
|
+
launcher_path_display: launcherDisplayPath,
|
|
1930
1933
|
log_path: this.kernel.path("api", name, "logs"),
|
|
1931
1934
|
plugin_menu: null,
|
|
1932
1935
|
portal: this.portal,
|
package/server/views/app.ejs
CHANGED
|
@@ -202,52 +202,148 @@ body.dark .app-header-info-popover-title {
|
|
|
202
202
|
body.dark .app-header-info-popover-description {
|
|
203
203
|
color: rgba(203, 213, 225, 0.78);
|
|
204
204
|
}
|
|
205
|
-
.app-header-info-popover-
|
|
206
|
-
.app-header-info-popover-link--muted {
|
|
205
|
+
.app-header-info-popover-meta {
|
|
207
206
|
margin-top: 12px;
|
|
208
|
-
|
|
209
|
-
display: flex;
|
|
210
|
-
align-items: center;
|
|
211
|
-
justify-content: space-between;
|
|
212
|
-
gap: 10px;
|
|
213
|
-
padding: 0 10px;
|
|
214
|
-
border-radius: 7px;
|
|
207
|
+
overflow: hidden;
|
|
215
208
|
border: 1px solid rgba(15, 23, 42, 0.1);
|
|
209
|
+
border-radius: 7px;
|
|
216
210
|
background: rgba(15, 23, 42, 0.035);
|
|
211
|
+
}
|
|
212
|
+
body.dark .app-header-info-popover-meta {
|
|
213
|
+
border-color: rgba(255, 255, 255, 0.1);
|
|
214
|
+
background: rgba(255, 255, 255, 0.06);
|
|
215
|
+
}
|
|
216
|
+
.app-header-info-popover-row {
|
|
217
|
+
min-height: 48px;
|
|
218
|
+
display: grid;
|
|
219
|
+
grid-template-columns: 26px minmax(0, 1fr) auto;
|
|
220
|
+
align-items: center;
|
|
221
|
+
gap: 10px;
|
|
222
|
+
padding: 7px 9px;
|
|
217
223
|
color: rgba(15, 23, 42, 0.88);
|
|
218
|
-
font-size: 12px;
|
|
219
|
-
font-weight: 650;
|
|
220
|
-
line-height: 1.2;
|
|
221
|
-
text-decoration: none;
|
|
222
224
|
box-sizing: border-box;
|
|
223
225
|
}
|
|
224
|
-
.app-header-info-popover-
|
|
226
|
+
.app-header-info-popover-row + .app-header-info-popover-row {
|
|
227
|
+
border-top: 1px solid rgba(15, 23, 42, 0.1);
|
|
228
|
+
}
|
|
229
|
+
body.dark .app-header-info-popover-row {
|
|
230
|
+
color: rgba(248, 250, 252, 0.9);
|
|
231
|
+
}
|
|
232
|
+
body.dark .app-header-info-popover-row + .app-header-info-popover-row {
|
|
233
|
+
border-top-color: rgba(255, 255, 255, 0.1);
|
|
234
|
+
}
|
|
235
|
+
.app-header-info-popover-row--link {
|
|
236
|
+
text-decoration: none;
|
|
237
|
+
}
|
|
238
|
+
.app-header-info-popover-row--link:hover {
|
|
225
239
|
background: rgba(15, 23, 42, 0.07);
|
|
226
240
|
}
|
|
227
|
-
.app-header-info-popover-link
|
|
241
|
+
body.dark .app-header-info-popover-row--link:hover {
|
|
242
|
+
background: rgba(255, 255, 255, 0.09);
|
|
243
|
+
}
|
|
244
|
+
.app-header-info-popover-row--link:focus-visible {
|
|
245
|
+
outline: 2px solid rgba(10, 132, 255, 0.55);
|
|
246
|
+
outline-offset: -2px;
|
|
247
|
+
}
|
|
248
|
+
.app-header-info-popover-row-icon {
|
|
249
|
+
width: 26px;
|
|
250
|
+
display: inline-flex;
|
|
251
|
+
align-items: center;
|
|
252
|
+
justify-content: center;
|
|
253
|
+
color: rgba(71, 85, 105, 0.78);
|
|
254
|
+
font-size: 18px;
|
|
255
|
+
}
|
|
256
|
+
body.dark .app-header-info-popover-row-icon {
|
|
257
|
+
color: rgba(226, 232, 240, 0.82);
|
|
258
|
+
}
|
|
259
|
+
.app-header-info-popover-row-copy {
|
|
228
260
|
min-width: 0;
|
|
261
|
+
}
|
|
262
|
+
.app-header-info-popover-row-label {
|
|
263
|
+
display: block;
|
|
264
|
+
color: rgba(15, 23, 42, 0.9);
|
|
265
|
+
font-size: 12px;
|
|
266
|
+
font-weight: 700;
|
|
267
|
+
line-height: 1.2;
|
|
268
|
+
}
|
|
269
|
+
body.dark .app-header-info-popover-row-label {
|
|
270
|
+
color: rgba(248, 250, 252, 0.92);
|
|
271
|
+
}
|
|
272
|
+
.app-header-info-popover-row-value {
|
|
273
|
+
display: block;
|
|
274
|
+
margin-top: 3px;
|
|
275
|
+
color: rgba(71, 85, 105, 0.8);
|
|
276
|
+
font-size: 11px;
|
|
277
|
+
font-weight: 500;
|
|
278
|
+
line-height: 1.2;
|
|
229
279
|
overflow: hidden;
|
|
230
280
|
text-overflow: ellipsis;
|
|
231
281
|
white-space: nowrap;
|
|
232
282
|
}
|
|
233
|
-
.app-header-info-popover-
|
|
283
|
+
body.dark .app-header-info-popover-row-value {
|
|
284
|
+
color: rgba(203, 213, 225, 0.76);
|
|
285
|
+
}
|
|
286
|
+
.app-header-info-popover-row-actions {
|
|
287
|
+
display: inline-flex;
|
|
288
|
+
align-items: center;
|
|
289
|
+
gap: 4px;
|
|
290
|
+
}
|
|
291
|
+
.app-header-info-popover-row-action {
|
|
292
|
+
appearance: none;
|
|
293
|
+
width: 28px;
|
|
294
|
+
height: 28px;
|
|
295
|
+
display: inline-flex;
|
|
296
|
+
align-items: center;
|
|
297
|
+
justify-content: center;
|
|
298
|
+
margin: 0;
|
|
299
|
+
padding: 0;
|
|
300
|
+
border: 1px solid rgba(15, 23, 42, 0.1);
|
|
301
|
+
border-radius: 6px;
|
|
302
|
+
background: rgba(255, 255, 255, 0.5);
|
|
303
|
+
color: rgba(71, 85, 105, 0.82);
|
|
304
|
+
font: inherit;
|
|
305
|
+
cursor: pointer;
|
|
306
|
+
}
|
|
307
|
+
.app-header-info-popover-row-action:hover {
|
|
308
|
+
border-color: rgba(15, 23, 42, 0.16);
|
|
309
|
+
background: rgba(15, 23, 42, 0.065);
|
|
310
|
+
color: rgba(15, 23, 42, 0.9);
|
|
311
|
+
}
|
|
312
|
+
.app-header-info-popover-row-action:focus-visible {
|
|
234
313
|
outline: 2px solid rgba(10, 132, 255, 0.55);
|
|
235
314
|
outline-offset: 2px;
|
|
236
315
|
}
|
|
237
|
-
|
|
238
|
-
|
|
316
|
+
.app-header-info-popover-row-action.is-copied {
|
|
317
|
+
color: #15803d;
|
|
318
|
+
}
|
|
319
|
+
body.dark .app-header-info-popover-row-action {
|
|
239
320
|
border-color: rgba(255, 255, 255, 0.1);
|
|
240
|
-
background: rgba(255, 255, 255, 0.
|
|
241
|
-
color: rgba(
|
|
321
|
+
background: rgba(255, 255, 255, 0.035);
|
|
322
|
+
color: rgba(226, 232, 240, 0.8);
|
|
242
323
|
}
|
|
243
|
-
body.dark .app-header-info-popover-
|
|
324
|
+
body.dark .app-header-info-popover-row-action:hover {
|
|
325
|
+
border-color: rgba(255, 255, 255, 0.16);
|
|
244
326
|
background: rgba(255, 255, 255, 0.09);
|
|
327
|
+
color: rgba(248, 250, 252, 0.94);
|
|
245
328
|
}
|
|
246
|
-
.app-header-info-popover-
|
|
247
|
-
|
|
329
|
+
body.dark .app-header-info-popover-row-action.is-copied {
|
|
330
|
+
color: #86efac;
|
|
331
|
+
}
|
|
332
|
+
.app-header-info-popover-row-trailing {
|
|
333
|
+
width: 28px;
|
|
334
|
+
height: 28px;
|
|
335
|
+
display: inline-flex;
|
|
336
|
+
align-items: center;
|
|
337
|
+
justify-content: center;
|
|
338
|
+
color: rgba(71, 85, 105, 0.72);
|
|
339
|
+
}
|
|
340
|
+
body.dark .app-header-info-popover-row-trailing {
|
|
341
|
+
color: rgba(226, 232, 240, 0.76);
|
|
342
|
+
}
|
|
343
|
+
.app-header-info-popover-row--muted .app-header-info-popover-row-value {
|
|
248
344
|
color: rgba(100, 116, 139, 0.78);
|
|
249
345
|
}
|
|
250
|
-
body.dark .app-header-info-popover-
|
|
346
|
+
body.dark .app-header-info-popover-row--muted .app-header-info-popover-row-value {
|
|
251
347
|
color: rgba(148, 163, 184, 0.86);
|
|
252
348
|
}
|
|
253
349
|
.app-header-identity-icon {
|
|
@@ -8281,6 +8377,10 @@ body.dark .pinokio-custom-terminal-header {
|
|
|
8281
8377
|
<%
|
|
8282
8378
|
const appInfoRemoteUrl = typeof launcher_remote_url === "string" ? launcher_remote_url : ""
|
|
8283
8379
|
const appInfoRemoteDisplayUrl = appInfoRemoteUrl.replace(/^https?:\/\//i, "")
|
|
8380
|
+
const appInfoFolderPath = typeof path === "string" ? path : ""
|
|
8381
|
+
const appInfoFolderDisplayPath = typeof launcher_path_display === "string" && launcher_path_display
|
|
8382
|
+
? launcher_path_display
|
|
8383
|
+
: appInfoFolderPath
|
|
8284
8384
|
%>
|
|
8285
8385
|
<body class='<%= [theme, "app-page"].filter(Boolean).join(" ") %>' data-platform="<%=platform%>" data-agent="<%=agent%>" data-view="<%=type%>">
|
|
8286
8386
|
<header class='navheader grabbable'>
|
|
@@ -8327,14 +8427,43 @@ body.dark .pinokio-custom-terminal-header {
|
|
|
8327
8427
|
<div class="app-header-info-popover-description"><%=config.description || 'No description provided.'%></div>
|
|
8328
8428
|
</div>
|
|
8329
8429
|
</div>
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
<
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
8430
|
+
<div class="app-header-info-popover-meta">
|
|
8431
|
+
<% if (appInfoFolderPath) { %>
|
|
8432
|
+
<div class="app-header-info-popover-row">
|
|
8433
|
+
<span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-regular fa-folder"></i></span>
|
|
8434
|
+
<span class="app-header-info-popover-row-copy">
|
|
8435
|
+
<span class="app-header-info-popover-row-label">App folder</span>
|
|
8436
|
+
<span class="app-header-info-popover-row-value" title="<%=appInfoFolderPath%>"><%=appInfoFolderDisplayPath%></span>
|
|
8437
|
+
</span>
|
|
8438
|
+
<span class="app-header-info-popover-row-actions">
|
|
8439
|
+
<button type="button" class="app-header-info-popover-row-action" title="Copy app folder" aria-label="Copy app folder" data-app-info-copy-path="<%=appInfoFolderPath%>">
|
|
8440
|
+
<i class="fa-regular fa-copy" aria-hidden="true"></i>
|
|
8441
|
+
</button>
|
|
8442
|
+
<button type="button" class="app-header-info-popover-row-action" title="Reveal app folder" aria-label="Reveal app folder" data-filepath="<%=appInfoFolderPath%>" data-app-info-reveal-path>
|
|
8443
|
+
<i class="fa-regular fa-folder-open" aria-hidden="true"></i>
|
|
8444
|
+
</button>
|
|
8445
|
+
</span>
|
|
8446
|
+
</div>
|
|
8447
|
+
<% } %>
|
|
8448
|
+
<% if (appInfoRemoteUrl) { %>
|
|
8449
|
+
<a class="app-header-info-popover-row app-header-info-popover-row--link" href="<%=appInfoRemoteUrl%>" title="<%=appInfoRemoteUrl%>" rel="noopener noreferrer" data-app-info-external-link>
|
|
8450
|
+
<span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-brands fa-github"></i></span>
|
|
8451
|
+
<span class="app-header-info-popover-row-copy">
|
|
8452
|
+
<span class="app-header-info-popover-row-label">Source</span>
|
|
8453
|
+
<span class="app-header-info-popover-row-value"><%=appInfoRemoteDisplayUrl%></span>
|
|
8454
|
+
</span>
|
|
8455
|
+
<span class="app-header-info-popover-row-trailing" aria-hidden="true"><i class="fa-solid fa-arrow-up-right-from-square"></i></span>
|
|
8456
|
+
</a>
|
|
8457
|
+
<% } else { %>
|
|
8458
|
+
<div class="app-header-info-popover-row app-header-info-popover-row--muted">
|
|
8459
|
+
<span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-brands fa-github"></i></span>
|
|
8460
|
+
<span class="app-header-info-popover-row-copy">
|
|
8461
|
+
<span class="app-header-info-popover-row-label">Source</span>
|
|
8462
|
+
<span class="app-header-info-popover-row-value">No browser-openable remote detected</span>
|
|
8463
|
+
</span>
|
|
8464
|
+
</div>
|
|
8465
|
+
<% } %>
|
|
8466
|
+
</div>
|
|
8338
8467
|
</div>
|
|
8339
8468
|
</div>
|
|
8340
8469
|
<span class='app-header-identity-separator' aria-hidden="true"></span>
|
|
@@ -8913,14 +9042,43 @@ body.dark .pinokio-custom-terminal-header {
|
|
|
8913
9042
|
<div class="app-header-info-popover-description"><%=config.description || 'No description provided.'%></div>
|
|
8914
9043
|
</div>
|
|
8915
9044
|
</div>
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
<
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
9045
|
+
<div class="app-header-info-popover-meta">
|
|
9046
|
+
<% if (appInfoFolderPath) { %>
|
|
9047
|
+
<div class="app-header-info-popover-row">
|
|
9048
|
+
<span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-regular fa-folder"></i></span>
|
|
9049
|
+
<span class="app-header-info-popover-row-copy">
|
|
9050
|
+
<span class="app-header-info-popover-row-label">App folder</span>
|
|
9051
|
+
<span class="app-header-info-popover-row-value" title="<%=appInfoFolderPath%>"><%=appInfoFolderDisplayPath%></span>
|
|
9052
|
+
</span>
|
|
9053
|
+
<span class="app-header-info-popover-row-actions">
|
|
9054
|
+
<button type="button" class="app-header-info-popover-row-action" title="Copy app folder" aria-label="Copy app folder" data-app-info-copy-path="<%=appInfoFolderPath%>">
|
|
9055
|
+
<i class="fa-regular fa-copy" aria-hidden="true"></i>
|
|
9056
|
+
</button>
|
|
9057
|
+
<button type="button" class="app-header-info-popover-row-action" title="Reveal app folder" aria-label="Reveal app folder" data-filepath="<%=appInfoFolderPath%>" data-app-info-reveal-path>
|
|
9058
|
+
<i class="fa-regular fa-folder-open" aria-hidden="true"></i>
|
|
9059
|
+
</button>
|
|
9060
|
+
</span>
|
|
9061
|
+
</div>
|
|
9062
|
+
<% } %>
|
|
9063
|
+
<% if (appInfoRemoteUrl) { %>
|
|
9064
|
+
<a class="app-header-info-popover-row app-header-info-popover-row--link" href="<%=appInfoRemoteUrl%>" title="<%=appInfoRemoteUrl%>" rel="noopener noreferrer" data-app-info-external-link>
|
|
9065
|
+
<span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-brands fa-github"></i></span>
|
|
9066
|
+
<span class="app-header-info-popover-row-copy">
|
|
9067
|
+
<span class="app-header-info-popover-row-label">Source</span>
|
|
9068
|
+
<span class="app-header-info-popover-row-value"><%=appInfoRemoteDisplayUrl%></span>
|
|
9069
|
+
</span>
|
|
9070
|
+
<span class="app-header-info-popover-row-trailing" aria-hidden="true"><i class="fa-solid fa-arrow-up-right-from-square"></i></span>
|
|
9071
|
+
</a>
|
|
9072
|
+
<% } else { %>
|
|
9073
|
+
<div class="app-header-info-popover-row app-header-info-popover-row--muted">
|
|
9074
|
+
<span class="app-header-info-popover-row-icon" aria-hidden="true"><i class="fa-brands fa-github"></i></span>
|
|
9075
|
+
<span class="app-header-info-popover-row-copy">
|
|
9076
|
+
<span class="app-header-info-popover-row-label">Source</span>
|
|
9077
|
+
<span class="app-header-info-popover-row-value">No browser-openable remote detected</span>
|
|
9078
|
+
</span>
|
|
9079
|
+
</div>
|
|
9080
|
+
<% } %>
|
|
9081
|
+
</div>
|
|
8924
9082
|
</div>
|
|
8925
9083
|
</div>
|
|
8926
9084
|
<span class='mobile-bottom-nav__identity-separator' aria-hidden="true"></span>
|
|
@@ -16638,6 +16796,48 @@ const rerenderMenuSection = (container, html) => {
|
|
|
16638
16796
|
popover.classList.toggle("hidden", isOpen)
|
|
16639
16797
|
trigger.setAttribute("aria-expanded", isOpen ? "false" : "true")
|
|
16640
16798
|
})
|
|
16799
|
+
root.querySelectorAll("[data-app-info-copy-path]").forEach((button) => {
|
|
16800
|
+
button.addEventListener("click", async (event) => {
|
|
16801
|
+
event.preventDefault()
|
|
16802
|
+
event.stopPropagation()
|
|
16803
|
+
const value = button.getAttribute("data-app-info-copy-path") || ""
|
|
16804
|
+
if (!value) {
|
|
16805
|
+
return
|
|
16806
|
+
}
|
|
16807
|
+
try {
|
|
16808
|
+
if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
|
|
16809
|
+
await navigator.clipboard.writeText(value)
|
|
16810
|
+
} else {
|
|
16811
|
+
const input = document.createElement("textarea")
|
|
16812
|
+
input.value = value
|
|
16813
|
+
input.setAttribute("readonly", "")
|
|
16814
|
+
input.style.position = "fixed"
|
|
16815
|
+
input.style.opacity = "0"
|
|
16816
|
+
document.body.appendChild(input)
|
|
16817
|
+
input.select()
|
|
16818
|
+
document.execCommand("copy")
|
|
16819
|
+
input.remove()
|
|
16820
|
+
}
|
|
16821
|
+
const icon = button.querySelector("i")
|
|
16822
|
+
const originalIconClass = icon ? icon.className : ""
|
|
16823
|
+
button.classList.add("is-copied")
|
|
16824
|
+
button.setAttribute("title", "Copied")
|
|
16825
|
+
button.setAttribute("aria-label", "App folder copied")
|
|
16826
|
+
if (icon) icon.className = "fa-solid fa-check"
|
|
16827
|
+
window.setTimeout(() => {
|
|
16828
|
+
button.classList.remove("is-copied")
|
|
16829
|
+
button.setAttribute("title", "Copy app folder")
|
|
16830
|
+
button.setAttribute("aria-label", "Copy app folder")
|
|
16831
|
+
if (icon) icon.className = originalIconClass
|
|
16832
|
+
}, 1400)
|
|
16833
|
+
} catch (_) {}
|
|
16834
|
+
})
|
|
16835
|
+
})
|
|
16836
|
+
root.querySelectorAll("[data-app-info-reveal-path]").forEach((button) => {
|
|
16837
|
+
button.addEventListener("click", () => {
|
|
16838
|
+
closeAppInfoPopovers()
|
|
16839
|
+
})
|
|
16840
|
+
})
|
|
16641
16841
|
root.querySelectorAll("[data-app-info-external-link]").forEach((link) => {
|
|
16642
16842
|
link.addEventListener("click", (event) => {
|
|
16643
16843
|
const href = link.getAttribute("href") || ""
|
|
@@ -998,9 +998,12 @@ test("app identity popover exposes launcher metadata and remote browser link", a
|
|
|
998
998
|
assert.ok(helperIndex > existingCommunityGitConfigIndex)
|
|
999
999
|
assert.ok(helperIndex < launcherRemoteIndex)
|
|
1000
1000
|
assert.ok(renderPropIndex > launcherRemoteIndex)
|
|
1001
|
-
assert.match(server, /
|
|
1001
|
+
assert.match(server, /const launcherPath = this\.kernel\.path\("api", name\)/)
|
|
1002
|
+
assert.match(server, /const launcherDisplayPath = this\.formatLogsDisplayPath\(launcherPath\)/)
|
|
1003
|
+
assert.match(server, /kernel\.api\.parentGitURI\(launcherPath\)/)
|
|
1002
1004
|
assert.match(server, /launcherRemoteUrl = buildGitRemoteWebUrl\(launcherRemote\)/)
|
|
1003
1005
|
assert.match(server, /launcher_remote_url: launcherRemoteUrl/)
|
|
1006
|
+
assert.match(server, /launcher_path_display: launcherDisplayPath/)
|
|
1004
1007
|
assert.match(server, /const buildGitRemoteWebUrl = \(value\) =>/)
|
|
1005
1008
|
assert.match(server, /return `https:\/\/\$\{sshUrlMatch\[1\]\}\/\$\{sshUrlMatch\[2\]\}`/)
|
|
1006
1009
|
assert.match(server, /return `https:\/\/\$\{scpMatch\[1\]\}\/\$\{scpMatch\[2\]\}`/)
|
|
@@ -1011,8 +1014,17 @@ test("app identity popover exposes launcher metadata and remote browser link", a
|
|
|
1011
1014
|
assert.match(appView, /class="app-header-info-popover-icon" src="<%=config\.icon \|\| '\/pinokio-black\.png'%>"/)
|
|
1012
1015
|
assert.match(appView, /const appInfoRemoteUrl = typeof launcher_remote_url === "string" \? launcher_remote_url : ""/)
|
|
1013
1016
|
assert.ok(appView.includes('const appInfoRemoteDisplayUrl = appInfoRemoteUrl.replace(/^https?:\\/\\//i, "")'))
|
|
1017
|
+
assert.match(appView, /const appInfoFolderPath = typeof path === "string" \? path : ""/)
|
|
1018
|
+
assert.match(appView, /const appInfoFolderDisplayPath = typeof launcher_path_display === "string"/)
|
|
1019
|
+
assert.match(appView, /data-app-info-copy-path="<%=appInfoFolderPath%>"/)
|
|
1020
|
+
assert.match(appView, /data-filepath="<%=appInfoFolderPath%>" data-app-info-reveal-path/)
|
|
1021
|
+
assert.match(appView, /fa-regular fa-folder/)
|
|
1022
|
+
assert.match(appView, /fa-brands fa-github/)
|
|
1023
|
+
assert.match(appView, /app-header-info-popover-row-label">App folder</)
|
|
1024
|
+
assert.match(appView, /app-header-info-popover-row-label">Source</)
|
|
1014
1025
|
assert.match(appView, /href="<%=appInfoRemoteUrl%>" title="<%=appInfoRemoteUrl%>" rel="noopener noreferrer" data-app-info-external-link/)
|
|
1015
|
-
assert.match(appView,
|
|
1026
|
+
assert.match(appView, /app-header-info-popover-row-value"><%=appInfoRemoteDisplayUrl%><\/span>/)
|
|
1027
|
+
assert.match(appView, /grid-template-columns: 26px minmax\(0, 1fr\) auto/)
|
|
1016
1028
|
assert.match(appView, /text-overflow: ellipsis/)
|
|
1017
1029
|
assert.match(appView, /white-space: nowrap/)
|
|
1018
1030
|
assert.match(appView, /window\.open\(href, "_blank"\)/)
|
|
@@ -1046,7 +1058,7 @@ test("app identity popover exposes launcher metadata and remote browser link", a
|
|
|
1046
1058
|
assert.match(appView, /\.mobile-bottom-nav \.resource-usage-popover \{[\s\S]*bottom: calc\(100% \+ 9px\);/)
|
|
1047
1059
|
assert.doesNotMatch(appView, /Open launcher remote/)
|
|
1048
1060
|
assert.doesNotMatch(appView, /fetch\("\/go"/)
|
|
1049
|
-
assert.doesNotMatch(appView, /app-
|
|
1061
|
+
assert.doesNotMatch(appView, /data-app-info-external-link[^>]*features="browser"/)
|
|
1050
1062
|
assert.doesNotMatch(appView, /appInfoGitHistoryUrl|hydrateAppInfoGithubUrl|buildAppInfoGithubUrl|launcher_github_url|Open launcher on GitHub|No GitHub remote detected/)
|
|
1051
1063
|
|
|
1052
1064
|
const start = appView.indexOf('<script>\n(() => {\n const appInfoRoots = Array.from(document.querySelectorAll("[data-app-info-root]"))')
|
|
@@ -1059,7 +1071,9 @@ test("app identity popover exposes launcher metadata and remote browser link", a
|
|
|
1059
1071
|
<div data-app-info-root>
|
|
1060
1072
|
<button type="button" data-app-header-info-trigger aria-expanded="false">Demo</button>
|
|
1061
1073
|
<div class="hidden" data-app-header-info-popover>
|
|
1062
|
-
<
|
|
1074
|
+
<button type="button" data-app-info-copy-path="/tmp/demo"><i class="fa-regular fa-copy"></i></button>
|
|
1075
|
+
<button type="button" data-filepath="/tmp/demo" data-app-info-reveal-path>Reveal</button>
|
|
1076
|
+
<a class="app-header-info-popover-row app-header-info-popover-row--link" href="https://gitlab.com/octocat/demo" title="https://gitlab.com/octocat/demo" data-app-info-external-link>gitlab.com/octocat/demo</a>
|
|
1063
1077
|
</div>
|
|
1064
1078
|
</div>
|
|
1065
1079
|
<iframe></iframe>
|
|
@@ -1069,6 +1083,13 @@ test("app identity popover exposes launcher metadata and remote browser link", a
|
|
|
1069
1083
|
pretendToBeVisual: true
|
|
1070
1084
|
})
|
|
1071
1085
|
const openedUrls = []
|
|
1086
|
+
const copiedPaths = []
|
|
1087
|
+
Object.defineProperty(dom.window.navigator, "clipboard", {
|
|
1088
|
+
configurable: true,
|
|
1089
|
+
value: {
|
|
1090
|
+
writeText: async (value) => copiedPaths.push(value)
|
|
1091
|
+
}
|
|
1092
|
+
})
|
|
1072
1093
|
dom.window.open = (url, target, features) => {
|
|
1073
1094
|
openedUrls.push({ url, target, features })
|
|
1074
1095
|
}
|
|
@@ -1080,7 +1101,7 @@ test("app identity popover exposes launcher metadata and remote browser link", a
|
|
|
1080
1101
|
|
|
1081
1102
|
assert.equal(popover.classList.contains("hidden"), true)
|
|
1082
1103
|
assert.equal(trigger.getAttribute("aria-expanded"), "false")
|
|
1083
|
-
const remoteLink = dom.window.document.querySelector(".app-header-info-popover-link")
|
|
1104
|
+
const remoteLink = dom.window.document.querySelector(".app-header-info-popover-row--link")
|
|
1084
1105
|
assert.ok(remoteLink)
|
|
1085
1106
|
assert.equal(remoteLink.getAttribute("href"), "https://gitlab.com/octocat/demo")
|
|
1086
1107
|
assert.equal(remoteLink.getAttribute("title"), "https://gitlab.com/octocat/demo")
|
|
@@ -1088,6 +1109,17 @@ test("app identity popover exposes launcher metadata and remote browser link", a
|
|
|
1088
1109
|
assert.equal(remoteLink.hasAttribute("features"), false)
|
|
1089
1110
|
assert.equal(remoteLink.textContent.trim(), "gitlab.com/octocat/demo")
|
|
1090
1111
|
|
|
1112
|
+
click()
|
|
1113
|
+
const copyButton = dom.window.document.querySelector("[data-app-info-copy-path]")
|
|
1114
|
+
copyButton.dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true, cancelable: true }))
|
|
1115
|
+
await new Promise((resolve) => setImmediate(resolve))
|
|
1116
|
+
assert.deepEqual(copiedPaths, ["/tmp/demo"])
|
|
1117
|
+
assert.equal(copyButton.classList.contains("is-copied"), true)
|
|
1118
|
+
assert.equal(copyButton.getAttribute("aria-label"), "App folder copied")
|
|
1119
|
+
assert.equal(popover.classList.contains("hidden"), false)
|
|
1120
|
+
dom.window.document.querySelector("[data-app-info-reveal-path]").click()
|
|
1121
|
+
assert.equal(popover.classList.contains("hidden"), true)
|
|
1122
|
+
|
|
1091
1123
|
click()
|
|
1092
1124
|
assert.equal(popover.classList.contains("hidden"), false)
|
|
1093
1125
|
assert.equal(trigger.getAttribute("aria-expanded"), "true")
|