@wix/himalaya-cli 0.1029.0 → 0.1031.0
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/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +7 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/wix-gateway.d.ts +32 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/wix-gateway.rules.d.ts +2 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +7 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/genie-chat/src/index.d.ts +64 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-genie-chat.mjs +41 -1
- package/dist/cli.mjs +298 -114
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/component-reference.json +0 -7
- package/guides/component-reference.md +0 -2
- package/guides/sdk-reference.json +50 -2
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +575 -214
- package/templates/beauty-salon/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/beauty-salon/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/beauty-salon/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/beauty-salon/tier5-src/himi-store-product/index.ts +36 -5
- package/templates/beauty-salon/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/beauty-salon-owner/config.ts +1 -1
- package/templates/beauty-salon-owner/dev/index.ts +247 -9
- package/templates/beauty-salon-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/beauty-salon-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/beauty-salon-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/beauty-salon-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/beauty-salon-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/branded-lite/dev/index.ts +699 -228
- package/templates/branded-lite/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/branded-lite/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/branded-lite/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/branded-lite/tier5-src/himi-branded-lite-notifsettings/index.ts +11 -6
- package/templates/branded-lite/tier5-src/himi-branded-lite-reviews/index.ts +11 -6
- package/templates/branded-lite/tier5-src/himi-store-product/index.ts +36 -5
- package/templates/branded-lite/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/community-club/dev/index.ts +451 -204
- package/templates/community-club/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/community-club/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/community-club/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/community-club/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/community-club-owner/config.ts +1 -1
- package/templates/community-club-owner/dev/index.ts +247 -9
- package/templates/community-club-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/community-club-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/community-club-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/community-club-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/community-club-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/community-club-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/community-club-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/community-club-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/events-meetups/dev/index.ts +451 -204
- package/templates/events-meetups/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/events-meetups/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/events-meetups/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/events-meetups/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/events-meetups-owner/config.ts +1 -1
- package/templates/events-meetups-owner/dev/index.ts +247 -9
- package/templates/events-meetups-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/events-meetups-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/events-meetups-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/events-meetups-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/events-meetups-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/gym-fitness/dev/index.ts +575 -214
- package/templates/gym-fitness/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/gym-fitness/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/gym-fitness/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/gym-fitness/tier5-src/himi-store-product/index.ts +36 -5
- package/templates/gym-fitness/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/gym-fitness-owner/config.ts +1 -1
- package/templates/gym-fitness-owner/dev/index.ts +247 -9
- package/templates/gym-fitness-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/gym-fitness-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/gym-fitness-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/gym-fitness-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/gym-fitness-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/himi-chat/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/nonprofit-cause/dev/index.ts +451 -204
- package/templates/nonprofit-cause/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/nonprofit-cause/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/nonprofit-cause/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/nonprofit-cause/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/nonprofit-cause-owner/config.ts +1 -1
- package/templates/nonprofit-cause-owner/dev/index.ts +247 -9
- package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/owner-lite/config.ts +1 -1
- package/templates/owner-lite/dev/index.ts +247 -9
- package/templates/owner-lite/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/owner-lite/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/owner-lite/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/owner-lite/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/owner-lite/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/owner-lite/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/podcast-creator/dev/index.ts +451 -204
- package/templates/podcast-creator/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/podcast-creator/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/podcast-creator/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/podcast-creator/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/podcast-creator-owner/config.ts +1 -1
- package/templates/podcast-creator-owner/dev/index.ts +247 -9
- package/templates/podcast-creator-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/podcast-creator-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/podcast-creator-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/podcast-creator-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/podcast-creator-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/portfolio-creative/dev/index.ts +575 -214
- package/templates/portfolio-creative/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/portfolio-creative/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/portfolio-creative/tier5-src/himi-store-product/index.ts +36 -5
- package/templates/portfolio-creative/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/portfolio-creative-owner/config.ts +1 -1
- package/templates/portfolio-creative-owner/dev/index.ts +247 -9
- package/templates/portfolio-creative-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/portfolio-creative-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/portfolio-creative-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/portfolio-creative-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/portfolio-creative-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/restaurant/dev/index.ts +451 -204
- package/templates/restaurant/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/restaurant/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/restaurant/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/restaurant/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/restaurant-owner/config.ts +1 -1
- package/templates/restaurant-owner/dev/index.ts +247 -9
- package/templates/restaurant-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/restaurant-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/restaurant-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/restaurant-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/restaurant-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/retail-store/dev/index.ts +575 -214
- package/templates/retail-store/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/retail-store/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/retail-store/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/retail-store/tier5-src/himi-store-product/index.ts +36 -5
- package/templates/retail-store/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/retail-store-owner/config.ts +1 -1
- package/templates/retail-store-owner/dev/index.ts +247 -9
- package/templates/retail-store-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/retail-store-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/retail-store-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/retail-store-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/retail-store-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
- package/templates/yoga-studio/dev/index.ts +451 -204
- package/templates/yoga-studio/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/yoga-studio/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/yoga-studio/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
- package/templates/yoga-studio/tier5-src/wix-spaces-app-language/index.ts +4 -2
- package/templates/yoga-studio-owner/config.ts +1 -1
- package/templates/yoga-studio-owner/dev/index.ts +247 -9
- package/templates/yoga-studio-owner/tier5-src/_shared/aria-attachments.ts +179 -0
- package/templates/yoga-studio-owner/tier5-src/_shared/aria-chat.ts +405 -20
- package/templates/yoga-studio-owner/tier5-src/_shared/collection-contract.ts +4 -1
- package/templates/yoga-studio-owner/tier5-src/_shared/owner-bookings.ts +20 -0
- package/templates/yoga-studio-owner/tier5-src/_shared/owner-load-error.ts +7 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
|
@@ -14,6 +14,9 @@ export interface CollectionConfig {
|
|
|
14
14
|
searchPlaceholder?: string;
|
|
15
15
|
sortLabels?: { default: string; az: string; za: string };
|
|
16
16
|
metadata?: string[];
|
|
17
|
+
/** Numeric 0–5 row field rendered as a Rating (accessible "N out of 5") instead of
|
|
18
|
+
* folding a "★★★★☆" glyph string into the metadata line, so screen readers get a value. */
|
|
19
|
+
rating?: string;
|
|
17
20
|
sectioned?: boolean;
|
|
18
21
|
view: 'list' | 'grid';
|
|
19
22
|
backendQuery?: boolean;
|
|
@@ -58,7 +61,7 @@ export const COLLECTIONS: Record<string, CollectionConfig> = {
|
|
|
58
61
|
himiBrandedCoupons: { rows: 'coupons', title: 'name', subtitle: 'subtitle', view: 'list', primaryVerb: { label: 'Get code' } },
|
|
59
62
|
himiBrandedNotifications: { rows: 'items', title: 'name', subtitle: 'subtitle', image: 'photo', metadata: ['unreadDot'], view: 'list' },
|
|
60
63
|
himiBrandedLoyalty: { rows: 'rewards', title: 'name', subtitle: 'description', view: 'grid', primaryVerb: { label: 'Redeem' } },
|
|
61
|
-
himiBrandedReviews: { rows: 'reviews', title: 'title', subtitle: 'body', metadata: ['author', '
|
|
64
|
+
himiBrandedReviews: { rows: 'reviews', title: 'title', subtitle: 'body', metadata: ['author'], rating: 'rating', view: 'list' },
|
|
62
65
|
himiBrandedPortfolio: { rows: 'projects', title: 'title', subtitle: 'subtitle', image: 'image', view: 'grid', gridImageHeight: 180 },
|
|
63
66
|
himiBrandedInvoices: { rows: 'invoices', title: 'title', subtitle: 'subtitle', view: 'list' },
|
|
64
67
|
himiBrandedBadges: { rows: 'badges', title: 'name', subtitle: 'description', view: 'grid' },
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { copyParam } from "./himi-copy.js";
|
|
2
2
|
|
|
3
|
-
/** Host-owned preview input. Absent on native and older hosts.
|
|
3
|
+
/** Host-owned preview input. Absent on native and older hosts.
|
|
4
|
+
*
|
|
5
|
+
* `"sample"` — the built-in demo records; `"live"` — the viewer's own business over the
|
|
6
|
+
* owner rung; `"fixtures"` — a DEV web host over a sealed hermetic gateway, where
|
|
7
|
+
* the dev fixtures are the sample data. `"fixtures"` is neither live nor demo, so a
|
|
8
|
+
* worker READS through the bridge as it does on a device; it is still a preview host
|
|
9
|
+
* (`isOwnerPreviewHost`), so failure copy may name the web preview. */
|
|
4
10
|
function ownerPreviewMode(): unknown {
|
|
5
11
|
return (globalThis as unknown as { himalaya?: { input?: Record<string, unknown> } }).himalaya?.input?.__himiOwnerPreview;
|
|
6
12
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineService } from "@himalaya/state";
|
|
2
2
|
import {
|
|
3
|
+
ACCENT_IDS,
|
|
3
4
|
ACCENT_KEY,
|
|
4
5
|
ACCENT_META,
|
|
5
6
|
DEFAULT_ACCENT,
|
|
@@ -29,6 +30,10 @@ interface State {
|
|
|
29
30
|
accentHex_sage: string;
|
|
30
31
|
accentHex_plum: string;
|
|
31
32
|
accentHex_ocean: string;
|
|
33
|
+
// Per-accent selection flags for the radio group (`selected_<id>`) and the
|
|
34
|
+
// check mark on the swatch (`notSelected_<id>`, hiddenWhen hides on TRUE). Flat
|
|
35
|
+
// fields for the same reason as the hex ones: the swatches are static nodes.
|
|
36
|
+
[flag: `selected_${string}` | `notSelected_${string}`]: boolean | string;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
interface StorageLike {
|
|
@@ -50,7 +55,13 @@ function paramValue(arg: unknown, key: string): string {
|
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
function build(pendingAccent: string, brandAccent: string): State {
|
|
58
|
+
const flags: Record<string, boolean> = {};
|
|
59
|
+
for (const id of ACCENT_IDS) {
|
|
60
|
+
flags[`selected_${id}`] = id === pendingAccent;
|
|
61
|
+
flags[`notSelected_${id}`] = id !== pendingAccent;
|
|
62
|
+
}
|
|
53
63
|
return {
|
|
64
|
+
...flags,
|
|
54
65
|
pendingAccent,
|
|
55
66
|
brandAccent,
|
|
56
67
|
accentHex_brand: brandAccent || ACCENT_META.amber.hex,
|
|
@@ -85,7 +96,7 @@ const svc = defineService<State, {
|
|
|
85
96
|
selectAccent: (state, arg) => {
|
|
86
97
|
const id = paramValue(arg, "id");
|
|
87
98
|
if (!isAccentId(id)) return state;
|
|
88
|
-
return
|
|
99
|
+
return build(id, state.brandAccent);
|
|
89
100
|
},
|
|
90
101
|
// Apply: persist the accent; the home worker re-reads it on launch.
|
|
91
102
|
apply: (state) => {
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
import { defineService } from "@himalaya/state";
|
|
6
6
|
import { dispatch } from "@himalaya/dispatch";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
/** `selected` drives the row's radio; `subtitle` stays for older descriptors. */
|
|
9
|
+
interface Row { id: string; name: string; subtitle: string; selected: boolean }
|
|
9
10
|
interface S { status: "ready"; options: Row[] }
|
|
10
11
|
|
|
11
12
|
/** Locales with catalogs (`tools/l10n/catalog.<tag>.json`) + LocaleStore support. */
|
|
12
|
-
const LOCALE_OPTIONS: Omit<Row, "subtitle">[] = [
|
|
13
|
+
const LOCALE_OPTIONS: Omit<Row, "subtitle" | "selected">[] = [
|
|
13
14
|
{ id: "en", name: "English" },
|
|
14
15
|
{ id: "es", name: "Español" },
|
|
15
16
|
{ id: "he", name: "עברית" },
|
|
@@ -19,6 +20,7 @@ function withSelected(selected: string): Row[] {
|
|
|
19
20
|
return LOCALE_OPTIONS.map((o) => ({
|
|
20
21
|
...o,
|
|
21
22
|
subtitle: o.id === selected ? "Selected" : "",
|
|
23
|
+
selected: o.id === selected,
|
|
22
24
|
}));
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -37,7 +37,7 @@ export default defineApp({
|
|
|
37
37
|
actions: "http://localhost:8190/v1/actions",
|
|
38
38
|
sync: "http://localhost:8190/v1/sync",
|
|
39
39
|
},
|
|
40
|
-
capabilities: ["live_activity","push","share","secure_storage","open_url","local_database","clipboard","ui"],
|
|
40
|
+
capabilities: ["live_activity","push","share","secure_storage","open_url","local_database","clipboard","ui","camera","presigned_upload"],
|
|
41
41
|
designTokensPath: "./tokens.json",
|
|
42
42
|
navigation: {
|
|
43
43
|
"navKind": "responsive",
|
|
@@ -50458,7 +50458,7 @@ const SCREENS = runtimeSetting({
|
|
|
50458
50458
|
"itemsPath": "$service:himiOwnerLiteManage.recents",
|
|
50459
50459
|
"items": [
|
|
50460
50460
|
{
|
|
50461
|
-
"id": "",
|
|
50461
|
+
"id": "himi_owner_lite.manage.recent.$item.id",
|
|
50462
50462
|
"body": {
|
|
50463
50463
|
"package": "himalaya",
|
|
50464
50464
|
"type": "VStack",
|
|
@@ -50603,7 +50603,7 @@ const SCREENS = runtimeSetting({
|
|
|
50603
50603
|
"spacing": 14,
|
|
50604
50604
|
"children": [
|
|
50605
50605
|
{
|
|
50606
|
-
"id": "",
|
|
50606
|
+
"id": "himi_owner_lite.manage.recent.create.$item.id",
|
|
50607
50607
|
"body": {
|
|
50608
50608
|
"package": "himalaya",
|
|
50609
50609
|
"type": "Text",
|
|
@@ -50628,7 +50628,7 @@ const SCREENS = runtimeSetting({
|
|
|
50628
50628
|
}
|
|
50629
50629
|
},
|
|
50630
50630
|
{
|
|
50631
|
-
"id": "",
|
|
50631
|
+
"id": "himi_owner_lite.manage.recent.handoff.$item.id",
|
|
50632
50632
|
"body": {
|
|
50633
50633
|
"package": "himalaya",
|
|
50634
50634
|
"type": "Text",
|
|
@@ -50764,7 +50764,7 @@ const SCREENS = runtimeSetting({
|
|
|
50764
50764
|
"itemsPath": "$item.areas",
|
|
50765
50765
|
"items": [
|
|
50766
50766
|
{
|
|
50767
|
-
"id": "",
|
|
50767
|
+
"id": "himi_owner_lite.manage.area.$item.id",
|
|
50768
50768
|
"body": {
|
|
50769
50769
|
"package": "himalaya",
|
|
50770
50770
|
"type": "VStack",
|
|
@@ -50909,7 +50909,7 @@ const SCREENS = runtimeSetting({
|
|
|
50909
50909
|
"spacing": 14,
|
|
50910
50910
|
"children": [
|
|
50911
50911
|
{
|
|
50912
|
-
"id": "",
|
|
50912
|
+
"id": "himi_owner_lite.manage.area.create.$item.id",
|
|
50913
50913
|
"body": {
|
|
50914
50914
|
"package": "himalaya",
|
|
50915
50915
|
"type": "Text",
|
|
@@ -50934,7 +50934,7 @@ const SCREENS = runtimeSetting({
|
|
|
50934
50934
|
}
|
|
50935
50935
|
},
|
|
50936
50936
|
{
|
|
50937
|
-
"id": "",
|
|
50937
|
+
"id": "himi_owner_lite.manage.area.handoff.$item.id",
|
|
50938
50938
|
"body": {
|
|
50939
50939
|
"package": "himalaya",
|
|
50940
50940
|
"type": "Text",
|
|
@@ -51714,7 +51714,7 @@ const SCREENS = runtimeSetting({
|
|
|
51714
51714
|
"props": {
|
|
51715
51715
|
"items": [
|
|
51716
51716
|
{
|
|
51717
|
-
"id": "",
|
|
51717
|
+
"id": "ol_drawer_nav.$item.id",
|
|
51718
51718
|
"body": {
|
|
51719
51719
|
"package": "himalaya",
|
|
51720
51720
|
"type": "ListItem",
|
|
@@ -51766,7 +51766,7 @@ const SCREENS = runtimeSetting({
|
|
|
51766
51766
|
"props": {
|
|
51767
51767
|
"items": [
|
|
51768
51768
|
{
|
|
51769
|
-
"id": "",
|
|
51769
|
+
"id": "ol_drawer_attention.$item.id",
|
|
51770
51770
|
"body": {
|
|
51771
51771
|
"package": "himalaya",
|
|
51772
51772
|
"type": "ListItem",
|
|
@@ -55327,6 +55327,45 @@ const SCREENS = runtimeSetting({
|
|
|
55327
55327
|
}
|
|
55328
55328
|
}
|
|
55329
55329
|
},
|
|
55330
|
+
{
|
|
55331
|
+
"id": "himi_owner_lite_aria.msg_attach_$item.id",
|
|
55332
|
+
"body": {
|
|
55333
|
+
"package": "himalaya",
|
|
55334
|
+
"type": "HStack",
|
|
55335
|
+
"props": {
|
|
55336
|
+
"spacing": 0,
|
|
55337
|
+
"children": [
|
|
55338
|
+
{
|
|
55339
|
+
"id": "",
|
|
55340
|
+
"body": {
|
|
55341
|
+
"package": "himalaya",
|
|
55342
|
+
"type": "Spacer",
|
|
55343
|
+
"props": {}
|
|
55344
|
+
},
|
|
55345
|
+
"modifiers": {
|
|
55346
|
+
"hiddenPath": "$item.notUser"
|
|
55347
|
+
}
|
|
55348
|
+
},
|
|
55349
|
+
{
|
|
55350
|
+
"id": "",
|
|
55351
|
+
"body": {
|
|
55352
|
+
"package": "himalaya",
|
|
55353
|
+
"type": "Text",
|
|
55354
|
+
"props": {
|
|
55355
|
+
"text": "$item.attachText",
|
|
55356
|
+
"style": "footnote",
|
|
55357
|
+
"color": "textSecondary",
|
|
55358
|
+
"maxLines": 3
|
|
55359
|
+
}
|
|
55360
|
+
}
|
|
55361
|
+
}
|
|
55362
|
+
]
|
|
55363
|
+
}
|
|
55364
|
+
},
|
|
55365
|
+
"modifiers": {
|
|
55366
|
+
"hiddenPath": "$item.attachHidden"
|
|
55367
|
+
}
|
|
55368
|
+
},
|
|
55330
55369
|
{
|
|
55331
55370
|
"id": "himi_owner_lite_aria.msg_$item.id.link1",
|
|
55332
55371
|
"body": {
|
|
@@ -58907,6 +58946,203 @@ const SCREENS = runtimeSetting({
|
|
|
58907
58946
|
}
|
|
58908
58947
|
}
|
|
58909
58948
|
},
|
|
58949
|
+
{
|
|
58950
|
+
"id": "himi_owner_lite_aria.attachments.bound",
|
|
58951
|
+
"body": {
|
|
58952
|
+
"package": "himalaya",
|
|
58953
|
+
"type": "LazyList",
|
|
58954
|
+
"props": {
|
|
58955
|
+
"itemsPath": "$service:himiOwnerLiteAria.attachments",
|
|
58956
|
+
"horizontal": true,
|
|
58957
|
+
"spacing": 8,
|
|
58958
|
+
"items": [
|
|
58959
|
+
{
|
|
58960
|
+
"id": "himi_owner_lite_aria.attachment_$item.id",
|
|
58961
|
+
"body": {
|
|
58962
|
+
"package": "himalaya",
|
|
58963
|
+
"type": "VStack",
|
|
58964
|
+
"props": {
|
|
58965
|
+
"spacing": 4,
|
|
58966
|
+
"children": [
|
|
58967
|
+
{
|
|
58968
|
+
"id": "himi_owner_lite_aria.attachment_thumb_$item.id",
|
|
58969
|
+
"body": {
|
|
58970
|
+
"package": "himalaya",
|
|
58971
|
+
"type": "Image",
|
|
58972
|
+
"props": {
|
|
58973
|
+
"url": "$item.thumbUrl",
|
|
58974
|
+
"width": 72,
|
|
58975
|
+
"height": 72,
|
|
58976
|
+
"contentMode": "fill",
|
|
58977
|
+
"shape": "rounded",
|
|
58978
|
+
"contentDescription": "$item.name"
|
|
58979
|
+
}
|
|
58980
|
+
},
|
|
58981
|
+
"modifiers": {
|
|
58982
|
+
"hiddenPath": "$item.thumbHidden"
|
|
58983
|
+
}
|
|
58984
|
+
},
|
|
58985
|
+
{
|
|
58986
|
+
"id": "",
|
|
58987
|
+
"body": {
|
|
58988
|
+
"package": "himalaya",
|
|
58989
|
+
"type": "Text",
|
|
58990
|
+
"props": {
|
|
58991
|
+
"text": "$item.statusText",
|
|
58992
|
+
"style": "caption",
|
|
58993
|
+
"color": "textSecondary",
|
|
58994
|
+
"maxLines": 2
|
|
58995
|
+
}
|
|
58996
|
+
},
|
|
58997
|
+
"modifiers": {
|
|
58998
|
+
"hiddenPath": "$item.statusHidden"
|
|
58999
|
+
}
|
|
59000
|
+
},
|
|
59001
|
+
{
|
|
59002
|
+
"id": "",
|
|
59003
|
+
"body": {
|
|
59004
|
+
"package": "himalaya",
|
|
59005
|
+
"type": "HStack",
|
|
59006
|
+
"props": {
|
|
59007
|
+
"spacing": 8,
|
|
59008
|
+
"children": [
|
|
59009
|
+
{
|
|
59010
|
+
"id": "himi_owner_lite_aria.attachment_retry_$item.id",
|
|
59011
|
+
"body": {
|
|
59012
|
+
"package": "himalaya",
|
|
59013
|
+
"type": "Text",
|
|
59014
|
+
"props": {
|
|
59015
|
+
"text": "Retry",
|
|
59016
|
+
"style": "caption",
|
|
59017
|
+
"color": "accentPrimary",
|
|
59018
|
+
"maxLines": 1
|
|
59019
|
+
}
|
|
59020
|
+
},
|
|
59021
|
+
"modifiers": {
|
|
59022
|
+
"onTap": {
|
|
59023
|
+
"actionId": "tier5.himiOwnerLiteAria.retryAttachment",
|
|
59024
|
+
"params": {
|
|
59025
|
+
"id": "$item.id"
|
|
59026
|
+
}
|
|
59027
|
+
},
|
|
59028
|
+
"hiddenPath": "$item.retryHidden"
|
|
59029
|
+
}
|
|
59030
|
+
},
|
|
59031
|
+
{
|
|
59032
|
+
"id": "himi_owner_lite_aria.attachment_remove_$item.id",
|
|
59033
|
+
"body": {
|
|
59034
|
+
"package": "himalaya",
|
|
59035
|
+
"type": "Icon",
|
|
59036
|
+
"props": {
|
|
59037
|
+
"name": "close",
|
|
59038
|
+
"size": 14,
|
|
59039
|
+
"tint": "textSecondary"
|
|
59040
|
+
}
|
|
59041
|
+
},
|
|
59042
|
+
"modifiers": {
|
|
59043
|
+
"onTap": {
|
|
59044
|
+
"actionId": "tier5.himiOwnerLiteAria.removeAttachment",
|
|
59045
|
+
"params": {
|
|
59046
|
+
"id": "$item.id"
|
|
59047
|
+
}
|
|
59048
|
+
},
|
|
59049
|
+
"accessibilityLabel": "Remove photo"
|
|
59050
|
+
}
|
|
59051
|
+
}
|
|
59052
|
+
]
|
|
59053
|
+
}
|
|
59054
|
+
}
|
|
59055
|
+
}
|
|
59056
|
+
]
|
|
59057
|
+
}
|
|
59058
|
+
},
|
|
59059
|
+
"modifiers": {
|
|
59060
|
+
"width": 72
|
|
59061
|
+
}
|
|
59062
|
+
}
|
|
59063
|
+
]
|
|
59064
|
+
}
|
|
59065
|
+
},
|
|
59066
|
+
"modifiers": {
|
|
59067
|
+
"hiddenPath": "$service:himiOwnerLiteAria.attachmentsHidden",
|
|
59068
|
+
"padding": {
|
|
59069
|
+
"leading": 0,
|
|
59070
|
+
"trailing": 0,
|
|
59071
|
+
"top": 8,
|
|
59072
|
+
"bottom": 0
|
|
59073
|
+
}
|
|
59074
|
+
}
|
|
59075
|
+
},
|
|
59076
|
+
{
|
|
59077
|
+
"id": "",
|
|
59078
|
+
"body": {
|
|
59079
|
+
"package": "himalaya",
|
|
59080
|
+
"type": "HStack",
|
|
59081
|
+
"props": {
|
|
59082
|
+
"spacing": 16,
|
|
59083
|
+
"children": [
|
|
59084
|
+
{
|
|
59085
|
+
"id": "himi_owner_lite_aria.attach.library",
|
|
59086
|
+
"body": {
|
|
59087
|
+
"package": "himalaya",
|
|
59088
|
+
"type": "Icon",
|
|
59089
|
+
"props": {
|
|
59090
|
+
"name": "image",
|
|
59091
|
+
"size": 22,
|
|
59092
|
+
"tint": "accentPrimary"
|
|
59093
|
+
}
|
|
59094
|
+
},
|
|
59095
|
+
"modifiers": {
|
|
59096
|
+
"onTap": {
|
|
59097
|
+
"actionId": "tier5.himiOwnerLiteAria.attach",
|
|
59098
|
+
"params": {
|
|
59099
|
+
"source": "library"
|
|
59100
|
+
}
|
|
59101
|
+
},
|
|
59102
|
+
"accessibilityLabel": "Add a photo"
|
|
59103
|
+
}
|
|
59104
|
+
},
|
|
59105
|
+
{
|
|
59106
|
+
"id": "himi_owner_lite_aria.attach.camera",
|
|
59107
|
+
"body": {
|
|
59108
|
+
"package": "himalaya",
|
|
59109
|
+
"type": "Icon",
|
|
59110
|
+
"props": {
|
|
59111
|
+
"name": "camera",
|
|
59112
|
+
"size": 22,
|
|
59113
|
+
"tint": "accentPrimary"
|
|
59114
|
+
}
|
|
59115
|
+
},
|
|
59116
|
+
"modifiers": {
|
|
59117
|
+
"onTap": {
|
|
59118
|
+
"actionId": "tier5.himiOwnerLiteAria.attach",
|
|
59119
|
+
"params": {
|
|
59120
|
+
"source": "camera"
|
|
59121
|
+
}
|
|
59122
|
+
},
|
|
59123
|
+
"accessibilityLabel": "Take a photo"
|
|
59124
|
+
}
|
|
59125
|
+
},
|
|
59126
|
+
{
|
|
59127
|
+
"id": "",
|
|
59128
|
+
"body": {
|
|
59129
|
+
"package": "himalaya",
|
|
59130
|
+
"type": "Spacer",
|
|
59131
|
+
"props": {}
|
|
59132
|
+
}
|
|
59133
|
+
}
|
|
59134
|
+
]
|
|
59135
|
+
}
|
|
59136
|
+
},
|
|
59137
|
+
"modifiers": {
|
|
59138
|
+
"padding": {
|
|
59139
|
+
"leading": 0,
|
|
59140
|
+
"trailing": 0,
|
|
59141
|
+
"top": 8,
|
|
59142
|
+
"bottom": 0
|
|
59143
|
+
}
|
|
59144
|
+
}
|
|
59145
|
+
},
|
|
58910
59146
|
{
|
|
58911
59147
|
"id": "form_aria",
|
|
58912
59148
|
"body": {
|
|
@@ -58992,7 +59228,9 @@ const SCREENS = runtimeSetting({
|
|
|
58992
59228
|
"wix_api",
|
|
58993
59229
|
"open_url",
|
|
58994
59230
|
"clipboard",
|
|
58995
|
-
"ui"
|
|
59231
|
+
"ui",
|
|
59232
|
+
"camera",
|
|
59233
|
+
"presigned_upload"
|
|
58996
59234
|
],
|
|
58997
59235
|
"minBinaryVersion": "0.1.0",
|
|
58998
59236
|
"bundleVersion": "0.0.1"
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// Photo attachments for the Aria composer — the pure half.
|
|
2
|
+
//
|
|
3
|
+
// Everything here is a decision that can be made without touching the device
|
|
4
|
+
// or the network: which files may be attached, how many, how large, what a chip
|
|
5
|
+
// in the composer says in each of its three states, and how a picked image is
|
|
6
|
+
// turned into the bytes an upload sends. The half that DOES touch the world —
|
|
7
|
+
// minting the upload, sending the bytes, picking — lives in `aria-chat.ts`
|
|
8
|
+
// (the mint, through `@himalaya/wix-genie-chat`) and in each app's adapter (the
|
|
9
|
+
// picker and the byte transfer, which are device capabilities the adapter's
|
|
10
|
+
// screen has to declare).
|
|
11
|
+
//
|
|
12
|
+
// This file is copied verbatim into every generated starter app, so it explains
|
|
13
|
+
// itself without pointing at anything only this repo has.
|
|
14
|
+
|
|
15
|
+
/** Image types the composer accepts. The first-party clients' own allowlist
|
|
16
|
+
* for images: png, jpeg (and the non-standard `image/jpg` some pickers still
|
|
17
|
+
* report), webp, gif and heic. Anything else is REFUSED with a line saying so,
|
|
18
|
+
* never silently dropped — the native Aria app drops unsupported files without a
|
|
19
|
+
* word, and an owner who picked something and sees nothing happen assumes the
|
|
20
|
+
* button is broken. */
|
|
21
|
+
export const ARIA_IMAGE_TYPES: readonly string[] = [
|
|
22
|
+
"image/png",
|
|
23
|
+
"image/jpeg",
|
|
24
|
+
"image/jpg",
|
|
25
|
+
"image/webp",
|
|
26
|
+
"image/gif",
|
|
27
|
+
"image/heic",
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
/** At most this many attachments ride one message. The native Aria app caps at
|
|
31
|
+
* 10; nothing on the wire says otherwise. */
|
|
32
|
+
export const ARIA_MAX_ATTACHMENTS = 10;
|
|
33
|
+
|
|
34
|
+
/** The largest image the composer will try to send, in bytes.
|
|
35
|
+
*
|
|
36
|
+
* Not a product choice: it is the ceiling of the transfer this slice uses. A
|
|
37
|
+
* picked photo crosses the worker bridge as a base64 string and is sent inline,
|
|
38
|
+
* and the inline upload refuses anything over 8 MiB (the `MAX_INLINE_BASE64_BYTES`
|
|
39
|
+
* bound of the pre-signed upload capability, which it enforces on every arm).
|
|
40
|
+
* Checking it HERE is what turns that refusal into a sentence the owner can act
|
|
41
|
+
* on, instead of a chip that fails for no stated reason. */
|
|
42
|
+
export const ARIA_MAX_IMAGE_BYTES = 8 * 1024 * 1024;
|
|
43
|
+
|
|
44
|
+
/** A chip in the composer. Every field is always present — a `$item.` path that
|
|
45
|
+
* is missing on some rows does not substitute — and each `…Hidden` flag
|
|
46
|
+
* collapses the part it names. */
|
|
47
|
+
export interface AriaAttachmentChip {
|
|
48
|
+
/** Minted by the worker, never derived from the file. The native Aria app keyed
|
|
49
|
+
* concurrent uploads by file NAME and collided on the second `IMG_0001.jpg`. */
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
mimeType: string;
|
|
53
|
+
state: "uploading" | "ready" | "failed";
|
|
54
|
+
/** The chip's thumbnail as a `data:` URI, set only when the picked image is
|
|
55
|
+
* small; "" otherwise, which collapses the preview. The full bytes an upload
|
|
56
|
+
* and a retry send are held by the worker, never in the chip, because the chip
|
|
57
|
+
* rides the service state and a large photo there would exceed the web
|
|
58
|
+
* runtime's frame limit. */
|
|
59
|
+
thumbUrl: string;
|
|
60
|
+
thumbHidden: boolean;
|
|
61
|
+
/** "Uploading…" / "Couldn't upload" / "" — collapses when empty. */
|
|
62
|
+
statusText: string;
|
|
63
|
+
statusHidden: boolean;
|
|
64
|
+
/** The retry control shows ONLY on a failed chip. */
|
|
65
|
+
retryHidden: boolean;
|
|
66
|
+
/** `genie-upload://<id>` once the bytes have landed; "" until then. The send
|
|
67
|
+
* carries a chip only when this is set. */
|
|
68
|
+
ref: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** What an upload reports back, delivered as a fresh action so it lands on the
|
|
72
|
+
* CURRENT state rather than on the snapshot the upload started from. */
|
|
73
|
+
export interface AriaAttachmentOutcome {
|
|
74
|
+
id: string;
|
|
75
|
+
ok: boolean;
|
|
76
|
+
/** Set when `ok`. */
|
|
77
|
+
ref?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface ParsedDataUri { mimeType: string; base64: string; bytes: number }
|
|
81
|
+
|
|
82
|
+
/** `data:<mime>;base64,<payload>` → its parts, or null for anything else.
|
|
83
|
+
*
|
|
84
|
+
* Only the base64 form: every picker this composer is wired to returns it, and
|
|
85
|
+
* a percent-encoded `data:` URI would need decoding the bridge cannot do. The
|
|
86
|
+
* byte count is computed from the payload length, so a multi-megabyte photo is
|
|
87
|
+
* sized without being decoded. */
|
|
88
|
+
export function parseDataUri(uri: string): ParsedDataUri | null {
|
|
89
|
+
const m = /^data:([^;,]*)((?:;[^;,]*)*?);base64,/i.exec(uri ?? "");
|
|
90
|
+
if (!m) return null;
|
|
91
|
+
const base64 = uri.slice(m[0].length).replace(/\s+/g, "");
|
|
92
|
+
const pad = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
|
|
93
|
+
const bytes = Math.max(0, Math.floor((base64.length * 3) / 4) - pad);
|
|
94
|
+
return { mimeType: (m[1] || "").trim().toLowerCase(), base64, bytes };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Normalize a MIME type a picker reported.
|
|
98
|
+
*
|
|
99
|
+
* Some pickers hand back a platform type identifier where a MIME type belongs
|
|
100
|
+
* (`public.jpeg`, `public.heic`), and the service validates the field as a MIME
|
|
101
|
+
* type. Mapped for the image identifiers this composer accepts; anything else
|
|
102
|
+
* is returned lowercased and left for the allowlist to judge. */
|
|
103
|
+
export function normalizeMime(mime: string): string {
|
|
104
|
+
const v = (mime ?? "").trim().toLowerCase();
|
|
105
|
+
switch (v) {
|
|
106
|
+
case "public.jpeg": return "image/jpeg";
|
|
107
|
+
case "public.png": return "image/png";
|
|
108
|
+
case "public.heic": return "image/heic";
|
|
109
|
+
case "com.compuserve.gif": return "image/gif";
|
|
110
|
+
case "org.webmproject.webp": return "image/webp";
|
|
111
|
+
case "image/jpg": return "image/jpeg";
|
|
112
|
+
default: return v;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** A file name for an image the picker did not name, by type. The service
|
|
117
|
+
* requires one (1–255 characters), and it is what the transcript shows. */
|
|
118
|
+
export function imageFileName(mimeType: string, n: number, given?: string): string {
|
|
119
|
+
const name = (given ?? "").trim();
|
|
120
|
+
if (name) return name.slice(0, 255);
|
|
121
|
+
const ext = mimeType === "image/png" ? "png"
|
|
122
|
+
: mimeType === "image/webp" ? "webp"
|
|
123
|
+
: mimeType === "image/gif" ? "gif"
|
|
124
|
+
: mimeType === "image/heic" ? "heic"
|
|
125
|
+
: "jpg";
|
|
126
|
+
return `photo-${n}.${ext}`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Why a picked file cannot be attached, or "" when it can. */
|
|
130
|
+
export type AttachRefusal = "" | "type" | "size" | "count";
|
|
131
|
+
|
|
132
|
+
export function refusalFor(parsed: ParsedDataUri | null, mimeType: string, attached: number): AttachRefusal {
|
|
133
|
+
if (attached >= ARIA_MAX_ATTACHMENTS) return "count";
|
|
134
|
+
if (!parsed || !ARIA_IMAGE_TYPES.includes(mimeType)) return "type";
|
|
135
|
+
if (parsed.bytes > ARIA_MAX_IMAGE_BYTES) return "size";
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** A chip in a given state. One constructor so the flags can never disagree
|
|
140
|
+
* with the state they describe — a failed chip without its retry control is
|
|
141
|
+
* the shape of bug this rules out. */
|
|
142
|
+
export function chipIn(
|
|
143
|
+
base: Pick<AriaAttachmentChip, "id" | "name" | "mimeType" | "thumbUrl">,
|
|
144
|
+
state: AriaAttachmentChip["state"],
|
|
145
|
+
labels: { uploading: string; failed: string },
|
|
146
|
+
ref = "",
|
|
147
|
+
): AriaAttachmentChip {
|
|
148
|
+
const statusText = state === "uploading" ? labels.uploading : state === "failed" ? labels.failed : "";
|
|
149
|
+
return {
|
|
150
|
+
...base,
|
|
151
|
+
state,
|
|
152
|
+
thumbHidden: !base.thumbUrl,
|
|
153
|
+
statusText,
|
|
154
|
+
statusHidden: !statusText,
|
|
155
|
+
retryHidden: state !== "failed",
|
|
156
|
+
ref: state === "ready" ? ref : "",
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Why Send is refused while attachments are pending, or "" when it is not.
|
|
161
|
+
*
|
|
162
|
+
* An upload still running would be dropped from the message, and a failed one
|
|
163
|
+
* would be sent as if the owner had never picked it — in both cases the
|
|
164
|
+
* assistant answers about a photo it never received. So the send waits, and
|
|
165
|
+
* says what it is waiting for. */
|
|
166
|
+
export function sendBlocker(chips: readonly AriaAttachmentChip[]): "" | "uploading" | "failed" {
|
|
167
|
+
if (chips.some((c) => c.state === "uploading")) return "uploading";
|
|
168
|
+
if (chips.some((c) => c.state === "failed")) return "failed";
|
|
169
|
+
return "";
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** The one line a bubble shows for its attachments: a paperclip and the file
|
|
173
|
+
* names. Text, not thumbnails, and not by choice: a `genie-upload://`
|
|
174
|
+
* reference has no published download url, so a sent photo cannot be shown
|
|
175
|
+
* again from the server's copy — and a resumed conversation has nothing else. */
|
|
176
|
+
export function attachmentLine(names: readonly string[]): string {
|
|
177
|
+
const shown = names.map((n) => n.trim()).filter(Boolean);
|
|
178
|
+
return shown.length ? `📎 ${shown.join(", ")}` : "";
|
|
179
|
+
}
|