Files
daily-notification-plugin/android/src/main/java/com/timesafari/dailynotification/FetchContext.java
Matthew Raymer d9bdeb6d02 refactor(android)!: restructure to standard Capacitor plugin layout
Restructure Android project from nested module layout to standard
Capacitor plugin structure following community conventions.

Structure Changes:
- Move plugin code from android/plugin/ to android/src/main/java/
- Move test app from android/app/ to test-apps/android-test-app/app/
- Remove nested android/plugin module structure
- Remove nested android/app test app structure

Build Infrastructure:
- Add Gradle wrapper files (gradlew, gradlew.bat, gradle/wrapper/)
- Transform android/build.gradle from root project to library module
- Update android/settings.gradle for standalone plugin builds
- Add android/gradle.properties with AndroidX configuration
- Add android/consumer-rules.pro for ProGuard rules

Configuration Updates:
- Add prepare script to package.json for automatic builds on npm install
- Update package.json version to 1.0.1
- Update android/build.gradle to properly resolve Capacitor dependencies
- Update test-apps/android-test-app/settings.gradle with correct paths
- Remove android/variables.gradle (hardcode values in build.gradle)

Documentation:
- Update BUILDING.md with new structure and build process
- Update INTEGRATION_GUIDE.md to reflect standard structure
- Update README.md to remove path fix warnings
- Add test-apps/BUILD_PROCESS.md documenting test app build flows

Test App Configuration:
- Fix android-test-app to correctly reference plugin and Capacitor
- Remove capacitor-cordova-android-plugins dependency (not needed)
- Update capacitor.settings.gradle path verification in fix script

BREAKING CHANGE: Plugin now uses standard Capacitor Android structure.
Consuming apps must update their capacitor.settings.gradle to reference
android/ instead of android/plugin/. This is automatically handled by
Capacitor CLI for apps using standard plugin installation.
2025-11-05 08:08:37 +00:00

131 lines
3.6 KiB
Java

/**
* FetchContext.java
*
* Context information provided to content fetchers about why a fetch was triggered.
*
* This class is part of the Integration Point Refactor (PR1) SPI implementation.
* It provides fetchers with metadata about the fetch request, including trigger
* type, scheduling information, and optional metadata.
*
* @author Matthew Raymer
* @version 1.0.0
*/
package com.timesafari.dailynotification;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Context provided to content fetchers about why fetch was triggered
*
* This follows the TypeScript interface from src/types/content-fetcher.ts and
* ensures type safety between JS and native fetcher implementations.
*/
public class FetchContext {
/**
* Reason why the fetch was triggered
*
* Valid values: "background_work", "prefetch", "manual", "scheduled"
*/
@NonNull
public final String trigger;
/**
* When notification is scheduled for (optional, epoch milliseconds)
*
* Only present when trigger is "prefetch" or "scheduled"
*/
@Nullable
public final Long scheduledTime;
/**
* When the fetch was triggered (required, epoch milliseconds)
*/
public final long fetchTime;
/**
* Additional context metadata (optional)
*
* Plugin may populate with app state, network info, etc.
* Fetcher can use for logging, debugging, or conditional logic.
*/
@NonNull
public final Map<String, Object> metadata;
/**
* Constructor with all fields
*
* @param trigger Trigger type (required)
* @param scheduledTime Scheduled time (optional)
* @param fetchTime When fetch triggered (required)
* @param metadata Additional metadata (optional, can be null)
*/
public FetchContext(
@NonNull String trigger,
@Nullable Long scheduledTime,
long fetchTime,
@Nullable Map<String, Object> metadata) {
if (trigger == null || trigger.isEmpty()) {
throw new IllegalArgumentException("trigger is required");
}
this.trigger = trigger;
this.scheduledTime = scheduledTime;
this.fetchTime = fetchTime;
this.metadata = metadata != null ?
Collections.unmodifiableMap(new HashMap<>(metadata)) :
Collections.emptyMap();
}
/**
* Constructor with minimal fields (no metadata)
*
* @param trigger Trigger type
* @param scheduledTime Scheduled time (can be null)
* @param fetchTime When fetch triggered
*/
public FetchContext(
@NonNull String trigger,
@Nullable Long scheduledTime,
long fetchTime) {
this(trigger, scheduledTime, fetchTime, null);
}
/**
* Get metadata value by key
*
* @param key Metadata key
* @return Value or null if not present
*/
@Nullable
public Object getMetadata(@NonNull String key) {
return metadata.get(key);
}
/**
* Check if metadata contains key
*
* @param key Metadata key
* @return True if key exists
*/
public boolean hasMetadata(@NonNull String key) {
return metadata.containsKey(key);
}
@Override
public String toString() {
return "FetchContext{" +
"trigger='" + trigger + '\'' +
", scheduledTime=" + scheduledTime +
", fetchTime=" + fetchTime +
", metadataSize=" + metadata.size() +
'}';
}
}