mirror of
https://github.com/kuhyx/wake-alarm.git
synced 2026-11-10 18:07:05 +01:00
On 2026-09-19 the phone was powered off after the bathroom tag and nothing on the PC noticed: every finished session was published and nothing read it. Now wake-alarm distils the phone's morning into an HMAC-signed ~/.local/state/wake_alarm/morning_session.json (wake-alarm-session.timer, 07:00-11:00 every 2 min) that screen-locker and leetcode-guard read to defer their locks -- provisionally until min(start + 90 min, 09:30) while the session is live, until 11:00 once it completed inside that cutoff, and not at all for a session finished later (the phone switched on at noon completes the legs then; that must un-lock nothing). The phone publishes the session at start as well as at finish (current_session, cleared with the finish stamp), so the PC can tell "started, not finished" from "never started". A required 1-5 energy tap joins the weigh-in and ships as latest_energy with a PC reader mirroring _weight (the shared half is _field_reader). Also fixes the vmbox harness, red since the 2026-09-11 home-tidy: the guest tree lives at ~/wake-alarm, and the INSTALL-OK grep matched vm's echo of the command line. Takes Flutter 3.47.5. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tp54ewdXRLaimUuT8LgYyn
50 lines
1.6 KiB
Dart
50 lines
1.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:wake_alarm_sync/services/weight_entry.dart';
|
|
|
|
/// Five chips, 1 to 5: the morning's energy, tapped next to the weigh-in.
|
|
///
|
|
/// Chips rather than a field because a rating is a tap, not a number to
|
|
/// type. The selected colour is the theme's chip container (a raised ink),
|
|
/// deliberately not the gold `primaryContainer`: `scripts/emu_morning.py`
|
|
/// finds the submit button by its gold pixels, and a gold chip sat above it
|
|
/// was found first -- and the label vanished into it.
|
|
class EnergyPicker extends StatelessWidget {
|
|
/// Creates the picker; [selected] is null until a chip is tapped.
|
|
const EnergyPicker({
|
|
required this.selected,
|
|
required this.onSelect,
|
|
super.key,
|
|
});
|
|
|
|
/// The chosen level, or null.
|
|
final int? selected;
|
|
|
|
/// Called with the tapped level.
|
|
final ValueChanged<int> onSelect;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: <Widget>[
|
|
Text('Energy', style: Theme.of(context).textTheme.labelLarge),
|
|
const SizedBox(height: 4),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: <Widget>[
|
|
for (var level = minEnergy; level <= maxEnergy; level++)
|
|
ChoiceChip(
|
|
label: Text('$level'),
|
|
selected: selected == level,
|
|
selectedColor: scheme.secondaryContainer,
|
|
showCheckmark: false,
|
|
onSelected: (_) => onSelect(level),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|