diet-guard/app/lib/main.dart
Krzysztof kuhy Rudnicki adbfb20e9a Add OAuth device flow, background notifications, and fix AGP9 release crash (Milestones 3–4)
M3 – GitHub OAuth device flow: replace PAT-paste with a guided "Connect
GitHub" button that runs the device-code flow; tapping with no client id
now opens a setup dialog (instructions + inline paste field) rather than
a buried inline hint. Bakes in the app's own OAuth App client id so fresh
installs work with zero manual config. Auto-syncs immediately after
connect. Verified end-to-end on the real phone: OAuth flow → token saved
→ PC's 48-entry log merged in (confirmed via food-bank vs manual source
labels in History).

M4 – Background meal-slot notifications: WorkManager periodic task (15 min
floor) checks for overdue slots and posts/cancels notifications via
flutter_local_notifications. New permissions: POST_NOTIFICATIONS,
WAKE_LOCK, RECEIVE_BOOT_COMPLETED, REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
INTERNET (was missing — latent sync bug). "Disable battery optimization"
button in Settings. Verified on real phone: WorkManager registered, forced
run posted a real notification ("Meal not logged / You haven't logged your
16:00 meal yet."), isolated to background path (only caller is the
WorkManager dispatcher, not any foreground lifecycle hook).

AGP9 release crash fix: AGP 9 defaults isMinifyEnabled/isShrinkResources
to true for release even with no proguard config; R8 stripped
WorkDatabase_Impl's reflection-only constructor, crashing every launch
with NoSuchMethodException. Explicitly disabled both flags in
build.gradle.kts. Verified via dexdump (constructor present) and on-device
launch (no crash). Proper R8 keep rules are the long-term fix; tracked.

177 tests, flutter analyze clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SWPUBzE24Ls9i9GMRwXnnn
2026-06-25 17:29:23 +02:00

50 lines
1.7 KiB
Dart

/// App entry point: initializes local storage services, registers the
/// background due-slot check, then shows the primary meal-logging screen.
library;
import 'dart:io';
import 'package:diet_guard_app/screens/log_meal_screen.dart';
import 'package:diet_guard_app/services/background_check_service.dart';
import 'package:diet_guard_app/services/foodbank_service.dart';
import 'package:diet_guard_app/services/log_storage_service.dart';
import 'package:diet_guard_app/services/notification_service.dart';
import 'package:flutter/material.dart';
import 'package:workmanager/workmanager.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await LogStorageService.init();
await FoodBankService.init();
final notifications = await NotificationService.init();
await notifications.requestPermission();
// WorkManager has no Linux/web/desktop implementation -- registering it
// there throws. Guard to the two platforms that ship it.
// coverage:ignore-start
if (Platform.isAndroid || Platform.isIOS) {
await Workmanager().initialize(backgroundCheckCallbackDispatcher);
await Workmanager().registerPeriodicTask(
backgroundCheckTaskName,
backgroundCheckTaskName,
frequency: const Duration(minutes: 15),
);
}
// coverage:ignore-end
runApp(const DietGuardApp());
}
/// Root widget for the Diet Guard companion app.
class DietGuardApp extends StatelessWidget {
/// Creates the [DietGuardApp] root widget.
const DietGuardApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Diet Guard',
theme: ThemeData(colorSchemeSeed: Colors.teal, useMaterial3: true),
home: const LogMealScreen(),
);
}
}