mirror of
https://github.com/kuhyx/diet-guard.git
synced 2026-07-04 13:23:11 +02:00
Ports github_client.dart and sync_settings.dart from ~/todo (PAT-paste instead of OAuth device flow), and writes a new (non-CRDT) sync_merge.dart and sync_service.dart matching diet_guard's Python _sync_merge.py/_sync.py algorithm exactly. Adds a settings screen for the PAT plus manual "Sync now", and wires lifecycle-triggered auto-sync (launch + resumed/paused) into the main logging screen, silent on failure per plan decision 4. Also adds Linux desktop platform scaffolding so this and future UI changes can be visually verified without a connected phone. Verified end-to-end against the real kuhyx/diet-guard-sync GitHub API on a Linux desktop build: Test connection and Sync now both round-trip to GitHub and surface real auth errors correctly via SnackBar. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RH2BHCKbDTiYJUMG3rb9nq
53 lines
1.6 KiB
Dart
53 lines
1.6 KiB
Dart
import 'package:flutter/services.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
/// In-memory fake for the `flutter_secure_storage` platform channel so tests
|
|
/// never touch the real OS keystore. Install it from a test (or `setUp`) and
|
|
/// it auto-removes on tear down.
|
|
///
|
|
/// Pass [throwing] to simulate a host with no secret service: every call
|
|
/// raises a [PlatformException], which exercises the plaintext-fallback
|
|
/// paths in [SyncSettings].
|
|
void installFakeSecureStorage({
|
|
Map<String, String>? initial,
|
|
bool throwing = false,
|
|
}) {
|
|
const channel = MethodChannel(
|
|
'plugins.it_nomads.com/flutter_secure_storage',
|
|
);
|
|
final store = <String, String>{...?initial};
|
|
final messenger =
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger;
|
|
|
|
messenger.setMockMethodCallHandler(channel, (call) async {
|
|
if (throwing) {
|
|
throw PlatformException(code: 'unavailable');
|
|
}
|
|
final args = (call.arguments as Map?) ?? const <Object?, Object?>{};
|
|
final key = args['key'] as String?;
|
|
switch (call.method) {
|
|
case 'read':
|
|
return store[key];
|
|
case 'write':
|
|
store[key!] = args['value'] as String;
|
|
return null;
|
|
case 'delete':
|
|
store.remove(key);
|
|
return null;
|
|
case 'containsKey':
|
|
return store.containsKey(key);
|
|
case 'readAll':
|
|
return Map<String, String>.from(store);
|
|
case 'deleteAll':
|
|
store.clear();
|
|
return null;
|
|
default:
|
|
return null;
|
|
}
|
|
});
|
|
|
|
addTearDown(() {
|
|
messenger.setMockMethodCallHandler(channel, null);
|
|
});
|
|
}
|