2026-06-28 08:11:43 +02:00
|
|
|
/// Writes workout result JSON to external storage (ADB) and the HTTP server.
|
2026-05-31 16:23:46 +02:00
|
|
|
library;
|
|
|
|
|
|
|
|
|
|
import 'dart:io';
|
|
|
|
|
import 'package:path_provider/path_provider.dart';
|
|
|
|
|
import 'package:workout_app/models/workout_session.dart';
|
|
|
|
|
import 'package:workout_app/services/http_server_service.dart';
|
|
|
|
|
|
2026-06-28 08:11:43 +02:00
|
|
|
/// Path on the phone's external storage where the PC reads workout data.
|
2026-05-31 16:23:46 +02:00
|
|
|
const String kSyncFilePath = '/sdcard/workout_result.json';
|
|
|
|
|
|
2026-06-28 08:11:43 +02:00
|
|
|
/// Handles writing completed workout sessions to disk and the HTTP server.
|
2026-05-31 16:23:46 +02:00
|
|
|
class SyncService {
|
|
|
|
|
/// Writes [session] as JSON to external storage and updates the HTTP server.
|
|
|
|
|
///
|
|
|
|
|
/// Falls back to app-external directory if /sdcard/ is not writable.
|
|
|
|
|
Future<SyncResult> writeWorkoutResult(WorkoutSession session) async {
|
|
|
|
|
final json = session.toJsonString();
|
|
|
|
|
|
|
|
|
|
// Always update the in-app HTTP server so the PC can read via WiFi.
|
2026-06-28 08:11:43 +02:00
|
|
|
HttpServerService.instance.latestWorkout = json;
|
2026-05-31 16:23:46 +02:00
|
|
|
|
|
|
|
|
// Try the primary path first (/sdcard/ — ADB-accessible without root).
|
|
|
|
|
try {
|
|
|
|
|
final file = File(kSyncFilePath);
|
|
|
|
|
await file.writeAsString(json);
|
2026-06-28 08:11:43 +02:00
|
|
|
return const SyncResult(success: true, path: kSyncFilePath);
|
2026-05-31 16:23:46 +02:00
|
|
|
} on Exception {
|
|
|
|
|
// Fallback: app-specific external directory (still ADB accessible).
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
final dir = await getExternalStorageDirectory();
|
|
|
|
|
if (dir != null) {
|
|
|
|
|
final file = File('${dir.path}/workout_result.json');
|
|
|
|
|
await file.writeAsString(json);
|
|
|
|
|
return SyncResult(success: true, path: file.path);
|
|
|
|
|
}
|
|
|
|
|
} on Exception {
|
|
|
|
|
// Fallback failed.
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 08:11:43 +02:00
|
|
|
return const SyncResult(
|
|
|
|
|
success: false,
|
|
|
|
|
path: null,
|
|
|
|
|
error: 'No writable external path',
|
|
|
|
|
);
|
2026-05-31 16:23:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 08:11:43 +02:00
|
|
|
/// Result of a [SyncService.writeWorkoutResult] call.
|
2026-05-31 16:23:46 +02:00
|
|
|
class SyncResult {
|
2026-06-28 08:11:43 +02:00
|
|
|
/// Creates a sync result.
|
2026-05-31 16:23:46 +02:00
|
|
|
const SyncResult({required this.success, required this.path, this.error});
|
|
|
|
|
|
2026-06-28 08:11:43 +02:00
|
|
|
/// Whether the write succeeded.
|
2026-05-31 16:23:46 +02:00
|
|
|
final bool success;
|
2026-06-28 08:11:43 +02:00
|
|
|
|
|
|
|
|
/// Absolute path where the file was written, or null on failure.
|
2026-05-31 16:23:46 +02:00
|
|
|
final String? path;
|
2026-06-28 08:11:43 +02:00
|
|
|
|
|
|
|
|
/// Human-readable error message on failure.
|
2026-05-31 16:23:46 +02:00
|
|
|
final String? error;
|
|
|
|
|
}
|