@wix/himalaya-cli 0.1618.0 → 0.1620.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 +13 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/telemetry/wix-bi/src/oneapp.d.ts +3 -2
- package/dist/cli.mjs +1223 -67
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/android-ux.md +66 -29
- package/guides/component-reference.json +5 -2
- package/guides/component-reference.md +3 -1
- package/guides/designing-himi-screens.md +43 -10
- package/guides/getting-started.md +2 -1
- package/guides/hhp.md +1 -1
- package/guides/himi-skill.md +2 -1
- package/guides/ios-ux.md +110 -31
- package/guides/mobile-ux.md +22 -5
- package/guides/skill.md +25 -1
- package/guides/tier-5-add-a-screen.md +2 -0
- package/package.json +2 -2
- package/templates/branded-lite/tier5-src/himi-branded-lite-shop/index.ts +27 -6
- package/templates/brandy/dev/index.ts +4 -3
- package/templates/retail-store/tier5-src/himi-branded-lite-shop/index.ts +27 -6
|
@@ -652,6 +652,20 @@ const register = withIapPresentation<S>({
|
|
|
652
652
|
},
|
|
653
653
|
});
|
|
654
654
|
|
|
655
|
+
/** A read that answers at once (a cache, a local fixture, a headless run whose transport never
|
|
656
|
+
* suspends) is over before the action that started it returns. Its `readChanged` is a dispatch
|
|
657
|
+
* of this same service from a detached job, which a headless run never services after the active
|
|
658
|
+
* action returns, and which on a device would commit under the skeleton the action is about to
|
|
659
|
+
* return. Wait a bounded number of turns and fold the settled status into the action's own
|
|
660
|
+
* result instead; a read that is still in flight keeps the skeleton and lands through
|
|
661
|
+
* `readChanged` as before. `undefined` means a newer action took over while this one waited. */
|
|
662
|
+
async function settledWithin(next: S, category: string, gen: number): Promise<S | undefined> {
|
|
663
|
+
const controller = reader(category);
|
|
664
|
+
for (let i = 0; i < 500 && controller.getStatus().refreshing; i++) await Promise.resolve();
|
|
665
|
+
if (gen !== generation) return undefined;
|
|
666
|
+
return controller.getStatus().refreshing ? next : currentReadState(next);
|
|
667
|
+
}
|
|
668
|
+
|
|
655
669
|
type A = (s: S, arg?: unknown) => S | undefined | Promise<S | undefined>;
|
|
656
670
|
const svc = register<S, Record<string, A>>("himiBrandedShop", {
|
|
657
671
|
state: BOOT,
|
|
@@ -659,8 +673,12 @@ const svc = register<S, Record<string, A>>("himiBrandedShop", {
|
|
|
659
673
|
actions: {
|
|
660
674
|
load: (s, arg) => load(s, arg),
|
|
661
675
|
// Pull to refresh: the categories and the scope again, from Wix.
|
|
662
|
-
refresh: (s, arg) =>
|
|
663
|
-
|
|
676
|
+
refresh: async (s, arg) => {
|
|
677
|
+
const next = await load(s, arg, true);
|
|
678
|
+
// The result owns its scope; another action may have changed the globals during load.
|
|
679
|
+
return next ? settledWithin(next, next.categorySelected, next.scopeGen) : undefined;
|
|
680
|
+
},
|
|
681
|
+
retry: (s) => settledWithin(showScope(s, s.categorySelected, true), s.categorySelected, generation),
|
|
664
682
|
recover: async () => { await fetchScope(selectedCategory, generation, true); return undefined; },
|
|
665
683
|
readChanged: (s, arg) => {
|
|
666
684
|
if (!arg || typeof arg !== 'object') return undefined;
|
|
@@ -683,7 +701,7 @@ const svc = register<S, Record<string, A>>("himiBrandedShop", {
|
|
|
683
701
|
// A background page landed for the current scope.
|
|
684
702
|
scopeGrew: (s) => derive(s),
|
|
685
703
|
// Single-select: one chip is always chosen.
|
|
686
|
-
selectCategory: (s, arg) => {
|
|
704
|
+
selectCategory: async (s, arg) => {
|
|
687
705
|
// The chip row sends { selectedIds }; a deselected chip falls back to All.
|
|
688
706
|
const selection = arg as { selectedIds?: unknown; refresh?: boolean } | undefined;
|
|
689
707
|
const id = selection?.selectedIds !== undefined ? selected(arg)[0] ?? ALL : idOf(arg);
|
|
@@ -691,12 +709,15 @@ const svc = register<S, Record<string, A>>("himiBrandedShop", {
|
|
|
691
709
|
const cancelsPendingRoute = !!pendingLink || selectedCategory !== id;
|
|
692
710
|
categoryIntentVersion++;
|
|
693
711
|
pendingLink = undefined;
|
|
694
|
-
|
|
712
|
+
// undefined, not s: s is the snapshot from before any in-flight load, loading flag included.
|
|
713
|
+
if (id !== ALL && !categories.some((c) => c.id === id)) return undefined;
|
|
695
714
|
// showScope compares the prior selection before committing the requested category.
|
|
696
715
|
// categorySelected is committed with the tap (showScope), so a tap back to the chip
|
|
697
716
|
// on screen while another category loads is a no-op on the right scope.
|
|
698
|
-
if (id === s.categorySelected) return cancelsPendingRoute || refresh ? showScope(s, id, refresh) :
|
|
699
|
-
const
|
|
717
|
+
if (id === s.categorySelected) return cancelsPendingRoute || refresh ? settledWithin(showScope(s, id, refresh), id, generation) : undefined;
|
|
718
|
+
const shown = showScope(s, id, refresh);
|
|
719
|
+
const next = await settledWithin(shown, id, generation);
|
|
720
|
+
if (!next) return undefined;
|
|
700
721
|
const pending = pendingAuxiliary;
|
|
701
722
|
if (pending && pending.version === auxiliaryVersion && pending.cartCount >= 0) {
|
|
702
723
|
pendingAuxiliary = undefined;
|
|
@@ -347,10 +347,11 @@ export default {
|
|
|
347
347
|
config,
|
|
348
348
|
homeScreenId: "site_home",
|
|
349
349
|
screens: {
|
|
350
|
-
// A fresh copy per build: descriptors are pure functions of the site block.
|
|
350
|
+
// A fresh copy per build: descriptors are pure functions of the site block. A JSON round
|
|
351
|
+
// trip, not structuredClone: `himi test` builds screens in the contained realm, which withholds it.
|
|
351
352
|
exact: {
|
|
352
|
-
...Object.fromEntries(Object.keys(SCREENS).map((id) => [id, () =>
|
|
353
|
-
himi_notification_settings: () =>
|
|
353
|
+
...Object.fromEntries(Object.keys(SCREENS).map((id) => [id, () => JSON.parse(JSON.stringify(SCREENS[id]))])),
|
|
354
|
+
himi_notification_settings: () => JSON.parse(JSON.stringify(NOTIFICATIONS)),
|
|
354
355
|
},
|
|
355
356
|
templated: [],
|
|
356
357
|
},
|
|
@@ -652,6 +652,20 @@ const register = withIapPresentation<S>({
|
|
|
652
652
|
},
|
|
653
653
|
});
|
|
654
654
|
|
|
655
|
+
/** A read that answers at once (a cache, a local fixture, a headless run whose transport never
|
|
656
|
+
* suspends) is over before the action that started it returns. Its `readChanged` is a dispatch
|
|
657
|
+
* of this same service from a detached job, which a headless run never services after the active
|
|
658
|
+
* action returns, and which on a device would commit under the skeleton the action is about to
|
|
659
|
+
* return. Wait a bounded number of turns and fold the settled status into the action's own
|
|
660
|
+
* result instead; a read that is still in flight keeps the skeleton and lands through
|
|
661
|
+
* `readChanged` as before. `undefined` means a newer action took over while this one waited. */
|
|
662
|
+
async function settledWithin(next: S, category: string, gen: number): Promise<S | undefined> {
|
|
663
|
+
const controller = reader(category);
|
|
664
|
+
for (let i = 0; i < 500 && controller.getStatus().refreshing; i++) await Promise.resolve();
|
|
665
|
+
if (gen !== generation) return undefined;
|
|
666
|
+
return controller.getStatus().refreshing ? next : currentReadState(next);
|
|
667
|
+
}
|
|
668
|
+
|
|
655
669
|
type A = (s: S, arg?: unknown) => S | undefined | Promise<S | undefined>;
|
|
656
670
|
const svc = register<S, Record<string, A>>("himiBrandedShop", {
|
|
657
671
|
state: BOOT,
|
|
@@ -659,8 +673,12 @@ const svc = register<S, Record<string, A>>("himiBrandedShop", {
|
|
|
659
673
|
actions: {
|
|
660
674
|
load: (s, arg) => load(s, arg),
|
|
661
675
|
// Pull to refresh: the categories and the scope again, from Wix.
|
|
662
|
-
refresh: (s, arg) =>
|
|
663
|
-
|
|
676
|
+
refresh: async (s, arg) => {
|
|
677
|
+
const next = await load(s, arg, true);
|
|
678
|
+
// The result owns its scope; another action may have changed the globals during load.
|
|
679
|
+
return next ? settledWithin(next, next.categorySelected, next.scopeGen) : undefined;
|
|
680
|
+
},
|
|
681
|
+
retry: (s) => settledWithin(showScope(s, s.categorySelected, true), s.categorySelected, generation),
|
|
664
682
|
recover: async () => { await fetchScope(selectedCategory, generation, true); return undefined; },
|
|
665
683
|
readChanged: (s, arg) => {
|
|
666
684
|
if (!arg || typeof arg !== 'object') return undefined;
|
|
@@ -683,7 +701,7 @@ const svc = register<S, Record<string, A>>("himiBrandedShop", {
|
|
|
683
701
|
// A background page landed for the current scope.
|
|
684
702
|
scopeGrew: (s) => derive(s),
|
|
685
703
|
// Single-select: one chip is always chosen.
|
|
686
|
-
selectCategory: (s, arg) => {
|
|
704
|
+
selectCategory: async (s, arg) => {
|
|
687
705
|
// The chip row sends { selectedIds }; a deselected chip falls back to All.
|
|
688
706
|
const selection = arg as { selectedIds?: unknown; refresh?: boolean } | undefined;
|
|
689
707
|
const id = selection?.selectedIds !== undefined ? selected(arg)[0] ?? ALL : idOf(arg);
|
|
@@ -691,12 +709,15 @@ const svc = register<S, Record<string, A>>("himiBrandedShop", {
|
|
|
691
709
|
const cancelsPendingRoute = !!pendingLink || selectedCategory !== id;
|
|
692
710
|
categoryIntentVersion++;
|
|
693
711
|
pendingLink = undefined;
|
|
694
|
-
|
|
712
|
+
// undefined, not s: s is the snapshot from before any in-flight load, loading flag included.
|
|
713
|
+
if (id !== ALL && !categories.some((c) => c.id === id)) return undefined;
|
|
695
714
|
// showScope compares the prior selection before committing the requested category.
|
|
696
715
|
// categorySelected is committed with the tap (showScope), so a tap back to the chip
|
|
697
716
|
// on screen while another category loads is a no-op on the right scope.
|
|
698
|
-
if (id === s.categorySelected) return cancelsPendingRoute || refresh ? showScope(s, id, refresh) :
|
|
699
|
-
const
|
|
717
|
+
if (id === s.categorySelected) return cancelsPendingRoute || refresh ? settledWithin(showScope(s, id, refresh), id, generation) : undefined;
|
|
718
|
+
const shown = showScope(s, id, refresh);
|
|
719
|
+
const next = await settledWithin(shown, id, generation);
|
|
720
|
+
if (!next) return undefined;
|
|
700
721
|
const pending = pendingAuxiliary;
|
|
701
722
|
if (pending && pending.version === auxiliaryVersion && pending.cartCount >= 0) {
|
|
702
723
|
pendingAuxiliary = undefined;
|