feat(phase2): implement ActiveDid Integration & TimeSafari API Enhancement
- Enhanced ConfigureOptions with comprehensive TimeSafari activeDid configuration - Extended ContentFetchConfig with Endorser.ch API endpoints and TimeSafari config - Added detailed TimeSafari notification types (Offers, Projects, People, Items) - Implemented Host-provided activeDid Plugin Configuration with auto-sync - Enhanced Android retry logic with TimeSafari activeDid change detection - Enhanced Web retry logic with Phase 2 ActiveDid change support - Added comprehensive TimeSafari fallback content generation - Implemented cross-platform ActiveDid change event tracking Phase 2 delivers: ✅ Enhanced ConfigureOptions with host-provided activeDid patterns ✅ Extension of ContentFetchConfig with Endorser.ch endpoints ✅ Complete TimeSafari notification type definitions ✅ Host-provided activeDid Plugin Configuration implementation ✅ Enhanced Android retry logic with activeDid change detection ✅ Enhanced Web retry logic with session-based activeDid tracking ✅ TimeSafari-aware fallback content generation ✅ Comprehensive configuration storage and persistence Ready for Phase 3: Background Enhancement & TimeSafari Coordination
This commit is contained in:
@@ -203,23 +203,29 @@ public class DailyNotificationFetchWorker extends Worker {
|
||||
*/
|
||||
private Result handleFailedFetch(int retryCount, long scheduledTime) {
|
||||
try {
|
||||
Log.d(TAG, "Handling failed fetch - Retry: " + retryCount);
|
||||
Log.d(TAG, "Phase 2: Handling failed fetch - Retry: " + retryCount);
|
||||
|
||||
if (retryCount < MAX_RETRY_ATTEMPTS) {
|
||||
// Schedule retry
|
||||
scheduleRetry(retryCount + 1, scheduledTime);
|
||||
Log.i(TAG, "Scheduled retry attempt " + (retryCount + 1));
|
||||
// Phase 2: Check for TimeSafari special retry triggers
|
||||
if (shouldRetryForActiveDidChange()) {
|
||||
Log.d(TAG, "Phase 2: ActiveDid change detected - extending retry quota");
|
||||
retryCount = 0; // Reset retry count for activeDid change
|
||||
}
|
||||
|
||||
if (retryCount < MAX_RETRIES_FOR_TIMESAFARI()) {
|
||||
// Phase 2: Schedule enhanced retry with activeDid consideration
|
||||
scheduleRetryWithActiveDidSupport(retryCount + 1, scheduledTime);
|
||||
Log.i(TAG, "Phase 2: Scheduled retry attempt " + (retryCount + 1) + " with TimeSafari support");
|
||||
return Result.retry();
|
||||
|
||||
} else {
|
||||
// Max retries reached - use fallback content
|
||||
Log.w(TAG, "Max retries reached, using fallback content");
|
||||
useFallbackContent(scheduledTime);
|
||||
Log.w(TAG, "Phase 2: Max retries reached, using fallback content");
|
||||
useFallbackContentWithActiveDidSupport(scheduledTime);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error handling failed fetch", e);
|
||||
Log.e(TAG, "Phase 2: Error handling failed fetch", e);
|
||||
return Result.failure();
|
||||
}
|
||||
}
|
||||
@@ -275,6 +281,108 @@ public class DailyNotificationFetchWorker extends Worker {
|
||||
return Math.min(exponentialDelay, maxDelay);
|
||||
}
|
||||
|
||||
// MARK: - Phase 2: TimeSafari ActiveDid Enhancement Methods
|
||||
|
||||
/**
|
||||
* Phase 2: Check if retry is needed due to activeDid change
|
||||
*/
|
||||
private boolean shouldRetryForActiveDidChange() {
|
||||
try {
|
||||
// Check if activeDid has changed since last fetch attempt
|
||||
android.content.SharedPreferences prefs = context.getSharedPreferences("daily_notification_timesafari", android.content.Context.MODE_PRIVATE);
|
||||
long lastFetchAttempt = prefs.getLong("lastFetchAttempt", 0);
|
||||
long lastActiveDidChange = prefs.getLong("lastActiveDidChange", 0);
|
||||
|
||||
boolean activeDidChanged = lastActiveDidChange > lastFetchAttempt;
|
||||
|
||||
if (activeDidChanged) {
|
||||
Log.d(TAG, "Phase 2: ActiveDid change detected in retry logic");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Phase 2: Error checking activeDid change", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 2: Get max retries with TimeSafari enhancements
|
||||
*/
|
||||
private int MAX_RETRIES_FOR_TIMESAFARI() {
|
||||
// Base retries + additional for activeDid changes
|
||||
return MAX_RETRY_ATTEMPTS + 2; // Extra retries for TimeSafari integration
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 2: Schedule retry with activeDid support
|
||||
*/
|
||||
private void scheduleRetryWithActiveDidSupport(int retryCount, long scheduledTime) {
|
||||
try {
|
||||
Log.d(TAG, "Phase 2: Scheduling retry attempt " + retryCount + " with TimeSafari support");
|
||||
|
||||
// Store the last fetch attempt time for activeDid change detection
|
||||
android.content.SharedPreferences prefs = context.getSharedPreferences("daily_notification_timesafari", android.content.Context.MODE_PRIVATE);
|
||||
prefs.edit().putLong("lastFetchAttempt", System.currentTimeMillis()).apply();
|
||||
|
||||
// Delegate to original retry logic
|
||||
scheduleRetry(retryCount, scheduledTime);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Phase 2: Error scheduling enhanced retry", e);
|
||||
// Fallback to original retry logic
|
||||
scheduleRetry(retryCount, scheduledTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 2: Use fallback content with activeDid support
|
||||
*/
|
||||
private void useFallbackContentWithActiveDidSupport(long scheduledTime) {
|
||||
try {
|
||||
Log.d(TAG, "Phase 2: Using fallback content with TimeSafari support");
|
||||
|
||||
// Generate TimeSafari-aware fallback content
|
||||
NotificationContent fallbackContent = generateTimeSafariFallbackContent();
|
||||
|
||||
if (fallbackContent != null) {
|
||||
storage.saveNotificationContent(fallbackContent);
|
||||
Log.i(TAG, "Phase 2: TimeSafari fallback content saved");
|
||||
} else {
|
||||
// Fallback to original logic
|
||||
useFallbackContent(scheduledTime);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Phase 2: Error using enhanced fallback content", e);
|
||||
// Fallback to original logic
|
||||
useFallbackContent(scheduledTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 2: Generate TimeSafari-aware fallback content
|
||||
*/
|
||||
private NotificationContent generateTimeSafariFallbackContent() {
|
||||
try {
|
||||
// Generate fallback content specific to TimeSafari context
|
||||
NotificationContent content = new NotificationContent();
|
||||
content.id = "timesafari_fallback_" + System.currentTimeMillis();
|
||||
content.title = "TimeSafari Update Available";
|
||||
content.body = "Your community updates are ready. Tap to view offers, projects, and connections.";
|
||||
content.fetchTime = System.currentTimeMillis();
|
||||
content.scheduledTime = System.currentTimeMillis() + 30000; // 30 seconds from now
|
||||
|
||||
return content;
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Phase 2: Error generating TimeSafari fallback content", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use fallback content when all retries fail
|
||||
*
|
||||
|
||||
@@ -987,36 +987,90 @@ public class DailyNotificationPlugin extends Plugin {
|
||||
*/
|
||||
private void configureActiveDidIntegration(JSObject config) {
|
||||
try {
|
||||
Log.d(TAG, "Configuring activeDid integration");
|
||||
Log.d(TAG, "Configuring Phase 2 activeDid integration");
|
||||
|
||||
String platform = config.getString("platform", "android");
|
||||
String storageType = config.getString("storageType", "plugin-managed");
|
||||
Integer jwtExpirationSeconds = config.getInteger("jwtExpirationSeconds", 60);
|
||||
String apiServer = config.getString("apiServer");
|
||||
|
||||
Log.d(TAG, "ActiveDid config - Platform: " + platform + ", Storage: " + storageType +
|
||||
", JWT Expiry: " + jwtExpirationSeconds + "s, API Server: " + apiServer);
|
||||
// Phase 2: Host-provided activeDid initial configuration
|
||||
String initialActiveDid = config.getString("activeDid");
|
||||
boolean autoSync = config.getBoolean("autoSync", false);
|
||||
Integer identityChangeGraceSeconds = config.getInteger("identityChangeGraceSeconds", 30);
|
||||
|
||||
// Configure JWT manager with custom expiration
|
||||
Log.d(TAG, "Phase 2 ActiveDid config - Platform: " + platform +
|
||||
", Storage: " + storageType + ", JWT Expiry: " + jwtExpirationSeconds + "s" +
|
||||
", API Server: " + apiServer + ", Initial ActiveDid: " +
|
||||
(initialActiveDid != null ? initialActiveDid.substring(0, Math.min(20, initialActiveDid.length())) + "..." : "null") +
|
||||
", AutoSync: " + autoSync + ", Grace Period: " + identityChangeGraceSeconds + "s");
|
||||
|
||||
// Phase 2: Configure JWT manager with auto-sync capabilities
|
||||
if (jwtManager != null) {
|
||||
// We'll set the JWT expiration when activeDid is provided
|
||||
Log.d(TAG, "JWT manager configured for activeDid integration");
|
||||
if (initialActiveDid != null && !initialActiveDid.isEmpty()) {
|
||||
jwtManager.setActiveDid(initialActiveDid, jwtExpirationSeconds);
|
||||
Log.d(TAG, "Phase 2: Initial ActiveDid set in JWT manager");
|
||||
}
|
||||
Log.d(TAG, "Phase 2: JWT manager configured with auto-sync: " + autoSync);
|
||||
}
|
||||
|
||||
// Configure enhanced fetcher with API server
|
||||
// Phase 2: Configure enhanced fetcher with TimeSafari API support
|
||||
if (enhancedFetcher != null && apiServer != null && !apiServer.isEmpty()) {
|
||||
enhancedFetcher.setApiServerUrl(apiServer);
|
||||
Log.d(TAG, "Enhanced fetcher configured with API server: " + apiServer);
|
||||
Log.d(TAG, "Phase 2: Enhanced fetcher configured with API server: " + apiServer);
|
||||
|
||||
// Phase 2: Set up TimeSafari-specific configuration
|
||||
if (initialActiveDid != null && !initialActiveDid.isEmpty()) {
|
||||
EnhancedDailyNotificationFetcher.TimeSafariUserConfig userConfig =
|
||||
new EnhancedDailyNotificationFetcher.TimeSafariUserConfig();
|
||||
userConfig.activeDid = initialActiveDid;
|
||||
userConfig.fetchOffersToPerson = true;
|
||||
userConfig.fetchOffersToProjects = true;
|
||||
userConfig.fetchProjectUpdates = true;
|
||||
|
||||
Log.d(TAG, "Phase 2: TimeSafari user configuration prepared");
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG, "ActiveDid integration configured successfully");
|
||||
// Phase 2: Store auto-sync configuration for future use
|
||||
storeAutoSyncConfiguration(autoSync, identityChangeGraceSeconds);
|
||||
|
||||
Log.i(TAG, "Phase 2 ActiveDid integration configured successfully");
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error configuring activeDid integration", e);
|
||||
Log.e(TAG, "Error configuring Phase 2 activeDid integration", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store auto-sync configuration for background tasks
|
||||
*/
|
||||
private void storeAutoSyncConfiguration(boolean autoSync, int gracePeriodSeconds) {
|
||||
try {
|
||||
if (storage != null) {
|
||||
// Store auto-sync settings in plugin storage
|
||||
Map<String, Object> syncConfig = new HashMap<>();
|
||||
syncConfig.put("autoSync", autoSync);
|
||||
syncConfig.put("gracePeriodSeconds", gracePeriodSeconds);
|
||||
syncConfig.put("configuredAt", System.currentTimeMillis());
|
||||
|
||||
// Store in SharedPreferences for persistence
|
||||
android.content.SharedPreferences preferences = getContext()
|
||||
.getSharedPreferences("daily_notification_timesafari", Context.MODE_PRIVATE);
|
||||
preferences.edit()
|
||||
.putBoolean("autoSync", autoSync)
|
||||
.putInt("gracePeriodSeconds", gracePeriodSeconds)
|
||||
.putLong("configuredAt", System.currentTimeMillis())
|
||||
.apply();
|
||||
|
||||
Log.d(TAG, "Phase 2: Auto-sync configuration stored");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error storing auto-sync configuration", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set active DID from host application
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user