You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
830 lines
22 KiB
830 lines
22 KiB
/**
|
|
* Daily Notification Plugin Definitions
|
|
*
|
|
* TypeScript definitions for the Daily Notification Plugin
|
|
* Aligned with Android implementation and test requirements
|
|
*
|
|
* @author Matthew Raymer
|
|
* @version 2.0.0
|
|
*/
|
|
|
|
export interface NotificationResponse {
|
|
id: string;
|
|
title: string;
|
|
body: string;
|
|
timestamp: number;
|
|
url?: string;
|
|
}
|
|
|
|
export interface NotificationOptions {
|
|
url?: string;
|
|
time?: string;
|
|
title?: string;
|
|
body?: string;
|
|
sound?: boolean;
|
|
priority?: 'high' | 'default' | 'low' | 'min' | 'max' | 'normal';
|
|
timezone?: string;
|
|
retryCount?: number;
|
|
retryInterval?: number;
|
|
offlineFallback?: boolean;
|
|
contentHandler?: ContentHandler;
|
|
headers?: Record<string, string>;
|
|
}
|
|
|
|
export interface ContentHandler {
|
|
(response?: any): Promise<{ title: string; body: string; data?: any }>;
|
|
}
|
|
|
|
|
|
|
|
export interface ScheduleOptions {
|
|
url?: string;
|
|
time?: string;
|
|
sound?: boolean;
|
|
priority?: 'high' | 'default' | 'low' | 'min' | 'max' | 'normal';
|
|
timezone?: string;
|
|
retryCount?: number;
|
|
retryInterval?: number;
|
|
offlineFallback?: boolean;
|
|
contentHandler?: ContentHandler;
|
|
headers?: Record<string, string>;
|
|
}
|
|
|
|
export interface NotificationSettings {
|
|
url?: string;
|
|
time?: string;
|
|
sound?: boolean;
|
|
priority?: string;
|
|
timezone?: string;
|
|
retryCount?: number;
|
|
retryInterval?: number;
|
|
offlineFallback?: boolean;
|
|
}
|
|
|
|
export interface NotificationStatus {
|
|
isEnabled?: boolean;
|
|
isScheduled?: boolean;
|
|
lastNotificationTime: number | Promise<number>;
|
|
nextNotificationTime: number | Promise<number>;
|
|
pending?: number;
|
|
settings: NotificationSettings;
|
|
error?: string;
|
|
}
|
|
|
|
export interface BatteryStatus {
|
|
level: number;
|
|
isCharging: boolean;
|
|
powerState: number;
|
|
isOptimizationExempt: boolean;
|
|
}
|
|
|
|
export interface PowerState {
|
|
powerState: number;
|
|
isOptimizationExempt: boolean;
|
|
}
|
|
|
|
export interface NotificationEvent extends Event {
|
|
detail: {
|
|
id: string;
|
|
action: string;
|
|
data?: any;
|
|
};
|
|
}
|
|
|
|
export interface PermissionStatus {
|
|
status?: string;
|
|
granted?: boolean;
|
|
notifications: PermissionState;
|
|
backgroundRefresh?: PermissionState; // iOS only
|
|
alert?: boolean;
|
|
badge?: boolean;
|
|
sound?: boolean;
|
|
lockScreen?: boolean;
|
|
carPlay?: boolean;
|
|
}
|
|
|
|
export type PermissionState = 'prompt' | 'prompt-with-rationale' | 'granted' | 'denied' | 'provisional' | 'ephemeral' | 'unknown';
|
|
|
|
// Additional interfaces for enhanced functionality
|
|
export interface NotificationMetrics {
|
|
scheduledTime: number;
|
|
actualDeliveryTime?: number;
|
|
contentAge: number;
|
|
engagement?: 'TAPPED' | 'DISMISSED' | 'IGNORED';
|
|
failureReason?: string;
|
|
platformInfo: PlatformInfo;
|
|
}
|
|
|
|
export interface PlatformInfo {
|
|
oem?: string;
|
|
osVersion: string;
|
|
appState: string;
|
|
}
|
|
|
|
export interface FallbackContent {
|
|
title: string;
|
|
body: string;
|
|
isEmergency: boolean;
|
|
age?: string;
|
|
}
|
|
|
|
export interface CachePolicy {
|
|
maxSize: number;
|
|
evictionPolicy: 'LRU' | 'FIFO' | 'TTL';
|
|
ttl?: number;
|
|
cleanupInterval: number;
|
|
}
|
|
|
|
export interface NetworkConfig {
|
|
timeout: number;
|
|
retryAttempts: number;
|
|
retryDelay: number;
|
|
offlineFallback: boolean;
|
|
}
|
|
|
|
export interface SchedulingConfig {
|
|
exactAlarms: boolean;
|
|
adaptiveScheduling: boolean;
|
|
quietHours?: {
|
|
start: string;
|
|
end: string;
|
|
enabled: boolean;
|
|
};
|
|
timezone: string;
|
|
}
|
|
|
|
export interface ConfigureOptions {
|
|
dbPath?: string;
|
|
storage?: 'shared' | 'tiered';
|
|
ttlSeconds?: number;
|
|
prefetchLeadMinutes?: number;
|
|
maxNotificationsPerDay?: number;
|
|
retentionDays?: number;
|
|
// Phase 2: TimeSafari ActiveDid Integration Enhancement
|
|
activeDidIntegration?: {
|
|
platform: 'android' | 'ios' | 'web' | 'electron';
|
|
storageType: 'plugin-managed' | 'host-managed';
|
|
jwtExpirationSeconds?: number;
|
|
apiServer?: string;
|
|
// Phase 2: Host-provided activeDid configuration
|
|
activeDid?: string; // Initial activeDid from host
|
|
hostCredentials?: {
|
|
platform?: string; // Platform identifier
|
|
accessToken?: string; // Optional access token
|
|
};
|
|
autoSync?: boolean; // Auto-sync activeDid changes
|
|
identityChangeGraceSeconds?: number; // Grace period for activeDid changes
|
|
};
|
|
}
|
|
|
|
// Dual Scheduling System Interfaces
|
|
export interface ContentFetchConfig {
|
|
enabled: boolean;
|
|
schedule: string; // Cron expression
|
|
url?: string;
|
|
headers?: Record<string, string>;
|
|
timeout?: number;
|
|
retryAttempts?: number;
|
|
retryDelay?: number;
|
|
callbacks: {
|
|
apiService?: string;
|
|
database?: string;
|
|
reporting?: string;
|
|
onSuccess?: (data: any) => Promise<void>;
|
|
onError?: (error: Error) => Promise<void>;
|
|
onComplete?: (result: ContentFetchResult) => Promise<void>;
|
|
};
|
|
contentHandler?: ContentHandler;
|
|
cachePolicy?: CachePolicy;
|
|
networkConfig?: NetworkConfig;
|
|
// Phase 2: TimeSafari Endorser.ch API configuration
|
|
timesafariConfig?: {
|
|
activeDid: string; // Required activeDid for authentication
|
|
endpoints?: {
|
|
offersToPerson?: string;
|
|
offersToPlans?: string;
|
|
projectsLastUpdated?: string;
|
|
};
|
|
syncConfig?: {
|
|
enableParallel?: boolean; // Enable parallel API requests
|
|
maxConcurrent?: number; // Max concurrent requests
|
|
batchSize?: number; // Batch size for requests
|
|
};
|
|
credentialConfig?: {
|
|
jwtSecret?: string; // JWT secret for signing
|
|
tokenExpirationMinutes?: number; // Token expiration
|
|
refreshThresholdMinutes?: number; // Refresh threshold
|
|
};
|
|
errorPolicy?: {
|
|
maxRetries?: number;
|
|
backoffMultiplier?: number;
|
|
activeDidChangeRetries?: number; // Special retry for activeDid changes
|
|
};
|
|
};
|
|
}
|
|
|
|
export interface UserNotificationConfig {
|
|
enabled: boolean;
|
|
schedule: string; // Cron expression
|
|
title?: string;
|
|
body?: string;
|
|
sound?: boolean;
|
|
vibration?: boolean;
|
|
priority?: 'low' | 'normal' | 'high';
|
|
badge?: boolean;
|
|
actions?: NotificationAction[];
|
|
category?: string;
|
|
userInfo?: Record<string, any>;
|
|
}
|
|
|
|
export interface NotificationAction {
|
|
id: string;
|
|
title: string;
|
|
icon?: string;
|
|
destructive?: boolean;
|
|
authenticationRequired?: boolean;
|
|
}
|
|
|
|
export interface DualScheduleConfiguration {
|
|
contentFetch: ContentFetchConfig;
|
|
userNotification: UserNotificationConfig;
|
|
relationship?: {
|
|
autoLink: boolean; // Automatically link content to notification
|
|
contentTimeout: number; // How long to wait for content before notification
|
|
fallbackBehavior: 'skip' | 'show_default' | 'retry';
|
|
};
|
|
}
|
|
|
|
export interface ContentFetchResult {
|
|
success: boolean;
|
|
data?: any;
|
|
timestamp: number;
|
|
contentAge: number;
|
|
error?: string;
|
|
retryCount: number;
|
|
metadata?: Record<string, any>;
|
|
}
|
|
|
|
export interface DualScheduleStatus {
|
|
contentFetch: {
|
|
isEnabled: boolean;
|
|
isScheduled: boolean;
|
|
lastFetchTime?: number;
|
|
nextFetchTime?: number;
|
|
lastFetchResult?: ContentFetchResult;
|
|
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;
|
|
};
|
|
}
|
|
|
|
// Enhanced DailyNotificationPlugin interface with dual scheduling
|
|
export interface DailyNotificationPlugin {
|
|
// Configuration methods
|
|
configure(options: ConfigureOptions): Promise<void>;
|
|
|
|
// Rolling window management
|
|
maintainRollingWindow(): Promise<void>;
|
|
getRollingWindowStats(): Promise<{
|
|
stats: string;
|
|
maintenanceNeeded: boolean;
|
|
timeUntilNextMaintenance: number;
|
|
}>;
|
|
|
|
// Exact alarm management
|
|
getExactAlarmStatus(): Promise<{
|
|
supported: boolean;
|
|
enabled: boolean;
|
|
canSchedule: boolean;
|
|
fallbackWindow: string;
|
|
}>;
|
|
requestExactAlarmPermission(): Promise<void>;
|
|
openExactAlarmSettings(): Promise<void>;
|
|
|
|
// Reboot recovery management
|
|
getRebootRecoveryStatus(): Promise<{
|
|
inProgress: boolean;
|
|
lastRecoveryTime: number;
|
|
timeSinceLastRecovery: number;
|
|
recoveryNeeded: boolean;
|
|
}>;
|
|
|
|
// Existing methods
|
|
scheduleDailyNotification(options: NotificationOptions | ScheduleOptions): Promise<void>;
|
|
getLastNotification(): Promise<NotificationResponse | null>;
|
|
cancelAllNotifications(): Promise<void>;
|
|
getNotificationStatus(): Promise<NotificationStatus>;
|
|
updateSettings(settings: NotificationSettings): Promise<void>;
|
|
getBatteryStatus(): Promise<BatteryStatus>;
|
|
requestBatteryOptimizationExemption(): Promise<void>;
|
|
setAdaptiveScheduling(options: { enabled: boolean }): Promise<void>;
|
|
getPowerState(): Promise<PowerState>;
|
|
checkPermissions(): Promise<PermissionStatus>;
|
|
requestPermissions(): Promise<PermissionStatus>;
|
|
|
|
// New dual scheduling methods
|
|
scheduleContentFetch(config: ContentFetchConfig): Promise<void>;
|
|
scheduleUserNotification(config: UserNotificationConfig): Promise<void>;
|
|
scheduleDualNotification(config: DualScheduleConfiguration): Promise<void>;
|
|
getDualScheduleStatus(): Promise<DualScheduleStatus>;
|
|
updateDualScheduleConfig(config: DualScheduleConfiguration): Promise<void>;
|
|
cancelDualSchedule(): Promise<void>;
|
|
pauseDualSchedule(): Promise<void>;
|
|
resumeDualSchedule(): Promise<void>;
|
|
|
|
// Content management methods
|
|
getContentCache(): Promise<Record<string, any>>;
|
|
clearContentCache(): Promise<void>;
|
|
getContentHistory(): Promise<ContentFetchResult[]>;
|
|
|
|
// Callback management methods
|
|
registerCallback(name: string, callback: Function): Promise<void>;
|
|
unregisterCallback(name: string): Promise<void>;
|
|
getRegisteredCallbacks(): Promise<string[]>;
|
|
|
|
// Phase 1: ActiveDid Management Methods (Option A Implementation)
|
|
setActiveDidFromHost(activeDid: string): Promise<void>;
|
|
onActiveDidChange(callback: (newActiveDid: string) => Promise<void>): void;
|
|
refreshAuthenticationForNewIdentity(activeDid: string): Promise<void>;
|
|
clearCacheForNewIdentity(): Promise<void>;
|
|
updateBackgroundTaskIdentity(activeDid: string): Promise<void>;
|
|
}
|
|
|
|
// Phase 1: TimeSafari Endorser.ch API Interfaces
|
|
export interface OffersResponse {
|
|
data: OfferSummaryRecord[];
|
|
hitLimit: boolean;
|
|
}
|
|
|
|
export interface OfferSummaryRecord {
|
|
jwtId: string;
|
|
handleId: string;
|
|
issuedAt: string;
|
|
offeredByDid: string;
|
|
recipientDid: string;
|
|
unit: string;
|
|
amount: number;
|
|
amountGiven: number;
|
|
amountGivenConfirmed: number;
|
|
objectDescription: string;
|
|
validThrough?: string;
|
|
fullClaim?: Record<string, any>;
|
|
}
|
|
|
|
export interface OffersToPlansResponse {
|
|
data: OfferToPlanSummaryRecord[];
|
|
hitLimit: boolean;
|
|
}
|
|
|
|
export interface OfferToPlanSummaryRecord {
|
|
jwtId: string;
|
|
planId: string;
|
|
handleId: string;
|
|
issuedAt: string;
|
|
offeredByDid: string;
|
|
unit: string;
|
|
amount: number;
|
|
amountGiven: number;
|
|
objectDescription: string;
|
|
validThrough?: string;
|
|
}
|
|
|
|
export interface PlansLastUpdatedResponse {
|
|
data: PlanSummaryWithPreviousClaim[];
|
|
hitLimit: boolean;
|
|
}
|
|
|
|
export interface PlanSummaryWithPreviousClaim {
|
|
plan: PlanSummary;
|
|
wrappedClaimBefore?: Record<string, any>;
|
|
}
|
|
|
|
export interface PlanSummary {
|
|
jwtId: string;
|
|
handleId: string;
|
|
name: string;
|
|
description: string;
|
|
issuerDid: string;
|
|
agentDid: string;
|
|
startTime: string;
|
|
endTime: string;
|
|
locLat?: number;
|
|
locLon?: number;
|
|
url?: string;
|
|
};
|
|
|
|
// Phase 2: Detailed TimeSafari Notification Types
|
|
export interface TimeSafariNotificationBundle {
|
|
offersToPerson?: OffersResponse;
|
|
offersToProjects?: OffersToPlansResponse;
|
|
projectUpdates?: PlansLastUpdatedResponse;
|
|
fetchTimestamp: number;
|
|
success: boolean;
|
|
error?: string;
|
|
metadata?: {
|
|
activeDid: string;
|
|
fetchDurationMs: number;
|
|
cachedResponses: number;
|
|
networkResponses: number;
|
|
};
|
|
}
|
|
|
|
export interface TimeSafariUserConfig {
|
|
activeDid: string; // Required for all operations
|
|
lastKnownOfferId?: string;
|
|
lastKnownPlanId?: string;
|
|
starredPlanIds?: string[];
|
|
fetchOffersToPerson?: boolean;
|
|
fetchOffersToProjects?: boolean;
|
|
fetchProjectUpdates?: boolean;
|
|
notificationPreferences?: {
|
|
offers: boolean;
|
|
projects: boolean;
|
|
people: boolean;
|
|
items: boolean;
|
|
};
|
|
}
|
|
|
|
// Enhanced notification types per specification
|
|
export interface TimeSafariOfferNotification {
|
|
type: 'offer';
|
|
subtype: 'new_to_me' | 'changed_to_me' | 'new_to_projects' | 'changed_to_projects' | 'new_to_favorites' | 'changed_to_favorites';
|
|
offer: OfferSummaryRecord;
|
|
relevantProjects?: PlanSummary[];
|
|
notificationPriority: 'high' | 'medium' | 'low';
|
|
}
|
|
|
|
export interface TimeSafariProjectNotification {
|
|
type: 'project';
|
|
subtype: 'local_and_new' | 'local_and_changed' | 'with_content_and_new' | 'favorite_and_changed';
|
|
project: PlanSummary;
|
|
changes?: {
|
|
fields: string[];
|
|
previousValues?: Record<string, any>;
|
|
};
|
|
relevantOffers?: OfferSummaryRecord[];
|
|
notificationPriority: 'high' | 'medium' | 'low';
|
|
}
|
|
|
|
export interface TimeSafariPersonNotification {
|
|
type: 'person';
|
|
subtype: 'local_and_new' | 'local_and_changed' | 'with_content_and_new' | 'favorite_and_changed';
|
|
personDid: string;
|
|
changes?: {
|
|
fields: string[];
|
|
previousValues?: Record<string, any>;
|
|
};
|
|
relevantProjects?: PlanSummary[];
|
|
notificationPriority: 'high' | 'medium' | 'low';
|
|
}
|
|
|
|
export interface TimeSafariItemNotification {
|
|
type: 'item';
|
|
subtype: 'local_and_new' | 'local_and_changed' | 'favorite_and_changed';
|
|
itemId: string;
|
|
changes?: {
|
|
fields: string[];
|
|
previousValues?: Record<string, any>;
|
|
};
|
|
relevantContext?: 'project' | 'offer' | 'person';
|
|
notificationPriority: 'high' | 'medium' | 'low';
|
|
}
|
|
|
|
// Union type for TimeSafari notifications
|
|
export type TimeSafariNotification =
|
|
| TimeSafariOfferNotification
|
|
| TimeSafariProjectNotification
|
|
| TimeSafariPersonNotification
|
|
| TimeSafariItemNotification;
|
|
|
|
// Enhanced ActiveDid Management Events
|
|
export interface ActiveDidChangeEventEnhanced extends ActiveDidChangeEvent {
|
|
sourceComponent: string; // 'host' | 'plugin' | 'background' | 'sync'
|
|
changeReason: 'user_switch' | 'session_expired' | 'background_refresh' | 'setup';
|
|
transitionDurationMs?: number;
|
|
relatedNotifications?: TimeSafariNotification[];
|
|
}
|
|
|
|
// TimeSafari-specific Platform Configuration
|
|
export interface TimeSafariPlatformConfig {
|
|
platform: 'android' | 'ios' | 'web' | 'electron';
|
|
storageType: 'plugin-managed' | 'host-managed';
|
|
syncStrategy: 'immediate' | 'batched' | 'scheduled';
|
|
permissions: {
|
|
notifications: boolean;
|
|
backgroundRefresh: boolean;
|
|
networkAccess: boolean;
|
|
};
|
|
capabilities: {
|
|
pushNotifications: boolean;
|
|
backgroundTasks: boolean;
|
|
identityManagement: boolean;
|
|
cryptoSigning: boolean;
|
|
};
|
|
}
|
|
|
|
export interface ActiveDidIntegrationConfig {
|
|
platform: 'android' | 'ios' | 'web' | 'electron';
|
|
storageType: 'plugin-managed' | 'host-managed';
|
|
jwtExpirationSeconds?: number;
|
|
apiServer?: string;
|
|
};
|
|
|
|
export interface ActiveDidChangeEvent {
|
|
activeDid: string;
|
|
timestamp: number;
|
|
source: 'host' | 'plugin';
|
|
};
|
|
|
|
// MARK: - Phase 3: TimeSafari Background Coordination Interfaces
|
|
|
|
/**
|
|
* Phase 3: Extended DailyNotificationPlugin interface with TimeSafari coordination
|
|
*/
|
|
export interface EnhancedDailyNotificationPlugin extends DailyNotificationPlugin {
|
|
// Phase 1: ActiveDid Management (already extended in parent)
|
|
|
|
// Phase 3: TimeSafari Background Coordination
|
|
coordinateBackgroundTasks(): Promise<void>;
|
|
handleAppLifecycleEvent(event: AppLifecycleEvent): Promise<void>;
|
|
getCoordinationStatus(): Promise<CoordinationStatus>;
|
|
}
|
|
|
|
/**
|
|
* Phase 3: App lifecycle events for TimeSafari coordination
|
|
*/
|
|
export type AppLifecycleEvent =
|
|
| 'app_background'
|
|
| 'app_foreground'
|
|
| 'app_resumed'
|
|
| 'app_paused'
|
|
| 'app_visibility_change'
|
|
| 'app_hidden'
|
|
| 'app_visible'
|
|
| 'app_blur'
|
|
| 'app_focus';
|
|
|
|
/**
|
|
* Phase 3: Coordination status for debugging and monitoring
|
|
*/
|
|
export interface CoordinationStatus {
|
|
platform: 'android' | 'ios' | 'web' | '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[];
|
|
activeDidTracking?: string;
|
|
}
|
|
|
|
/**
|
|
* Phase 3: PlatformServiceMixin coordination configuration
|
|
*/
|
|
export interface PlatformServiceMixinConfig {
|
|
enableAutoCoordination?: boolean;
|
|
coordinationTimeout?: number; // Max time for coordination attempts
|
|
enableLifecycleEvents?: boolean;
|
|
enableBackgroundSync?: boolean;
|
|
enableStatePersistence?: boolean;
|
|
coordinationGracePeriod?: number; // Grace period for coordination
|
|
eventHandlers?: {
|
|
[K in AppLifecycleEvent]?: () => Promise<void>;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Phase 3: WorkManager coordination data
|
|
*/
|
|
export interface WorkManagerCoordinationData {
|
|
timesafariCoordination: boolean;
|
|
coordinationTimestamp: number;
|
|
activeDidTracking: string;
|
|
platformCoordinationVersion?: number;
|
|
coordinationTimeouts?: {
|
|
maxCoordinationAge: number;
|
|
maxExecutionTime: number;
|
|
maxRetryAge: number;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Phase 3: Background execution constraints
|
|
*/
|
|
export interface BackgroundExecutionConstraints {
|
|
devicePowerMode?: 'normal' | 'low_power' | 'critical';
|
|
appForegroundState?: 'foreground' | 'background' | 'inactive';
|
|
activeDidStability?: 'stable' | 'changing' | 'unknown';
|
|
coordinationFreshness?: 'fresh' | 'stale' | 'expired';
|
|
networkAvailability?: 'cellular' | 'wifi' | 'offline';
|
|
batteryLevel?: 'high' | 'medium' | 'low' | 'critical';
|
|
}
|
|
|
|
/**
|
|
* Phase 3: Coordination report
|
|
*/
|
|
export interface CoordinationReport {
|
|
success: boolean;
|
|
operation: string;
|
|
duration: number;
|
|
constraints: BackgroundExecutionConstraints;
|
|
errors?: string[];
|
|
timestamp: number;
|
|
activeDid?: string;
|
|
authUsed: boolean;
|
|
platformSpecific?: Record<string, any>;
|
|
}
|
|
|
|
/**
|
|
* Phase 3: TimeSafari state synchronization data
|
|
*/
|
|
export interface TimeSafariSyncData {
|
|
authenticationState: {
|
|
activeDid: string;
|
|
jwtExpiration?: number;
|
|
tokenRefreshNeeded: boolean;
|
|
};
|
|
notificationState: {
|
|
lastDelivery: number;
|
|
lastDeliveryId?: string;
|
|
pendingDeliveries: string[];
|
|
};
|
|
backgroundTaskState: {
|
|
lastBackgroundExecution: number;
|
|
lastCoordinationSuccess: number;
|
|
pendingCoordinationTasks: string[];
|
|
};
|
|
activeDidHistory: {
|
|
changes: Array<{
|
|
did: string;
|
|
timestamp: number;
|
|
source: string;
|
|
}>;
|
|
pendingUpdates: string[];
|
|
};
|
|
}
|
|
|
|
// MARK: - Phase 4: TimeSafari Notification Types
|
|
|
|
/**
|
|
* Phase 4: TimeSafari-specific notification interfaces
|
|
*/
|
|
export interface TimeSafariNotificationBundle {
|
|
offersToPerson?: OffersResponse;
|
|
offersToProjects?: OffersToPlansResponse;
|
|
projectUpdates?: PlansLastUpdatedResponse;
|
|
fetchTimestamp: number;
|
|
success: boolean;
|
|
error?: string;
|
|
metadata?: {
|
|
activeDid: string;
|
|
fetchDurationMs: number;
|
|
cachedResponses: number;
|
|
networkResponses: number;
|
|
};
|
|
}
|
|
|
|
export interface TimeSafariUserConfig {
|
|
activeDid: string;
|
|
starredPlanIds?: string[];
|
|
lastKnownOfferId?: string;
|
|
lastKnownPlanId?: string;
|
|
fetchOffersToPerson?: boolean;
|
|
fetchOffersToProjects?: boolean;
|
|
fetchProjectUpdates?: boolean;
|
|
notificationPreferences?: {
|
|
offers: boolean;
|
|
projects: boolean;
|
|
people: boolean;
|
|
items: boolean;
|
|
};
|
|
}
|
|
|
|
// TimeSafari notification subtype types
|
|
export type TimeSafariOfferSubtype =
|
|
| 'new_to_me'
|
|
| 'changed_to_me'
|
|
| 'new_to_projects'
|
|
| 'changed_to_projects'
|
|
| 'new_to_favorites'
|
|
| 'changed_to_favorites';
|
|
|
|
export type TimeSafariProjectSubtype =
|
|
| 'local_and_new'
|
|
| 'local_and_changed'
|
|
| 'with_content_and_new'
|
|
| 'favorite_and_changed';
|
|
|
|
export type TimeSafariPersonSubtype =
|
|
| 'local_and_new'
|
|
| 'local_and_changed'
|
|
| 'with_content_and_new'
|
|
| 'favorite_and_changed';
|
|
|
|
export type TimeSafariItemSubtype =
|
|
| 'local_and_new'
|
|
| 'local_and_changed'
|
|
| 'favorite_and_changed';
|
|
|
|
// Individual notification interfaces
|
|
export interface TimeSafariOfferNotification {
|
|
type: 'offer';
|
|
subtype: TimeSafariOfferSubtype;
|
|
offer: OfferSummaryRecord; // Simplified to single type initially
|
|
relevantProjects?: PlanSummary[];
|
|
notificationPriority: 'high' | 'medium' | 'low';
|
|
timestamp: number;
|
|
}
|
|
|
|
export interface TimeSafariProjectNotification {
|
|
type: 'project';
|
|
subtype: TimeSafariProjectSubtype;
|
|
project: PlanSummary;
|
|
previousClaim?: any; // Previous claim data
|
|
notificationPriority: 'high' | 'medium' | 'low';
|
|
timestamp: number;
|
|
}
|
|
|
|
export interface TimeSafariPersonNotification {
|
|
type: 'person';
|
|
subtype: TimeSafariPersonSubtype;
|
|
person: {
|
|
did: string;
|
|
name?: string;
|
|
};
|
|
notificationPriority: 'high' | 'medium' | 'low';
|
|
timestamp: number;
|
|
personDid: string; // Add missing property
|
|
}
|
|
|
|
export interface TimeSafariItemNotification {
|
|
type: 'item';
|
|
subtype: TimeSafariItemSubtype;
|
|
item: {
|
|
id: string;
|
|
name?: string;
|
|
type?: string;
|
|
};
|
|
notificationPriority: 'high' | 'medium' | 'low';
|
|
timestamp: number;
|
|
itemId: string; // Add missing property
|
|
}
|
|
|
|
// Union type for all TimeSafari notification types
|
|
export type TimeSafariNotificationType =
|
|
| TimeSafariOfferNotification
|
|
| TimeSafariProjectNotification
|
|
| TimeSafariPersonNotification
|
|
| TimeSafariItemNotification;
|
|
|
|
// Enhanced notification interface for Phase 4
|
|
export interface EnhancedTimeSafariNotification {
|
|
type: 'offer' | 'project' | 'person' | 'item';
|
|
subtype: string;
|
|
notificationPriority: 'high' | 'medium' | 'low';
|
|
timestamp: number;
|
|
disabled: boolean;
|
|
sound: boolean;
|
|
vibration: boolean;
|
|
badge: boolean;
|
|
priority: 'low' | 'normal' | 'high';
|
|
metadata?: {
|
|
generatedAt: number;
|
|
platform: string;
|
|
userDid?: string;
|
|
preferencesVersion?: number;
|
|
fallback?: boolean;
|
|
message?: string;
|
|
};
|
|
// Type-specific properties (union approach)
|
|
offer?: OfferSummaryRecord;
|
|
project?: PlanSummary;
|
|
person?: { did: any; name?: string };
|
|
item?: { id: string; name?: string; type?: string };
|
|
relevantProjects?: PlanSummary[];
|
|
previousClaim?: any;
|
|
}
|