Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
5a2a38c
test(backup): settings travel in a full export and come back on import
mikenrafter Nov 7, 2026
a51e335
feat(backup): a full export carries your settings, and an import brin…
mikenrafter Nov 7, 2026
65f9ad0
fix(backup): device-bound alarm, workout and pairing state stays on t…
mikenrafter Nov 7, 2026
5d9960b
fix(backup): a custom coach server address stays on the phone
mikenrafter Nov 7, 2026
39adde9
fix(backup): a rebuild keeps the alarm schedule; settings adoption is…
mikenrafter Nov 7, 2026
3d08396
fix(backup): review round 1 — alarm reload, ChatGPT notice, skipped r…
mikenrafter Nov 7, 2026
370f2b8
fix(backup): a live setting of the wrong type is refused and reported
mikenrafter Nov 7, 2026
75ec46a
l10n(ru): drop the =1 branch gen-l10n reports as overridden by one
mikenrafter Nov 7, 2026
2dddb3b
fix(backup): the skipped-settings card no longer claims everything el…
mikenrafter Nov 7, 2026
84ef43d
fix(backup): refuse a restored setting whose type differs from how th…
mikenrafter Nov 9, 2026
1f04a65
fix(backup): an import no longer drops Monday from the alarm schedule
mikenrafter Nov 9, 2026
1535082
fix(backup): the bulk restore and raw archive merge keep rows at rowi…
mikenrafter Nov 9, 2026
9673b1c
fix(backup): an import no longer undoes Cancel-all
mikenrafter Nov 9, 2026
1f43d8b
backup: companion_url no longer travels (a restored file could redire…
abdulsaheel Nov 10, 2026
8630989
merge main
abdulsaheel Nov 10, 2026
900f5af
fix(backup): read the Cancel-all marker only when the backup carries …
mikenrafter Nov 10, 2026
557cc5a
merge main
abdulsaheel Nov 13, 2026
ae66dce
Merge branch 'pr/edge-settings-backup' of https://github.com/mikenraf…
abdulsaheel Nov 13, 2026
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
29 changes: 29 additions & 0 deletions lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:provider/provider.dart';
import 'ai/briefing.dart' show BriefingPeriod;
import 'coach/coach_config.dart';
import 'data/db.dart';
import 'data/backup_extras.dart' show settingsRestoredSignal;
import 'l10n/app_localizations.dart';
import 'notify/notification_service.dart';
import 'notify/tap_router.dart';
Expand All @@ -15,6 +16,7 @@ import 'state/app_state.dart';
import 'state/clock_format.dart';
import 'state/locale_controller.dart';
import 'state/prefs.dart';
import 'state/units_controller.dart';
import 'telemetry/telemetry_service.dart';
import 'theme/theme_controller.dart';
import 'theme/theme_switcher.dart';
Expand Down Expand Up @@ -62,6 +64,7 @@ class _OpenStrapAppState extends State<OpenStrapApp> with WidgetsBindingObserver
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
settingsRestoredSignal.addListener(_onSettingsRestored);
unawaited(LocalDb.setForeground(
screenReadsForeground(WidgetsBinding.instance.lifecycleState)));
// Hand the BYOK provider config to AppState (briefing generation + the
Expand All @@ -76,8 +79,34 @@ class _OpenStrapAppState extends State<OpenStrapApp> with WidgetsBindingObserver
});
}

void _onSettingsRestored() {
if (!mounted) return;
unawaited(_reloadRestoredSetting('theme_choice',
context.read<ThemeController>().reloadFromPrefs));
unawaited(_reloadRestoredSetting('locale_override',
context.read<LocaleController>().reloadFromPrefs));
unawaited(_reloadRestoredSetting('units_system',
context.read<UnitsController>().reloadFromPrefs));
unawaited(_reloadRestoredSetting('clock_format',
context.read<ClockFormatController>().reloadFromPrefs));
}

Future<void> _reloadRestoredSetting(
String key, Future<void> Function() reload) async {
try {
await reload();
} catch (error, stack) {
// Controllers parse before replacing their value, so a malformed pref
// leaves the current/default choice active while other reloads continue.
debugPrint('[import] $key reload failed: $error');
TelemetryService.instance.recordNonFatal(error, stack,
reason: 'restored $key reload failed');
}
}

@override
void dispose() {
settingsRestoredSignal.removeListener(_onSettingsRestored);
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
Expand Down
Loading
Loading