// Bridge to the native PollingPlugin (see // android/app/src/main/java/chat/vojo/app/PollingPlugin.java). // // Drives the WorkManager-based /notifications polling fallback used on // networks where FCM (mtalk.google.com:5228) is blocked. JS owns the // credential + room-name cache lifecycle; native owns the periodic fetch // and notification rendering. // // Web has no analogue: the Service Worker already wakes for push without // needing a periodic poll, and browsers don't expose a 15-minute periodic // background API anyway. The web fallback is a no-op. import { registerPlugin } from '@capacitor/core'; import { isAndroidPlatform } from '../utils/capacitor'; export type RoomMetadataMap = Record; interface PollingPluginIface { saveSession(opts: { accessToken: string; homeserverUrl: string; userId?: string }): Promise; clearSession(): Promise; // Tolerant of both legacy (`roomId: "Display"`) and new structured shape // (`roomId: { name, isDirect }`) — the Java side decides the message // channel (DM vs group) based on the structured value when present. saveRoomNames(opts: { names: RoomMetadataMap }): Promise; schedule(opts: { intervalMinutes: number }): Promise; cancel(): Promise; dismissRoom(opts: { roomId: string }): Promise; } const noopPlugin: PollingPluginIface = { saveSession: async () => undefined, clearSession: async () => undefined, saveRoomNames: async () => undefined, schedule: async () => undefined, cancel: async () => undefined, dismissRoom: async () => undefined, }; const plugin = registerPlugin('Polling', { web: noopPlugin, }); const guard = async (fn: () => Promise, fallback: T): Promise => { if (!isAndroidPlatform()) return fallback; try { return await fn(); } catch (err) { // Old APK installed before the plugin shipped, or transient bridge // error. Swallow — polling is a best-effort backup channel, not a // hard dependency on the foreground push lifecycle. // eslint-disable-next-line no-console console.warn('[polling] native call failed:', err); return fallback; } }; export const polling = { saveSession: (opts: { accessToken: string; homeserverUrl: string; userId?: string }) => guard(() => plugin.saveSession(opts), undefined), clearSession: () => guard(() => plugin.clearSession(), undefined), saveRoomNames: (names: RoomMetadataMap) => guard(() => plugin.saveRoomNames({ names }), undefined), schedule: (intervalMinutes = 15) => guard(() => plugin.schedule({ intervalMinutes }), undefined), cancel: () => guard(() => plugin.cancel(), undefined), dismissRoom: (roomId: string) => guard(() => plugin.dismissRoom({ roomId }), undefined), };