fix(web): companion-gate the store banner + manual intro trigger (#61 residual)
Only the auto-popup was companion-gated — inside the companion WebView users still saw the 'install the companion' banner in the App Store and could pop the intro overlay through it. Gates all three paths on isCompanionApp(): CompanionBanner self-hides, openCompanionIntro() is a no-op, and the manual-open watcher in CompanionIntroOverlay refuses to open (the overlay's raw window check also moves to the canonical helper so there is exactly one detection). No APK change.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import { describe, it, expect, afterEach, beforeEach } from 'vitest'
|
||||
import { companionIntroRequested, openCompanionIntro } from '../useCompanionIntro'
|
||||
|
||||
// #61: the manual intro trigger (App Store banner etc.) must be a no-op inside
|
||||
// the companion app's WebView — the "install the companion" pitch is nonsense
|
||||
// where the user is already running it. The auto-popup was already gated
|
||||
// (CompanionIntroOverlay.onMounted); openCompanionIntro is the second, manual
|
||||
// path and the banner render (CompanionBanner) the third.
|
||||
|
||||
type TestWindow = Window & { ArchipelagoNative?: unknown }
|
||||
const w = window as TestWindow
|
||||
|
||||
beforeEach(() => {
|
||||
companionIntroRequested.value = false
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
delete w.ArchipelagoNative
|
||||
})
|
||||
|
||||
describe('openCompanionIntro', () => {
|
||||
it('raises the manual intro request in a plain browser/PWA', () => {
|
||||
expect(companionIntroRequested.value).toBe(false)
|
||||
openCompanionIntro()
|
||||
expect(companionIntroRequested.value).toBe(true)
|
||||
})
|
||||
|
||||
it('is a no-op inside the companion app (bridge with openInApp)', () => {
|
||||
w.ArchipelagoNative = { openInApp: () => {}, openExternal: () => {} }
|
||||
openCompanionIntro()
|
||||
expect(companionIntroRequested.value).toBe(false)
|
||||
})
|
||||
|
||||
it('still fires when the bridge exists but is not the companion shell', () => {
|
||||
// Partial bridge (no openInApp) is not the companion app — a future
|
||||
// embedder must still see the pitch.
|
||||
w.ArchipelagoNative = { openExternal: () => {} }
|
||||
openCompanionIntro()
|
||||
expect(companionIntroRequested.value).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -1,13 +1,20 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { isCompanionApp } from '@/utils/openExternal'
|
||||
|
||||
/**
|
||||
* Cross-view trigger for the Remote Companion intro/pairing modal
|
||||
* (CompanionIntroOverlay, mounted once in Dashboard.vue). Views like the
|
||||
* App Store banner call openCompanionIntro() to pop it on demand — this
|
||||
* bypasses the once-per-browser auto-show gate.
|
||||
*
|
||||
* Inside the companion app's own WebView the whole pitch is nonsense — the
|
||||
* user is already running it — so the trigger is a no-op there (#61: the
|
||||
* auto-popup was gated, this manual path and CompanionBanner weren't).
|
||||
*/
|
||||
export const companionIntroRequested = ref(false)
|
||||
|
||||
export function openCompanionIntro(): void {
|
||||
if (isCompanionApp()) return
|
||||
companionIntroRequested.value = true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user