mirror of
https://github.com/kuhyx/wake-alarm.git
synced 2026-11-10 19:27:02 +01:00
- Sick days screen (own name, sick icon, cat-2 fill): tap today or a later day to mark it sick, tap again to clear; past days inert. Writes the sickdays wire format (state sick/cleared + actor, one HLC per write) to sickdays-sync/devices via crdt_sync syncLog. - Mutual exclusion in both pickers: each syncs the other pool on open and refuses a date it holds, naming the pool; an unreadable pool refuses all. - Native SickDays cache (fail closed via DayCache); AlarmReceiver skips the ring with reason "sick_day" (no markFired, no ring_started); StickCheck verdict sick_day, streak skips sick days; stakes card says so. - Pre-alarm pool sync: allow-while-idle alarm at 21:00 and A-30 (request code 1006) runs a headless engine (poolSyncMain) that pulls both pools from RTDB and rewrites both native caches, so a PC mark arrives with the app closed. The ring decision stays a cache read. - JVM unit tests (JUnit 4.13.2) for DayCache, RingDecision, PoolSyncSchedule, StickCheck; Dart tests; Dart->Python interop check. pylint hook skipped: verify.py imports sickdays, not in the hook env until the sickdays-v0.1.0 tag exists; run by hand in a sickdays venv (10.00/10). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xfj1sxKH9VBPqpcAni8Jry
44 lines
1.7 KiB
Dart
44 lines
1.7 KiB
Dart
import 'package:crdt_sync/crdt_sync.dart';
|
|
import 'package:wake_alarm_sync/services/alarm_scheduler.dart';
|
|
import 'package:wake_alarm_sync/services/day_pool_sync.dart';
|
|
import 'package:wake_alarm_sync/services/firebase_backend.dart';
|
|
import 'package:wake_alarm_sync/services/sick_day_pool.dart';
|
|
|
|
/// Moves the sick-day pool between this phone and every other device, over
|
|
/// `sickdays-sync/devices` -- the node `sickdays sync` on the PC uses.
|
|
///
|
|
/// Every sync ends by handing the merged pool to the native ring path
|
|
/// ([AlarmScheduler.setSickDays]): that cache, not the Dart store, is what
|
|
/// `AlarmReceiver` reads when it decides whether to ring.
|
|
class SickDaySync {
|
|
/// Creates a syncer; both seams are injectable for tests.
|
|
SickDaySync({
|
|
Future<RemoteStore?> Function()? openClient,
|
|
AlarmScheduler? scheduler,
|
|
}) : _openClient = openClient ?? openFirebase,
|
|
_scheduler = scheduler ?? AlarmScheduler();
|
|
|
|
final Future<RemoteStore?> Function() _openClient;
|
|
final AlarmScheduler _scheduler;
|
|
|
|
/// Pulls, merges and pushes [pool], then refreshes the native cache.
|
|
/// Never throws; see [syncDayPoolLog].
|
|
Future<String> sync(SickDayPool pool) => syncDayPoolLog(
|
|
openClient: _openClient,
|
|
deviceId: pool.deviceId,
|
|
pathPrefix: SickDayPool.pathPrefix,
|
|
filename: SickDayPool.filename,
|
|
commitMessage: 'sickdays: update pool',
|
|
snapshot: pool.snapshot,
|
|
replaceAll: pool.replaceAll,
|
|
publish: () => publishToNative(pool),
|
|
logName: 'SickDaySync',
|
|
);
|
|
|
|
/// Writes the pool's sick dates where `AlarmReceiver` can read them.
|
|
Future<void> publishToNative(SickDayPool pool) => publishQuietly(
|
|
() => _scheduler.setSickDays(pool.sickIsoDates()),
|
|
logName: 'SickDaySync',
|
|
);
|
|
}
|