@blocklet/launcher-workflow 2.4.4 → 2.4.5

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.
Files changed (39) hide show
  1. package/es/components/in-progress-session.js +1 -1
  2. package/es/components/launch-serverless/allocate.js +181 -0
  3. package/es/components/launch-serverless/install.js +203 -0
  4. package/es/components/launch-serverless/shared/base-serverless-layout.js +53 -0
  5. package/es/components/launch-serverless/shared/common-components.js +605 -0
  6. package/es/components/launch-serverless/shared/loading-display-layout.js +122 -0
  7. package/es/components/launch-serverless/shared/retry-error-message.js +45 -0
  8. package/es/components/launch-serverless/start-app.js +356 -0
  9. package/es/contexts/request.js +2 -2
  10. package/es/hooks/use-serial-polling.js +43 -0
  11. package/es/install.js +28 -0
  12. package/es/launch.js +1 -1
  13. package/es/locales/en.js +71 -14
  14. package/es/locales/zh.js +68 -12
  15. package/es/paid.js +1 -1
  16. package/es/prepare.js +1 -1
  17. package/es/start-app.js +28 -0
  18. package/es/util.js +181 -2
  19. package/lib/components/in-progress-session.js +3 -3
  20. package/lib/components/launch-serverless/allocate.js +198 -0
  21. package/lib/components/launch-serverless/install.js +223 -0
  22. package/lib/components/launch-serverless/shared/base-serverless-layout.js +59 -0
  23. package/lib/components/launch-serverless/shared/common-components.js +635 -0
  24. package/lib/components/launch-serverless/shared/loading-display-layout.js +131 -0
  25. package/lib/components/launch-serverless/shared/retry-error-message.js +52 -0
  26. package/lib/components/launch-serverless/start-app.js +369 -0
  27. package/lib/contexts/request.js +2 -2
  28. package/lib/hooks/use-serial-polling.js +49 -0
  29. package/lib/install.js +35 -0
  30. package/lib/launch.js +2 -2
  31. package/lib/locales/en.js +71 -14
  32. package/lib/locales/zh.js +68 -12
  33. package/lib/paid.js +2 -2
  34. package/lib/prepare.js +2 -2
  35. package/lib/start-app.js +35 -0
  36. package/lib/util.js +214 -11
  37. package/package.json +8 -5
  38. package/es/components/launch-serverless.js +0 -115
  39. package/lib/components/launch-serverless.js +0 -89
@@ -0,0 +1,635 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ActionCardBox = ActionCardBox;
7
+ exports.AppSuccessDisplay = AppSuccessDisplay;
8
+ exports.ErrorDisplay = ErrorDisplay;
9
+ exports.LoadingContainer = LoadingContainer;
10
+ exports.ProductIntroCarousel = ProductIntroCarousel;
11
+ exports.StyledProgress = StyledProgress;
12
+ exports.TimeText = TimeText;
13
+ exports.calculateEstimatedTime = void 0;
14
+ exports.proxyUrl = proxyUrl;
15
+ exports.useDisplayProgress = useDisplayProgress;
16
+ exports.useFormatTime = exports.useElapsedTime = void 0;
17
+ var _util = require("@blocklet/launcher-util/es/util");
18
+ var _ContentCopy = _interopRequireDefault(require("@mui/icons-material/ContentCopy"));
19
+ var _Dashboard = _interopRequireDefault(require("@mui/icons-material/Dashboard"));
20
+ var _Info = _interopRequireDefault(require("@mui/icons-material/Info"));
21
+ var _Inventory = _interopRequireDefault(require("@mui/icons-material/Inventory2"));
22
+ var _OpenInNew = _interopRequireDefault(require("@mui/icons-material/OpenInNew"));
23
+ var _TaskAlt = _interopRequireDefault(require("@mui/icons-material/TaskAlt"));
24
+ var _material = require("@mui/material");
25
+ var _Chip = _interopRequireDefault(require("@mui/material/Chip"));
26
+ var _IconButton = _interopRequireDefault(require("@mui/material/IconButton"));
27
+ var _propTypes = _interopRequireDefault(require("prop-types"));
28
+ var _react = _interopRequireWildcard(require("react"));
29
+ var _ufo = require("ufo");
30
+ var _Img = _interopRequireDefault(require("@arcblock/ux/lib/Img"));
31
+ var _locale = require("../../../contexts/locale");
32
+ var _util2 = require("../../../util");
33
+ var _jsxRuntime = require("react/jsx-runtime");
34
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
35
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
36
+ function proxyUrl(url) {
37
+ if (url.startsWith('/')) {
38
+ return (0, _ufo.joinURL)(window.location.origin, url);
39
+ }
40
+ return "".concat(window.location.origin, "/.well-known/service/proxy?url=").concat(url);
41
+ }
42
+ const COMPONENT_BASE_TIME = 2; // 每个组件基础处理时间 4s
43
+ const SIZE_TIME_RATIO = 0.2; // 每 1MB 增加 1s
44
+ // 计算预估安装时间
45
+ const calculateEstimatedTime = exports.calculateEstimatedTime = function calculateEstimatedTime() {
46
+ let components = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
47
+ if (!Array.isArray(components) || components.length === 0) {
48
+ return 0;
49
+ }
50
+
51
+ // 计算所有组件的总大小(MB)
52
+ const totalSizeMB = components.reduce((acc, comp) => {
53
+ var _comp$meta;
54
+ const sizeInMB = ((comp === null || comp === void 0 || (_comp$meta = comp.meta) === null || _comp$meta === void 0 || (_comp$meta = _comp$meta.dist) === null || _comp$meta === void 0 ? void 0 : _comp$meta.size) || 0) / (1024 * 1024);
55
+ return acc + sizeInMB;
56
+ }, 0);
57
+
58
+ // 计算总时间
59
+ const totalTime = components.length * COMPONENT_BASE_TIME + totalSizeMB * SIZE_TIME_RATIO;
60
+ return Math.ceil(totalTime);
61
+ };
62
+ function LoadingContainer(_ref) {
63
+ let {
64
+ children
65
+ } = _ref;
66
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Box, {
67
+ sx: {
68
+ padding: '32px 16px 16px 16px',
69
+ maxWidth: 'sm',
70
+ width: '100%',
71
+ margin: '0 auto',
72
+ borderRadius: '16px',
73
+ position: 'relative',
74
+ overflow: 'hidden'
75
+ },
76
+ children: children
77
+ });
78
+ }
79
+ LoadingContainer.propTypes = {
80
+ children: _propTypes.default.node.isRequired
81
+ };
82
+ function StyledProgress(_ref2) {
83
+ let {
84
+ value
85
+ } = _ref2;
86
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.LinearProgress, {
87
+ variant: "determinate",
88
+ value: value,
89
+ sx: {
90
+ height: 8,
91
+ borderRadius: 4,
92
+ background: '#f5f5f5',
93
+ '& .MuiLinearProgress-bar': {
94
+ borderRadius: 4,
95
+ background: 'linear-gradient(90deg, #1976d2, #42a5f5)'
96
+ }
97
+ }
98
+ });
99
+ }
100
+ StyledProgress.propTypes = {
101
+ value: _propTypes.default.number.isRequired
102
+ };
103
+ function TimeText(_ref3) {
104
+ let {
105
+ children
106
+ } = _ref3;
107
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
108
+ sx: {
109
+ fontSize: 14,
110
+ color: '#888',
111
+ marginLeft: 8,
112
+ minWidth: 90,
113
+ textAlign: 'right',
114
+ display: 'inline-block'
115
+ },
116
+ children: children
117
+ });
118
+ }
119
+ TimeText.propTypes = {
120
+ children: _propTypes.default.node.isRequired
121
+ };
122
+ function ActionCardBox(_ref4) {
123
+ let {
124
+ children,
125
+ tipFlag = null
126
+ } = _ref4;
127
+ const childrenRef = (0, _react.useRef)(children);
128
+ childrenRef.current = children;
129
+ const [isTransitioning, setIsTransitioning] = (0, _react.useState)(false);
130
+ const [currentContent, setCurrentContent] = (0, _react.useState)(children);
131
+ (0, _react.useEffect)(() => {
132
+ if (tipFlag !== null) {
133
+ // 开始动画:透明度 1 -> 0
134
+ setIsTransitioning(true);
135
+
136
+ // 400ms 后替换内容并开始显示:透明度 0 -> 1
137
+ const timer = setTimeout(() => {
138
+ setCurrentContent(childrenRef.current);
139
+ setIsTransitioning(false);
140
+ }, 400);
141
+ return () => clearTimeout(timer);
142
+ }
143
+ return undefined;
144
+ }, [tipFlag]);
145
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
146
+ variant: "body1",
147
+ sx: {
148
+ textAlign: 'center',
149
+ opacity: isTransitioning ? 0 : 0.5,
150
+ transition: 'opacity 0.4s ease-in-out'
151
+ },
152
+ children: currentContent
153
+ });
154
+ }
155
+ ActionCardBox.propTypes = {
156
+ children: _propTypes.default.node.isRequired,
157
+ tipFlag: _propTypes.default.any // 可以是任何类型,用于触发动画
158
+ };
159
+
160
+ // 公共 Hook:格式化时间
161
+ const useFormatTime = () => {
162
+ const formatTime = seconds => {
163
+ const mins = Math.floor(seconds / 60);
164
+ const secs = seconds % 60;
165
+ return "".concat(mins, ":").concat(secs.toString().padStart(2, '0'));
166
+ };
167
+ return formatTime;
168
+ };
169
+
170
+ // 公共 Hook:时间递增
171
+ exports.useFormatTime = useFormatTime;
172
+ const useElapsedTime = exports.useElapsedTime = function useElapsedTime() {
173
+ let elapsedSeconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
174
+ const [time, setTime] = (0, _react.useState)(elapsedSeconds);
175
+ const timerRef = (0, _react.useRef)();
176
+ (0, _react.useEffect)(() => {
177
+ timerRef.current = setInterval(() => {
178
+ setTime(t => t + 1);
179
+ }, 1000);
180
+ return () => clearInterval(timerRef.current);
181
+ }, []);
182
+ return time;
183
+ };
184
+
185
+ // 公共 Hook:动态进度
186
+ function useDisplayProgress(start) {
187
+ let duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;
188
+ const [progress, setProgress] = (0, _react.useState)(start);
189
+ (0, _react.useEffect)(() => {
190
+ setProgress(prev => Math.max(prev, start));
191
+ }, [start]);
192
+ (0, _react.useEffect)(() => {
193
+ const timerDuration = Math.round((duration || 1) * 1000 / 99);
194
+ const interval = setInterval(() => {
195
+ setProgress(prev => Math.min(prev + 1, 99));
196
+ }, timerDuration);
197
+ return () => clearInterval(interval);
198
+ }, [duration]);
199
+ return progress;
200
+ }
201
+
202
+ // 公共组件:产品介绍轮播
203
+ function ProductIntroCarousel(_ref5) {
204
+ let {
205
+ tips
206
+ } = _ref5;
207
+ const [slideIndex, setSlideIndex] = (0, _react.useState)(Math.floor(Math.random() * tips.length));
208
+ const [slideIn, setSlideIn] = (0, _react.useState)(true);
209
+ const usedIndicesRef = (0, _react.useRef)(new Set([0]));
210
+ (0, _react.useEffect)(() => {
211
+ // 获取下一个随机索引(排除已使用的)
212
+ const getNextRandomIndex = () => {
213
+ const availableIndices = tips.map((_, index) => index).filter(index => !usedIndicesRef.current.has(index));
214
+
215
+ // 如果所有索引都用过了,重置并重新开始
216
+ if (availableIndices.length === 0) {
217
+ usedIndicesRef.current = new Set();
218
+ return Math.floor(Math.random() * tips.length);
219
+ }
220
+
221
+ // 从可用索引中随机选择一个
222
+ const randomIndex = Math.floor(Math.random() * availableIndices.length);
223
+ return availableIndices[randomIndex];
224
+ };
225
+ const timer = setInterval(() => {
226
+ setSlideIn(false);
227
+ setTimeout(() => {
228
+ const nextIndex = getNextRandomIndex();
229
+ setSlideIndex(nextIndex);
230
+ usedIndicesRef.current = new Set([...usedIndicesRef.current, nextIndex]);
231
+ setSlideIn(true);
232
+ }, 400);
233
+ }, 6000);
234
+ return () => clearInterval(timer);
235
+ }, [tips]);
236
+ if (!tips[slideIndex]) {
237
+ return null;
238
+ }
239
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Alert, {
240
+ severity: "info",
241
+ sx: {
242
+ mt: 8,
243
+ p: 1.5,
244
+ opacity: slideIn ? 0.8 : 0,
245
+ transform: slideIn ? 'translateY(0)' : 'translateY(6px)',
246
+ transition: 'all 0.4s ease-in-out'
247
+ },
248
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.AlertTitle, {
249
+ sx: {
250
+ textAlign: 'left'
251
+ },
252
+ children: tips[slideIndex].title
253
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
254
+ variant: "body2",
255
+ color: "text.secondary",
256
+ sx: {
257
+ textAlign: 'left'
258
+ },
259
+ children: tips[slideIndex].desc
260
+ })]
261
+ });
262
+ }
263
+ ProductIntroCarousel.propTypes = {
264
+ tips: _propTypes.default.arrayOf(_propTypes.default.shape({
265
+ title: _propTypes.default.string.isRequired,
266
+ desc: _propTypes.default.string.isRequired
267
+ })).isRequired
268
+ };
269
+
270
+ // 公共组件:错误处理
271
+ function ErrorDisplay(_ref6) {
272
+ let {
273
+ error = null,
274
+ onRetry = null
275
+ } = _ref6;
276
+ const {
277
+ t
278
+ } = (0, _locale.useLocaleContext)();
279
+ if (!error) return null;
280
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
281
+ sx: {
282
+ mt: 3,
283
+ p: 2,
284
+ bgcolor: 'error.light',
285
+ borderRadius: 1
286
+ },
287
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
288
+ color: "error",
289
+ variant: "body2",
290
+ children: error
291
+ }), onRetry && /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Box, {
292
+ sx: {
293
+ mt: 1
294
+ },
295
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
296
+ type: "button",
297
+ onClick: onRetry,
298
+ style: {
299
+ background: 'none',
300
+ border: '1px solid #f44336',
301
+ color: '#f44336',
302
+ padding: '4px 8px',
303
+ borderRadius: '4px',
304
+ cursor: 'pointer'
305
+ },
306
+ children: t('loading.retry')
307
+ })
308
+ })]
309
+ });
310
+ }
311
+ ErrorDisplay.propTypes = {
312
+ error: _propTypes.default.string,
313
+ onRetry: _propTypes.default.func
314
+ };
315
+ function AppSuccessDisplay(_ref7) {
316
+ let {
317
+ accessibleUrl,
318
+ sessionId,
319
+ blockletInfo,
320
+ urls,
321
+ launchSession
322
+ } = _ref7;
323
+ const theme = (0, _material.useTheme)();
324
+ const {
325
+ t
326
+ } = (0, _locale.useLocaleContext)();
327
+
328
+ // 获取应用基本信息
329
+ const appName = (blockletInfo === null || blockletInfo === void 0 ? void 0 : blockletInfo.appName) || t('startApp.unknownApp');
330
+ const appVersion = (blockletInfo === null || blockletInfo === void 0 ? void 0 : blockletInfo.appVersion) || '';
331
+ const appLogo = (blockletInfo === null || blockletInfo === void 0 ? void 0 : blockletInfo.appLogo) || '';
332
+ (0, _react.useEffect)(() => {
333
+ const stepActive = document.querySelector('.step-active');
334
+ if (stepActive) {
335
+ stepActive.classList.add('step-checked');
336
+ }
337
+ }, []);
338
+ const [accessibleUrls, setAccessibleUrls] = (0, _react.useState)([accessibleUrl]);
339
+ (0, _react.useEffect)(() => {
340
+ const checkUrls = urls.filter(url => !accessibleUrls.includes(url));
341
+ checkUrls.forEach(url => {
342
+ (0, _util2.checkUrlAccessible)(url, 10 * 60 * 1000).then(res => {
343
+ if (res) {
344
+ setAccessibleUrls(prev => {
345
+ const accessible = [...prev, url];
346
+ return urls.filter(item => accessible.includes(item));
347
+ });
348
+ }
349
+ });
350
+ });
351
+ }, [accessibleUrls, urls]);
352
+ const appUrl = accessibleUrls[0] || urls[0];
353
+
354
+ // 功能卡片数据 - 2x2 网格布局
355
+ const featureCards = [{
356
+ id: 'visit-app',
357
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(_OpenInNew.default, {
358
+ sx: {
359
+ fontSize: 24,
360
+ color: 'primary.main'
361
+ }
362
+ }),
363
+ title: t('startApp.visitApp'),
364
+ description: t('startApp.visitAppDesc'),
365
+ onClick: () => window.open((0, _ufo.joinURL)((0, _util.getBaseURL)(), "/api/launches/".concat(sessionId, "/redirect/app?appUrl=").concat(appUrl)), '_blank')
366
+ }, {
367
+ id: 'dashboard',
368
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Dashboard.default, {
369
+ sx: {
370
+ fontSize: 24,
371
+ color: 'primary.main'
372
+ }
373
+ }),
374
+ title: t('startApp.dashboard'),
375
+ description: t('startApp.dashboardDesc'),
376
+ onClick: () => window.open((0, _ufo.joinURL)((0, _util.getBaseURL)(), "/api/launches/".concat(sessionId, "/redirect/dashboard?appUrl=").concat(appUrl)), '_blank')
377
+ }, {
378
+ id: 'subscription',
379
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Info.default, {
380
+ sx: {
381
+ fontSize: 24,
382
+ color: 'primary.main'
383
+ }
384
+ }),
385
+ title: t('startApp.subscription'),
386
+ description: t('startApp.subscriptionDesc'),
387
+ onClick: () => window.open((0, _util.getSubscriptionLink)(launchSession.subscriptionId), '_blank'),
388
+ show: !!launchSession.subscriptionId
389
+ }, {
390
+ id: 'my-orders',
391
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Inventory.default, {
392
+ sx: {
393
+ fontSize: 24,
394
+ color: 'primary.main'
395
+ }
396
+ }),
397
+ title: t('startApp.myOrders'),
398
+ description: t('startApp.myOrdersDesc'),
399
+ onClick: () => window.open((0, _ufo.joinURL)((0, _util.getBaseURL)(), '/u/orders'), '_blank')
400
+ }];
401
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
402
+ sx: {
403
+ width: '100%',
404
+ maxWidth: 800,
405
+ margin: '0 auto',
406
+ p: {
407
+ xs: 2,
408
+ sm: 3
409
+ }
410
+ },
411
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
412
+ textAlign: "center",
413
+ mb: 4,
414
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Box, {
415
+ sx: {
416
+ width: 80,
417
+ height: 80,
418
+ borderRadius: '50%',
419
+ backgroundColor: (0, _material.alpha)(theme.palette.success.main, 0.2),
420
+ display: 'flex',
421
+ alignItems: 'center',
422
+ justifyContent: 'center',
423
+ margin: '0 auto 16px'
424
+ },
425
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_TaskAlt.default, {
426
+ sx: {
427
+ fontSize: 40,
428
+ color: 'success.main'
429
+ }
430
+ })
431
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Typography, {
432
+ variant: "h3",
433
+ component: "h1",
434
+ fontWeight: "bold",
435
+ gutterBottom: true,
436
+ children: ["\uD83C\uDF89 ", t('startApp.started')]
437
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
438
+ variant: "body1",
439
+ color: "text.secondary",
440
+ children: t('startApp.startedDescription')
441
+ })]
442
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
443
+ sx: {
444
+ p: 3,
445
+ mb: 3,
446
+ borderRadius: 2,
447
+ border: '1px solid',
448
+ borderColor: 'divider',
449
+ backgroundColor: 'background.paper'
450
+ },
451
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
452
+ display: "flex",
453
+ alignItems: "center",
454
+ gap: 2,
455
+ mb: 2,
456
+ flexWrap: "wrap",
457
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
458
+ flex: 1,
459
+ display: "flex",
460
+ alignItems: "center",
461
+ gap: 2,
462
+ children: [appLogo ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Img.default, {
463
+ src: (0, _ufo.joinURL)(appUrl, appLogo),
464
+ alt: appName,
465
+ width: 48,
466
+ height: 48,
467
+ style: {
468
+ borderRadius: 10,
469
+ overflow: 'hidden'
470
+ }
471
+ }, appUrl) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
472
+ flex: 1,
473
+ textAlign: "left",
474
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
475
+ variant: "h6",
476
+ color: "text.hint",
477
+ mb: 1,
478
+ children: t('startApp.projectName')
479
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
480
+ variant: "body1",
481
+ fontWeight: "medium",
482
+ children: appName
483
+ })]
484
+ })]
485
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
486
+ flex: 1,
487
+ display: "flex",
488
+ alignItems: "center",
489
+ gap: 2,
490
+ minWidth: {
491
+ xs: '100%',
492
+ sm: 'auto'
493
+ },
494
+ children: [appVersion ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
495
+ flex: 1,
496
+ textAlign: "left",
497
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
498
+ variant: "h6",
499
+ color: "text.hint",
500
+ mb: 1,
501
+ children: t('startApp.version')
502
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Chip.default, {
503
+ label: "v".concat(appVersion),
504
+ size: "small",
505
+ color: "primary",
506
+ variant: "outlined"
507
+ })]
508
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
509
+ flex: 1,
510
+ textAlign: "left",
511
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
512
+ variant: "h6",
513
+ color: "text.hint",
514
+ mb: 1,
515
+ children: t('startApp.status')
516
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Chip.default, {
517
+ label: t('startApp.running'),
518
+ size: "small",
519
+ color: "success"
520
+ })]
521
+ })]
522
+ })]
523
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
524
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
525
+ variant: "h6",
526
+ color: "text.hint",
527
+ textAlign: "left",
528
+ children: t('startApp.visitUrl')
529
+ }), urls.map(url => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
530
+ display: "flex",
531
+ alignItems: "center",
532
+ mt: 1,
533
+ gap: 1,
534
+ sx: {
535
+ backgroundColor: 'divider',
536
+ borderRadius: 1,
537
+ py: 0.5,
538
+ px: 1.5,
539
+ flex: 1
540
+ },
541
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Box, {
542
+ sx: {
543
+ width: 8,
544
+ height: 8,
545
+ borderRadius: '50%',
546
+ backgroundColor: accessibleUrls.includes(url) ? 'success.main' : 'error.main'
547
+ }
548
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
549
+ variant: "body2",
550
+ textAlign: "left",
551
+ sx: {
552
+ flex: 1,
553
+ fontSize: '0.875rem',
554
+ wordBreak: 'break-all'
555
+ },
556
+ children: url
557
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
558
+ size: "small",
559
+ onClick: () => navigator.clipboard.writeText(url),
560
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ContentCopy.default, {
561
+ sx: {
562
+ fontSize: 16
563
+ }
564
+ })
565
+ })]
566
+ }, url))]
567
+ })]
568
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Box, {
569
+ display: "grid",
570
+ gridTemplateColumns: {
571
+ xs: '1fr',
572
+ sm: '1fr 1fr'
573
+ },
574
+ gap: 2,
575
+ children: featureCards.filter(card => card.show !== false).map(card => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
576
+ sx: {
577
+ p: 3,
578
+ display: 'flex',
579
+ alignItems: 'center',
580
+ justifyContent: 'flex-start',
581
+ cursor: 'pointer',
582
+ gap: 1,
583
+ borderRadius: 2,
584
+ border: '1px solid',
585
+ borderColor: 'divider',
586
+ backgroundColor: 'background.paper',
587
+ transition: 'all 0.2s ease',
588
+ '&:hover': {
589
+ boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)'
590
+ }
591
+ },
592
+ onClick: card.onClick,
593
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Box, {
594
+ sx: {
595
+ width: 48,
596
+ height: 48,
597
+ borderRadius: 2,
598
+ backgroundColor: 'rgba(0, 0, 0, 0.04)',
599
+ display: 'flex',
600
+ alignItems: 'center',
601
+ justifyContent: 'center'
602
+ },
603
+ children: card.icon
604
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
605
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
606
+ variant: "subtitle2",
607
+ fontWeight: "bold",
608
+ textAlign: "left",
609
+ gutterBottom: true,
610
+ children: card.title
611
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
612
+ variant: "caption",
613
+ color: "text.secondary",
614
+ textAlign: "center",
615
+ sx: {
616
+ display: '-webkit-box',
617
+ WebkitLineClamp: 2,
618
+ WebkitBoxOrient: 'vertical',
619
+ overflow: 'hidden',
620
+ fontSize: '0.75rem'
621
+ },
622
+ children: card.description
623
+ })]
624
+ })]
625
+ }, card.id))
626
+ }, appUrl)]
627
+ });
628
+ }
629
+ AppSuccessDisplay.propTypes = {
630
+ launchSession: _propTypes.default.object.isRequired,
631
+ urls: _propTypes.default.arrayOf(_propTypes.default.string).isRequired,
632
+ accessibleUrl: _propTypes.default.string.isRequired,
633
+ sessionId: _propTypes.default.string.isRequired,
634
+ blockletInfo: _propTypes.default.object.isRequired
635
+ };