|
|
@ -469,4 +469,346 @@ export class DailyNotificationWeb extends WebPlugin implements DailyNotification |
|
|
|
throw error; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// MARK: - Phase 3: Web TimeSafari Coordination Methods
|
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Coordinate background tasks with TimeSafari PlatformServiceMixin |
|
|
|
*/ |
|
|
|
async coordinateBackgroundTasks(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Coordinating background tasks with PlatformServiceMixin'); |
|
|
|
|
|
|
|
// Check visibility state for coordination
|
|
|
|
const visibilityState = document.visibilityState; |
|
|
|
const isBackgrounded = this.isAppBackgrounded(); |
|
|
|
|
|
|
|
console.log('DNP-WEB-PHASE3: App state - visibility:', visibilityState, 'backgrounded:', isBackgrounded); |
|
|
|
|
|
|
|
if (isBackgrounded) { |
|
|
|
// Activate background coordination
|
|
|
|
await this.activateBackgroundCoordination(); |
|
|
|
} else { |
|
|
|
// Pause non-critical coordination for foreground usage
|
|
|
|
await this.pauseNonCriticalCoordination(); |
|
|
|
} |
|
|
|
|
|
|
|
console.log('DNP-WEB-PHASE3: Background task coordination completed'); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error coordinating background tasks:', error); |
|
|
|
throw error; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Handle app lifecycle events for web platform |
|
|
|
*/ |
|
|
|
async handleAppLifecycleEvent(lifecycleEvent: string): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Handling app lifecycle event:', lifecycleEvent); |
|
|
|
|
|
|
|
switch (lifecycleEvent) { |
|
|
|
case 'app_visibility_change': |
|
|
|
await this.handleVisibilityChange(); |
|
|
|
break; |
|
|
|
case 'app_hidden': |
|
|
|
await this.handleAppHidden(); |
|
|
|
break; |
|
|
|
case 'app_visible': |
|
|
|
await this.handleAppVisible(); |
|
|
|
break; |
|
|
|
case 'app_blur': |
|
|
|
await this.handleWindowBlur(); |
|
|
|
break; |
|
|
|
case 'app_focus': |
|
|
|
await this.handleWindowFocus(); |
|
|
|
break; |
|
|
|
default: |
|
|
|
console.warn('DNP-WEB-PHASE3: Unknown lifecycle event:', lifecycleEvent); |
|
|
|
} |
|
|
|
|
|
|
|
console.log('DNP-WEB-PHASE3: Lifecycle event handled:', lifecycleEvent); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error handling lifecycle event:', error); |
|
|
|
throw error; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Check if app is backgrounded on web |
|
|
|
*/ |
|
|
|
private isAppBackgrounded(): boolean { |
|
|
|
try { |
|
|
|
// Check multiple indicators of background state
|
|
|
|
const isHidden = document.visibilityState === 'hidden'; |
|
|
|
const isNotFocused = document.hasFocus() === false; |
|
|
|
const isBlurred = window.blur !== undefined; |
|
|
|
|
|
|
|
const backgrounded = isHidden || isNotFocused || isBlurred; |
|
|
|
|
|
|
|
console.log('DNP-WEB-PHASE3: Background check - hidden:', isHidden, 'focused:', isNotFocused, 'blurred:', isBlurred, 'result:', backgrounded); |
|
|
|
|
|
|
|
return backgrounded; |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error checking background state:', error); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Activate background coordination |
|
|
|
*/ |
|
|
|
private async activateBackgroundCoordination(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Activating background coordination'); |
|
|
|
|
|
|
|
// Store coordination state
|
|
|
|
sessionStorage.setItem('dnp_coordination_active', 'true'); |
|
|
|
sessionStorage.setItem('dnp_coordination_timestamp', Date.now().toString()); |
|
|
|
|
|
|
|
// Set up background coordination listener
|
|
|
|
this.setupBackgroundCoordinationListener(); |
|
|
|
|
|
|
|
console.log('DNP-WEB-PHASE3: Background coordination activated'); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error activating background coordination:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Pause non-critical coordination |
|
|
|
*/ |
|
|
|
private async pauseNonCriticalCoordination(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Pausing non-critical coordination'); |
|
|
|
|
|
|
|
// Store pause state
|
|
|
|
sessionStorage.setItem('dnp_coordination_paused', 'true'); |
|
|
|
sessionStorage.setItem('dnp_coordination_pause_timestamp', Date.now().toString()); |
|
|
|
|
|
|
|
// Remove background coordination listener
|
|
|
|
this.removeBackgroundCoordinationListener(); |
|
|
|
|
|
|
|
console.log('DNP-WEB-PHASE3: Non-critical coordination paused'); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error pausing coordination:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Handle visibility change |
|
|
|
*/ |
|
|
|
private async handleVisibilityChange(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Handling visibility change'); |
|
|
|
|
|
|
|
const isBackgrounded = this.isAppBackgrounded(); |
|
|
|
|
|
|
|
if (isBackgrounded) { |
|
|
|
await this.activateBackgroundCoordination(); |
|
|
|
} else { |
|
|
|
await this.pauseNonCriticalCoordination(); |
|
|
|
// Sync state when coming to foreground
|
|
|
|
await this.syncTimeSafariState(); |
|
|
|
} |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error handling visibility change:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Handle app hidden |
|
|
|
*/ |
|
|
|
private async handleAppHidden(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: App hidden - activating background coordination'); |
|
|
|
|
|
|
|
await this.activateBackgroundCoordination(); |
|
|
|
|
|
|
|
// Store app state
|
|
|
|
sessionStorage.setItem('dnp_app_hidden_timestamp', Date.now().toString()); |
|
|
|
sessionStorage.setItem('dnp_app_is_hidden', 'true'); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error handling app hidden:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Handle app visible |
|
|
|
*/ |
|
|
|
private async handleAppVisible(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: App visible - updating coordination'); |
|
|
|
|
|
|
|
await this.pauseNonCriticalCoordination(); |
|
|
|
|
|
|
|
// Store app state
|
|
|
|
sessionStorage.setItem('dnp_app_visible_timestamp', Date.now().toString()); |
|
|
|
sessionStorage.setItem('dnp_app_is_hidden', 'false'); |
|
|
|
|
|
|
|
// Check activeDid coordination
|
|
|
|
await this.checkActiveDidCoordinationWeb(); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error handling app visible:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Handle window blur |
|
|
|
*/ |
|
|
|
private async handleWindowBlur(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Window blurred - activating background coordination'); |
|
|
|
|
|
|
|
await this.activateBackgroundCoordination(); |
|
|
|
|
|
|
|
sessionStorage.setItem('dnp_window_blur_timestamp', Date.now().toString()); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error handling window blur:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Handle window focus |
|
|
|
*/ |
|
|
|
private async handleWindowFocus(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Window focused - updating coordination'); |
|
|
|
|
|
|
|
await this.pauseNonCriticalCoordination(); |
|
|
|
|
|
|
|
sessionStorage.setItem('dnp_window_focus_timestamp', Date.now().toString()); |
|
|
|
|
|
|
|
// Sync TimeSafari state
|
|
|
|
await this.syncTimeSafariState(); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error handling window focus:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Check activeDid coordination for web |
|
|
|
*/ |
|
|
|
private async checkActiveDidCoordinationWeb(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Checking activeDid coordination'); |
|
|
|
|
|
|
|
const lastActiveDidChange = sessionStorage.getItem('dnp_last_active_did_change'); |
|
|
|
const lastAppVisible = sessionStorage.getItem('dnp_app_visible_timestamp'); |
|
|
|
|
|
|
|
if (lastActiveDidChange && lastAppVisible) { |
|
|
|
const activeDidChangeTime = parseInt(lastActiveDidChange); |
|
|
|
const visibleTime = parseInt(lastAppVisible); |
|
|
|
|
|
|
|
// If activeDid changed while app was hidden, update coordination
|
|
|
|
if (activeDidChangeTime > visibleTime) { |
|
|
|
console.log('DNP-WEB-PHASE3: ActiveDid changed while hidden - updating coordination'); |
|
|
|
|
|
|
|
await this.clearCacheForNewIdentity(); |
|
|
|
await this.refreshAuthenticationForNewIdentity(''); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error checking activeDid coordination:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Sync TimeSafari state for web |
|
|
|
*/ |
|
|
|
private async syncTimeSafariState(): Promise<void> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Syncing TimeSafari state'); |
|
|
|
|
|
|
|
// Sync authentication state (placeholder - implement if needed)
|
|
|
|
console.log('DNP-WEB-PHASE3: Sync authentication state (placeholder)'); |
|
|
|
|
|
|
|
// Sync notification delivery tracking
|
|
|
|
const lastBackgroundDelivery = sessionStorage.getItem('dnp_last_background_delivery'); |
|
|
|
if (lastBackgroundDelivery) { |
|
|
|
const deliveryId = sessionStorage.getItem('dnp_last_background_delivery_id'); |
|
|
|
console.log('DNP-WEB-PHASE3: Synced background delivery:', deliveryId); |
|
|
|
} |
|
|
|
|
|
|
|
console.log('DNP-WEB-PHASE3: TimeSafari state sync completed'); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error syncing TimeSafari state:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Set up background coordination listener |
|
|
|
*/ |
|
|
|
private setupBackgroundCoordinationListener(): void { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Setting up background coordination listener'); |
|
|
|
|
|
|
|
// Listen for visibility changes
|
|
|
|
document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this)); |
|
|
|
|
|
|
|
// Listen for window blur/focus
|
|
|
|
window.addEventListener('blur', this.handleWindowBlur.bind(this)); |
|
|
|
window.addEventListener('focus', this.handleWindowFocus.bind(this)); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error setting up coordination listener:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Remove background coordination listener |
|
|
|
*/ |
|
|
|
private removeBackgroundCoordinationListener(): void { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Removing background coordination listener'); |
|
|
|
|
|
|
|
// Remove listeners (using bound functions)
|
|
|
|
document.removeEventListener('visibilitychange', this.handleVisibilityChange.bind(this)); |
|
|
|
window.removeEventListener('blur', this.handleWindowBlur.bind(this)); |
|
|
|
window.removeEventListener('focus', this.handleWindowFocus.bind(this)); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error removing coordination listener:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Phase 3: Get coordination status for web debugging |
|
|
|
*/ |
|
|
|
async getCoordinationStatus(): Promise<Record<string, any>> { |
|
|
|
try { |
|
|
|
console.log('DNP-WEB-PHASE3: Getting coordination status'); |
|
|
|
|
|
|
|
const status = { |
|
|
|
platform: 'web', |
|
|
|
coordinationActive: sessionStorage.getItem('dnp_coordination_active') === 'true', |
|
|
|
coordinationPaused: sessionStorage.getItem('dnp_coordination_paused') === 'true', |
|
|
|
appHidden: sessionStorage.getItem('dnp_app_is_hidden') === 'true', |
|
|
|
visibilityState: document.visibilityState, |
|
|
|
focused: document.hasFocus(), |
|
|
|
lastActiveDidChange: sessionStorage.getItem('dnp_last_active_did_change'), |
|
|
|
lastCoordinationTimestamp: sessionStorage.getItem('dnp_coordination_timestamp'), |
|
|
|
lastVisibilityChange: sessionStorage.getItem('dnp_app_visible_timestamp') |
|
|
|
}; |
|
|
|
|
|
|
|
console.log('DNP-WEB-PHASE3: Coordination status:', status); |
|
|
|
return status; |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('DNP-WEB-PHASE3: Error getting coordination status:', error); |
|
|
|
throw error; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|