@wix/himalaya-cli 0.1633.0 → 0.1634.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/stdlib/wix-sdk/members-feed-viewer/src/index.d.ts +10 -6
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/members-v1/src/index.d.ts +34 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-members-feed-viewer.mjs +8 -7
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-members.mjs +29 -0
- package/dist/browser-plane/assets.json +166 -0
- package/dist/browser-plane/host.html +156 -0
- package/dist/browser-plane/package-reader.js +4 -0
- package/dist/browser-plane/preview-deferred/368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5.bin +0 -0
- package/dist/browser-plane/preview-deferred/37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29.bin +0 -0
- package/dist/browser-plane/preview-deferred/4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02.bin +0 -0
- package/dist/browser-plane/preview-deferred/521a0e528916d678d7588b2cddf3dadd3bb959a6d62426382f61c77a82017e35.bin +1 -0
- package/dist/browser-plane/preview-deferred/62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9.bin +0 -0
- package/dist/browser-plane/preview-deferred/642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e.bin +0 -0
- package/dist/browser-plane/preview-deferred/97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1.bin +0 -0
- package/dist/browser-plane/preview-deferred/a33cfe728c584fdba4fcc1fd54bcdc2f9f2f13889ddbb5b2bd1d0f8cbe49b84e.bin +28 -0
- package/dist/browser-plane/preview-deferred/bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa.bin +0 -0
- package/dist/browser-plane/preview-deferred/c3457ce58c96b65f303fec0ddf5f06733004eaf9e21e62302b155ec63a7765f7.bin +56 -0
- package/dist/browser-plane/preview-deferred/d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134.bin +0 -0
- package/dist/browser-plane/preview-deferred/dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b.bin +0 -0
- package/dist/browser-plane/preview-deferred/dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5.bin +0 -0
- package/dist/browser-plane/preview-deferred/ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf.bin +0 -0
- package/dist/browser-plane/sw.js +13 -0
- package/dist/browser-plane/t5-frame.html +350 -0
- package/dist/browser-plane/t5-worker-frame.html +350 -0
- package/dist/cli.mjs +6412 -5067
- package/dist/preview-assets.generated.bin +0 -0
- package/fixtures/wix-canned.json +31 -1
- package/guides/himi-json-output.md +2 -0
- package/guides/one-app-to-himi-app.md +81 -5
- package/guides/sdk-reference.json +34 -3
- package/package.json +3 -3
- package/templates/beauty-salon/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/branded-lite/config.ts +7 -0
- package/templates/branded-lite/dev/index.ts +719 -83
- package/templates/branded-lite/himalaya.content.json +3 -0
- package/templates/branded-lite/l10n/en.json +4 -2
- package/templates/branded-lite/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/branded-lite/tier5-src/_shared/business-chat-history.ts +4 -1
- package/templates/branded-lite/tier5-src/_shared/business-chat-presenter.ts +2 -7
- package/templates/branded-lite/tier5-src/_shared/header-badges.ts +1 -1
- package/templates/branded-lite/tier5-src/_shared/inbox-rooms.ts +68 -0
- package/templates/branded-lite/tier5-src/_shared/member-activity.ts +34 -0
- package/templates/branded-lite/tier5-src/_shared/member-row-extras.ts +167 -0
- package/templates/branded-lite/tier5-src/_shared/notification-target.ts +141 -0
- package/templates/branded-lite/tier5-src/_shared/source-badges.ts +6 -4
- package/templates/branded-lite/tier5-src/_shared/wix-member-links.ts +114 -0
- package/templates/branded-lite/tier5-src/business-chat/index.ts +114 -59
- package/templates/branded-lite/tier5-src/himi-branded-lite-inbox/index.ts +83 -0
- package/templates/branded-lite/tier5-src/himi-branded-lite-notifications/index.ts +62 -7
- package/templates/branded-lite/tier5-src/wix-spaces-members/index.ts +60 -12
- package/templates/community-club/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/events-meetups/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/gym-fitness/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/nonprofit-cause/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/podcast-creator/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/portfolio-creative/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/restaurant/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/retail-store/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/salon-spa/dev/index.ts +112 -70
- package/templates/salon-spa/tier5-src/_shared/branded-lite-hosted.ts +1 -0
- package/templates/salon-spa/tier5-src/_shared/business-chat-history.ts +4 -1
- package/templates/salon-spa/tier5-src/_shared/business-chat-presenter.ts +2 -7
- package/templates/salon-spa/tier5-src/_shared/inbox-rooms.ts +68 -0
- package/templates/salon-spa/tier5-src/business-chat/index.ts +114 -59
- package/templates/yoga-studio/tier5-src/_shared/branded-lite-hosted.ts +1 -0
|
@@ -1,23 +1,34 @@
|
|
|
1
1
|
// Public site-member directory. Search, sorting, totals and offset paging match
|
|
2
2
|
// OneApp's Members v1 query; no owner roster or build-time count is substituted.
|
|
3
3
|
import { defineService } from "@himalaya/state";
|
|
4
|
-
import { queryMembers, type WixMember } from "@himalaya/wix-members";
|
|
4
|
+
import { queryMembers, followMember, unfollowMember, type WixMember } from "@himalaya/wix-members";
|
|
5
5
|
import { createCollectionQuery } from "../_shared/collection-query.js";
|
|
6
6
|
import { readAccess, assertReadAccess, readAccessDenied, type ReadAccess } from "../_shared/member-read.js";
|
|
7
7
|
import { memberAccessChanged } from "../_shared/member-access.js";
|
|
8
8
|
import { withEmptyFlags } from "../_shared/empty-flags.js";
|
|
9
|
+
import { copyParam, stashCopy } from "../_shared/himi-copy.js";
|
|
10
|
+
import { memberRowExtras, followLabel, type MemberRowExtras } from "../_shared/member-row-extras.js";
|
|
9
11
|
|
|
10
|
-
interface Row { id: string; name: string;
|
|
12
|
+
interface Row extends MemberRowExtras { id: string; name: string; initial: string; photo: string; sectionTitle: string }
|
|
11
13
|
interface S {
|
|
12
14
|
status: "loading" | "ready" | "error";
|
|
13
15
|
members: Row[]; emptyText: string;
|
|
14
16
|
query: string; total: number | null; searchLabel: string;
|
|
15
17
|
nextCursor: string; noMore: boolean; noPageError: boolean;
|
|
16
18
|
error: string; notErrored: boolean; notLoading: boolean; hideSearch: boolean;
|
|
19
|
+
followHint: string;
|
|
17
20
|
}
|
|
18
21
|
const PAGE_SIZE = 50;
|
|
19
22
|
const SEARCH_FIELDS = ["contact.firstName", "contact.lastName", "profile.nickname"];
|
|
20
23
|
let directoryAccess: ReadAccess | undefined;
|
|
24
|
+
// A Follow the signed-in member just made or undone. Rows keep the state they were read with, so this
|
|
25
|
+
// shows the change at once; the next first-page read replaces it with what the server says.
|
|
26
|
+
const followChanges = new Map<string, boolean>();
|
|
27
|
+
const pendingFollows = new Set<string>();
|
|
28
|
+
|
|
29
|
+
/** Who a directory read, and a write that follows it, belong to: the site and the signed-in member. A reload
|
|
30
|
+
* builds a NEW ReadAccess object for the same reader, so identity says nothing; this key does. */
|
|
31
|
+
const readerKey = (access: ReadAccess | undefined): string => access ? JSON.stringify([access.tenant, access.member.scope, access.member.email]) : "";
|
|
21
32
|
|
|
22
33
|
function name(m: WixMember): string {
|
|
23
34
|
const nick = m.profile?.nickname?.trim();
|
|
@@ -25,10 +36,14 @@ function name(m: WixMember): string {
|
|
|
25
36
|
const full = [m.contact?.firstName, m.contact?.lastName].filter(Boolean).join(" ").trim();
|
|
26
37
|
return full || "Member";
|
|
27
38
|
}
|
|
28
|
-
function row(m: WixMember): Row {
|
|
39
|
+
function row(m: WixMember, extras: MemberRowExtras): Row {
|
|
29
40
|
const n = name(m);
|
|
30
41
|
// Login emails are not directory subtitles. Only public profile content is presented.
|
|
31
|
-
return { id: m.id, name: n,
|
|
42
|
+
return { id: m.id, name: n, initial: (n[0] || "#").toUpperCase(), photo: m.profile?.photo?.url || "", sectionTitle: "", ...extras };
|
|
43
|
+
}
|
|
44
|
+
function withFollowChange(item: Row): Row {
|
|
45
|
+
const following = followChanges.get(item.id);
|
|
46
|
+
return following === undefined ? item : { ...item, isFollowing: following, followLabel: followLabel(following) };
|
|
32
47
|
}
|
|
33
48
|
function sections(rows: Row[]): Row[] {
|
|
34
49
|
const groups = new Map<string, Row[]>();
|
|
@@ -47,16 +62,17 @@ const directory = createCollectionQuery<Row>({
|
|
|
47
62
|
if (!Number.isSafeInteger(offset) || offset < 0) throw new Error("Invalid member page offset");
|
|
48
63
|
const access = cursor ? directoryAccess : await readAccess();
|
|
49
64
|
if (!access) throw memberAccessChanged();
|
|
50
|
-
if (!cursor) directoryAccess = access;
|
|
65
|
+
if (!cursor) { directoryAccess = access; followChanges.clear(); followHint = ""; }
|
|
51
66
|
await assertReadAccess(access);
|
|
52
67
|
const response = await queryMembers({ query: {
|
|
53
68
|
filter: { status: "APPROVED", privacyStatus: "PUBLIC" },
|
|
54
69
|
sorting: [{ fieldName: "profile.nickname", order: "ASC" }],
|
|
55
70
|
paging: { limit: PAGE_SIZE, offset },
|
|
56
71
|
}, ...(criteria.query ? { search: { expression: criteria.query, fields: SEARCH_FIELDS } } : {}) });
|
|
72
|
+
if (!Array.isArray(response.members) || response.members.some(member => !member?.id)) throw new Error("Invalid member page");
|
|
73
|
+
const extras = response.members.length ? await memberRowExtras(response.members.map(member => member.id), access) : undefined;
|
|
57
74
|
await assertReadAccess(access);
|
|
58
75
|
if (access !== directoryAccess) throw memberAccessChanged();
|
|
59
|
-
if (!Array.isArray(response.members) || response.members.some(member => !member?.id)) throw new Error("Invalid member page");
|
|
60
76
|
const metadata = response.metadata;
|
|
61
77
|
if (metadata?.offset !== undefined && metadata.offset !== offset) throw new Error("Mismatched member page offset");
|
|
62
78
|
const total = !metadata?.tooManyToCount && typeof metadata?.total === "number" && Number.isSafeInteger(metadata.total) && metadata.total >= 0
|
|
@@ -64,7 +80,7 @@ const directory = createCollectionQuery<Row>({
|
|
|
64
80
|
const next = offset + response.members.length;
|
|
65
81
|
if (!response.members.length && total !== undefined && total > next) throw new Error("Incomplete member page");
|
|
66
82
|
return {
|
|
67
|
-
items: response.members.map(row), total,
|
|
83
|
+
items: response.members.map(member => row(member, extras!(member.id))), total,
|
|
68
84
|
nextCursor: response.members.length && (total === undefined ? response.members.length === PAGE_SIZE : next < total) ? String(next) : "",
|
|
69
85
|
};
|
|
70
86
|
},
|
|
@@ -73,6 +89,7 @@ const directory = createCollectionQuery<Row>({
|
|
|
73
89
|
// Set once the reader has typed a search: from then on the field stays mounted, even while a cleared search
|
|
74
90
|
// reloads the full directory (no rows, no query yet), so it never unmounts and loses focus mid-edit.
|
|
75
91
|
let searched = false;
|
|
92
|
+
let followHint = "";
|
|
76
93
|
|
|
77
94
|
function project(): S {
|
|
78
95
|
const page = directory.getState();
|
|
@@ -81,7 +98,7 @@ function project(): S {
|
|
|
81
98
|
const failed = page.status === "error";
|
|
82
99
|
return {
|
|
83
100
|
status: failed ? "error" : loading ? "loading" : "ready",
|
|
84
|
-
members: sections(page.items), query: page.criteria.query, total,
|
|
101
|
+
members: sections(page.items.map(withFollowChange)), query: page.criteria.query, total,
|
|
85
102
|
searchLabel: total === null ? "" : `${total} ${total === 1 ? "member" : "members"}`,
|
|
86
103
|
emptyText: page.status === "ready" && !page.items.length ? page.criteria.query ? "No results" : "No members yet" : "",
|
|
87
104
|
nextCursor: loading || page.loadingMore || page.pageError ? "" : page.nextCursor,
|
|
@@ -94,21 +111,24 @@ function project(): S {
|
|
|
94
111
|
// A successful empty SEARCH keeps its field reachable (to clear the query); a directory that is
|
|
95
112
|
// loading or truly empty (no query, no rows) has nothing to search.
|
|
96
113
|
hideSearch: failed || (!page.items.length && !page.criteria.query && !searched),
|
|
114
|
+
followHint,
|
|
97
115
|
};
|
|
98
116
|
}
|
|
99
117
|
const svc = defineService<S, {
|
|
100
|
-
load: (s: S) => Promise<undefined>;
|
|
118
|
+
load: (s: S, arg?: unknown) => Promise<undefined>;
|
|
101
119
|
filter: (s: S, arg?: unknown) => Promise<undefined>;
|
|
102
120
|
loadMore: (s: S) => Promise<undefined>;
|
|
103
121
|
retry: (s: S) => Promise<undefined>;
|
|
122
|
+
toggleFollow: (s: S, arg?: unknown) => Promise<S | undefined>;
|
|
104
123
|
changed: (s: S) => S;
|
|
105
124
|
}>("spacesMembers", withEmptyFlags({
|
|
106
125
|
state: { status: "loading", members: [], emptyText: "", query: "", total: null, searchLabel: "", nextCursor: "", noMore: true, noPageError: true,
|
|
107
|
-
error: "", notErrored: true, notLoading: false, hideSearch: true },
|
|
126
|
+
error: "", notErrored: true, notLoading: false, hideSearch: true, followHint: "" },
|
|
108
127
|
// A restored worker must re-read the current reader/site before showing a roster.
|
|
109
|
-
notHydrated: ["status", "members", "emptyText", "query", "total", "searchLabel", "nextCursor", "noMore", "noPageError", "error", "notErrored", "notLoading", "hideSearch"],
|
|
128
|
+
notHydrated: ["status", "members", "emptyText", "query", "total", "searchLabel", "nextCursor", "noMore", "noPageError", "error", "notErrored", "notLoading", "hideSearch", "followHint"],
|
|
110
129
|
actions: {
|
|
111
|
-
|
|
130
|
+
// The screen's onAppear carries the copy pack (the owner's wording, the stock translations) and the app language.
|
|
131
|
+
load: async (_s, arg) => { stashCopy(arg); await directory.query(directory.getState().criteria); return undefined; },
|
|
112
132
|
filter: async (_s, arg) => {
|
|
113
133
|
const value = typeof arg === "string" ? arg : (arg as { value?: unknown })?.value;
|
|
114
134
|
if (typeof value === "string" && value.trim()) searched = true;
|
|
@@ -116,6 +136,34 @@ const svc = defineService<S, {
|
|
|
116
136
|
},
|
|
117
137
|
loadMore: async () => { await directory.loadMore(); return undefined; },
|
|
118
138
|
retry: async () => { await directory.retry(); return undefined; },
|
|
139
|
+
// Only a signed-in member reaches this: a Visitor's Follow opens sign-in from the descriptor instead.
|
|
140
|
+
toggleFollow: async (_s, arg) => {
|
|
141
|
+
const id = (arg as { id?: unknown } | undefined)?.id;
|
|
142
|
+
const access = directoryAccess;
|
|
143
|
+
if (typeof id !== "string" || !id || !access?.member.email || pendingFollows.has(id)) return undefined;
|
|
144
|
+
const row = directory.getState().items.find(item => item.id === id);
|
|
145
|
+
if (!row) return undefined;
|
|
146
|
+
const following = withFollowChange(row).isFollowing;
|
|
147
|
+
pendingFollows.add(id);
|
|
148
|
+
try {
|
|
149
|
+
await assertReadAccess(access);
|
|
150
|
+
if (following) await unfollowMember(id); else await followMember(id);
|
|
151
|
+
await assertReadAccess(access);
|
|
152
|
+
// A first-page reload (typing in search, Retry) may have replaced directoryAccess while the write was in
|
|
153
|
+
// flight. The write still stands for the same reader on the same site, so it is recorded; only another
|
|
154
|
+
// reader's list must not take it.
|
|
155
|
+
if (readerKey(access) !== readerKey(directoryAccess)) return undefined;
|
|
156
|
+
followChanges.set(id, !following);
|
|
157
|
+
followHint = "";
|
|
158
|
+
} catch {
|
|
159
|
+
// A failed write belongs to the member who tapped: the control keeps its state and says so.
|
|
160
|
+
if (readerKey(access) !== readerKey(directoryAccess)) return undefined;
|
|
161
|
+
followHint = copyParam("members.followError", "Couldn't update Follow — try again.");
|
|
162
|
+
} finally {
|
|
163
|
+
pendingFollows.delete(id);
|
|
164
|
+
}
|
|
165
|
+
return project();
|
|
166
|
+
},
|
|
119
167
|
changed: () => project(),
|
|
120
168
|
},
|
|
121
169
|
}, { members: "noMembers" }));
|
|
@@ -97,6 +97,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
|
|
|
97
97
|
himi_gift_card: ["giftCards"],
|
|
98
98
|
himi_gift_cards: ["giftCards"],
|
|
99
99
|
himi_groups: ["groups"],
|
|
100
|
+
himi_inbox: ["inbox"],
|
|
100
101
|
himi_group_about: ["groups"],
|
|
101
102
|
himi_my_groups: ["groups"],
|
|
102
103
|
himi_invoice: ["invoices"],
|
|
@@ -97,6 +97,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
|
|
|
97
97
|
himi_gift_card: ["giftCards"],
|
|
98
98
|
himi_gift_cards: ["giftCards"],
|
|
99
99
|
himi_groups: ["groups"],
|
|
100
|
+
himi_inbox: ["inbox"],
|
|
100
101
|
himi_group_about: ["groups"],
|
|
101
102
|
himi_my_groups: ["groups"],
|
|
102
103
|
himi_invoice: ["invoices"],
|
|
@@ -97,6 +97,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
|
|
|
97
97
|
himi_gift_card: ["giftCards"],
|
|
98
98
|
himi_gift_cards: ["giftCards"],
|
|
99
99
|
himi_groups: ["groups"],
|
|
100
|
+
himi_inbox: ["inbox"],
|
|
100
101
|
himi_group_about: ["groups"],
|
|
101
102
|
himi_my_groups: ["groups"],
|
|
102
103
|
himi_invoice: ["invoices"],
|
|
@@ -97,6 +97,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
|
|
|
97
97
|
himi_gift_card: ["giftCards"],
|
|
98
98
|
himi_gift_cards: ["giftCards"],
|
|
99
99
|
himi_groups: ["groups"],
|
|
100
|
+
himi_inbox: ["inbox"],
|
|
100
101
|
himi_group_about: ["groups"],
|
|
101
102
|
himi_my_groups: ["groups"],
|
|
102
103
|
himi_invoice: ["invoices"],
|
|
@@ -97,6 +97,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
|
|
|
97
97
|
himi_gift_card: ["giftCards"],
|
|
98
98
|
himi_gift_cards: ["giftCards"],
|
|
99
99
|
himi_groups: ["groups"],
|
|
100
|
+
himi_inbox: ["inbox"],
|
|
100
101
|
himi_group_about: ["groups"],
|
|
101
102
|
himi_my_groups: ["groups"],
|
|
102
103
|
himi_invoice: ["invoices"],
|
|
@@ -97,6 +97,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
|
|
|
97
97
|
himi_gift_card: ["giftCards"],
|
|
98
98
|
himi_gift_cards: ["giftCards"],
|
|
99
99
|
himi_groups: ["groups"],
|
|
100
|
+
himi_inbox: ["inbox"],
|
|
100
101
|
himi_group_about: ["groups"],
|
|
101
102
|
himi_my_groups: ["groups"],
|
|
102
103
|
himi_invoice: ["invoices"],
|
|
@@ -97,6 +97,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
|
|
|
97
97
|
himi_gift_card: ["giftCards"],
|
|
98
98
|
himi_gift_cards: ["giftCards"],
|
|
99
99
|
himi_groups: ["groups"],
|
|
100
|
+
himi_inbox: ["inbox"],
|
|
100
101
|
himi_group_about: ["groups"],
|
|
101
102
|
himi_my_groups: ["groups"],
|
|
102
103
|
himi_invoice: ["invoices"],
|
|
@@ -97,6 +97,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
|
|
|
97
97
|
himi_gift_card: ["giftCards"],
|
|
98
98
|
himi_gift_cards: ["giftCards"],
|
|
99
99
|
himi_groups: ["groups"],
|
|
100
|
+
himi_inbox: ["inbox"],
|
|
100
101
|
himi_group_about: ["groups"],
|
|
101
102
|
himi_my_groups: ["groups"],
|
|
102
103
|
himi_invoice: ["invoices"],
|
|
@@ -12714,7 +12714,7 @@ const SCREENS = runtimeSetting({
|
|
|
12714
12714
|
"type": "Text",
|
|
12715
12715
|
"props": {
|
|
12716
12716
|
"text": "$item.bodyMarkdown",
|
|
12717
|
-
"style": "
|
|
12717
|
+
"style": "caption",
|
|
12718
12718
|
"color": "textPrimary",
|
|
12719
12719
|
"collapseWhenEmpty": true,
|
|
12720
12720
|
"textDirection": "auto",
|
|
@@ -12918,7 +12918,8 @@ const SCREENS = runtimeSetting({
|
|
|
12918
12918
|
}
|
|
12919
12919
|
}
|
|
12920
12920
|
],
|
|
12921
|
-
"spacing": 6
|
|
12921
|
+
"spacing": 6,
|
|
12922
|
+
"horizontal": false
|
|
12922
12923
|
}
|
|
12923
12924
|
},
|
|
12924
12925
|
"modifiers": {
|
|
@@ -12941,7 +12942,7 @@ const SCREENS = runtimeSetting({
|
|
|
12941
12942
|
"modifiers": {}
|
|
12942
12943
|
}
|
|
12943
12944
|
],
|
|
12944
|
-
"spacing":
|
|
12945
|
+
"spacing": 5,
|
|
12945
12946
|
"alignment": "leading"
|
|
12946
12947
|
}
|
|
12947
12948
|
},
|
|
@@ -12958,12 +12959,12 @@ const SCREENS = runtimeSetting({
|
|
|
12958
12959
|
},
|
|
12959
12960
|
"cornerRadius": 16,
|
|
12960
12961
|
"padding": {
|
|
12961
|
-
"leading":
|
|
12962
|
-
"trailing":
|
|
12963
|
-
"top":
|
|
12964
|
-
"bottom":
|
|
12962
|
+
"leading": 8,
|
|
12963
|
+
"trailing": 8,
|
|
12964
|
+
"top": 8,
|
|
12965
|
+
"bottom": 8
|
|
12965
12966
|
},
|
|
12966
|
-
"maxWidth":
|
|
12967
|
+
"maxWidth": 300,
|
|
12967
12968
|
"hiddenPath": "$item.isCard"
|
|
12968
12969
|
}
|
|
12969
12970
|
},
|
|
@@ -13372,7 +13373,8 @@ const SCREENS = runtimeSetting({
|
|
|
13372
13373
|
}
|
|
13373
13374
|
}
|
|
13374
13375
|
],
|
|
13375
|
-
"spacing": 6
|
|
13376
|
+
"spacing": 6,
|
|
13377
|
+
"horizontal": false
|
|
13376
13378
|
}
|
|
13377
13379
|
},
|
|
13378
13380
|
"modifiers": {
|
|
@@ -13524,7 +13526,7 @@ const SCREENS = runtimeSetting({
|
|
|
13524
13526
|
"type": "Text",
|
|
13525
13527
|
"props": {
|
|
13526
13528
|
"text": "$item.bodyText",
|
|
13527
|
-
"style": "
|
|
13529
|
+
"style": "caption",
|
|
13528
13530
|
"color": "textOnAccent",
|
|
13529
13531
|
"collapseWhenEmpty": true,
|
|
13530
13532
|
"textDirection": "auto",
|
|
@@ -13549,7 +13551,7 @@ const SCREENS = runtimeSetting({
|
|
|
13549
13551
|
"modifiers": {}
|
|
13550
13552
|
}
|
|
13551
13553
|
],
|
|
13552
|
-
"spacing":
|
|
13554
|
+
"spacing": 5,
|
|
13553
13555
|
"alignment": "leading"
|
|
13554
13556
|
}
|
|
13555
13557
|
},
|
|
@@ -13560,12 +13562,12 @@ const SCREENS = runtimeSetting({
|
|
|
13560
13562
|
},
|
|
13561
13563
|
"cornerRadius": 16,
|
|
13562
13564
|
"padding": {
|
|
13563
|
-
"leading":
|
|
13564
|
-
"trailing":
|
|
13565
|
-
"top":
|
|
13566
|
-
"bottom":
|
|
13565
|
+
"leading": 8,
|
|
13566
|
+
"trailing": 8,
|
|
13567
|
+
"top": 8,
|
|
13568
|
+
"bottom": 8
|
|
13567
13569
|
},
|
|
13568
|
-
"maxWidth":
|
|
13570
|
+
"maxWidth": 300
|
|
13569
13571
|
}
|
|
13570
13572
|
}
|
|
13571
13573
|
],
|
|
@@ -13787,10 +13789,11 @@ const SCREENS = runtimeSetting({
|
|
|
13787
13789
|
"type": "Text",
|
|
13788
13790
|
"props": {
|
|
13789
13791
|
"text": "$item.label",
|
|
13790
|
-
"style": "
|
|
13792
|
+
"style": "caption",
|
|
13791
13793
|
"color": "accentPrimary",
|
|
13792
13794
|
"collapseWhenEmpty": true,
|
|
13793
|
-
"textDirection": "auto"
|
|
13795
|
+
"textDirection": "auto",
|
|
13796
|
+
"maxLines": 1
|
|
13794
13797
|
}
|
|
13795
13798
|
},
|
|
13796
13799
|
"modifiers": {}
|
|
@@ -13801,13 +13804,13 @@ const SCREENS = runtimeSetting({
|
|
|
13801
13804
|
}
|
|
13802
13805
|
},
|
|
13803
13806
|
"modifiers": {
|
|
13804
|
-
"fillMaxWidth":
|
|
13805
|
-
"cornerRadius":
|
|
13807
|
+
"fillMaxWidth": false,
|
|
13808
|
+
"cornerRadius": 12,
|
|
13806
13809
|
"padding": {
|
|
13807
|
-
"leading":
|
|
13808
|
-
"trailing":
|
|
13809
|
-
"top":
|
|
13810
|
-
"bottom":
|
|
13810
|
+
"leading": 10,
|
|
13811
|
+
"trailing": 10,
|
|
13812
|
+
"top": 5,
|
|
13813
|
+
"bottom": 5
|
|
13811
13814
|
},
|
|
13812
13815
|
"background": {
|
|
13813
13816
|
"token": "accentSurface"
|
|
@@ -13837,10 +13840,11 @@ const SCREENS = runtimeSetting({
|
|
|
13837
13840
|
"type": "Text",
|
|
13838
13841
|
"props": {
|
|
13839
13842
|
"text": "$item.label",
|
|
13840
|
-
"style": "
|
|
13843
|
+
"style": "caption",
|
|
13841
13844
|
"color": "textSecondary",
|
|
13842
13845
|
"collapseWhenEmpty": true,
|
|
13843
|
-
"textDirection": "auto"
|
|
13846
|
+
"textDirection": "auto",
|
|
13847
|
+
"maxLines": 1
|
|
13844
13848
|
}
|
|
13845
13849
|
},
|
|
13846
13850
|
"modifiers": {}
|
|
@@ -13851,16 +13855,16 @@ const SCREENS = runtimeSetting({
|
|
|
13851
13855
|
}
|
|
13852
13856
|
},
|
|
13853
13857
|
"modifiers": {
|
|
13854
|
-
"fillMaxWidth":
|
|
13855
|
-
"cornerRadius":
|
|
13858
|
+
"fillMaxWidth": false,
|
|
13859
|
+
"cornerRadius": 12,
|
|
13856
13860
|
"padding": {
|
|
13857
|
-
"leading":
|
|
13858
|
-
"trailing":
|
|
13859
|
-
"top":
|
|
13860
|
-
"bottom":
|
|
13861
|
+
"leading": 10,
|
|
13862
|
+
"trailing": 10,
|
|
13863
|
+
"top": 5,
|
|
13864
|
+
"bottom": 5
|
|
13861
13865
|
},
|
|
13862
13866
|
"background": {
|
|
13863
|
-
"token": "
|
|
13867
|
+
"token": "surfaceSecondary"
|
|
13864
13868
|
},
|
|
13865
13869
|
"hiddenPath": "$item.enabled"
|
|
13866
13870
|
}
|
|
@@ -13871,11 +13875,12 @@ const SCREENS = runtimeSetting({
|
|
|
13871
13875
|
}
|
|
13872
13876
|
},
|
|
13873
13877
|
"modifiers": {
|
|
13874
|
-
"fillMaxWidth":
|
|
13878
|
+
"fillMaxWidth": false
|
|
13875
13879
|
}
|
|
13876
13880
|
}
|
|
13877
13881
|
],
|
|
13878
|
-
"spacing":
|
|
13882
|
+
"spacing": 8,
|
|
13883
|
+
"horizontal": true
|
|
13879
13884
|
}
|
|
13880
13885
|
},
|
|
13881
13886
|
"modifiers": {
|
|
@@ -13891,41 +13896,72 @@ const SCREENS = runtimeSetting({
|
|
|
13891
13896
|
"props": {
|
|
13892
13897
|
"children": [
|
|
13893
13898
|
{
|
|
13894
|
-
"id": "himi_business_chat.
|
|
13899
|
+
"id": "himi_business_chat.draft_shell",
|
|
13895
13900
|
"body": {
|
|
13896
13901
|
"package": "himalaya",
|
|
13897
|
-
"type": "
|
|
13902
|
+
"type": "ZStack",
|
|
13898
13903
|
"props": {
|
|
13899
|
-
"
|
|
13900
|
-
"
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13904
|
+
"alignment": "center",
|
|
13905
|
+
"children": [
|
|
13906
|
+
{
|
|
13907
|
+
"id": "himi_business_chat.draft_outline",
|
|
13908
|
+
"body": {
|
|
13909
|
+
"package": "himalaya",
|
|
13910
|
+
"type": "VStack",
|
|
13911
|
+
"props": {
|
|
13912
|
+
"children": [],
|
|
13913
|
+
"spacing": 0,
|
|
13914
|
+
"alignment": "leading"
|
|
13915
|
+
}
|
|
13916
|
+
},
|
|
13917
|
+
"modifiers": {
|
|
13918
|
+
"fillMaxWidth": true,
|
|
13919
|
+
"height": 40,
|
|
13920
|
+
"background": {
|
|
13921
|
+
"token": "surfacePrimary"
|
|
13922
|
+
},
|
|
13923
|
+
"cornerRadius": 20,
|
|
13924
|
+
"border": {
|
|
13925
|
+
"width": 1,
|
|
13926
|
+
"color": {
|
|
13927
|
+
"token": "border"
|
|
13928
|
+
}
|
|
13929
|
+
}
|
|
13930
|
+
}
|
|
13931
|
+
},
|
|
13932
|
+
{
|
|
13933
|
+
"id": "himi_business_chat.draft",
|
|
13934
|
+
"body": {
|
|
13935
|
+
"package": "himalaya",
|
|
13936
|
+
"type": "TextField",
|
|
13937
|
+
"props": {
|
|
13938
|
+
"valuePath": "$service:businessChat.draft",
|
|
13939
|
+
"onChange": {
|
|
13940
|
+
"actionId": "tier5.businessChat.setDraft"
|
|
13941
|
+
},
|
|
13942
|
+
"placeholder": "Type your message…",
|
|
13943
|
+
"maxLength": 4000,
|
|
13944
|
+
"multilineMaxLines": 1,
|
|
13945
|
+
"borderless": true
|
|
13946
|
+
}
|
|
13947
|
+
},
|
|
13948
|
+
"modifiers": {
|
|
13949
|
+
"fillMaxWidth": true,
|
|
13950
|
+
"accessibilityLabel": "Type your message",
|
|
13951
|
+
"padding": {
|
|
13952
|
+
"leading": 8,
|
|
13953
|
+
"trailing": 8,
|
|
13954
|
+
"top": 0,
|
|
13955
|
+
"bottom": 0
|
|
13956
|
+
}
|
|
13957
|
+
}
|
|
13958
|
+
}
|
|
13959
|
+
]
|
|
13907
13960
|
}
|
|
13908
13961
|
},
|
|
13909
13962
|
"modifiers": {
|
|
13910
13963
|
"weight": 1,
|
|
13911
|
-
"fillMaxWidth": true
|
|
13912
|
-
"accessibilityLabel": "Type your message",
|
|
13913
|
-
"padding": {
|
|
13914
|
-
"leading": 12,
|
|
13915
|
-
"trailing": 10,
|
|
13916
|
-
"top": 2,
|
|
13917
|
-
"bottom": 2
|
|
13918
|
-
},
|
|
13919
|
-
"background": {
|
|
13920
|
-
"token": "surfacePrimary"
|
|
13921
|
-
},
|
|
13922
|
-
"cornerRadius": 22,
|
|
13923
|
-
"border": {
|
|
13924
|
-
"width": 1,
|
|
13925
|
-
"color": {
|
|
13926
|
-
"token": "border"
|
|
13927
|
-
}
|
|
13928
|
-
}
|
|
13964
|
+
"fillMaxWidth": true
|
|
13929
13965
|
}
|
|
13930
13966
|
},
|
|
13931
13967
|
{
|
|
@@ -13992,16 +14028,22 @@ const SCREENS = runtimeSetting({
|
|
|
13992
14028
|
}
|
|
13993
14029
|
}
|
|
13994
14030
|
],
|
|
13995
|
-
"spacing":
|
|
14031
|
+
"spacing": 6,
|
|
13996
14032
|
"alignment": "center"
|
|
13997
14033
|
}
|
|
13998
14034
|
},
|
|
13999
14035
|
"modifiers": {
|
|
14000
|
-
"fillMaxWidth": true
|
|
14036
|
+
"fillMaxWidth": true,
|
|
14037
|
+
"padding": {
|
|
14038
|
+
"leading": 8,
|
|
14039
|
+
"trailing": 8,
|
|
14040
|
+
"top": 0,
|
|
14041
|
+
"bottom": 0
|
|
14042
|
+
}
|
|
14001
14043
|
}
|
|
14002
14044
|
}
|
|
14003
14045
|
],
|
|
14004
|
-
"spacing":
|
|
14046
|
+
"spacing": 0,
|
|
14005
14047
|
"alignment": "leading"
|
|
14006
14048
|
}
|
|
14007
14049
|
},
|
|
@@ -14012,10 +14054,10 @@ const SCREENS = runtimeSetting({
|
|
|
14012
14054
|
"token": "surfacePrimary"
|
|
14013
14055
|
},
|
|
14014
14056
|
"padding": {
|
|
14015
|
-
"leading":
|
|
14016
|
-
"trailing":
|
|
14017
|
-
"top":
|
|
14018
|
-
"bottom":
|
|
14057
|
+
"leading": 0,
|
|
14058
|
+
"trailing": 0,
|
|
14059
|
+
"top": 4,
|
|
14060
|
+
"bottom": 0
|
|
14019
14061
|
}
|
|
14020
14062
|
}
|
|
14021
14063
|
},
|
|
@@ -97,6 +97,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
|
|
|
97
97
|
himi_gift_card: ["giftCards"],
|
|
98
98
|
himi_gift_cards: ["giftCards"],
|
|
99
99
|
himi_groups: ["groups"],
|
|
100
|
+
himi_inbox: ["inbox"],
|
|
100
101
|
himi_group_about: ["groups"],
|
|
101
102
|
himi_my_groups: ["groups"],
|
|
102
103
|
himi_invoice: ["invoices"],
|
|
@@ -27,7 +27,10 @@ export function smartChatHistory(aiMessages: unknown[], memberPage: unknown[], p
|
|
|
27
27
|
const mine = sender === 'SITE_VISITOR' && VISITOR_TYPES.has(kind);
|
|
28
28
|
if (!mine && !(sender === 'ASSISTANT' && ASSISTANT_TYPES.has(kind)) && !(sender === 'USER' && STAFF_TYPES.has(kind))) continue;
|
|
29
29
|
const body = object(message.body);
|
|
30
|
-
const
|
|
30
|
+
const selectedAction = kind === 'VISITOR_OPTION_SELECTED' && Array.isArray(body.additionalData)
|
|
31
|
+
? body.additionalData.map(object).find(part => part.type === 'select_option' && text(part.action).trim())?.action
|
|
32
|
+
: '';
|
|
33
|
+
const bodyText = [text(body.mainText) || text(selectedAction), text(body.footerText)].filter(Boolean).join('\n');
|
|
31
34
|
const rich = memberRows.get(text(message.inboxId));
|
|
32
35
|
// A quick-reply-only metadata answer is not an empty bubble (the options are shown by the composer).
|
|
33
36
|
if (!bodyText && !rich) continue;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isBusinessRoom } from "./inbox-rooms.js";
|
|
1
2
|
import { businessChatCopy } from "./business-chat-copy.js";
|
|
2
3
|
import { formatMonthDay } from "./engine-intl.js";
|
|
3
4
|
type RecordValue = Record<string, unknown>;
|
|
@@ -78,13 +79,7 @@ const object = (value: unknown): RecordValue =>
|
|
|
78
79
|
/** Return a sole existing two-party business room, or a unique business-name match among several;
|
|
79
80
|
* never create a room or guess among remaining matches. */
|
|
80
81
|
export function selectExistingBusinessRoom(rooms: unknown[], businessName?: string, requireUnambiguous = false): { id: string; participantId: string } | undefined {
|
|
81
|
-
let candidates = rooms.filter(
|
|
82
|
-
const room = object(value);
|
|
83
|
-
return typeof room.id === "string" && !!room.id &&
|
|
84
|
-
typeof room.participantId === "string" && !!room.participantId &&
|
|
85
|
-
room.participantCount === 2 && room.clientReferenceType === "contactId" &&
|
|
86
|
-
Object.keys(object(room.businessContext)).length > 0;
|
|
87
|
-
});
|
|
82
|
+
let candidates = rooms.filter(isBusinessRoom);
|
|
88
83
|
const candidateCount = candidates.length;
|
|
89
84
|
if (candidateCount > 1 && businessName?.trim()) {
|
|
90
85
|
// Keep case significant so differently named businesses are not conflated.
|