@wix/himalaya-cli 0.1525.0 → 0.1526.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/builder.d.ts +14 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +22 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/worker-subtree-safe-types.generated.d.ts +4 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +7 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +13 -0
- package/dist/cli.mjs +137 -39
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/designing-himi-screens.md +43 -18
- package/guides/recipe-dynamic-list.md +7 -7
- package/guides/recipe-four-state.md +47 -41
- package/guides/recipe-search.md +1 -1
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +69 -40
- package/templates/beauty-salon/tier5-src/himi-branded-lite-agenda/index.ts +9 -1
- package/templates/beauty-salon/tier5-src/himi-branded-lite-place-summary/index.ts +12 -1
- package/templates/beauty-salon/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/branded-lite/dev/index.ts +165 -88
- package/templates/branded-lite/tier5-src/business-chat/index.ts +4 -0
- package/templates/branded-lite/tier5-src/himi-branded-lite-agenda/index.ts +9 -1
- package/templates/branded-lite/tier5-src/himi-branded-lite-place-summary/index.ts +12 -1
- package/templates/branded-lite/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/community-club/dev/index.ts +40 -21
- package/templates/community-club/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/events-meetups/dev/index.ts +36 -19
- package/templates/events-meetups/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/gym-fitness/dev/index.ts +73 -42
- package/templates/gym-fitness/tier5-src/himi-branded-lite-agenda/index.ts +9 -1
- package/templates/gym-fitness/tier5-src/himi-branded-lite-place-summary/index.ts +12 -1
- package/templates/gym-fitness/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/nonprofit-cause/dev/index.ts +47 -29
- package/templates/nonprofit-cause/tier5-src/himi-branded-lite-place-summary/index.ts +12 -1
- package/templates/nonprofit-cause/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/podcast-creator/dev/index.ts +47 -29
- package/templates/podcast-creator/tier5-src/himi-branded-lite-place-summary/index.ts +12 -1
- package/templates/podcast-creator/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/portfolio-creative/dev/index.ts +52 -27
- package/templates/portfolio-creative/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/restaurant/dev/index.ts +48 -25
- package/templates/restaurant/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/retail-store/dev/index.ts +44 -23
- package/templates/retail-store/tier5-src/himi-store-account/index.ts +69 -10
- package/templates/yoga-studio/dev/index.ts +57 -34
- package/templates/yoga-studio/tier5-src/himi-branded-lite-agenda/index.ts +9 -1
- package/templates/yoga-studio/tier5-src/himi-branded-lite-place-summary/index.ts +12 -1
- package/templates/yoga-studio/tier5-src/himi-store-account/index.ts +69 -10
|
@@ -2085,8 +2085,10 @@ const SCREENS = runtimeSetting({
|
|
|
2085
2085
|
"actionId": "himi.open",
|
|
2086
2086
|
"params": {
|
|
2087
2087
|
"screenId": "himi_sign_in",
|
|
2088
|
-
"mode": "signin"
|
|
2089
|
-
|
|
2088
|
+
"mode": "signin",
|
|
2089
|
+
"modal": "1"
|
|
2090
|
+
},
|
|
2091
|
+
"presentation": "sheet"
|
|
2090
2092
|
}
|
|
2091
2093
|
}
|
|
2092
2094
|
}
|
|
@@ -2104,8 +2106,10 @@ const SCREENS = runtimeSetting({
|
|
|
2104
2106
|
"actionId": "himi.open",
|
|
2105
2107
|
"params": {
|
|
2106
2108
|
"screenId": "himi_sign_in",
|
|
2107
|
-
"mode": "register"
|
|
2108
|
-
|
|
2109
|
+
"mode": "register",
|
|
2110
|
+
"modal": "1"
|
|
2111
|
+
},
|
|
2112
|
+
"presentation": "sheet"
|
|
2109
2113
|
}
|
|
2110
2114
|
}
|
|
2111
2115
|
}
|
|
@@ -3307,6 +3311,8 @@ const SCREENS = runtimeSetting({
|
|
|
3307
3311
|
"memberAccountLinks": "1",
|
|
3308
3312
|
"restorePurchases": "1",
|
|
3309
3313
|
"signInScreen": "himi_sign_in",
|
|
3314
|
+
"signInPresentation": "sheet",
|
|
3315
|
+
"signInReturnTab": "profile",
|
|
3310
3316
|
"pollIdentity": "1",
|
|
3311
3317
|
"copy": "{\"account.subtitle\":\"Reservations, RSVPs and saved content in one place.\",\"storeAccount.authBody\":\"Sign in to continue — reservations and RSVPs stay with you.\",\"storeAccount.authBodyRegister\":\"Create a member account to continue — reservations and RSVPs stay with you.\"}"
|
|
3312
3318
|
}
|
|
@@ -3562,8 +3568,10 @@ const SCREENS = runtimeSetting({
|
|
|
3562
3568
|
"params": {
|
|
3563
3569
|
"screenId": "himi_sign_in",
|
|
3564
3570
|
"mode": "signin",
|
|
3565
|
-
"returnScreenId": "himi_account_settings"
|
|
3566
|
-
|
|
3571
|
+
"returnScreenId": "himi_account_settings",
|
|
3572
|
+
"modal": "1"
|
|
3573
|
+
},
|
|
3574
|
+
"presentation": "sheet"
|
|
3567
3575
|
}
|
|
3568
3576
|
}
|
|
3569
3577
|
},
|
|
@@ -5473,8 +5481,7 @@ const SCREENS = runtimeSetting({
|
|
|
5473
5481
|
"style": "primary",
|
|
5474
5482
|
"fullWidth": true,
|
|
5475
5483
|
"action": {
|
|
5476
|
-
"actionId": "
|
|
5477
|
-
"presentation": "back"
|
|
5484
|
+
"actionId": "tier5.himiStoreAccount.leave"
|
|
5478
5485
|
}
|
|
5479
5486
|
}
|
|
5480
5487
|
}
|
|
@@ -5515,7 +5522,7 @@ const SCREENS = runtimeSetting({
|
|
|
5515
5522
|
"declaredCapabilities": [
|
|
5516
5523
|
"wix_api"
|
|
5517
5524
|
],
|
|
5518
|
-
"minBinaryVersion": "
|
|
5525
|
+
"minBinaryVersion": "1.7.0",
|
|
5519
5526
|
"bundleVersion": "0.0.1"
|
|
5520
5527
|
}
|
|
5521
5528
|
},
|
|
@@ -6382,8 +6389,10 @@ const SCREENS = runtimeSetting({
|
|
|
6382
6389
|
"screenId": "himi_sign_in",
|
|
6383
6390
|
"mode": "signin",
|
|
6384
6391
|
"intent": "profile",
|
|
6385
|
-
"returnScreenId": "himi_view_profile"
|
|
6386
|
-
|
|
6392
|
+
"returnScreenId": "himi_view_profile",
|
|
6393
|
+
"modal": "1"
|
|
6394
|
+
},
|
|
6395
|
+
"presentation": "sheet"
|
|
6387
6396
|
}
|
|
6388
6397
|
}
|
|
6389
6398
|
}
|
|
@@ -7482,8 +7491,10 @@ const SCREENS = runtimeSetting({
|
|
|
7482
7491
|
"screenId": "himi_sign_in",
|
|
7483
7492
|
"mode": "signin",
|
|
7484
7493
|
"intent": "addresses",
|
|
7485
|
-
"returnScreenId": "himi_addresses"
|
|
7486
|
-
|
|
7494
|
+
"returnScreenId": "himi_addresses",
|
|
7495
|
+
"modal": "1"
|
|
7496
|
+
},
|
|
7497
|
+
"presentation": "sheet"
|
|
7487
7498
|
}
|
|
7488
7499
|
}
|
|
7489
7500
|
}
|
|
@@ -8539,8 +8550,10 @@ const SCREENS = runtimeSetting({
|
|
|
8539
8550
|
"screenId": "himi_sign_in",
|
|
8540
8551
|
"mode": "signin",
|
|
8541
8552
|
"intent": "addresses",
|
|
8542
|
-
"returnScreenId": "himi_address"
|
|
8543
|
-
|
|
8553
|
+
"returnScreenId": "himi_address",
|
|
8554
|
+
"modal": "1"
|
|
8555
|
+
},
|
|
8556
|
+
"presentation": "sheet"
|
|
8544
8557
|
}
|
|
8545
8558
|
}
|
|
8546
8559
|
}
|
|
@@ -9210,8 +9223,10 @@ const SCREENS = runtimeSetting({
|
|
|
9210
9223
|
"screenId": "himi_sign_in",
|
|
9211
9224
|
"mode": "signin",
|
|
9212
9225
|
"intent": "wallet",
|
|
9213
|
-
"returnScreenId": "himi_wallet"
|
|
9214
|
-
|
|
9226
|
+
"returnScreenId": "himi_wallet",
|
|
9227
|
+
"modal": "1"
|
|
9228
|
+
},
|
|
9229
|
+
"presentation": "sheet"
|
|
9215
9230
|
}
|
|
9216
9231
|
}
|
|
9217
9232
|
}
|
|
@@ -12432,8 +12447,10 @@ const SCREENS = runtimeSetting({
|
|
|
12432
12447
|
"screenId": "himi_sign_in",
|
|
12433
12448
|
"mode": "signin",
|
|
12434
12449
|
"intent": "post",
|
|
12435
|
-
"returnScreenId": "himi_create_post"
|
|
12436
|
-
|
|
12450
|
+
"returnScreenId": "himi_create_post",
|
|
12451
|
+
"modal": "1"
|
|
12452
|
+
},
|
|
12453
|
+
"presentation": "sheet"
|
|
12437
12454
|
}
|
|
12438
12455
|
}
|
|
12439
12456
|
}
|
|
@@ -19464,8 +19481,10 @@ const SCREENS = runtimeSetting({
|
|
|
19464
19481
|
"params": {
|
|
19465
19482
|
"screenId": "himi_sign_in",
|
|
19466
19483
|
"intent": "food-orders",
|
|
19467
|
-
"returnScreenId": "himi_food_orders"
|
|
19468
|
-
|
|
19484
|
+
"returnScreenId": "himi_food_orders",
|
|
19485
|
+
"modal": "1"
|
|
19486
|
+
},
|
|
19487
|
+
"presentation": "sheet"
|
|
19469
19488
|
}
|
|
19470
19489
|
}
|
|
19471
19490
|
}
|
|
@@ -20643,8 +20662,10 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
20643
20662
|
"screenId": "himi_sign_in",
|
|
20644
20663
|
"intent": "basket",
|
|
20645
20664
|
"returnScreenId": "himi_menu_item",
|
|
20646
|
-
"returnId": "$service:himiBrandedMenuItem.id"
|
|
20647
|
-
|
|
20665
|
+
"returnId": "$service:himiBrandedMenuItem.id",
|
|
20666
|
+
"modal": "1"
|
|
20667
|
+
},
|
|
20668
|
+
"presentation": "sheet"
|
|
20648
20669
|
},
|
|
20649
20670
|
"leadingIcon": "person"
|
|
20650
20671
|
}
|
|
@@ -22569,8 +22590,10 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
22569
22590
|
"params": {
|
|
22570
22591
|
"screenId": "himi_sign_in",
|
|
22571
22592
|
"mode": "signin",
|
|
22572
|
-
"intent": "rsvp"
|
|
22573
|
-
|
|
22593
|
+
"intent": "rsvp",
|
|
22594
|
+
"modal": "1"
|
|
22595
|
+
},
|
|
22596
|
+
"presentation": "sheet"
|
|
22574
22597
|
}
|
|
22575
22598
|
}
|
|
22576
22599
|
},
|
|
@@ -26,6 +26,10 @@ interface AuthRouteInput {
|
|
|
26
26
|
returnScreenId?: string;
|
|
27
27
|
returnId?: string;
|
|
28
28
|
returnChannelId?: string;
|
|
29
|
+
/** Standalone sign-in only: "1" when it was opened as a modal (sheet / cover). */
|
|
30
|
+
modal?: string;
|
|
31
|
+
/** Modal only: the tab whose stack the return screen opens on once the modal closes. */
|
|
32
|
+
returnTab?: string;
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
// The screen's boot input survives refresh; consuming it must survive too.
|
|
@@ -61,6 +65,12 @@ function authIntentFromArg(arg: unknown, prev: Pick<S, "authIntent" | "authConte
|
|
|
61
65
|
};
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
/** How the standalone form leaves. A modal is closed: on web `back` pops the tab's stack,
|
|
69
|
+
* not the modal. A pushed form goes back. */
|
|
70
|
+
function leaveNav(): "dismiss" | "back" {
|
|
71
|
+
return routeInput().modal === "1" ? "dismiss" : "back";
|
|
72
|
+
}
|
|
73
|
+
|
|
64
74
|
/** Where a successful sign-in returns to, or null. Never Account itself — that would
|
|
65
75
|
* only push a second copy of the screen the member is already on. */
|
|
66
76
|
function resumeTarget(s: Pick<S, "returnScreenId" | "returnId" | "returnChannelId">): { screenId: string; args?: Record<string, string> } | null {
|
|
@@ -78,11 +88,26 @@ function resumeTarget(s: Pick<S, "returnScreenId" | "returnId" | "returnChannelI
|
|
|
78
88
|
* On the standalone sign-in screen the target is pushed, not a `replace`: on iOS and
|
|
79
89
|
* Android `replace` resets the stack to its root, which would drop the screens the
|
|
80
90
|
* visitor came through. Back from the target shows the form again, and the form sends a
|
|
81
|
-
* member back on appear (settle). With no target the form goes back.
|
|
91
|
+
* member back on appear (settle). With no target the form goes back.
|
|
92
|
+
*
|
|
93
|
+
* A modal form closes. A target pushed from here would open inside the modal (iOS, Android)
|
|
94
|
+
* or under it (web), so a modal that names a `returnTab` hands the target to that tab: the
|
|
95
|
+
* host closes the modal, then pushes it on that tab's stack (Account's member rows). A host
|
|
96
|
+
* showing no such tab (a drawer, a narrow Mac window) drops that request whole, modal and
|
|
97
|
+
* all, so the modal is also dismissed directly: it always closes, and the row opens where
|
|
98
|
+
* the tab exists. With no `returnTab` it only closes, and the screen under it loads again —
|
|
99
|
+
* the screen that opened the modal is the return target. */
|
|
82
100
|
function resumeAfterAuth(next: S): S {
|
|
83
101
|
const target = resumeTarget(next);
|
|
84
102
|
if (!next.isMember) return next;
|
|
85
|
-
|
|
103
|
+
const tab = routeInput().modal === "1" ? routeInput().returnTab ?? "" : "";
|
|
104
|
+
if (target && tab && next.standalone) {
|
|
105
|
+
routeInputConsumed = true;
|
|
106
|
+
void dispatch("himi.open", { presentation: "dismiss" });
|
|
107
|
+
const cleared = derive({ ...next, authIntent: "", authContextName: "", returnScreenId: "", returnId: "", returnChannelId: "" });
|
|
108
|
+
return navigate(cleared, target.args ? { tab, screenId: target.screenId, args: target.args } : { tab, screenId: target.screenId });
|
|
109
|
+
}
|
|
110
|
+
if (!target || routeInput().modal === "1") return next.standalone ? navigate(next, { presentation: leaveNav() }) : next;
|
|
86
111
|
routeInputConsumed = true;
|
|
87
112
|
const cleared = derive({ ...next, authIntent: "", authContextName: "", returnScreenId: "", returnId: "", returnChannelId: "" });
|
|
88
113
|
return navigate(cleared, target);
|
|
@@ -96,11 +121,31 @@ function forwardToSignIn(next: S): S {
|
|
|
96
121
|
if (!next.authIntent && !next.returnScreenId) return next;
|
|
97
122
|
routeInputConsumed = true;
|
|
98
123
|
const args: Record<string, string> = { mode: "signin" };
|
|
99
|
-
for (const key of ["authIntent", "authContextName"
|
|
100
|
-
if (next[key]) args[key === "authIntent" ? "intent" :
|
|
124
|
+
for (const key of ["authIntent", "authContextName"] as const) {
|
|
125
|
+
if (next[key]) args[key === "authIntent" ? "intent" : "contextName"] = next[key];
|
|
126
|
+
}
|
|
127
|
+
return openSignIn(derive({ ...next, authIntent: "", authContextName: "", returnScreenId: "", returnId: "", returnChannelId: "" }),
|
|
128
|
+
args, resumeTarget(next));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Account sends a guest to the standalone sign-in screen, with `after`, the member screen to
|
|
132
|
+
* open once signed in. With a `signInPresentation` appear param it opens as that modal, and
|
|
133
|
+
* `after` goes on Account's own tab (`signInReturnTab`) when the modal closes; pushed, the form
|
|
134
|
+
* pushes `after` itself (resumeAfterAuth). */
|
|
135
|
+
function openSignIn(next: S, args: Record<string, string>, after: { screenId: string; args?: Record<string, string> } | null): S {
|
|
136
|
+
const screenId = next.signInScreen || "himi_sign_in";
|
|
137
|
+
const presentation = signInPresentationRequested;
|
|
138
|
+
const back: Record<string, string> = {};
|
|
139
|
+
if (after) {
|
|
140
|
+
back.returnScreenId = after.screenId;
|
|
141
|
+
if (after.args?.id) back.returnId = after.args.id;
|
|
142
|
+
if (after.args?.channelId) back.returnChannelId = after.args.channelId;
|
|
101
143
|
}
|
|
102
|
-
return navigate(
|
|
103
|
-
|
|
144
|
+
if (!presentation) return navigate(next, { screenId, args: { ...args, ...back } });
|
|
145
|
+
const modalArgs: Record<string, string> = { ...args, modal: "1" };
|
|
146
|
+
// With no tab to open it on, a modal has no way to the member screen: it only closes.
|
|
147
|
+
if (after && signInReturnTabRequested) Object.assign(modalArgs, back, { returnTab: signInReturnTabRequested });
|
|
148
|
+
return navigate(next, { screenId, presentation, args: modalArgs });
|
|
104
149
|
}
|
|
105
150
|
|
|
106
151
|
/** After a load: the standalone sign-in screen sends a member back (a stale link, or a
|
|
@@ -128,8 +173,11 @@ function settle(next: S, arg: unknown, latest = true): S {
|
|
|
128
173
|
// The appear refresh returns `_nav`, which every host applies — binaries from before
|
|
129
174
|
// worker nav dispatch included. Only an arg-less load, whose result iOS
|
|
130
175
|
// discards, dispatches.
|
|
131
|
-
if (strField(arg, "standalone") === "1") return navigate(cleared, { presentation:
|
|
132
|
-
|
|
176
|
+
if (strField(arg, "standalone") === "1") return navigate(cleared, { presentation: leaveNav() });
|
|
177
|
+
// Not from a modal: nothing pushed over it comes back to it, and on iOS the closing modal's
|
|
178
|
+
// own screen reloads here once, after it has asked to close — a late dismiss would close
|
|
179
|
+
// whatever modal is open by then.
|
|
180
|
+
if (routeInput().modal !== "1") void dispatch("himi.open", { presentation: leaveNav() });
|
|
133
181
|
return cleared;
|
|
134
182
|
}
|
|
135
183
|
// Account forwards only on an appear refresh: the boot `load()` has no params and its
|
|
@@ -180,6 +228,10 @@ let appliedSeq = 0;
|
|
|
180
228
|
// The appear params belong to the worker session too, like the two flags above: a probe
|
|
181
229
|
// dropped because the visitor typed must not take them with it.
|
|
182
230
|
let signInScreenRequested = "";
|
|
231
|
+
/** Account only: how it opens the standalone sign-in screen ("" = push). */
|
|
232
|
+
let signInPresentationRequested: "" | "sheet" | "full_screen" = "";
|
|
233
|
+
/** Account only: its tab, where a member screen opens after a modal sign-in. */
|
|
234
|
+
let signInReturnTabRequested = "";
|
|
183
235
|
let standaloneRequested = false;
|
|
184
236
|
let pollIdentityRequested = false;
|
|
185
237
|
// Bumped by every mode switch, so a dropped probe never puts back a mode the visitor left.
|
|
@@ -210,6 +262,9 @@ function appearConfig(s: S, arg: unknown): AppearConfig {
|
|
|
210
262
|
passwordDraft = "";
|
|
211
263
|
}
|
|
212
264
|
signInScreenRequested ||= strField(arg, "signInScreen") || s.signInScreen;
|
|
265
|
+
const presentation = strField(arg, "signInPresentation");
|
|
266
|
+
if (presentation === "sheet" || presentation === "full_screen") signInPresentationRequested = presentation;
|
|
267
|
+
signInReturnTabRequested ||= strField(arg, "signInReturnTab");
|
|
213
268
|
// Only the sign-in screen's route carries `mode`, so it marks the form from the boot load on.
|
|
214
269
|
standaloneRequested ||= s.standalone || appearing || (!routeInputConsumed && !!routeInput().mode);
|
|
215
270
|
pollIdentityRequested ||= s.pollIdentity || strField(arg, "pollIdentity") === "1";
|
|
@@ -676,6 +731,7 @@ const svc = defineService<S, {
|
|
|
676
731
|
signOut: (s: S) => Promise<S>;
|
|
677
732
|
sync: (s: S) => Promise<S | undefined>;
|
|
678
733
|
openMember: (s: S, arg?: unknown) => Promise<S>;
|
|
734
|
+
leave: (s: S) => S;
|
|
679
735
|
restorePublish: (s: S) => S;
|
|
680
736
|
iapRestore: (s: S) => Promise<undefined>;
|
|
681
737
|
}>("himiStoreAccount", {
|
|
@@ -756,7 +812,8 @@ const svc = defineService<S, {
|
|
|
756
812
|
return "next" in r ? r.next : undefined;
|
|
757
813
|
},
|
|
758
814
|
// A row to a member-only screen shows to a guest too. A member opens it; a guest signs
|
|
759
|
-
// in first and the sign-in screen
|
|
815
|
+
// in first, and the sign-in screen then opens the row's screen — as a modal, by closing
|
|
816
|
+
// and pushing it on this tab (openSignIn) — so Back returns here either way.
|
|
760
817
|
openMember: async (s, arg): Promise<S> => {
|
|
761
818
|
const screenId = strField(arg, "screenId");
|
|
762
819
|
if (!screenId) return s;
|
|
@@ -764,8 +821,10 @@ const svc = defineService<S, {
|
|
|
764
821
|
// From the state as it is now: a probe may have landed during the identity read.
|
|
765
822
|
const now = svc.getState();
|
|
766
823
|
if (member) return navigate(now, { screenId });
|
|
767
|
-
return
|
|
824
|
+
return openSignIn(now, { mode: "signin" }, { screenId });
|
|
768
825
|
},
|
|
826
|
+
// The standalone form's Continue: leaves the form the way it was opened.
|
|
827
|
+
leave: (s) => navigate(s, { presentation: leaveNav() }),
|
|
769
828
|
// Typing means any focus request was delivered: clear the tokens (safe while mounted, since
|
|
770
829
|
// bumpToken never repeats), so a visit rarely ends — and a pooled form rarely reopens —
|
|
771
830
|
// holding one.
|
|
@@ -1723,8 +1723,10 @@ const SCREENS = runtimeSetting({
|
|
|
1723
1723
|
"actionId": "himi.open",
|
|
1724
1724
|
"params": {
|
|
1725
1725
|
"screenId": "himi_sign_in",
|
|
1726
|
-
"mode": "signin"
|
|
1727
|
-
|
|
1726
|
+
"mode": "signin",
|
|
1727
|
+
"modal": "1"
|
|
1728
|
+
},
|
|
1729
|
+
"presentation": "sheet"
|
|
1728
1730
|
}
|
|
1729
1731
|
}
|
|
1730
1732
|
}
|
|
@@ -1742,8 +1744,10 @@ const SCREENS = runtimeSetting({
|
|
|
1742
1744
|
"actionId": "himi.open",
|
|
1743
1745
|
"params": {
|
|
1744
1746
|
"screenId": "himi_sign_in",
|
|
1745
|
-
"mode": "register"
|
|
1746
|
-
|
|
1747
|
+
"mode": "register",
|
|
1748
|
+
"modal": "1"
|
|
1749
|
+
},
|
|
1750
|
+
"presentation": "sheet"
|
|
1747
1751
|
}
|
|
1748
1752
|
}
|
|
1749
1753
|
}
|
|
@@ -2864,6 +2868,8 @@ const SCREENS = runtimeSetting({
|
|
|
2864
2868
|
"memberAccountLinks": "1",
|
|
2865
2869
|
"restorePurchases": "1",
|
|
2866
2870
|
"signInScreen": "himi_sign_in",
|
|
2871
|
+
"signInPresentation": "sheet",
|
|
2872
|
+
"signInReturnTab": "profile",
|
|
2867
2873
|
"pollIdentity": "1",
|
|
2868
2874
|
"cartCount": "1",
|
|
2869
2875
|
"copy": "{\"account.subtitle\":\"Orders and saved content in one place.\",\"storeAccount.authBody\":\"Sign in to continue — your cart stays with you.\",\"storeAccount.authBodyRegister\":\"Create a member account to continue — your cart stays with you.\"}"
|
|
@@ -3139,8 +3145,10 @@ const SCREENS = runtimeSetting({
|
|
|
3139
3145
|
"params": {
|
|
3140
3146
|
"screenId": "himi_sign_in",
|
|
3141
3147
|
"mode": "signin",
|
|
3142
|
-
"returnScreenId": "himi_account_settings"
|
|
3143
|
-
|
|
3148
|
+
"returnScreenId": "himi_account_settings",
|
|
3149
|
+
"modal": "1"
|
|
3150
|
+
},
|
|
3151
|
+
"presentation": "sheet"
|
|
3144
3152
|
}
|
|
3145
3153
|
}
|
|
3146
3154
|
},
|
|
@@ -5050,8 +5058,7 @@ const SCREENS = runtimeSetting({
|
|
|
5050
5058
|
"style": "primary",
|
|
5051
5059
|
"fullWidth": true,
|
|
5052
5060
|
"action": {
|
|
5053
|
-
"actionId": "
|
|
5054
|
-
"presentation": "back"
|
|
5061
|
+
"actionId": "tier5.himiStoreAccount.leave"
|
|
5055
5062
|
}
|
|
5056
5063
|
}
|
|
5057
5064
|
}
|
|
@@ -5092,7 +5099,7 @@ const SCREENS = runtimeSetting({
|
|
|
5092
5099
|
"declaredCapabilities": [
|
|
5093
5100
|
"wix_api"
|
|
5094
5101
|
],
|
|
5095
|
-
"minBinaryVersion": "
|
|
5102
|
+
"minBinaryVersion": "1.7.0",
|
|
5096
5103
|
"bundleVersion": "0.0.1"
|
|
5097
5104
|
}
|
|
5098
5105
|
},
|
|
@@ -5959,8 +5966,10 @@ const SCREENS = runtimeSetting({
|
|
|
5959
5966
|
"screenId": "himi_sign_in",
|
|
5960
5967
|
"mode": "signin",
|
|
5961
5968
|
"intent": "profile",
|
|
5962
|
-
"returnScreenId": "himi_view_profile"
|
|
5963
|
-
|
|
5969
|
+
"returnScreenId": "himi_view_profile",
|
|
5970
|
+
"modal": "1"
|
|
5971
|
+
},
|
|
5972
|
+
"presentation": "sheet"
|
|
5964
5973
|
}
|
|
5965
5974
|
}
|
|
5966
5975
|
}
|
|
@@ -14783,8 +14792,10 @@ const SCREENS = runtimeSetting({
|
|
|
14783
14792
|
"screenId": "himi_sign_in",
|
|
14784
14793
|
"mode": "signin",
|
|
14785
14794
|
"intent": "orders",
|
|
14786
|
-
"returnScreenId": "himi_orders"
|
|
14787
|
-
|
|
14795
|
+
"returnScreenId": "himi_orders",
|
|
14796
|
+
"modal": "1"
|
|
14797
|
+
},
|
|
14798
|
+
"presentation": "sheet"
|
|
14788
14799
|
}
|
|
14789
14800
|
}
|
|
14790
14801
|
}
|
|
@@ -15417,8 +15428,10 @@ const SCREENS = runtimeSetting({
|
|
|
15417
15428
|
"screenId": "himi_sign_in",
|
|
15418
15429
|
"mode": "signin",
|
|
15419
15430
|
"intent": "addresses",
|
|
15420
|
-
"returnScreenId": "himi_addresses"
|
|
15421
|
-
|
|
15431
|
+
"returnScreenId": "himi_addresses",
|
|
15432
|
+
"modal": "1"
|
|
15433
|
+
},
|
|
15434
|
+
"presentation": "sheet"
|
|
15422
15435
|
}
|
|
15423
15436
|
}
|
|
15424
15437
|
}
|
|
@@ -16474,8 +16487,10 @@ const SCREENS = runtimeSetting({
|
|
|
16474
16487
|
"screenId": "himi_sign_in",
|
|
16475
16488
|
"mode": "signin",
|
|
16476
16489
|
"intent": "addresses",
|
|
16477
|
-
"returnScreenId": "himi_address"
|
|
16478
|
-
|
|
16490
|
+
"returnScreenId": "himi_address",
|
|
16491
|
+
"modal": "1"
|
|
16492
|
+
},
|
|
16493
|
+
"presentation": "sheet"
|
|
16479
16494
|
}
|
|
16480
16495
|
}
|
|
16481
16496
|
}
|
|
@@ -17145,8 +17160,10 @@ const SCREENS = runtimeSetting({
|
|
|
17145
17160
|
"screenId": "himi_sign_in",
|
|
17146
17161
|
"mode": "signin",
|
|
17147
17162
|
"intent": "wallet",
|
|
17148
|
-
"returnScreenId": "himi_wallet"
|
|
17149
|
-
|
|
17163
|
+
"returnScreenId": "himi_wallet",
|
|
17164
|
+
"modal": "1"
|
|
17165
|
+
},
|
|
17166
|
+
"presentation": "sheet"
|
|
17150
17167
|
}
|
|
17151
17168
|
}
|
|
17152
17169
|
}
|
|
@@ -17367,8 +17384,10 @@ const SCREENS = runtimeSetting({
|
|
|
17367
17384
|
"screenId": "himi_sign_in",
|
|
17368
17385
|
"mode": "signin",
|
|
17369
17386
|
"intent": "post",
|
|
17370
|
-
"returnScreenId": "himi_create_post"
|
|
17371
|
-
|
|
17387
|
+
"returnScreenId": "himi_create_post",
|
|
17388
|
+
"modal": "1"
|
|
17389
|
+
},
|
|
17390
|
+
"presentation": "sheet"
|
|
17372
17391
|
}
|
|
17373
17392
|
}
|
|
17374
17393
|
}
|
|
@@ -21602,8 +21621,10 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
21602
21621
|
"params": {
|
|
21603
21622
|
"screenId": "himi_sign_in",
|
|
21604
21623
|
"returnScreenId": "himi_order",
|
|
21605
|
-
"returnId": "$service:himiBrandedOrder.id"
|
|
21606
|
-
|
|
21624
|
+
"returnId": "$service:himiBrandedOrder.id",
|
|
21625
|
+
"modal": "1"
|
|
21626
|
+
},
|
|
21627
|
+
"presentation": "sheet"
|
|
21607
21628
|
}
|
|
21608
21629
|
}
|
|
21609
21630
|
},
|
|
@@ -26,6 +26,10 @@ interface AuthRouteInput {
|
|
|
26
26
|
returnScreenId?: string;
|
|
27
27
|
returnId?: string;
|
|
28
28
|
returnChannelId?: string;
|
|
29
|
+
/** Standalone sign-in only: "1" when it was opened as a modal (sheet / cover). */
|
|
30
|
+
modal?: string;
|
|
31
|
+
/** Modal only: the tab whose stack the return screen opens on once the modal closes. */
|
|
32
|
+
returnTab?: string;
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
// The screen's boot input survives refresh; consuming it must survive too.
|
|
@@ -61,6 +65,12 @@ function authIntentFromArg(arg: unknown, prev: Pick<S, "authIntent" | "authConte
|
|
|
61
65
|
};
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
/** How the standalone form leaves. A modal is closed: on web `back` pops the tab's stack,
|
|
69
|
+
* not the modal. A pushed form goes back. */
|
|
70
|
+
function leaveNav(): "dismiss" | "back" {
|
|
71
|
+
return routeInput().modal === "1" ? "dismiss" : "back";
|
|
72
|
+
}
|
|
73
|
+
|
|
64
74
|
/** Where a successful sign-in returns to, or null. Never Account itself — that would
|
|
65
75
|
* only push a second copy of the screen the member is already on. */
|
|
66
76
|
function resumeTarget(s: Pick<S, "returnScreenId" | "returnId" | "returnChannelId">): { screenId: string; args?: Record<string, string> } | null {
|
|
@@ -78,11 +88,26 @@ function resumeTarget(s: Pick<S, "returnScreenId" | "returnId" | "returnChannelI
|
|
|
78
88
|
* On the standalone sign-in screen the target is pushed, not a `replace`: on iOS and
|
|
79
89
|
* Android `replace` resets the stack to its root, which would drop the screens the
|
|
80
90
|
* visitor came through. Back from the target shows the form again, and the form sends a
|
|
81
|
-
* member back on appear (settle). With no target the form goes back.
|
|
91
|
+
* member back on appear (settle). With no target the form goes back.
|
|
92
|
+
*
|
|
93
|
+
* A modal form closes. A target pushed from here would open inside the modal (iOS, Android)
|
|
94
|
+
* or under it (web), so a modal that names a `returnTab` hands the target to that tab: the
|
|
95
|
+
* host closes the modal, then pushes it on that tab's stack (Account's member rows). A host
|
|
96
|
+
* showing no such tab (a drawer, a narrow Mac window) drops that request whole, modal and
|
|
97
|
+
* all, so the modal is also dismissed directly: it always closes, and the row opens where
|
|
98
|
+
* the tab exists. With no `returnTab` it only closes, and the screen under it loads again —
|
|
99
|
+
* the screen that opened the modal is the return target. */
|
|
82
100
|
function resumeAfterAuth(next: S): S {
|
|
83
101
|
const target = resumeTarget(next);
|
|
84
102
|
if (!next.isMember) return next;
|
|
85
|
-
|
|
103
|
+
const tab = routeInput().modal === "1" ? routeInput().returnTab ?? "" : "";
|
|
104
|
+
if (target && tab && next.standalone) {
|
|
105
|
+
routeInputConsumed = true;
|
|
106
|
+
void dispatch("himi.open", { presentation: "dismiss" });
|
|
107
|
+
const cleared = derive({ ...next, authIntent: "", authContextName: "", returnScreenId: "", returnId: "", returnChannelId: "" });
|
|
108
|
+
return navigate(cleared, target.args ? { tab, screenId: target.screenId, args: target.args } : { tab, screenId: target.screenId });
|
|
109
|
+
}
|
|
110
|
+
if (!target || routeInput().modal === "1") return next.standalone ? navigate(next, { presentation: leaveNav() }) : next;
|
|
86
111
|
routeInputConsumed = true;
|
|
87
112
|
const cleared = derive({ ...next, authIntent: "", authContextName: "", returnScreenId: "", returnId: "", returnChannelId: "" });
|
|
88
113
|
return navigate(cleared, target);
|
|
@@ -96,11 +121,31 @@ function forwardToSignIn(next: S): S {
|
|
|
96
121
|
if (!next.authIntent && !next.returnScreenId) return next;
|
|
97
122
|
routeInputConsumed = true;
|
|
98
123
|
const args: Record<string, string> = { mode: "signin" };
|
|
99
|
-
for (const key of ["authIntent", "authContextName"
|
|
100
|
-
if (next[key]) args[key === "authIntent" ? "intent" :
|
|
124
|
+
for (const key of ["authIntent", "authContextName"] as const) {
|
|
125
|
+
if (next[key]) args[key === "authIntent" ? "intent" : "contextName"] = next[key];
|
|
126
|
+
}
|
|
127
|
+
return openSignIn(derive({ ...next, authIntent: "", authContextName: "", returnScreenId: "", returnId: "", returnChannelId: "" }),
|
|
128
|
+
args, resumeTarget(next));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Account sends a guest to the standalone sign-in screen, with `after`, the member screen to
|
|
132
|
+
* open once signed in. With a `signInPresentation` appear param it opens as that modal, and
|
|
133
|
+
* `after` goes on Account's own tab (`signInReturnTab`) when the modal closes; pushed, the form
|
|
134
|
+
* pushes `after` itself (resumeAfterAuth). */
|
|
135
|
+
function openSignIn(next: S, args: Record<string, string>, after: { screenId: string; args?: Record<string, string> } | null): S {
|
|
136
|
+
const screenId = next.signInScreen || "himi_sign_in";
|
|
137
|
+
const presentation = signInPresentationRequested;
|
|
138
|
+
const back: Record<string, string> = {};
|
|
139
|
+
if (after) {
|
|
140
|
+
back.returnScreenId = after.screenId;
|
|
141
|
+
if (after.args?.id) back.returnId = after.args.id;
|
|
142
|
+
if (after.args?.channelId) back.returnChannelId = after.args.channelId;
|
|
101
143
|
}
|
|
102
|
-
return navigate(
|
|
103
|
-
|
|
144
|
+
if (!presentation) return navigate(next, { screenId, args: { ...args, ...back } });
|
|
145
|
+
const modalArgs: Record<string, string> = { ...args, modal: "1" };
|
|
146
|
+
// With no tab to open it on, a modal has no way to the member screen: it only closes.
|
|
147
|
+
if (after && signInReturnTabRequested) Object.assign(modalArgs, back, { returnTab: signInReturnTabRequested });
|
|
148
|
+
return navigate(next, { screenId, presentation, args: modalArgs });
|
|
104
149
|
}
|
|
105
150
|
|
|
106
151
|
/** After a load: the standalone sign-in screen sends a member back (a stale link, or a
|
|
@@ -128,8 +173,11 @@ function settle(next: S, arg: unknown, latest = true): S {
|
|
|
128
173
|
// The appear refresh returns `_nav`, which every host applies — binaries from before
|
|
129
174
|
// worker nav dispatch included. Only an arg-less load, whose result iOS
|
|
130
175
|
// discards, dispatches.
|
|
131
|
-
if (strField(arg, "standalone") === "1") return navigate(cleared, { presentation:
|
|
132
|
-
|
|
176
|
+
if (strField(arg, "standalone") === "1") return navigate(cleared, { presentation: leaveNav() });
|
|
177
|
+
// Not from a modal: nothing pushed over it comes back to it, and on iOS the closing modal's
|
|
178
|
+
// own screen reloads here once, after it has asked to close — a late dismiss would close
|
|
179
|
+
// whatever modal is open by then.
|
|
180
|
+
if (routeInput().modal !== "1") void dispatch("himi.open", { presentation: leaveNav() });
|
|
133
181
|
return cleared;
|
|
134
182
|
}
|
|
135
183
|
// Account forwards only on an appear refresh: the boot `load()` has no params and its
|
|
@@ -180,6 +228,10 @@ let appliedSeq = 0;
|
|
|
180
228
|
// The appear params belong to the worker session too, like the two flags above: a probe
|
|
181
229
|
// dropped because the visitor typed must not take them with it.
|
|
182
230
|
let signInScreenRequested = "";
|
|
231
|
+
/** Account only: how it opens the standalone sign-in screen ("" = push). */
|
|
232
|
+
let signInPresentationRequested: "" | "sheet" | "full_screen" = "";
|
|
233
|
+
/** Account only: its tab, where a member screen opens after a modal sign-in. */
|
|
234
|
+
let signInReturnTabRequested = "";
|
|
183
235
|
let standaloneRequested = false;
|
|
184
236
|
let pollIdentityRequested = false;
|
|
185
237
|
// Bumped by every mode switch, so a dropped probe never puts back a mode the visitor left.
|
|
@@ -210,6 +262,9 @@ function appearConfig(s: S, arg: unknown): AppearConfig {
|
|
|
210
262
|
passwordDraft = "";
|
|
211
263
|
}
|
|
212
264
|
signInScreenRequested ||= strField(arg, "signInScreen") || s.signInScreen;
|
|
265
|
+
const presentation = strField(arg, "signInPresentation");
|
|
266
|
+
if (presentation === "sheet" || presentation === "full_screen") signInPresentationRequested = presentation;
|
|
267
|
+
signInReturnTabRequested ||= strField(arg, "signInReturnTab");
|
|
213
268
|
// Only the sign-in screen's route carries `mode`, so it marks the form from the boot load on.
|
|
214
269
|
standaloneRequested ||= s.standalone || appearing || (!routeInputConsumed && !!routeInput().mode);
|
|
215
270
|
pollIdentityRequested ||= s.pollIdentity || strField(arg, "pollIdentity") === "1";
|
|
@@ -676,6 +731,7 @@ const svc = defineService<S, {
|
|
|
676
731
|
signOut: (s: S) => Promise<S>;
|
|
677
732
|
sync: (s: S) => Promise<S | undefined>;
|
|
678
733
|
openMember: (s: S, arg?: unknown) => Promise<S>;
|
|
734
|
+
leave: (s: S) => S;
|
|
679
735
|
restorePublish: (s: S) => S;
|
|
680
736
|
iapRestore: (s: S) => Promise<undefined>;
|
|
681
737
|
}>("himiStoreAccount", {
|
|
@@ -756,7 +812,8 @@ const svc = defineService<S, {
|
|
|
756
812
|
return "next" in r ? r.next : undefined;
|
|
757
813
|
},
|
|
758
814
|
// A row to a member-only screen shows to a guest too. A member opens it; a guest signs
|
|
759
|
-
// in first and the sign-in screen
|
|
815
|
+
// in first, and the sign-in screen then opens the row's screen — as a modal, by closing
|
|
816
|
+
// and pushing it on this tab (openSignIn) — so Back returns here either way.
|
|
760
817
|
openMember: async (s, arg): Promise<S> => {
|
|
761
818
|
const screenId = strField(arg, "screenId");
|
|
762
819
|
if (!screenId) return s;
|
|
@@ -764,8 +821,10 @@ const svc = defineService<S, {
|
|
|
764
821
|
// From the state as it is now: a probe may have landed during the identity read.
|
|
765
822
|
const now = svc.getState();
|
|
766
823
|
if (member) return navigate(now, { screenId });
|
|
767
|
-
return
|
|
824
|
+
return openSignIn(now, { mode: "signin" }, { screenId });
|
|
768
825
|
},
|
|
826
|
+
// The standalone form's Continue: leaves the form the way it was opened.
|
|
827
|
+
leave: (s) => navigate(s, { presentation: leaveNav() }),
|
|
769
828
|
// Typing means any focus request was delivered: clear the tokens (safe while mounted, since
|
|
770
829
|
// bumpToken never repeats), so a visit rarely ends — and a pooled form rarely reopens —
|
|
771
830
|
// holding one.
|