@volley/vwr-loader 1.6.0 → 1.7.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/cli.js +51 -25
- package/dist/cli.js.map +1 -1
- package/dist/vwr/src/envDefaults.d.ts.map +1 -1
- package/dist/vwr/src/envDefaults.js +6 -39
- package/dist/vwr/src/envDefaults.js.map +1 -1
- package/dist/vwr/src/iframe.d.ts +25 -0
- package/dist/vwr/src/iframe.d.ts.map +1 -0
- package/dist/vwr/src/iframe.js +82 -0
- package/dist/vwr/src/iframe.js.map +1 -0
- package/dist/vwr/src/native/app-lifecycle/factory.d.ts +7 -0
- package/dist/vwr/src/native/app-lifecycle/factory.d.ts.map +1 -0
- package/dist/vwr/src/native/app-lifecycle/factory.js +68 -0
- package/dist/vwr/src/native/app-lifecycle/factory.js.map +1 -0
- package/dist/vwr/src/native/app-lifecycle/rpc.d.ts +15 -0
- package/dist/vwr/src/native/app-lifecycle/rpc.d.ts.map +1 -0
- package/dist/vwr/src/native/app-lifecycle/rpc.js +46 -0
- package/dist/vwr/src/native/app-lifecycle/rpc.js.map +1 -0
- package/dist/vwr/src/native/capacitor-bridge/rpc.d.ts +33 -0
- package/dist/vwr/src/native/capacitor-bridge/rpc.d.ts.map +1 -0
- package/dist/vwr/src/native/capacitor-bridge/rpc.js +129 -0
- package/dist/vwr/src/native/capacitor-bridge/rpc.js.map +1 -0
- package/dist/vwr/src/native/device-info/factory.d.ts +9 -0
- package/dist/vwr/src/native/device-info/factory.d.ts.map +1 -0
- package/dist/vwr/src/native/device-info/factory.js +28 -0
- package/dist/vwr/src/native/device-info/factory.js.map +1 -0
- package/dist/vwr/src/native/device-info/firetvCollector.d.ts +9 -0
- package/dist/vwr/src/native/device-info/firetvCollector.d.ts.map +1 -0
- package/dist/vwr/src/native/device-info/firetvCollector.js +180 -0
- package/dist/vwr/src/native/device-info/firetvCollector.js.map +1 -0
- package/dist/vwr/src/native/device-info/lgCollector.d.ts +8 -0
- package/dist/vwr/src/native/device-info/lgCollector.d.ts.map +1 -0
- package/dist/vwr/src/native/device-info/lgCollector.js +136 -0
- package/dist/vwr/src/native/device-info/lgCollector.js.map +1 -0
- package/dist/vwr/src/native/device-info/mobileCollector.d.ts +9 -0
- package/dist/vwr/src/native/device-info/mobileCollector.d.ts.map +1 -0
- package/dist/vwr/src/native/device-info/mobileCollector.js +47 -0
- package/dist/vwr/src/native/device-info/mobileCollector.js.map +1 -0
- package/dist/vwr/src/native/device-info/rpc.d.ts +51 -0
- package/dist/vwr/src/native/device-info/rpc.d.ts.map +1 -0
- package/dist/vwr/src/native/device-info/rpc.js +46 -0
- package/dist/vwr/src/native/device-info/rpc.js.map +1 -0
- package/dist/vwr/src/native/device-info/samsungCollector.d.ts +9 -0
- package/dist/vwr/src/native/device-info/samsungCollector.d.ts.map +1 -0
- package/dist/vwr/src/native/device-info/samsungCollector.js +86 -0
- package/dist/vwr/src/native/device-info/samsungCollector.js.map +1 -0
- package/dist/vwr/src/native/device-info/webCollector.d.ts +4 -0
- package/dist/vwr/src/native/device-info/webCollector.d.ts.map +1 -0
- package/dist/vwr/src/native/device-info/webCollector.js +56 -0
- package/dist/vwr/src/native/device-info/webCollector.js.map +1 -0
- package/dist/vwr/src/native/native-bridge/rpc.d.ts +33 -0
- package/dist/vwr/src/native/native-bridge/rpc.d.ts.map +1 -0
- package/dist/vwr/src/native/native-bridge/rpc.js +114 -0
- package/dist/vwr/src/native/native-bridge/rpc.js.map +1 -0
- package/dist/vwr/src/native/screensaver-prevention/LGLunaService.d.ts +14 -0
- package/dist/vwr/src/native/screensaver-prevention/LGLunaService.d.ts.map +1 -0
- package/dist/vwr/src/native/screensaver-prevention/LGLunaService.js +187 -0
- package/dist/vwr/src/native/screensaver-prevention/LGLunaService.js.map +1 -0
- package/dist/vwr/src/native/screensaver-prevention/rpc.d.ts +27 -0
- package/dist/vwr/src/native/screensaver-prevention/rpc.d.ts.map +1 -0
- package/dist/vwr/src/native/screensaver-prevention/rpc.js +71 -0
- package/dist/vwr/src/native/screensaver-prevention/rpc.js.map +1 -0
- package/dist/vwr/src/observability.d.ts +35 -0
- package/dist/vwr/src/observability.d.ts.map +1 -0
- package/dist/vwr/src/observability.js +68 -0
- package/dist/vwr/src/observability.js.map +1 -0
- package/dist/vwr/src/shellEnvDefaults.d.ts +15 -0
- package/dist/vwr/src/shellEnvDefaults.d.ts.map +1 -0
- package/dist/vwr/src/shellEnvDefaults.js +34 -0
- package/dist/vwr/src/shellEnvDefaults.js.map +1 -0
- package/dist/vwr/src/types.d.ts +56 -0
- package/dist/vwr/src/types.d.ts.map +1 -0
- package/dist/vwr/src/types.js +27 -0
- package/dist/vwr/src/types.js.map +1 -0
- package/dist/vwr/src/urlUtils.d.ts +17 -0
- package/dist/vwr/src/urlUtils.d.ts.map +1 -0
- package/dist/vwr/src/urlUtils.js +42 -0
- package/dist/vwr/src/urlUtils.js.map +1 -0
- package/dist/vwr/src/vwrBootstrap.d.ts +26 -0
- package/dist/vwr/src/vwrBootstrap.d.ts.map +1 -0
- package/dist/vwr/src/vwrBootstrap.js +176 -0
- package/dist/vwr/src/vwrBootstrap.js.map +1 -0
- package/dist/vwr/src/vwrConfig.d.ts.map +1 -1
- package/dist/vwr/src/vwrConfig.js +11 -2
- package/dist/vwr/src/vwrConfig.js.map +1 -1
- package/{src → dist/vwr-loader}/index.html +1 -1
- package/dist/vwr-loader/src/__mocks__/invalidVwrModule.d.ts +2 -0
- package/dist/vwr-loader/src/__mocks__/invalidVwrModule.d.ts.map +1 -0
- package/dist/vwr-loader/src/__mocks__/invalidVwrModule.js +2 -0
- package/dist/vwr-loader/src/__mocks__/invalidVwrModule.js.map +1 -0
- package/dist/vwr-loader/src/index.d.ts +3 -3
- package/dist/vwr-loader/src/index.d.ts.map +1 -1
- package/dist/vwr-loader/src/index.js +2 -2
- package/dist/vwr-loader/src/index.js.map +1 -1
- package/dist/vwr-loader/src/loadVwr.d.ts.map +1 -1
- package/dist/vwr-loader/src/loadVwr.js +28 -22
- package/dist/vwr-loader/src/loadVwr.js.map +1 -1
- package/dist/vwr-loader/src/logger.d.ts +1 -1
- package/dist/vwr-loader/src/logger.d.ts.map +1 -1
- package/dist/vwr-loader/src/logger.js +1 -1
- package/dist/vwr-loader/src/logger.js.map +1 -1
- package/dist/vwr-loader/src/main.js +1 -1
- package/dist/vwr-loader/src/main.js.map +1 -1
- package/package.json +4 -5
- package/dist/assets/profiler-BRmTNL9s.js +0 -2
- package/dist/assets/profiler-BRmTNL9s.js.map +0 -1
- package/dist/assets/startRecording-CuFdVhxx.js +0 -3
- package/dist/assets/startRecording-CuFdVhxx.js.map +0 -1
- package/dist/index.html +0 -25
- package/dist/main.js +0 -12
- package/dist/main.js.map +0 -1
- package/src/__mocks__/@datadog/browser-logs.ts +0 -35
- package/src/__mocks__/@datadog/browser-rum.ts +0 -27
- package/src/__mocks__/vwrModule.ts +0 -3
- package/src/amplitudeFlagFetcher.test.ts +0 -175
- package/src/amplitudeFlagFetcher.ts +0 -105
- package/src/errors/InitializationError.ts +0 -105
- package/src/errors/ensureError.ts +0 -6
- package/src/errors/index.ts +0 -16
- package/src/exitHandler.test.ts +0 -417
- package/src/exitHandler.ts +0 -233
- package/src/getEnvironment.test.ts +0 -417
- package/src/getEnvironment.ts +0 -144
- package/src/getShellVersion.test.ts +0 -403
- package/src/getShellVersion.ts +0 -133
- package/src/index.ts +0 -7
- package/src/loadVwr.test.ts +0 -554
- package/src/loadVwr.ts +0 -363
- package/src/logger.ts +0 -11
- package/src/main.test.ts +0 -157
- package/src/main.ts +0 -128
- package/src/polyfills.ts +0 -32
- package/src/test-setup.ts +0 -5
- package/src/vite-env.d.ts +0 -33
package/src/exitHandler.test.ts
DELETED
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
exitIfBackNavigation,
|
|
5
|
-
setupFireTVBackButtonHandler,
|
|
6
|
-
setupLGBackButtonHandler,
|
|
7
|
-
} from "./exitHandler"
|
|
8
|
-
import { logger } from "./logger"
|
|
9
|
-
|
|
10
|
-
describe("exitHandler", () => {
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
vi.clearAllMocks()
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
afterEach(() => {
|
|
16
|
-
vi.restoreAllMocks()
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
describe("exitIfBackNavigation", () => {
|
|
20
|
-
it("should not exit when navigation type is not back_forward", () => {
|
|
21
|
-
vi.spyOn(performance, "getEntriesByType").mockReturnValue([
|
|
22
|
-
{ type: "navigate" } as PerformanceNavigationTiming,
|
|
23
|
-
])
|
|
24
|
-
|
|
25
|
-
const mockExit = vi.fn()
|
|
26
|
-
window.tizen = {
|
|
27
|
-
application: {
|
|
28
|
-
getAppInfo: () => ({ version: "1.0.0" }),
|
|
29
|
-
getCurrentApplication: () => ({ exit: mockExit }),
|
|
30
|
-
},
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
exitIfBackNavigation("SAMSUNG_TV")
|
|
34
|
-
|
|
35
|
-
expect(mockExit).not.toHaveBeenCalled()
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it("should exit Samsung app when back_forward detected", () => {
|
|
39
|
-
vi.spyOn(performance, "getEntriesByType").mockReturnValue([
|
|
40
|
-
{ type: "back_forward" } as PerformanceNavigationTiming,
|
|
41
|
-
])
|
|
42
|
-
|
|
43
|
-
const mockExit = vi.fn()
|
|
44
|
-
window.tizen = {
|
|
45
|
-
application: {
|
|
46
|
-
getAppInfo: () => ({ version: "1.0.0" }),
|
|
47
|
-
getCurrentApplication: () => ({ exit: mockExit }),
|
|
48
|
-
},
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
exitIfBackNavigation("SAMSUNG_TV")
|
|
52
|
-
|
|
53
|
-
expect(mockExit).toHaveBeenCalled()
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it("should close window for LG app when back_forward detected", () => {
|
|
57
|
-
vi.spyOn(performance, "getEntriesByType").mockReturnValue([
|
|
58
|
-
{ type: "back_forward" } as PerformanceNavigationTiming,
|
|
59
|
-
])
|
|
60
|
-
|
|
61
|
-
const mockClose = vi.fn()
|
|
62
|
-
vi.spyOn(window, "close").mockImplementation(mockClose)
|
|
63
|
-
|
|
64
|
-
exitIfBackNavigation("LG_TV")
|
|
65
|
-
|
|
66
|
-
expect(mockClose).toHaveBeenCalled()
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it("should not exit when no navigation entries exist", () => {
|
|
70
|
-
vi.spyOn(performance, "getEntriesByType").mockReturnValue([])
|
|
71
|
-
|
|
72
|
-
const mockClose = vi.fn()
|
|
73
|
-
vi.spyOn(window, "close").mockImplementation(mockClose)
|
|
74
|
-
|
|
75
|
-
exitIfBackNavigation("LG_TV")
|
|
76
|
-
|
|
77
|
-
expect(mockClose).not.toHaveBeenCalled()
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
it("should handle errors gracefully", () => {
|
|
81
|
-
vi.spyOn(performance, "getEntriesByType").mockImplementation(() => {
|
|
82
|
-
throw new Error("Performance API not available")
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
// Should not throw
|
|
86
|
-
expect(() => exitIfBackNavigation("SAMSUNG_TV")).not.toThrow()
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it("should exit Fire TV app when back_forward detected", () => {
|
|
90
|
-
vi.spyOn(performance, "getEntriesByType").mockReturnValue([
|
|
91
|
-
{ type: "back_forward" } as PerformanceNavigationTiming,
|
|
92
|
-
])
|
|
93
|
-
|
|
94
|
-
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
95
|
-
window.Capacitor = {
|
|
96
|
-
Plugins: {
|
|
97
|
-
AppLifecycle: { exitApp: mockExitApp },
|
|
98
|
-
},
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
exitIfBackNavigation("FIRE_TV")
|
|
102
|
-
|
|
103
|
-
expect(mockExitApp).toHaveBeenCalled()
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
it("should handle Fire TV without Capacitor gracefully", () => {
|
|
107
|
-
vi.spyOn(performance, "getEntriesByType").mockReturnValue([
|
|
108
|
-
{ type: "back_forward" } as PerformanceNavigationTiming,
|
|
109
|
-
])
|
|
110
|
-
|
|
111
|
-
window.Capacitor = undefined
|
|
112
|
-
|
|
113
|
-
expect(() => exitIfBackNavigation("FIRE_TV")).not.toThrow()
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
it("should log when Fire TV exit promise rejects", async () => {
|
|
117
|
-
vi.spyOn(performance, "getEntriesByType").mockReturnValue([
|
|
118
|
-
{ type: "back_forward" } as PerformanceNavigationTiming,
|
|
119
|
-
])
|
|
120
|
-
|
|
121
|
-
const mockExitApp = vi
|
|
122
|
-
.fn()
|
|
123
|
-
.mockRejectedValue(new Error("exit failed"))
|
|
124
|
-
const loggerErrorSpy = vi.spyOn(logger, "error")
|
|
125
|
-
|
|
126
|
-
window.Capacitor = {
|
|
127
|
-
Plugins: {
|
|
128
|
-
AppLifecycle: { exitApp: mockExitApp },
|
|
129
|
-
},
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
exitIfBackNavigation("FIRE_TV")
|
|
133
|
-
|
|
134
|
-
await vi.waitFor(() => {
|
|
135
|
-
expect(loggerErrorSpy).toHaveBeenCalledWith(
|
|
136
|
-
{ error: expect.any(Error) },
|
|
137
|
-
"[Shell] Failed to exit Fire TV app"
|
|
138
|
-
)
|
|
139
|
-
})
|
|
140
|
-
})
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
describe("setupFireTVBackButtonHandler", () => {
|
|
144
|
-
const ANDROID_BACK_KEYCODE = 4
|
|
145
|
-
type KeyDownListener = (event: { keyCode: number }) => void
|
|
146
|
-
|
|
147
|
-
it("should call Capacitor AppLifecycle.exitApp when InputHandler emits back keyDown", async () => {
|
|
148
|
-
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
149
|
-
const mockRemoveListener = vi.fn().mockResolvedValue(undefined)
|
|
150
|
-
let capturedListener: KeyDownListener | null = null
|
|
151
|
-
const mockAddListener = vi
|
|
152
|
-
.fn()
|
|
153
|
-
.mockImplementation(
|
|
154
|
-
async (eventName: string, listener: KeyDownListener) => {
|
|
155
|
-
if (eventName === "keyDown") {
|
|
156
|
-
capturedListener = listener
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return {
|
|
160
|
-
remove: mockRemoveListener,
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
window.Capacitor = {
|
|
166
|
-
Plugins: {
|
|
167
|
-
AppLifecycle: { exitApp: mockExitApp },
|
|
168
|
-
InputHandler: {
|
|
169
|
-
addListener: mockAddListener,
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const cleanup = setupFireTVBackButtonHandler()
|
|
175
|
-
|
|
176
|
-
await vi.waitFor(() => {
|
|
177
|
-
expect(mockAddListener).toHaveBeenCalledWith(
|
|
178
|
-
"keyDown",
|
|
179
|
-
expect.any(Function)
|
|
180
|
-
)
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
capturedListener?.({ keyCode: ANDROID_BACK_KEYCODE })
|
|
184
|
-
|
|
185
|
-
expect(mockExitApp).toHaveBeenCalled()
|
|
186
|
-
|
|
187
|
-
cleanup()
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
it("should handle missing Capacitor gracefully", () => {
|
|
191
|
-
window.Capacitor = undefined
|
|
192
|
-
|
|
193
|
-
const cleanup = setupFireTVBackButtonHandler()
|
|
194
|
-
|
|
195
|
-
expect(() => cleanup()).not.toThrow()
|
|
196
|
-
cleanup()
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
it("should not trigger when InputHandler emits non-back keyDown", async () => {
|
|
200
|
-
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
201
|
-
let capturedListener: KeyDownListener | null = null
|
|
202
|
-
const mockAddListener = vi
|
|
203
|
-
.fn()
|
|
204
|
-
.mockImplementation(
|
|
205
|
-
async (eventName: string, listener: KeyDownListener) => {
|
|
206
|
-
if (eventName === "keyDown") {
|
|
207
|
-
capturedListener = listener
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return {
|
|
211
|
-
remove: vi.fn().mockResolvedValue(undefined),
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
window.Capacitor = {
|
|
217
|
-
Plugins: {
|
|
218
|
-
AppLifecycle: { exitApp: mockExitApp },
|
|
219
|
-
InputHandler: {
|
|
220
|
-
addListener: mockAddListener,
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const cleanup = setupFireTVBackButtonHandler()
|
|
226
|
-
|
|
227
|
-
await vi.waitFor(() => {
|
|
228
|
-
expect(mockAddListener).toHaveBeenCalledWith(
|
|
229
|
-
"keyDown",
|
|
230
|
-
expect.any(Function)
|
|
231
|
-
)
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
capturedListener?.({ keyCode: 13 })
|
|
235
|
-
|
|
236
|
-
expect(mockExitApp).not.toHaveBeenCalled()
|
|
237
|
-
|
|
238
|
-
cleanup()
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
it("should remove InputHandler listener when cleanup is called", async () => {
|
|
242
|
-
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
243
|
-
const mockRemoveListener = vi.fn().mockResolvedValue(undefined)
|
|
244
|
-
const mockAddListener = vi.fn().mockResolvedValue({
|
|
245
|
-
remove: mockRemoveListener,
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
window.Capacitor = {
|
|
249
|
-
Plugins: {
|
|
250
|
-
AppLifecycle: { exitApp: mockExitApp },
|
|
251
|
-
InputHandler: {
|
|
252
|
-
addListener: mockAddListener,
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const cleanup = setupFireTVBackButtonHandler()
|
|
258
|
-
|
|
259
|
-
await vi.waitFor(() => {
|
|
260
|
-
expect(mockAddListener).toHaveBeenCalledWith(
|
|
261
|
-
"keyDown",
|
|
262
|
-
expect.any(Function)
|
|
263
|
-
)
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
cleanup()
|
|
267
|
-
|
|
268
|
-
await vi.waitFor(() => {
|
|
269
|
-
expect(mockRemoveListener).toHaveBeenCalled()
|
|
270
|
-
})
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
it("should support InputHandler addListener returning a sync handle", async () => {
|
|
274
|
-
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
275
|
-
const mockRemoveListener = vi.fn().mockResolvedValue(undefined)
|
|
276
|
-
let capturedListener: KeyDownListener | null = null
|
|
277
|
-
const mockAddListener = vi
|
|
278
|
-
.fn()
|
|
279
|
-
.mockImplementation(
|
|
280
|
-
(eventName: string, listener: KeyDownListener) => {
|
|
281
|
-
if (eventName === "keyDown") {
|
|
282
|
-
capturedListener = listener
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return {
|
|
286
|
-
remove: mockRemoveListener,
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
)
|
|
290
|
-
|
|
291
|
-
window.Capacitor = {
|
|
292
|
-
Plugins: {
|
|
293
|
-
AppLifecycle: { exitApp: mockExitApp },
|
|
294
|
-
InputHandler: {
|
|
295
|
-
addListener: mockAddListener,
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const cleanup = setupFireTVBackButtonHandler()
|
|
301
|
-
|
|
302
|
-
expect(mockAddListener).toHaveBeenCalledWith(
|
|
303
|
-
"keyDown",
|
|
304
|
-
expect.any(Function)
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
capturedListener?.({ keyCode: ANDROID_BACK_KEYCODE })
|
|
308
|
-
expect(mockExitApp).toHaveBeenCalled()
|
|
309
|
-
|
|
310
|
-
cleanup()
|
|
311
|
-
|
|
312
|
-
await vi.waitFor(() => {
|
|
313
|
-
expect(mockRemoveListener).toHaveBeenCalled()
|
|
314
|
-
})
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
it("should handle missing InputHandler plugin gracefully", () => {
|
|
318
|
-
const mockExitApp = vi.fn().mockResolvedValue(undefined)
|
|
319
|
-
window.Capacitor = {
|
|
320
|
-
Plugins: {
|
|
321
|
-
AppLifecycle: { exitApp: mockExitApp },
|
|
322
|
-
},
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const cleanup = setupFireTVBackButtonHandler()
|
|
326
|
-
|
|
327
|
-
expect(mockExitApp).not.toHaveBeenCalled()
|
|
328
|
-
expect(() => cleanup()).not.toThrow()
|
|
329
|
-
})
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
describe("setupLGBackButtonHandler", () => {
|
|
333
|
-
const LG_BACK_KEYCODE = 461
|
|
334
|
-
|
|
335
|
-
it("should call webOS.platformBack when back button is pressed", () => {
|
|
336
|
-
const mockPlatformBack = vi.fn()
|
|
337
|
-
window.webOS = { platformBack: mockPlatformBack }
|
|
338
|
-
|
|
339
|
-
const cleanup = setupLGBackButtonHandler()
|
|
340
|
-
|
|
341
|
-
// Simulate LG back button press
|
|
342
|
-
const event = new KeyboardEvent("keydown", {
|
|
343
|
-
keyCode: LG_BACK_KEYCODE,
|
|
344
|
-
})
|
|
345
|
-
document.dispatchEvent(event)
|
|
346
|
-
|
|
347
|
-
expect(mockPlatformBack).toHaveBeenCalled()
|
|
348
|
-
|
|
349
|
-
cleanup()
|
|
350
|
-
})
|
|
351
|
-
|
|
352
|
-
it("should fall back to window.close when platformBack is not available", () => {
|
|
353
|
-
window.webOS = {} // No platformBack
|
|
354
|
-
const mockClose = vi.fn()
|
|
355
|
-
vi.spyOn(window, "close").mockImplementation(mockClose)
|
|
356
|
-
|
|
357
|
-
const cleanup = setupLGBackButtonHandler()
|
|
358
|
-
|
|
359
|
-
const event = new KeyboardEvent("keydown", {
|
|
360
|
-
keyCode: LG_BACK_KEYCODE,
|
|
361
|
-
})
|
|
362
|
-
document.dispatchEvent(event)
|
|
363
|
-
|
|
364
|
-
expect(mockClose).toHaveBeenCalled()
|
|
365
|
-
|
|
366
|
-
cleanup()
|
|
367
|
-
})
|
|
368
|
-
|
|
369
|
-
it("should not trigger on other key presses", () => {
|
|
370
|
-
const mockPlatformBack = vi.fn()
|
|
371
|
-
window.webOS = { platformBack: mockPlatformBack }
|
|
372
|
-
|
|
373
|
-
const cleanup = setupLGBackButtonHandler()
|
|
374
|
-
|
|
375
|
-
// Simulate a different key press (Enter = 13)
|
|
376
|
-
const event = new KeyboardEvent("keydown", { keyCode: 13 })
|
|
377
|
-
document.dispatchEvent(event)
|
|
378
|
-
|
|
379
|
-
expect(mockPlatformBack).not.toHaveBeenCalled()
|
|
380
|
-
|
|
381
|
-
cleanup()
|
|
382
|
-
})
|
|
383
|
-
|
|
384
|
-
it("should remove event listener when cleanup is called", () => {
|
|
385
|
-
const mockPlatformBack = vi.fn()
|
|
386
|
-
window.webOS = { platformBack: mockPlatformBack }
|
|
387
|
-
|
|
388
|
-
const cleanup = setupLGBackButtonHandler()
|
|
389
|
-
cleanup()
|
|
390
|
-
|
|
391
|
-
// Simulate back button press after cleanup
|
|
392
|
-
const event = new KeyboardEvent("keydown", {
|
|
393
|
-
keyCode: LG_BACK_KEYCODE,
|
|
394
|
-
})
|
|
395
|
-
document.dispatchEvent(event)
|
|
396
|
-
|
|
397
|
-
expect(mockPlatformBack).not.toHaveBeenCalled()
|
|
398
|
-
})
|
|
399
|
-
|
|
400
|
-
it("should handle missing webOS object gracefully", () => {
|
|
401
|
-
window.webOS = undefined
|
|
402
|
-
const mockClose = vi.fn()
|
|
403
|
-
vi.spyOn(window, "close").mockImplementation(mockClose)
|
|
404
|
-
|
|
405
|
-
const cleanup = setupLGBackButtonHandler()
|
|
406
|
-
|
|
407
|
-
const event = new KeyboardEvent("keydown", {
|
|
408
|
-
keyCode: LG_BACK_KEYCODE,
|
|
409
|
-
})
|
|
410
|
-
document.dispatchEvent(event)
|
|
411
|
-
|
|
412
|
-
expect(mockClose).toHaveBeenCalled()
|
|
413
|
-
|
|
414
|
-
cleanup()
|
|
415
|
-
})
|
|
416
|
-
})
|
|
417
|
-
})
|
package/src/exitHandler.ts
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Back button / exit handling for vwr-loader.
|
|
3
|
-
*
|
|
4
|
-
* This is a safety net for when VWR fails to load and user presses back.
|
|
5
|
-
* When VWR loads successfully, it handles exit behavior itself.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { logger } from "./logger"
|
|
9
|
-
|
|
10
|
-
/** LG webOS back button keycode */
|
|
11
|
-
const LG_BACK_KEYCODE = 461
|
|
12
|
-
|
|
13
|
-
/** Android back button keycode (used by Fire TV InputHandler plugin) */
|
|
14
|
-
const ANDROID_BACK_KEYCODE = 4
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Exit the app if the page was loaded via back/forward navigation.
|
|
18
|
-
*
|
|
19
|
-
* This is a safety net for Samsung/LG TVs: if VWR failed to load and user
|
|
20
|
-
* pressed back, they'd land on the loader again. This detects that and exits.
|
|
21
|
-
*
|
|
22
|
-
* Note: On LG TV with disableBackHistoryAPI: true, this won't trigger
|
|
23
|
-
* because the platform doesn't automatically navigate back. Use
|
|
24
|
-
* setupLGBackButtonHandler() for LG back button support.
|
|
25
|
-
*/
|
|
26
|
-
export function exitIfBackNavigation(platform: Platform): void {
|
|
27
|
-
try {
|
|
28
|
-
const navEntries = performance.getEntriesByType("navigation")
|
|
29
|
-
const navEntry = navEntries[0] as
|
|
30
|
-
| PerformanceNavigationTiming
|
|
31
|
-
| undefined
|
|
32
|
-
|
|
33
|
-
if (navEntry?.type === "back_forward") {
|
|
34
|
-
logger.info(
|
|
35
|
-
{ platform, navigationType: navEntry.type },
|
|
36
|
-
"[Shell] Back navigation detected, exiting app"
|
|
37
|
-
)
|
|
38
|
-
exitApp(platform)
|
|
39
|
-
}
|
|
40
|
-
} catch (error) {
|
|
41
|
-
// Performance API may not be available on all platforms
|
|
42
|
-
logger.warn({ error }, "[Shell] Could not check navigation type")
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Set up LG back button (keycode 461) handler.
|
|
48
|
-
*
|
|
49
|
-
* On LG TV with disableBackHistoryAPI: true in appinfo.json, the platform
|
|
50
|
-
* doesn't automatically handle the back button. This sets up a keydown
|
|
51
|
-
* listener to call webOS.platformBack() which shows the system exit popup
|
|
52
|
-
* on webOS 6.0+ or launches Home on older versions.
|
|
53
|
-
*
|
|
54
|
-
* Once VWR loads successfully, call the returned cleanup function - VWR/PSDK
|
|
55
|
-
* will take over back button handling with its own custom modal.
|
|
56
|
-
*
|
|
57
|
-
* @returns Cleanup function to remove the listener
|
|
58
|
-
*/
|
|
59
|
-
export function setupLGBackButtonHandler(): () => void {
|
|
60
|
-
const handleKeyDown = (event: KeyboardEvent): void => {
|
|
61
|
-
if (event.keyCode === LG_BACK_KEYCODE) {
|
|
62
|
-
logger.info(
|
|
63
|
-
"[Shell] LG back button pressed, triggering platform exit"
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
if (window.webOS?.platformBack) {
|
|
67
|
-
window.webOS.platformBack()
|
|
68
|
-
} else {
|
|
69
|
-
logger.warn(
|
|
70
|
-
"[Shell] webOS.platformBack not available, using window.close"
|
|
71
|
-
)
|
|
72
|
-
window.close()
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
document.addEventListener("keydown", handleKeyDown)
|
|
78
|
-
logger.info("[Shell] LG back button handler registered")
|
|
79
|
-
|
|
80
|
-
return () => {
|
|
81
|
-
document.removeEventListener("keydown", handleKeyDown)
|
|
82
|
-
logger.info("[Shell] LG back button handler removed")
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Set up Fire TV back button (keycode 4) handler.
|
|
88
|
-
*
|
|
89
|
-
* On Fire TV, the native shell intercepts the back button at the Activity
|
|
90
|
-
* level and forwards it to JavaScript via the InputHandler Capacitor plugin.
|
|
91
|
-
* During the vwr-loader loading phase, we subscribe directly to InputHandler
|
|
92
|
-
* keyDown events and call Capacitor AppLifecycle.exitApp().
|
|
93
|
-
*
|
|
94
|
-
* Once VWR loads successfully, call the returned cleanup function - VWR
|
|
95
|
-
* will take over back button handling.
|
|
96
|
-
*
|
|
97
|
-
* @returns Cleanup function to remove the listener
|
|
98
|
-
*/
|
|
99
|
-
export function setupFireTVBackButtonHandler(): () => void {
|
|
100
|
-
const inputHandler = window.Capacitor?.Plugins?.InputHandler
|
|
101
|
-
|
|
102
|
-
if (!inputHandler?.addListener) {
|
|
103
|
-
logger.warn("[Shell] Capacitor InputHandler plugin not available")
|
|
104
|
-
return () => {
|
|
105
|
-
logger.info("[Shell] Fire TV back button handler removed")
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
let listenerHandle: { remove: () => Promise<void> | void } | null = null
|
|
110
|
-
let isCleanedUp = false
|
|
111
|
-
|
|
112
|
-
const listenerRegistration = Promise.resolve(
|
|
113
|
-
inputHandler.addListener("keyDown", (event: { keyCode: number }) => {
|
|
114
|
-
if (event.keyCode === ANDROID_BACK_KEYCODE) {
|
|
115
|
-
logger.info("[Shell] Fire TV back button pressed, exiting app")
|
|
116
|
-
exitFireTVApp()
|
|
117
|
-
}
|
|
118
|
-
})
|
|
119
|
-
)
|
|
120
|
-
.then((handle: { remove: () => Promise<void> | void }) => {
|
|
121
|
-
listenerHandle = handle
|
|
122
|
-
|
|
123
|
-
if (isCleanedUp) {
|
|
124
|
-
return Promise.resolve(handle.remove()).catch(
|
|
125
|
-
(error: unknown) => {
|
|
126
|
-
logger.error(
|
|
127
|
-
{ error },
|
|
128
|
-
"[Shell] Failed to remove Fire TV back button handler"
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return undefined
|
|
135
|
-
})
|
|
136
|
-
.catch((error: unknown) => {
|
|
137
|
-
logger.error(
|
|
138
|
-
{ error },
|
|
139
|
-
"[Shell] Failed to register Fire TV back button handler"
|
|
140
|
-
)
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
logger.info("[Shell] Fire TV back button handler registered")
|
|
144
|
-
|
|
145
|
-
return () => {
|
|
146
|
-
isCleanedUp = true
|
|
147
|
-
|
|
148
|
-
if (listenerHandle) {
|
|
149
|
-
void Promise.resolve(listenerHandle.remove()).catch(
|
|
150
|
-
(error: unknown) => {
|
|
151
|
-
logger.error(
|
|
152
|
-
{ error },
|
|
153
|
-
"[Shell] Failed to remove Fire TV back button handler"
|
|
154
|
-
)
|
|
155
|
-
}
|
|
156
|
-
)
|
|
157
|
-
listenerHandle = null
|
|
158
|
-
} else {
|
|
159
|
-
void listenerRegistration
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
logger.info("[Shell] Fire TV back button handler removed")
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Exit the app using platform-specific methods.
|
|
168
|
-
*
|
|
169
|
-
* @param platform - Platform identifier
|
|
170
|
-
*/
|
|
171
|
-
function exitApp(platform: Platform): void {
|
|
172
|
-
switch (platform) {
|
|
173
|
-
case "SAMSUNG_TV":
|
|
174
|
-
exitSamsungApp()
|
|
175
|
-
break
|
|
176
|
-
case "LG_TV":
|
|
177
|
-
exitLGAppViaBackNavigation()
|
|
178
|
-
break
|
|
179
|
-
case "FIRE_TV":
|
|
180
|
-
exitFireTVApp()
|
|
181
|
-
break
|
|
182
|
-
// Mobile apps handle exit at the native layer
|
|
183
|
-
// Web doesn't have a meaningful "exit" concept
|
|
184
|
-
default:
|
|
185
|
-
logger.info({ platform }, "[Shell] No platform-specific exit")
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function exitSamsungApp(): void {
|
|
190
|
-
try {
|
|
191
|
-
if (window.tizen?.application?.getCurrentApplication) {
|
|
192
|
-
window.tizen.application.getCurrentApplication().exit()
|
|
193
|
-
} else {
|
|
194
|
-
logger.warn("[Shell] Tizen exit API not available")
|
|
195
|
-
}
|
|
196
|
-
} catch (error) {
|
|
197
|
-
logger.error({ error }, "[Shell] Failed to exit Samsung app")
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Exit LG app when back navigation is detected.
|
|
203
|
-
* Uses window.close() for immediate exit since user already navigated back.
|
|
204
|
-
*/
|
|
205
|
-
function exitLGAppViaBackNavigation(): void {
|
|
206
|
-
try {
|
|
207
|
-
window.close()
|
|
208
|
-
} catch (error) {
|
|
209
|
-
logger.error({ error }, "[Shell] Failed to exit LG app")
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Exit Fire TV app via Capacitor AppLifecycle plugin.
|
|
215
|
-
*/
|
|
216
|
-
function exitFireTVApp(): void {
|
|
217
|
-
try {
|
|
218
|
-
if (window.Capacitor?.Plugins?.AppLifecycle?.exitApp) {
|
|
219
|
-
void window.Capacitor.Plugins.AppLifecycle.exitApp().catch(
|
|
220
|
-
(error: unknown) => {
|
|
221
|
-
logger.error(
|
|
222
|
-
{ error },
|
|
223
|
-
"[Shell] Failed to exit Fire TV app"
|
|
224
|
-
)
|
|
225
|
-
}
|
|
226
|
-
)
|
|
227
|
-
} else {
|
|
228
|
-
logger.warn("[Shell] Capacitor AppLifecycle plugin not available")
|
|
229
|
-
}
|
|
230
|
-
} catch (error) {
|
|
231
|
-
logger.error({ error }, "[Shell] Failed to exit Fire TV app")
|
|
232
|
-
}
|
|
233
|
-
}
|