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.
 
 
 
 
 
 

15 KiB

TimeSafari PWA - DailyNotification Plugin Integration Guide

Author: Matthew Raymer
Version: 1.0.0
Created: 2025-10-08 06:24:57 UTC

Overview

This guide shows how to integrate the DailyNotification plugin with the existing TimeSafari PWA architecture, specifically the CapacitorPlatformService and PlatformServiceMixin patterns. The integration maintains the same interfaces and patterns while adding enhanced functionality.

TimeSafari PWA Architecture Analysis

Existing Architecture Components

1. CapacitorPlatformService

  • Location: src/services/platforms/CapacitorPlatformService.ts
  • Purpose: Provides native mobile functionality through Capacitor plugins
  • Features: File system, camera, SQLite database operations, platform detection
  • Key Methods: dbQuery, dbExec, takePicture, writeFile, getCapabilities

2. PlatformServiceFactory

  • Location: src/services/PlatformServiceFactory.ts
  • Purpose: Factory pattern for creating platform-specific service implementations
  • Pattern: Singleton pattern with environment-based platform detection
  • Platforms: capacitor, electron, web (default)

3. PlatformServiceMixin

  • Location: src/utils/PlatformServiceMixin.ts
  • Purpose: Vue.js mixin providing cached platform service access and utility methods
  • Features: Database operations, settings management, contact management, logging
  • Key Methods: $db, $exec, $settings, $contacts, $saveSettings

Existing TimeSafari Patterns

1. Settings Management

// Existing TimeSafari settings pattern
const settings = await this.$settings();
const activeDid = settings.activeDid;
const starredPlanHandleIds = settings.starredPlanHandleIds;
const apiServer = settings.apiServer;

2. Database Operations

// Existing TimeSafari database pattern
const result = await this.$dbQuery("SELECT * FROM settings WHERE id = 1");
const contacts = await this.$contacts();
await this.$saveSettings({ starredPlanHandleIds: newIds });

3. Platform Detection

// Existing TimeSafari platform detection
if (this.isCapacitor) {
  // Native mobile functionality
} else {
  // Web browser functionality
}

DailyNotification Plugin Integration

Integration Strategy

The DailyNotification plugin integrates with the existing TimeSafari PWA architecture by:

  1. Extending CapacitorPlatformService: Adding DailyNotification functionality to the existing platform service
  2. Using PlatformServiceMixin: Leveraging existing database and settings patterns
  3. Maintaining Interfaces: Keeping the same method signatures and behavior
  4. Platform Detection: Only initializing on Capacitor platforms

Enhanced CapacitorPlatformService

export class EnhancedCapacitorPlatformService {
  private platformService = PlatformServiceFactory.getInstance();
  private dailyNotificationService: DailyNotification | null = null;
  private integrationService: TimeSafariIntegrationService | null = null;

  async initializeDailyNotification(): Promise<void> {
    // Get existing TimeSafari settings
    const settings = await this.getTimeSafariSettings();
    
    // Configure plugin with TimeSafari data
    await DailyNotification.configure({
      timesafariConfig: {
        activeDid: settings.activeDid,
        endpoints: {
          projectsLastUpdated: `${settings.apiServer}/api/v2/report/plansLastUpdatedBetween`
        },
        starredProjectsConfig: {
          enabled: true,
          starredPlanHandleIds: settings.starredPlanHandleIds,
          lastAckedJwtId: settings.lastAckedStarredPlanChangesJwtId,
          fetchInterval: '0 8 * * *'
        }
      },
      networkConfig: {
        baseURL: settings.apiServer,
        timeout: 30000
      }
    });
  }

  async loadNewStarredProjectChanges(): Promise<StarredProjectsResponse> {
    // Enhanced version of existing TimeSafari method
    const settings = await this.getTimeSafariSettings();
    
    if (!settings.activeDid || !settings.starredPlanHandleIds?.length) {
      return { data: [], hitLimit: false };
    }

    // Use plugin's enhanced fetching
    return await this.integrationService!.getStarredProjectsWithChanges(
      settings.activeDid,
      settings.starredPlanHandleIds,
      settings.lastAckedStarredPlanChangesJwtId
    );
  }
}

Vue.js Component Integration

export const TimeSafariDailyNotificationMixin = {
  data() {
    return {
      // Existing TimeSafari data
      activeDid: '',
      starredPlanHandleIds: [] as string[],
      lastAckedStarredPlanChangesJwtId: '',
      numNewStarredProjectChanges: 0,
      newStarredProjectChangesHitLimit: false,
      
      // Plugin integration
      enhancedPlatformService: null as EnhancedCapacitorPlatformService | null
    };
  },

  async mounted() {
    // Initialize DailyNotification when component mounts (only on Capacitor)
    if (this.isCapacitor) {
      await this.initializeDailyNotification();
    }
  },

  methods: {
    async initializeDailyNotification(): Promise<void> {
      this.enhancedPlatformService = new EnhancedCapacitorPlatformService();
      await this.enhancedPlatformService.initializeDailyNotification();
    },

    async loadNewStarredProjectChanges(): Promise<void> {
      if (this.isCapacitor && this.enhancedPlatformService) {
        // Use plugin-enhanced method on Capacitor
        const result = await this.enhancedPlatformService.loadNewStarredProjectChanges();
        this.numNewStarredProjectChanges = result.data.length;
        this.newStarredProjectChangesHitLimit = result.hitLimit;
      } else {
        // Use existing web method in browser
        await this.loadNewStarredProjectChangesWeb();
      }
    }
  }
};

Integration Steps

Step 1: Install the Plugin

# In TimeSafari PWA project
npm install ssh://git@173.199.124.46:222/trent_larson/daily-notification-plugin.git

Step 2: Create Enhanced Platform Service

Create src/services/platforms/EnhancedCapacitorPlatformService.ts:

import { DailyNotification } from '@timesafari/daily-notification-plugin';
import { TimeSafariIntegrationService } from '@timesafari/daily-notification-plugin';
import { PlatformServiceFactory } from '@/services/PlatformServiceFactory';

export class EnhancedCapacitorPlatformService {
  // Implementation from the example above
}

Step 3: Extend PlatformServiceMixin

Add to src/utils/PlatformServiceMixin.ts:

export const PlatformServiceMixin = {
  // ... existing mixin code ...
  
  methods: {
    // ... existing methods ...
    
    /**
     * Initialize DailyNotification plugin (Capacitor only)
     */
    async $initializeDailyNotification(): Promise<void> {
      if (this.isCapacitor) {
        const enhancedService = new EnhancedCapacitorPlatformService();
        await enhancedService.initializeDailyNotification();
        this._enhancedPlatformService = enhancedService;
      }
    },

    /**
     * Enhanced loadNewStarredProjectChanges method
     */
    async $loadNewStarredProjectChanges(): Promise<StarredProjectsResponse> {
      if (this.isCapacitor && this._enhancedPlatformService) {
        return await this._enhancedPlatformService.loadNewStarredProjectChanges();
      } else {
        // Fall back to existing web method
        return await this.$loadNewStarredProjectChangesWeb();
      }
    }
  }
};

Step 4: Update Vue Components

In your existing TimeSafari Vue components:

export default defineComponent({
  name: 'TimeSafariHomeView',
  
  mixins: [PlatformServiceMixin],
  
  async mounted() {
    // Initialize DailyNotification (only on Capacitor)
    if (this.isCapacitor) {
      await this.$initializeDailyNotification();
    }
  },

  methods: {
    async loadNewStarredProjectChanges() {
      // Use enhanced method
      const result = await this.$loadNewStarredProjectChanges();
      this.numNewStarredProjectChanges = result.data.length;
      this.newStarredProjectChangesHitLimit = result.hitLimit;
    }
  }
});

Configuration Mapping

TimeSafari Settings → Plugin Configuration

TimeSafari Setting Plugin Configuration Purpose
settings.activeDid timesafariConfig.activeDid User authentication
settings.apiServer networkConfig.baseURL API endpoint
settings.starredPlanHandleIds starredProjectsConfig.starredPlanHandleIds Project IDs to fetch
settings.lastAckedStarredPlanChangesJwtId starredProjectsConfig.lastAckedJwtId Pagination token

Existing Methods → Enhanced Methods

Existing Method Enhanced Method Enhancement
loadNewStarredProjectChanges() $loadNewStarredProjectChanges() Background fetching, structured logging
getStarredProjectsWithChanges() integrationService.getStarredProjectsWithChanges() Retry logic, circuit breaker
Settings storage Plugin storage adapter Tiered storage, TTL management

Platform-Specific Behavior

Capacitor (Android/iOS)

  • Plugin Enabled: Full DailyNotification functionality
  • Background Fetching: WorkManager (Android), BGTaskScheduler (iOS)
  • Notifications: Native notification channels and categories
  • Storage: SQLite with plugin's tiered storage system

Web Browser

  • Plugin Disabled: Uses existing TimeSafari web code
  • No Background Fetching: Limited to browser capabilities
  • No Native Notifications: Uses web notifications API
  • Storage: Existing TimeSafari storage patterns

Electron

  • Plugin Enabled: Desktop-specific functionality
  • Background Tasks: Electron main process
  • Desktop Notifications: Native desktop notifications
  • Storage: SQLite with plugin's tiered storage system

Benefits of Integration

1. Same Interface, Enhanced Functionality

  • Existing loadNewStarredProjectChanges() method works exactly the same
  • Enhanced with background fetching, structured logging, and error handling
  • No changes required to existing UI code

2. Leverages Existing TimeSafari Patterns

  • Uses existing PlatformServiceMixin for database operations
  • Integrates with existing settings management
  • Maintains existing platform detection patterns

3. Platform-Optimized Performance

  • Capacitor: Native mobile optimizations with WorkManager/BGTaskScheduler
  • Web: Falls back to existing web code seamlessly
  • Electron: Desktop-specific optimizations

4. Enhanced Observability

  • Structured logging with event IDs
  • Performance metrics and monitoring
  • Error tracking and analysis
  • Health checks and status monitoring

Migration Strategy

Phase 1: Parallel Implementation

  1. Keep existing code unchanged
  2. Add enhanced platform service alongside existing code
  3. Test both implementations in parallel
  4. Compare results to ensure compatibility

Phase 2: Gradual Migration

  1. Replace individual methods one by one
  2. Use enhanced error handling and logging
  3. Maintain existing UI and user experience
  4. Add plugin-specific features gradually

Phase 3: Full Integration

  1. Replace all TimeSafari request patterns with plugin
  2. Remove duplicate code
  3. Leverage plugin's advanced features
  4. Optimize performance with plugin's caching and batching

Testing Strategy

1. Platform-Specific Testing

// Test on different platforms
const testPlatforms = async () => {
  if (Capacitor.getPlatform() === 'android') {
    // Test Android-specific functionality
  } else if (Capacitor.getPlatform() === 'ios') {
    // Test iOS-specific functionality
  } else {
    // Test web fallback
  }
};

2. Parallel Testing

// Test both implementations
const testBothImplementations = async () => {
  // Existing TimeSafari implementation
  const existingResult = await this.loadNewStarredProjectChangesOriginal();
  
  // Plugin-enhanced implementation
  const pluginResult = await this.$loadNewStarredProjectChanges();
  
  // Compare results
  assert.deepEqual(existingResult, pluginResult);
};

3. Performance Testing

// Compare performance
const performanceTest = async () => {
  const start = Date.now();
  await this.$loadNewStarredProjectChanges();
  const pluginTime = Date.now() - start;
  
  console.log('Plugin performance:', pluginTime);
};

Common Integration Patterns

1. Settings Integration

// Get TimeSafari settings
const settings = await this.$settings();

// Configure plugin with settings
await DailyNotification.configure({
  timesafariConfig: {
    activeDid: settings.activeDid,
    starredPlanHandleIds: settings.starredPlanHandleIds
  }
});

2. Database Integration

// Store plugin results in TimeSafari database
await this.$dbExec(
  "INSERT OR REPLACE INTO temp (id, data) VALUES (?, ?)",
  ['starred_projects_latest', JSON.stringify(result)]
);

3. Error Handling Integration

// Use existing TimeSafari error handling patterns
try {
  const result = await this.$loadNewStarredProjectChanges();
  // Handle success
} catch (error) {
  // Use existing TimeSafari error logging
  await this.$logError(`Failed to load starred projects: ${error.message}`);
}

Troubleshooting

Common Issues

1. Plugin Not Initializing

// Check platform detection
if (!this.isCapacitor) {
  console.log('Plugin only works on Capacitor platforms');
  return;
}

2. Settings Not Found

// Ensure settings are loaded
const settings = await this.$settings();
if (!settings.activeDid) {
  console.log('No active DID found');
  return;
}

3. Database Connection Issues

// Check database connection
try {
  await this.$dbQuery("SELECT 1");
} catch (error) {
  console.error('Database connection failed:', error);
}

Debug Methods

1. Plugin Status

const status = await this.getDailyNotificationStatus();
console.log('Plugin status:', status);

2. Settings Debug

await this.$debugMergedSettings(this.activeDid);

3. Performance Debug

const metrics = await DailyNotification.getMetrics();
console.log('Plugin metrics:', metrics);

Conclusion

The DailyNotification plugin integrates seamlessly with the existing TimeSafari PWA architecture by:

  • Extending CapacitorPlatformService with enhanced functionality
  • Using PlatformServiceMixin for database and settings operations
  • Maintaining existing interfaces and method signatures
  • Providing platform-specific optimizations for Capacitor, Web, and Electron
  • Enhancing observability with structured logging and metrics

The integration maintains the same developer experience while adding powerful new features like background fetching, native notifications, and comprehensive monitoring.


Next Steps:

  1. Review the integration example and understand the architecture
  2. Test the enhanced platform service with existing TimeSafari code
  3. Gradually migrate individual methods to use the plugin
  4. Leverage the plugin's advanced features for enhanced user experience