fix(03-04): Telegram LocationManager deep-link — LOCATION SETTINGS CTA on denied cards + locationManagerUpdated chain re-run
This commit is contained in:
@@ -23,6 +23,7 @@ export interface ShellStrings {
|
|||||||
deniedRegister: string;
|
deniedRegister: string;
|
||||||
ctaTryAgain: string;
|
ctaTryAgain: string;
|
||||||
ctaAskViaChat: string;
|
ctaAskViaChat: string;
|
||||||
|
ctaLocationSettings: string;
|
||||||
deniedHeadline: string;
|
deniedHeadline: string;
|
||||||
deniedBody: string;
|
deniedBody: string;
|
||||||
deniedHint: string;
|
deniedHint: string;
|
||||||
@@ -54,6 +55,7 @@ export const strings: Record<Locale, ShellStrings> = {
|
|||||||
deniedRegister: "GEO // LOCATION",
|
deniedRegister: "GEO // LOCATION",
|
||||||
ctaTryAgain: "TRY AGAIN",
|
ctaTryAgain: "TRY AGAIN",
|
||||||
ctaAskViaChat: "ASK VIA CHAT",
|
ctaAskViaChat: "ASK VIA CHAT",
|
||||||
|
ctaLocationSettings: "LOCATION SETTINGS",
|
||||||
deniedHeadline: "Location is switched off",
|
deniedHeadline: "Location is switched off",
|
||||||
deniedBody: "araharah guides you from where you physically are. Without location there is no route to draw.",
|
deniedBody: "araharah guides you from where you physically are. Without location there is no route to draw.",
|
||||||
deniedHint: "Grant location to Telegram, or send a pin in this chat: attach → Location.",
|
deniedHint: "Grant location to Telegram, or send a pin in this chat: attach → Location.",
|
||||||
@@ -81,6 +83,7 @@ export const strings: Record<Locale, ShellStrings> = {
|
|||||||
deniedRegister: "GEO // LOCATION",
|
deniedRegister: "GEO // LOCATION",
|
||||||
ctaTryAgain: "CUBA LAGI",
|
ctaTryAgain: "CUBA LAGI",
|
||||||
ctaAskViaChat: "MINTA VIA CHAT",
|
ctaAskViaChat: "MINTA VIA CHAT",
|
||||||
|
ctaLocationSettings: "TETAPAN LOKASI",
|
||||||
deniedHeadline: "Lokasi dimatikan",
|
deniedHeadline: "Lokasi dimatikan",
|
||||||
deniedBody: "araharah memandu dari kedudukan sebenar anda. Tanpa lokasi, tiada laluan boleh dilukis.",
|
deniedBody: "araharah memandu dari kedudukan sebenar anda. Tanpa lokasi, tiada laluan boleh dilukis.",
|
||||||
deniedHint: "Benarkan lokasi untuk Telegram, atau hantar pin dalam chat ini: lampiran → Lokasi.",
|
deniedHint: "Benarkan lokasi untuk Telegram, atau hantar pin dalam chat ini: lampiran → Lokasi.",
|
||||||
|
|||||||
+30
-2
@@ -101,7 +101,14 @@ async function boot(): Promise<void> {
|
|||||||
const bootCard1 = buildBootCard(locale, 1);
|
const bootCard1 = buildBootCard(locale, 1);
|
||||||
const bootCard2 = buildBootCard(locale, 2);
|
const bootCard2 = buildBootCard(locale, 2);
|
||||||
const deniedCard = buildDeniedCard(locale, { awaitingPin: false });
|
const deniedCard = buildDeniedCard(locale, { awaitingPin: false });
|
||||||
const awaitingCard = buildDeniedCard(locale, { awaitingPin: true });
|
const awaitingCard = buildDeniedCard(
|
||||||
|
locale,
|
||||||
|
// Debug round 2: the Telegram-only deep-link. LocationManager presence
|
||||||
|
// is the whole eligibility test — off-Telegram (Desktop/browser) there
|
||||||
|
// is nothing for openSettings() to open, and navigator.geolocation
|
||||||
|
// denial is handled by the OS settings hint copy instead.
|
||||||
|
{ awaitingPin: true, withLocationSettings: wa?.LocationManager !== undefined },
|
||||||
|
);
|
||||||
const lostCard = buildSignalLostCard(locale);
|
const lostCard = buildSignalLostCard(locale);
|
||||||
const gantryOf = (card: HTMLElement): HTMLElement => {
|
const gantryOf = (card: HTMLElement): HTMLElement => {
|
||||||
const el = card.querySelector(".gantry");
|
const el = card.querySelector(".gantry");
|
||||||
@@ -117,7 +124,17 @@ async function boot(): Promise<void> {
|
|||||||
// is a second buildDeniedCard instance (03-03 stub note) — wiring only the
|
// is a second buildDeniedCard instance (03-03 stub note) — wiring only the
|
||||||
// first left TRY AGAIN / ASK VIA CHAT dead on the awaiting-pin card.
|
// first left TRY AGAIN / ASK VIA CHAT dead on the awaiting-pin card.
|
||||||
const wireDeniedActions = (card: HTMLElement): void => {
|
const wireDeniedActions = (card: HTMLElement): void => {
|
||||||
const retryButton = card.querySelector(".btn-secondary");
|
const settingsButton = card.querySelector('[data-role="open-location-settings"]');
|
||||||
|
if (settingsButton instanceof HTMLButtonElement) {
|
||||||
|
// Debug round 2: deep-links Telegram's pane where the user re-grants
|
||||||
|
// location for this bot (the "no way to turn on location" report).
|
||||||
|
settingsButton.addEventListener("click", () => {
|
||||||
|
const lm = wa?.LocationManager;
|
||||||
|
if (lm && typeof lm.openSettings === "function") lm.openSettings();
|
||||||
|
void runFromSession(); // sheet open OR older client without the API — re-request either way
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const retryButton = card.querySelector(".card-actions .btn-secondary:not([data-role])");
|
||||||
if (retryButton instanceof HTMLButtonElement) {
|
if (retryButton instanceof HTMLButtonElement) {
|
||||||
retryButton.addEventListener("click", () => void runFromSession()); // re-runs from link 1
|
retryButton.addEventListener("click", () => void runFromSession()); // re-runs from link 1
|
||||||
}
|
}
|
||||||
@@ -129,6 +146,17 @@ async function boot(): Promise<void> {
|
|||||||
wireDeniedActions(deniedCard);
|
wireDeniedActions(deniedCard);
|
||||||
wireDeniedActions(awaitingCard);
|
wireDeniedActions(awaitingCard);
|
||||||
|
|
||||||
|
// Debug round 2: after the user grants location from Telegram's sheet
|
||||||
|
// (opened via openSettings), the client fires locationManagerUpdated —
|
||||||
|
// re-run the chain immediately instead of waiting for a manual tap.
|
||||||
|
// The Wire: only live Data events on the wrapper — guard chainInFlight.
|
||||||
|
if (wa && typeof wa.onEvent === "function" && wa.LocationManager) {
|
||||||
|
wa.onEvent("locationManagerUpdated", () => {
|
||||||
|
if (chainInFlight) return;
|
||||||
|
void runFromSession();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function showCard(card: HTMLElement | null, register: "center" | "bottom" = "center"): void {
|
function showCard(card: HTMLElement | null, register: "center" | "bottom" = "center"): void {
|
||||||
if (card !== null) {
|
if (card !== null) {
|
||||||
stack.replaceChildren(card);
|
stack.replaceChildren(card);
|
||||||
|
|||||||
+17
-9
@@ -126,15 +126,23 @@ export function buildBootCard(locale: Locale, stage: 1 | 2): HTMLElement {
|
|||||||
* issue #77) and the retry CTA is .btn-secondary (the RESEARCH Pitfall 4
|
* issue #77) and the retry CTA is .btn-secondary (the RESEARCH Pitfall 4
|
||||||
* inversion, recorded as a callout in the UI-SPEC). With opts.awaitingPin
|
* inversion, recorded as a callout in the UI-SPEC). With opts.awaitingPin
|
||||||
* the body swaps to the chat-fallback waiting copy. */
|
* the body swaps to the chat-fallback waiting copy. */
|
||||||
export function buildDeniedCard(locale: Locale, opts: { awaitingPin?: boolean } = {}): HTMLElement {
|
export function buildDeniedCard(
|
||||||
return mountHintedCard(
|
locale: Locale,
|
||||||
locale,
|
opts: { awaitingPin?: boolean; withLocationSettings?: boolean } = {},
|
||||||
"deniedRegister",
|
): HTMLElement {
|
||||||
"deniedHeadline",
|
const card = mountHintedCard(locale, "deniedRegister", "deniedHeadline", opts.awaitingPin ? "chatFallbackWaiting" : "deniedBody", "deniedHint", true);
|
||||||
opts.awaitingPin ? "chatFallbackWaiting" : "deniedBody",
|
// Debug-round addition (03-DEVICE-MATRIX round 2): Telegram-only recovery
|
||||||
"deniedHint",
|
// path — opens Telegram's own location-access pane via LocationManager.
|
||||||
true,
|
// Its callback fires locationManagerUpdated; main.ts re-runs the chain.
|
||||||
);
|
if (opts.withLocationSettings) {
|
||||||
|
const el = document.createElement("button");
|
||||||
|
el.type = "button";
|
||||||
|
el.className = "btn-secondary";
|
||||||
|
el.dataset.role = "open-location-settings";
|
||||||
|
el.textContent = strings[locale].ctaLocationSettings;
|
||||||
|
card.querySelector(".card-actions")?.appendChild(el);
|
||||||
|
}
|
||||||
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** SYS-labeled position register — the 45s-staleness card (folds into the
|
/** SYS-labeled position register — the 45s-staleness card (folds into the
|
||||||
|
|||||||
Reference in New Issue
Block a user