Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions lib/providers/app_state_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5100,6 +5100,7 @@ class AppStateProvider extends ChangeNotifier with WidgetsBindingObserver {

// Extract session_id into local variable — never stored in shared state
final offlineSessionId = effectiveAuth!['session_id'] as String?;
final uploadPublicKey = publicKey!;
if (offlineSessionId == null) {
debugError('[OFFLINE] Auth succeeded but no session_id in response');
return OfflineUploadResult.authFailed;
Expand Down Expand Up @@ -5179,6 +5180,12 @@ class AppStateProvider extends ChangeNotifier with WidgetsBindingObserver {
if (result == UploadResult.success) {
uploadedCount += batch.length;
debugLog('[OFFLINE] Uploaded batch $batchNum: ${batch.length} pings');
_forwardOfflineBatchToCustomApi(
batch,
batchNum: batchNum,
publicKey: uploadPublicKey,
auth: effectiveAuth,
);
continue;
}

Expand Down Expand Up @@ -5234,6 +5241,32 @@ class AppStateProvider extends ChangeNotifier with WidgetsBindingObserver {
}
}

/// Forward a successfully uploaded offline batch to the Custom API endpoint.
void _forwardOfflineBatchToCustomApi(
List<Map<String, dynamic>> batch, {
required int batchNum,
required String publicKey,
required Map<String, dynamic> auth,
}) {
final contact = publicKey.length >= 8
? publicKey.substring(0, 8).toUpperCase()
: null;
var iata = zoneCode ?? _preferences.iataCode;
final zone = auth['zone'];
if (zone is Map && zone['code'] != null) {
iata = zone['code'].toString();
}
debugLog(
'[OFFLINE] Custom API forward for batch $batchNum '
'(${batch.length} pings, contact=$contact, iata=$iata)');
_customApiService.forwardPings(
batch,
contactOverride: contact,
iataOverride: iata,
source: 'offline',
);
}

/// Delete an offline session without uploading
Future<void> deleteOfflineSession(String filename) async {
await _offlineSessionService.deleteSession(filename);
Expand Down
41 changes: 33 additions & 8 deletions lib/services/custom_api_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,42 @@ class CustomApiService {
_client = client ?? http.Client();

/// Fire-and-forget: forward pings to the custom endpoint.
/// Called after successful MeshMapper upload. Never throws.
void forwardPings(List<Map<String, dynamic>> pings) {
/// Called after successful MeshMapper upload (online queue or offline session).
/// Never throws.
void forwardPings(
List<Map<String, dynamic>> pings, {
String? contactOverride,
String? iataOverride,
String source = 'online',
}) {
if (pings.isEmpty) return;

final prefs = _prefsGetter();
if (!prefs.customApiEnabled) return;
if (prefs.customApiUrl == null || prefs.customApiUrl!.isEmpty) return;
if (prefs.customApiKey == null || prefs.customApiKey!.isEmpty) return;
debugLog(
'[CUSTOM API] Forward requested ($source): ${pings.length} item(s)');

if (!prefs.customApiEnabled) {
debugLog('[CUSTOM API] Forward skipped ($source): Custom API disabled');
return;
}
if (prefs.customApiUrl == null || prefs.customApiUrl!.isEmpty) {
debugLog('[CUSTOM API] Forward skipped ($source): URL not configured');
return;
}
if (prefs.customApiKey == null || prefs.customApiKey!.isEmpty) {
debugLog('[CUSTOM API] Forward skipped ($source): API key not configured');
return;
}

// Enrich with contact and iata (custom API only — never sent to MeshMapper)
final contact =
prefs.customApiIncludeContact ? contactGetter?.call() : null;
final iata = iataGetter?.call();
final contact = prefs.customApiIncludeContact
? (contactOverride ?? contactGetter?.call())
: null;
final iata = iataOverride ?? iataGetter?.call();

debugLog(
'[CUSTOM API] Forwarding ($source) → ${prefs.customApiUrl} '
'(contact=${contact ?? "off"}, iata=${iata ?? "none"})');

final enriched = pings.map((ping) {
final enrichedPing = Map<String, dynamic>.from(ping);
Expand Down