@tutti-os/workspace-app-center 0.0.12 → 0.0.13
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/dist/{chunk-PD2WLRHE.js → chunk-7BJAJ7F3.js} +1 -1
- package/dist/chunk-7BJAJ7F3.js.map +1 -0
- package/dist/{chunk-O3XCZVHE.js → chunk-DPJRK63W.js} +203 -31
- package/dist/chunk-DPJRK63W.js.map +1 -0
- package/dist/contracts/index.d.ts +7 -3
- package/dist/contracts/index.js +1 -1
- package/dist/core/index.d.ts +8 -3
- package/dist/core/index.js +1 -1
- package/dist/i18n/index.js +115 -147
- package/dist/i18n/index.js.map +1 -1
- package/dist/{index-DT5o9P2u.d.ts → index-Clfpl59g.d.ts} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/ui/index.d.ts +3 -2
- package/dist/ui/index.js +228 -109
- package/dist/ui/index.js.map +1 -1
- package/dist/{viewModel-BpgU7_M1.d.ts → viewModel-D_kMlhKv.d.ts} +13 -1
- package/package.json +3 -3
- package/dist/chunk-O3XCZVHE.js.map +0 -1
- package/dist/chunk-PD2WLRHE.js.map +0 -1
package/dist/ui/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from "../chunk-2HXFGEJS.js";
|
|
8
8
|
|
|
9
9
|
// src/ui/AppCard.tsx
|
|
10
|
+
import { memo, useCallback, useMemo } from "react";
|
|
10
11
|
import {
|
|
11
12
|
Button,
|
|
12
13
|
ChatIcon,
|
|
@@ -25,21 +26,30 @@ import {
|
|
|
25
26
|
cn
|
|
26
27
|
} from "@tutti-os/ui-system";
|
|
27
28
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
28
|
-
|
|
29
|
+
var AppCard = memo(function AppCard2({
|
|
29
30
|
actions,
|
|
30
31
|
app,
|
|
31
32
|
className,
|
|
32
33
|
copy
|
|
33
34
|
}) {
|
|
34
35
|
const statusLabel = copy.t(app.statusLabelKey);
|
|
35
|
-
const
|
|
36
|
+
const installBusy = app.installProgress != null || app.status === "installing";
|
|
37
|
+
const busyStatusLabel = installBusy ? copy.t("status.installing") : statusLabel;
|
|
38
|
+
const showInstallProgressRing = installBusy;
|
|
39
|
+
const statusButtonTitle = app.installProgress ? resolveInstallProgressTitle(copy, app.installProgress, busyStatusLabel) : statusLabel;
|
|
40
|
+
const primaryActionLabel = app.primaryAction === "install" ? copy.t("actions.installApp") : app.primaryAction === "retry" ? copy.t("actions.retryApp") : app.primaryAction === "update" ? app.availableVersion ? copy.t("labels.updateAvailable", {
|
|
41
|
+
version: app.availableVersion
|
|
42
|
+
}) : copy.t("actions.updateApp") : copy.t("actions.openApp");
|
|
36
43
|
const canExecutePrimaryAction = app.primaryAction !== "none";
|
|
37
44
|
const canOpenFromCard = app.canOpen;
|
|
38
45
|
const canPublishFactoryUpdate = app.canPublishFactoryUpdate && !!app.factoryJobId;
|
|
39
46
|
const canOpenFactorySession = app.canOpenFactorySession && !!app.factoryAgentSessionId && !!app.factoryJobId;
|
|
40
|
-
const actionContext =
|
|
47
|
+
const actionContext = useMemo(
|
|
48
|
+
() => createWorkspaceAppActionContext(app),
|
|
49
|
+
[app]
|
|
50
|
+
);
|
|
41
51
|
const hasMoreActions = canPublishFactoryUpdate || canOpenFactorySession || app.canExport || app.canDelete || app.canReplaceIcon || app.canOpenFolder || app.canOpenPackageFolder || app.canUninstall;
|
|
42
|
-
const executePrimaryAction = () => {
|
|
52
|
+
const executePrimaryAction = useCallback(() => {
|
|
43
53
|
if (app.primaryAction === "retry") {
|
|
44
54
|
void actions.retryApp?.(app.id);
|
|
45
55
|
return;
|
|
@@ -55,12 +65,25 @@ function AppCard({
|
|
|
55
65
|
if (app.primaryAction === "open") {
|
|
56
66
|
void actions.openApp?.(app.id, actionContext);
|
|
57
67
|
}
|
|
58
|
-
};
|
|
59
|
-
const executeCardAction = () => {
|
|
68
|
+
}, [actionContext, actions, app.id, app.primaryAction]);
|
|
69
|
+
const executeCardAction = useCallback(() => {
|
|
60
70
|
if (canOpenFromCard) {
|
|
61
71
|
void actions.openApp?.(app.id, actionContext);
|
|
62
72
|
}
|
|
63
|
-
};
|
|
73
|
+
}, [actionContext, actions, app.id, canOpenFromCard]);
|
|
74
|
+
const handleCardKeyDown = useCallback(
|
|
75
|
+
(event) => {
|
|
76
|
+
if (!canOpenFromCard || event.key !== "Enter" && event.key !== " ") {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
executeCardAction();
|
|
81
|
+
},
|
|
82
|
+
[canOpenFromCard, executeCardAction]
|
|
83
|
+
);
|
|
84
|
+
const handleReplaceIcon = useCallback(() => {
|
|
85
|
+
void actions.replaceAppIcon?.(app.id);
|
|
86
|
+
}, [actions, app.id]);
|
|
64
87
|
return /* @__PURE__ */ jsxs(
|
|
65
88
|
"article",
|
|
66
89
|
{
|
|
@@ -74,13 +97,7 @@ function AppCard({
|
|
|
74
97
|
role: "listitem",
|
|
75
98
|
tabIndex: canOpenFromCard ? 0 : -1,
|
|
76
99
|
onClick: executeCardAction,
|
|
77
|
-
onKeyDown:
|
|
78
|
-
if (!canOpenFromCard || event.key !== "Enter" && event.key !== " ") {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
event.preventDefault();
|
|
82
|
-
executeCardAction();
|
|
83
|
-
},
|
|
100
|
+
onKeyDown: handleCardKeyDown,
|
|
84
101
|
children: [
|
|
85
102
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
86
103
|
/* @__PURE__ */ jsx(
|
|
@@ -88,13 +105,11 @@ function AppCard({
|
|
|
88
105
|
{
|
|
89
106
|
app,
|
|
90
107
|
replaceIconLabel: copy.t("actions.replaceIcon"),
|
|
91
|
-
onReplaceIcon:
|
|
92
|
-
void actions.replaceAppIcon?.(app.id);
|
|
93
|
-
}
|
|
108
|
+
onReplaceIcon: handleReplaceIcon
|
|
94
109
|
}
|
|
95
110
|
),
|
|
96
111
|
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
97
|
-
hasMoreActions ? /* @__PURE__ */ jsx(
|
|
112
|
+
/* @__PURE__ */ jsx("div", { className: "flex size-8 shrink-0 items-center justify-center", children: hasMoreActions ? /* @__PURE__ */ jsx(
|
|
98
113
|
AppCardMoreActions,
|
|
99
114
|
{
|
|
100
115
|
actions,
|
|
@@ -103,27 +118,37 @@ function AppCard({
|
|
|
103
118
|
canPublishFactoryUpdate,
|
|
104
119
|
copy
|
|
105
120
|
}
|
|
106
|
-
) : null,
|
|
107
|
-
/* @__PURE__ */
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
event
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
121
|
+
) : null }),
|
|
122
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
123
|
+
/* @__PURE__ */ jsx(
|
|
124
|
+
Button,
|
|
125
|
+
{
|
|
126
|
+
className: cn(
|
|
127
|
+
"min-w-[56px] shrink-0",
|
|
128
|
+
!canExecutePrimaryAction ? "cursor-default" : null,
|
|
129
|
+
canExecutePrimaryAction ? app.primaryAction === "retry" ? statusClassName(app.status) : "text-[var(--text-primary)]" : statusClassName(app.status)
|
|
130
|
+
),
|
|
131
|
+
disabled: !canExecutePrimaryAction,
|
|
132
|
+
size: "default",
|
|
133
|
+
title: statusButtonTitle,
|
|
134
|
+
type: "button",
|
|
135
|
+
variant: "ghost",
|
|
136
|
+
onClick: (event) => {
|
|
137
|
+
event.stopPropagation();
|
|
138
|
+
executePrimaryAction();
|
|
139
|
+
},
|
|
140
|
+
children: canExecutePrimaryAction ? primaryActionLabel : busyStatusLabel
|
|
141
|
+
}
|
|
142
|
+
),
|
|
143
|
+
showInstallProgressRing ? /* @__PURE__ */ jsx(
|
|
144
|
+
AppInstallProgressRing,
|
|
145
|
+
{
|
|
146
|
+
ariaLabel: copy.t("status.installProgress.progressAria"),
|
|
147
|
+
fallbackPercent: 0,
|
|
148
|
+
progress: app.installProgress
|
|
149
|
+
}
|
|
150
|
+
) : null
|
|
151
|
+
] })
|
|
127
152
|
] })
|
|
128
153
|
] }),
|
|
129
154
|
/* @__PURE__ */ jsxs("div", { className: "mt-5 flex min-h-0 min-w-0 flex-1 flex-col p-1", children: [
|
|
@@ -132,52 +157,21 @@ function AppCard({
|
|
|
132
157
|
/* @__PURE__ */ jsx("h3", { className: "block min-w-0 truncate text-[15px] font-semibold leading-6 tracking-[0] text-[var(--text-primary)]", children: app.name }),
|
|
133
158
|
app.version ? /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-none text-[11px] leading-4 text-[var(--text-tertiary)] opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100", children: copy.t("labels.version", { version: app.version }) }) : null
|
|
134
159
|
] }),
|
|
135
|
-
app.updateAvailable && app.availableVersion ? /* @__PURE__ */ jsx(
|
|
136
|
-
"button",
|
|
137
|
-
{
|
|
138
|
-
className: cn(
|
|
139
|
-
"mt-1 inline-flex max-w-full items-center rounded-[4px] bg-[color-mix(in_srgb,var(--state-warning)_12%,transparent)] px-2 py-0.5 text-[11px] leading-4 text-[var(--state-warning)] outline-none transition-colors hover:bg-[color-mix(in_srgb,var(--state-warning)_18%,transparent)] focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--state-warning)_42%,transparent)]",
|
|
140
|
-
app.canUpdate ? "cursor-pointer" : "cursor-default"
|
|
141
|
-
),
|
|
142
|
-
disabled: !app.canUpdate,
|
|
143
|
-
title: copy.t("actions.updateApp"),
|
|
144
|
-
type: "button",
|
|
145
|
-
onClick: (event) => {
|
|
146
|
-
event.stopPropagation();
|
|
147
|
-
if (app.canUpdate) {
|
|
148
|
-
void actions.updateApp?.(app.id, "badge_button");
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
children: /* @__PURE__ */ jsx("span", { className: "truncate", children: copy.t("labels.updateAvailable", {
|
|
152
|
-
version: app.availableVersion
|
|
153
|
-
}) })
|
|
154
|
-
}
|
|
155
|
-
) : null,
|
|
156
160
|
app.description ? /* @__PURE__ */ jsx("p", { className: "mt-2 line-clamp-3 text-[13px] font-normal leading-[1.3] text-[var(--text-secondary)]", children: app.description }) : null
|
|
157
161
|
] }),
|
|
158
|
-
app.errorMessage
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
) : null,
|
|
167
|
-
app.tags.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-wrap gap-1.5", children: app.tags.slice(0, 3).map((tag) => /* @__PURE__ */ jsx(
|
|
168
|
-
"span",
|
|
169
|
-
{
|
|
170
|
-
className: "inline-flex h-5 max-w-full items-center rounded-[4px] bg-[var(--transparency-block)] px-2 text-[11px] leading-4 text-[var(--text-secondary)]",
|
|
171
|
-
children: /* @__PURE__ */ jsx("span", { className: "truncate", children: tag })
|
|
172
|
-
},
|
|
173
|
-
tag
|
|
174
|
-
)) }) : null
|
|
175
|
-
] }) : null
|
|
162
|
+
app.errorMessage ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex min-w-0 flex-col gap-3 pt-3", children: /* @__PURE__ */ jsx(
|
|
163
|
+
"p",
|
|
164
|
+
{
|
|
165
|
+
className: "min-w-0 rounded-[6px] bg-[color-mix(in_srgb,var(--state-danger)_10%,transparent)] px-2 py-1 text-[11px] leading-4 text-[var(--state-danger)]",
|
|
166
|
+
title: app.errorMessage,
|
|
167
|
+
children: copy.t("messages.appRuntimeFailed")
|
|
168
|
+
}
|
|
169
|
+
) }) : null
|
|
176
170
|
] })
|
|
177
171
|
]
|
|
178
172
|
}
|
|
179
173
|
);
|
|
180
|
-
}
|
|
174
|
+
});
|
|
181
175
|
function createWorkspaceAppActionContext(app) {
|
|
182
176
|
return {
|
|
183
177
|
installationId: app.installationId ?? null,
|
|
@@ -210,6 +204,13 @@ function AppCardMoreActions({
|
|
|
210
204
|
key: "modify-app-with-agent",
|
|
211
205
|
label: copy.t("actions.modifyAppWithAgent"),
|
|
212
206
|
onSelect: () => {
|
|
207
|
+
if (app.factoryEditAction === "open_session") {
|
|
208
|
+
void actions.openFactoryJobAgentSession?.(
|
|
209
|
+
app.factoryAgentSessionId ?? "",
|
|
210
|
+
app.factoryProvider
|
|
211
|
+
);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
213
214
|
void actions.modifyAppWithAgent?.(
|
|
214
215
|
app.factoryJobId ?? "",
|
|
215
216
|
app.factoryAgentSessionId ?? "",
|
|
@@ -403,6 +404,72 @@ function AppIcon({
|
|
|
403
404
|
) : null
|
|
404
405
|
] });
|
|
405
406
|
}
|
|
407
|
+
function AppInstallProgressRing({
|
|
408
|
+
ariaLabel,
|
|
409
|
+
fallbackPercent,
|
|
410
|
+
progress
|
|
411
|
+
}) {
|
|
412
|
+
const percent = progress == null ? Math.max(0, Math.min(100, Math.round(fallbackPercent))) : Math.max(0, Math.min(100, Math.round(progress.overallPercent)));
|
|
413
|
+
return /* @__PURE__ */ jsx(
|
|
414
|
+
"span",
|
|
415
|
+
{
|
|
416
|
+
"aria-label": ariaLabel,
|
|
417
|
+
"aria-valuemax": 100,
|
|
418
|
+
"aria-valuemin": 0,
|
|
419
|
+
"aria-valuenow": percent,
|
|
420
|
+
className: "relative inline-flex size-[14px] shrink-0 items-center justify-center rounded-full",
|
|
421
|
+
role: "progressbar",
|
|
422
|
+
style: {
|
|
423
|
+
background: `conic-gradient(var(--text-secondary) ${percent}%, color-mix(in srgb, var(--text-secondary) 24%, transparent) 0)`
|
|
424
|
+
},
|
|
425
|
+
children: /* @__PURE__ */ jsx(
|
|
426
|
+
"span",
|
|
427
|
+
{
|
|
428
|
+
"aria-hidden": "true",
|
|
429
|
+
className: "absolute inset-[2px] rounded-full bg-[var(--surface-panel)]"
|
|
430
|
+
}
|
|
431
|
+
)
|
|
432
|
+
}
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
function resolveInstallProgressTitle(copy, progress, statusLabel) {
|
|
436
|
+
const byteLabel = formatInstallProgressBytes(copy, progress);
|
|
437
|
+
const percent = Math.max(
|
|
438
|
+
0,
|
|
439
|
+
Math.min(100, Math.round(progress.overallPercent))
|
|
440
|
+
);
|
|
441
|
+
if (byteLabel) {
|
|
442
|
+
return `${statusLabel} \xB7 ${byteLabel} \xB7 ${percent}%`;
|
|
443
|
+
}
|
|
444
|
+
return `${statusLabel} \xB7 ${percent}%`;
|
|
445
|
+
}
|
|
446
|
+
function formatInstallProgressBytes(copy, progress) {
|
|
447
|
+
if (progress.userPhase !== "downloading" || progress.downloadedBytes == null) {
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
const downloaded = formatByteSize(progress.downloadedBytes);
|
|
451
|
+
if (progress.totalBytes == null || progress.totalBytes <= 0) {
|
|
452
|
+
return downloaded;
|
|
453
|
+
}
|
|
454
|
+
return copy.t("status.installProgress.downloadedOfTotal", {
|
|
455
|
+
downloaded,
|
|
456
|
+
total: formatByteSize(progress.totalBytes)
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
function formatByteSize(value) {
|
|
460
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
461
|
+
return "0 B";
|
|
462
|
+
}
|
|
463
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
464
|
+
let size = value;
|
|
465
|
+
let unitIndex = 0;
|
|
466
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
467
|
+
size /= 1024;
|
|
468
|
+
unitIndex += 1;
|
|
469
|
+
}
|
|
470
|
+
const precision = size >= 10 || unitIndex === 0 ? 0 : 1;
|
|
471
|
+
return `${size.toFixed(precision)} ${units[unitIndex]}`;
|
|
472
|
+
}
|
|
406
473
|
function statusClassName(status) {
|
|
407
474
|
if (status === "failed") {
|
|
408
475
|
return "text-[var(--state-danger)]";
|
|
@@ -417,7 +484,7 @@ function statusClassName(status) {
|
|
|
417
484
|
}
|
|
418
485
|
|
|
419
486
|
// src/ui/AppCenterPanel.tsx
|
|
420
|
-
import { useEffect, useId, useMemo, useState } from "react";
|
|
487
|
+
import { useEffect, useId, useMemo as useMemo2, useState } from "react";
|
|
421
488
|
import {
|
|
422
489
|
Badge,
|
|
423
490
|
BareIconButton,
|
|
@@ -491,10 +558,10 @@ var factoryTemplates = [
|
|
|
491
558
|
];
|
|
492
559
|
var recommendedCategoryTabDefinitions = [
|
|
493
560
|
{ id: "all", labelKey: null },
|
|
494
|
-
{ id: "tools", labelKey: "categories.tools" },
|
|
495
|
-
{ id: "content-creation", labelKey: "categories.contentCreation" },
|
|
496
561
|
{ id: "product-design", labelKey: "categories.productDesign" },
|
|
497
|
-
{ id: "
|
|
562
|
+
{ id: "content-creation", labelKey: "categories.contentCreation" },
|
|
563
|
+
{ id: "office", labelKey: "categories.office" },
|
|
564
|
+
{ id: "tools", labelKey: "categories.tools" }
|
|
498
565
|
];
|
|
499
566
|
function AppCenterPanel({
|
|
500
567
|
actions,
|
|
@@ -517,6 +584,8 @@ function AppCenterPanel({
|
|
|
517
584
|
const [pendingDeleteApp, setPendingDeleteApp] = useState(null);
|
|
518
585
|
const [uninstallAppBusy, setUninstallAppBusy] = useState(false);
|
|
519
586
|
const [pendingUninstallApp, setPendingUninstallApp] = useState(null);
|
|
587
|
+
const [updateAppBusy, setUpdateAppBusy] = useState(false);
|
|
588
|
+
const [pendingUpdateApp, setPendingUpdateApp] = useState(null);
|
|
520
589
|
const [displayName, setDisplayName] = useState("");
|
|
521
590
|
const [prompt, setPrompt] = useState("");
|
|
522
591
|
const [providerConfiguration, setProviderConfiguration] = useState(null);
|
|
@@ -525,7 +594,7 @@ function AppCenterPanel({
|
|
|
525
594
|
const [selectedModel, setSelectedModel] = useState("");
|
|
526
595
|
const [selectedPermissionModeId, setSelectedPermissionModeId] = useState("");
|
|
527
596
|
const [selectedReasoningEffort, setSelectedReasoningEffort] = useState("");
|
|
528
|
-
const normalizedProviderOptions =
|
|
597
|
+
const normalizedProviderOptions = useMemo2(
|
|
529
598
|
() => providerOptions.map((option) => {
|
|
530
599
|
const provider = option.provider.trim();
|
|
531
600
|
const label = option.label.trim() || provider;
|
|
@@ -695,27 +764,45 @@ function AppCenterPanel({
|
|
|
695
764
|
}
|
|
696
765
|
void actions.openFactoryJobAgentSession?.(agentSessionId, job.provider);
|
|
697
766
|
};
|
|
698
|
-
const cardActions =
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
767
|
+
const cardActions = useMemo2(
|
|
768
|
+
() => ({
|
|
769
|
+
...actions,
|
|
770
|
+
deleteApp: (appId, appName) => {
|
|
771
|
+
setPendingDeleteApp({
|
|
772
|
+
id: appId,
|
|
773
|
+
installed: viewModel.apps.find((app) => app.id === appId)?.installed ?? false,
|
|
774
|
+
name: appName
|
|
775
|
+
});
|
|
776
|
+
},
|
|
777
|
+
uninstallApp: (appId) => {
|
|
778
|
+
const app = viewModel.apps.find((item) => item.id === appId);
|
|
779
|
+
if (!app) {
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
setPendingUninstallApp({
|
|
783
|
+
id: app.id,
|
|
784
|
+
name: app.name,
|
|
785
|
+
sourceKind: app.sourceKind
|
|
786
|
+
});
|
|
787
|
+
},
|
|
788
|
+
updateApp: (appId, trigger) => {
|
|
789
|
+
const app = viewModel.apps.find((item) => item.id === appId);
|
|
790
|
+
if (!app) {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
if (app.installed && app.status === "running") {
|
|
794
|
+
setPendingUpdateApp({
|
|
795
|
+
id: app.id,
|
|
796
|
+
name: app.name,
|
|
797
|
+
trigger
|
|
798
|
+
});
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
void actions.updateApp?.(appId, trigger);
|
|
711
802
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
sourceKind: app.sourceKind
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
|
-
};
|
|
803
|
+
}),
|
|
804
|
+
[actions, viewModel.apps]
|
|
805
|
+
);
|
|
719
806
|
const loadingMessage = catalogStatus === "loading" ? copy.t("messages.catalogLoading") : null;
|
|
720
807
|
const catalogLoading = catalogStatus === "loading";
|
|
721
808
|
const failedMessage = catalogStatus === "failed" ? copy.t("messages.catalogFailed") : null;
|
|
@@ -775,6 +862,9 @@ function AppCenterPanel({
|
|
|
775
862
|
const uninstallAppConfirmTitle = copy.t("confirmations.uninstallAppTitle", {
|
|
776
863
|
name: pendingUninstallApp?.name ?? ""
|
|
777
864
|
});
|
|
865
|
+
const updateAppConfirmTitle = copy.t("confirmations.updateAppTitle", {
|
|
866
|
+
name: pendingUpdateApp?.name ?? ""
|
|
867
|
+
});
|
|
778
868
|
return /* @__PURE__ */ jsxs2(
|
|
779
869
|
"section",
|
|
780
870
|
{
|
|
@@ -785,7 +875,7 @@ function AppCenterPanel({
|
|
|
785
875
|
),
|
|
786
876
|
children: [
|
|
787
877
|
statusToast ? /* @__PURE__ */ jsx2(AppCenterStatusToast, { toast: statusToast }) : null,
|
|
788
|
-
/* @__PURE__ */ jsx2("div", { className: "flex min-h-0 flex-1 flex-col gap-5 overflow-auto px-6 pb-6 pt-5 [container-type:inline-size]", children: /* @__PURE__ */ jsxs2("section", { className: "flex min-w-0 flex-col gap-3", children: [
|
|
878
|
+
/* @__PURE__ */ jsx2("div", { className: "flex min-h-0 flex-1 flex-col gap-5 overflow-auto px-6 pb-6 pt-5 [container-type:inline-size]", children: /* @__PURE__ */ jsxs2("section", { className: "flex min-h-0 min-w-0 flex-1 flex-col gap-3", children: [
|
|
789
879
|
/* @__PURE__ */ jsxs2("div", { className: "flex h-8 min-w-0 items-center justify-between gap-3", children: [
|
|
790
880
|
/* @__PURE__ */ jsx2(
|
|
791
881
|
SectionTabs,
|
|
@@ -1024,6 +1114,35 @@ function AppCenterPanel({
|
|
|
1024
1114
|
}
|
|
1025
1115
|
}
|
|
1026
1116
|
),
|
|
1117
|
+
/* @__PURE__ */ jsx2(
|
|
1118
|
+
ConfirmationDialog,
|
|
1119
|
+
{
|
|
1120
|
+
cancelLabel: copy.t("actions.cancel"),
|
|
1121
|
+
confirmBusy: updateAppBusy,
|
|
1122
|
+
confirmLabel: copy.t("actions.updateApp"),
|
|
1123
|
+
description: copy.t("confirmations.updateRunningAppDescription"),
|
|
1124
|
+
open: pendingUpdateApp != null,
|
|
1125
|
+
title: updateAppConfirmTitle,
|
|
1126
|
+
onConfirm: () => {
|
|
1127
|
+
const app = pendingUpdateApp;
|
|
1128
|
+
if (!app) {
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
setUpdateAppBusy(true);
|
|
1132
|
+
void Promise.resolve(
|
|
1133
|
+
actions.updateApp?.(app.id, app.trigger)
|
|
1134
|
+
).finally(() => {
|
|
1135
|
+
setUpdateAppBusy(false);
|
|
1136
|
+
setPendingUpdateApp(null);
|
|
1137
|
+
});
|
|
1138
|
+
},
|
|
1139
|
+
onOpenChange: (nextOpen) => {
|
|
1140
|
+
if (!nextOpen && !updateAppBusy) {
|
|
1141
|
+
setPendingUpdateApp(null);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
),
|
|
1027
1146
|
/* @__PURE__ */ jsx2(
|
|
1028
1147
|
Dialog,
|
|
1029
1148
|
{
|
|
@@ -1471,7 +1590,7 @@ function AppCardGrid({
|
|
|
1471
1590
|
"div",
|
|
1472
1591
|
{
|
|
1473
1592
|
"aria-label": title,
|
|
1474
|
-
className: "flex min-h-
|
|
1593
|
+
className: "flex min-h-0 min-w-0 flex-1 items-center justify-center rounded-[8px] px-6 text-center text-[13px] leading-5 text-[var(--text-secondary)]",
|
|
1475
1594
|
role: "status",
|
|
1476
1595
|
children: emptyMessage
|
|
1477
1596
|
}
|
|
@@ -1524,7 +1643,7 @@ function RecommendedCategoryTabs({
|
|
|
1524
1643
|
"div",
|
|
1525
1644
|
{
|
|
1526
1645
|
"aria-label": copy.t("labels.appCategories"),
|
|
1527
|
-
className: "-mx-1 flex min-w-0 items-center gap-2 overflow-x-auto px-1 py-1",
|
|
1646
|
+
className: "-mx-1 flex min-h-10 min-w-0 items-center gap-2 overflow-x-auto px-1 py-1",
|
|
1528
1647
|
role: "tablist",
|
|
1529
1648
|
children: tabs.map((tab) => {
|
|
1530
1649
|
const selected = tab.id === value;
|
|
@@ -1533,8 +1652,8 @@ function RecommendedCategoryTabs({
|
|
|
1533
1652
|
{
|
|
1534
1653
|
"aria-selected": selected,
|
|
1535
1654
|
className: cn2(
|
|
1536
|
-
"flex h-8 shrink-0 items-center rounded-[8px] px-3 text-[13px] font-semibold leading-5 tracking-[0] transition-colors duration-150 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-
|
|
1537
|
-
selected ? "
|
|
1655
|
+
"flex h-8 shrink-0 items-center rounded-[8px] px-3 text-[13px] font-semibold leading-5 tracking-[0] transition-colors duration-150 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-[var(--border-focus)]",
|
|
1656
|
+
selected ? "bg-[var(--background-fronted)] text-[var(--text-primary)] shadow-[inset_0_0_0_1px_var(--line-1)]" : "text-[var(--text-tertiary)] hover:text-[var(--text-primary)]"
|
|
1538
1657
|
),
|
|
1539
1658
|
role: "tab",
|
|
1540
1659
|
type: "button",
|