644 lines
16 KiB
TypeScript
644 lines
16 KiB
TypeScript
/**
|
|
* Daily Notification Plugin - Web Implementation
|
|
*
|
|
* Web platform implementation for Capacitor Daily Notification Plugin.
|
|
*
|
|
* **Note:** Daily notifications are not supported on web platforms.
|
|
* This implementation provides clear error messages for all methods.
|
|
*
|
|
* @author Matthew Raymer
|
|
* @version 1.3.1
|
|
*/
|
|
|
|
import type {
|
|
DailyNotificationPlugin,
|
|
PermissionState,
|
|
Schedule,
|
|
ScheduleWithStatus,
|
|
CreateScheduleInput,
|
|
Config,
|
|
CreateConfigInput,
|
|
Callback,
|
|
CreateCallbackInput,
|
|
History,
|
|
HistoryStats,
|
|
PendingNotificationsResult,
|
|
DeliveredNotificationsResult,
|
|
NotificationCenterSettingsSnapshot,
|
|
NotificationPermissionStatus,
|
|
BackgroundTaskStatus,
|
|
} from './definitions';
|
|
import { DailyNotificationError, ErrorCode } from './core/errors';
|
|
|
|
/**
|
|
* Web implementation of DailyNotificationPlugin
|
|
*
|
|
* All methods throw errors indicating that daily notifications
|
|
* are not supported on web platforms.
|
|
*/
|
|
export class DailyNotificationWeb implements DailyNotificationPlugin {
|
|
private throwNotSupported(): never {
|
|
throw new DailyNotificationError(
|
|
ErrorCode.NOT_SUPPORTED,
|
|
'Daily notifications are not supported on web platforms. Please use this plugin on iOS or Android.',
|
|
{
|
|
guidance: 'Use native iOS or Android implementation for this feature',
|
|
platform: 'web'
|
|
}
|
|
);
|
|
}
|
|
|
|
async configure(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async configureNativeFetcher(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async maintainRollingWindow(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getRollingWindowStats(): Promise<{
|
|
stats: string;
|
|
maintenanceNeeded: boolean;
|
|
timeUntilNextMaintenance: number;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getExactAlarmStatus(): Promise<{
|
|
supported: boolean;
|
|
enabled: boolean;
|
|
canSchedule: boolean;
|
|
fallbackWindow: string;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async requestExactAlarmPermission(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async openExactAlarmSettings(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getRebootRecoveryStatus(): Promise<{
|
|
inProgress: boolean;
|
|
lastRecoveryTime: number;
|
|
timeSinceLastRecovery: number;
|
|
recoveryNeeded: boolean;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async scheduleDailyNotification(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async isAlarmScheduled(): Promise<{ scheduled: boolean; triggerAtMillis: number }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getNextAlarmTime(): Promise<{ scheduled: boolean; triggerAtMillis?: number }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async testAlarm(): Promise<{ scheduled: boolean; secondsFromNow: number; triggerAtMillis: number }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getLastNotification(): Promise<null> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async cancelAllNotifications(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async clearApiNotifications(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getNotificationStatus(): Promise<{
|
|
isEnabled?: boolean;
|
|
isScheduled?: boolean;
|
|
lastNotificationTime: number | Promise<number>;
|
|
nextNotificationTime: number | Promise<number>;
|
|
pending?: number;
|
|
settings: Record<string, unknown>;
|
|
error?: string;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async updateSettings(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getBatteryStatus(): Promise<{
|
|
level: number;
|
|
isCharging: boolean;
|
|
powerState: number;
|
|
isOptimizationExempt: boolean;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async requestBatteryOptimizationExemption(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async setAdaptiveScheduling(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getPowerState(): Promise<{
|
|
powerState: number;
|
|
isOptimizationExempt: boolean;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async checkPermissions(): Promise<{
|
|
status?: string;
|
|
granted?: boolean;
|
|
notifications: PermissionState;
|
|
backgroundRefresh?: PermissionState;
|
|
alert?: boolean;
|
|
badge?: boolean;
|
|
sound?: boolean;
|
|
lockScreen?: boolean;
|
|
carPlay?: boolean;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async requestPermissions(): Promise<{
|
|
status?: string;
|
|
granted?: boolean;
|
|
notifications: PermissionState;
|
|
backgroundRefresh?: PermissionState;
|
|
alert?: boolean;
|
|
badge?: boolean;
|
|
sound?: boolean;
|
|
lockScreen?: boolean;
|
|
carPlay?: boolean;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async checkPermissionStatus(): Promise<{
|
|
notificationsEnabled: boolean;
|
|
exactAlarmEnabled: boolean;
|
|
wakeLockEnabled: boolean;
|
|
allPermissionsGranted: boolean;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async requestNotificationPermissions(): Promise<{
|
|
status?: string;
|
|
granted?: boolean;
|
|
notifications: PermissionState;
|
|
backgroundRefresh?: PermissionState;
|
|
alert?: boolean;
|
|
badge?: boolean;
|
|
sound?: boolean;
|
|
lockScreen?: boolean;
|
|
carPlay?: boolean;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getPendingNotifications(): Promise<PendingNotificationsResult> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getDeliveredNotifications(): Promise<DeliveredNotificationsResult> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getNotificationSettings(): Promise<NotificationCenterSettingsSnapshot> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getNotificationPermissionStatus(): Promise<NotificationPermissionStatus> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async requestNotificationPermission(): Promise<{ granted: boolean }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getBackgroundTaskStatus(): Promise<BackgroundTaskStatus> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async openNotificationSettings(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async openBackgroundAppRefreshSettings(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async isChannelEnabled(): Promise<{ enabled: boolean; channelId: string }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async openChannelSettings(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async checkStatus(): Promise<{
|
|
isEnabled?: boolean;
|
|
isScheduled?: boolean;
|
|
lastNotificationTime: number | Promise<number>;
|
|
nextNotificationTime: number | Promise<number>;
|
|
pending?: number;
|
|
settings: Record<string, unknown>;
|
|
error?: string;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async scheduleContentFetch(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async scheduleUserNotification(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async scheduleDualNotification(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getDualScheduleStatus(): Promise<{
|
|
contentFetch: {
|
|
isEnabled: boolean;
|
|
isScheduled: boolean;
|
|
lastFetchTime?: number;
|
|
nextFetchTime?: number;
|
|
lastFetchResult?: {
|
|
success: boolean;
|
|
data?: Record<string, unknown>;
|
|
timestamp: number;
|
|
contentAge: number;
|
|
error?: string;
|
|
retryCount: number;
|
|
metadata?: Record<string, unknown>;
|
|
};
|
|
pendingFetches: number;
|
|
};
|
|
userNotification: {
|
|
isEnabled: boolean;
|
|
isScheduled: boolean;
|
|
lastNotificationTime?: number;
|
|
nextNotificationTime?: number;
|
|
pendingNotifications: number;
|
|
};
|
|
relationship: {
|
|
isLinked: boolean;
|
|
contentAvailable: boolean;
|
|
lastLinkTime?: number;
|
|
};
|
|
overall: {
|
|
isActive: boolean;
|
|
lastActivity: number;
|
|
errorCount: number;
|
|
successRate: number;
|
|
};
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async updateDualScheduleConfig(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async cancelDualSchedule(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async pauseDualSchedule(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async resumeDualSchedule(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getContentCache(): Promise<Record<string, unknown>> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async clearContentCache(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getContentHistory(): Promise<Array<{
|
|
success: boolean;
|
|
data?: Record<string, unknown>;
|
|
timestamp: number;
|
|
contentAge: number;
|
|
error?: string;
|
|
retryCount: number;
|
|
metadata?: Record<string, unknown>;
|
|
}>> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async registerCallback(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async unregisterCallback(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getRegisteredCallbacks(): Promise<string[]> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getSchedules(_options?: { kind?: 'fetch' | 'notify'; enabled?: boolean }): Promise<{ schedules: Schedule[] }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getSchedulesWithStatus(_options?: { kind?: 'fetch' | 'notify'; enabled?: boolean }): Promise<{ schedules: ScheduleWithStatus[] }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getSchedule(_id: string): Promise<Schedule | null> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async createSchedule(_schedule: CreateScheduleInput): Promise<Schedule> {
|
|
// Web stub: no timing needed (throws immediately)
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async updateSchedule(_id: string, _updates: unknown): Promise<Schedule> {
|
|
// Web stub: no timing needed (throws immediately)
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async deleteSchedule(_id: string): Promise<void> {
|
|
// Web stub: no timing needed (throws immediately)
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
/**
|
|
* Get current plugin state (development only)
|
|
* @internal
|
|
*/
|
|
async getDebugState(): Promise<{
|
|
schedules: Schedule[];
|
|
configs: Config[];
|
|
callbacks: Callback[];
|
|
metrics: {
|
|
eventCount: number;
|
|
successRate: number;
|
|
avgFetchTime: number;
|
|
avgNotifyTime: number;
|
|
};
|
|
}> {
|
|
// Web implementation: debug methods not supported
|
|
throw new DailyNotificationError(
|
|
ErrorCode.NOT_SUPPORTED,
|
|
'Debug methods not available on web platform',
|
|
{
|
|
guidance: 'Use native iOS or Android implementation for debug features',
|
|
platform: 'web'
|
|
}
|
|
);
|
|
}
|
|
|
|
async enableSchedule(_id: string, _enabled: boolean): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async calculateNextRunTime(_schedule: string): Promise<number> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getContentCacheById(_options?: { id?: string }): Promise<{
|
|
id: string;
|
|
fetchedAt: number;
|
|
ttlSeconds: number;
|
|
payload: string;
|
|
meta?: string;
|
|
} | null> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getLatestContentCache(): Promise<{
|
|
id: string;
|
|
fetchedAt: number;
|
|
ttlSeconds: number;
|
|
payload: string;
|
|
meta?: string;
|
|
} | null> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getContentCacheHistory(_limit?: number): Promise<{ history: Array<{
|
|
id: string;
|
|
fetchedAt: number;
|
|
ttlSeconds: number;
|
|
payload: string;
|
|
meta?: string;
|
|
}> }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async saveContentCache(_content: unknown): Promise<{
|
|
id: string;
|
|
fetchedAt: number;
|
|
ttlSeconds: number;
|
|
payload: string;
|
|
meta?: string;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async clearContentCacheEntries(_options?: { olderThan?: number }): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getConfig(_key: string, _options?: { timesafariDid?: string }): Promise<Config | null> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getAllConfigs(_options?: { timesafariDid?: string; configType?: string }): Promise<{ configs: Config[] }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async setConfig(_config: CreateConfigInput): Promise<Config> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async updateConfig(_key: string, _value: string, _options?: { timesafariDid?: string }): Promise<Config> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async deleteConfig(_key: string, _options?: { timesafariDid?: string }): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getCallbacks(_options?: { enabled?: boolean }): Promise<{ callbacks: Callback[] }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getCallback(_id: string): Promise<Callback | null> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async registerCallbackConfig(_callback: CreateCallbackInput): Promise<Callback> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async updateCallback(_id: string, _updates: unknown): Promise<Callback> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async deleteCallback(_id: string): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async enableCallback(_id: string, _enabled: boolean): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getHistoryStats(): Promise<HistoryStats> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getHistory(_options?: { since?: number; kind?: 'fetch' | 'notify' | 'callback'; limit?: number }): Promise<{ history: History[] }> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async setActiveDidFromHost(_activeDid: string): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
onActiveDidChange(_callback: (newActiveDid: string) => Promise<void>): void {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
setJsContentFetcher(_fetcher: unknown): void {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async refreshAuthenticationForNewIdentity(_activeDid: string): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async clearCacheForNewIdentity(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async updateBackgroundTaskIdentity(_activeDid: string): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async updateStarredPlans(_options: { planIds: string[] }): Promise<{
|
|
success: boolean;
|
|
planIdsCount: number;
|
|
updatedAt: number;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getStarredPlans(): Promise<{
|
|
planIds: string[];
|
|
count: number;
|
|
updatedAt: number;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async triggerImmediateFetch(): Promise<{
|
|
success: boolean;
|
|
message: string;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async scheduleDailyReminder(_options: unknown): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async cancelDailyReminder(_reminderId: string): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getScheduledReminders(): Promise<Array<{
|
|
id: string;
|
|
title: string;
|
|
body: string;
|
|
time: string;
|
|
sound: boolean;
|
|
vibration: boolean;
|
|
priority: 'low' | 'normal' | 'high';
|
|
repeatDaily: boolean;
|
|
timezone?: string;
|
|
isScheduled: boolean;
|
|
createdAt: number;
|
|
}>> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async updateDailyReminder(_reminderId: string, _options: unknown): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async enableNativeFetcher(_enable: boolean): Promise<{
|
|
enabled: boolean;
|
|
registered: boolean;
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async setPolicy(_policy: unknown): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async coordinateBackgroundTasks(): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async handleAppLifecycleEvent(_event: unknown): Promise<void> {
|
|
this.throwNotSupported();
|
|
}
|
|
|
|
async getCoordinationStatus(): Promise<{
|
|
platform: 'android' | 'ios' | 'electron';
|
|
coordinationActive: boolean;
|
|
coordinationPaused: boolean;
|
|
autoSync?: boolean;
|
|
appBackgrounded?: boolean;
|
|
appHidden?: boolean;
|
|
visibilityState?: DocumentVisibilityState;
|
|
focused?: boolean;
|
|
lastActiveDidChange?: number;
|
|
lastCoordinationTimestamp?: number;
|
|
lastAppBackgrounded?: number;
|
|
lastAppForegrounded?: number;
|
|
lastCoordinationSuccess?: number;
|
|
lastCoordinationFailure?: number;
|
|
coordinationErrors?: string[];
|
|
}> {
|
|
this.throwNotSupported();
|
|
}
|
|
}
|
|
|
|
// Export singleton instance
|
|
const DailyNotification = new DailyNotificationWeb();
|
|
|
|
export { DailyNotification };
|
|
|