@calo-design/cli 0.9.6 → 0.9.7
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/bin/mirror-push.js +30 -27
- package/package.json +1 -1
package/bin/mirror-push.js
CHANGED
|
@@ -444,7 +444,7 @@ function switchToChannel(channel: string): void {
|
|
|
444
444
|
await Updates.fetchUpdateAsync();
|
|
445
445
|
// Defer the reload off the awaited chain (JSI teardown race — mirror.ts).
|
|
446
446
|
setTimeout(() => { void Updates.reloadAsync().catch(() => { switching = false; }); }, 300);
|
|
447
|
-
})().catch(() => { switching = false; });
|
|
447
|
+
})().catch((e) => { console.warn("[mirror-switch] switch to", channel, "failed:", String(e)); switching = false; });
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
// "/open/<slug>", "scheme://open/<slug>" (host parses as "open"), and
|
|
@@ -465,14 +465,6 @@ function launcherSlug(path: string): string | null {
|
|
|
465
465
|
}
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
-
/** "/" when the URL is the launcher's (starting a switch if it names another prototype), null otherwise. */
|
|
469
|
-
export function handleLauncherPath(path: string): string | null {
|
|
470
|
-
const slug = launcherSlug(path);
|
|
471
|
-
if (slug === null) return null;
|
|
472
|
-
if (slug && slug !== PROTOTYPE) switchToChannel(slug);
|
|
473
|
-
return "/";
|
|
474
|
-
}
|
|
475
|
-
|
|
476
468
|
// Warm-link coverage. After Updates.reloadAsync() the React Native
|
|
477
469
|
// Linking 'url' event no longer reaches the reloaded JS context (verified on
|
|
478
470
|
// Android: the launcher's original context gets warm links, a prototype's
|
|
@@ -480,32 +472,43 @@ export function handleLauncherPath(path: string): string | null {
|
|
|
480
472
|
// URL store, so listen there — and on every foreground, sweep getLinkingURL()
|
|
481
473
|
// in case the event itself was missed. lastHandled stops the sweep from
|
|
482
474
|
// re-firing on URLs we've already acted on.
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
475
|
+
/**
|
|
476
|
+
* "/" when the URL is the launcher's, null otherwise. NEVER starts a switch:
|
|
477
|
+
* the initial URL of a reloaded context can be the STALE activity intent (on
|
|
478
|
+
* Android the activity keeps the intent that cold-started the app), and
|
|
479
|
+
* switching on it ping-pongs between prototypes. Switching decisions belong to
|
|
480
|
+
* the sweep below, which reads expo-linking's always-current URL store.
|
|
481
|
+
*/
|
|
482
|
+
export function handleLauncherPath(path: string): string | null {
|
|
483
|
+
return launcherSlug(path) === null ? null : "/";
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// The launcher-URL store is handle-once: after acting on a URL, clear it so a
|
|
487
|
+
// context created later (e.g. by a feed tap, which carries no URL) can't
|
|
488
|
+
// replay it as a phantom switch.
|
|
489
|
+
function sweepLinkingURL(): void {
|
|
490
|
+
let url: string | null = null;
|
|
491
|
+
try { url = ExpoLinking.getLinkingURL() ?? null; } catch { return; }
|
|
492
|
+
if (!url) return;
|
|
493
|
+
const slug = launcherSlug(url);
|
|
494
|
+
if (slug === null) return; // the prototype's own deep link — not ours to touch
|
|
495
|
+
try { ExpoLinking.clearInitialURL(); } catch {}
|
|
496
|
+
if (slug && slug !== PROTOTYPE) switchToChannel(slug);
|
|
489
497
|
}
|
|
490
498
|
|
|
491
499
|
export function subscribeLauncherLinks(): { remove: () => void } {
|
|
492
|
-
//
|
|
493
|
-
|
|
494
|
-
try { lastHandled = ExpoLinking.getLinkingURL() ?? null; } catch {}
|
|
495
|
-
const sweep = () => {
|
|
496
|
-
try { handleWarmUrl(ExpoLinking.getLinkingURL() ?? null); } catch {}
|
|
497
|
-
};
|
|
498
|
-
const linkSub = ExpoLinking.addEventListener("url", ({ url }) => handleWarmUrl(url));
|
|
500
|
+
sweepLinkingURL(); // the URL that created this context (cold link or switch)
|
|
501
|
+
const linkSub = ExpoLinking.addEventListener("url", () => sweepLinkingURL());
|
|
499
502
|
const stateSub = AppState.addEventListener("change", (state) => {
|
|
500
|
-
if (state === "active")
|
|
503
|
+
if (state === "active") sweepLinkingURL();
|
|
501
504
|
});
|
|
502
505
|
// The load-bearing path: in a context created by Updates.reloadAsync() the
|
|
503
506
|
// native->JS EVENT bridge (RN Linking, AppState, expo-linking's emitter) is
|
|
504
507
|
// dead on Android, but expo-linking's native lifecycle listener still writes
|
|
505
|
-
// every incoming URL to
|
|
506
|
-
// pure JS. Poll it; the listeners above
|
|
507
|
-
//
|
|
508
|
-
const timer = setInterval(
|
|
508
|
+
// every incoming URL to the store getLinkingURL() reads — and timers are
|
|
509
|
+
// pure JS. Poll it; the listeners above cover contexts where events work,
|
|
510
|
+
// and clearInitialURL() makes whichever path runs first win cleanly.
|
|
511
|
+
const timer = setInterval(sweepLinkingURL, 1500);
|
|
509
512
|
return {
|
|
510
513
|
remove: () => {
|
|
511
514
|
linkSub.remove();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@calo-design/cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.7",
|
|
4
4
|
"description": "One-line setup for Calo design tooling: logs in with your Calo email and installs the calo-design skill + design-system packages. No GitHub account needed.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"calo-design": "bin/cli.js"
|