RELEASE: moved from beta to First stable release.

Check CHANGELOG.md for full changelog
This commit is contained in:
Ujwal
2026-02-27 04:14:40 +05:45
parent eecb823e62
commit 7992d65bc8
64 changed files with 6208 additions and 2752 deletions
+26 -5
View File
@@ -1,16 +1,22 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:app_links/app_links.dart';
import 'services/session_manager.dart';
import 'services/settings_service.dart';
import 'services/screen_time_service.dart';
import 'services/focusgram_router.dart';
import 'services/injection_controller.dart';
import 'screens/onboarding_page.dart';
import 'screens/main_webview_page.dart';
import 'screens/breath_gate_screen.dart';
import 'screens/app_session_picker.dart';
import 'screens/cooldown_gate_screen.dart';
import 'services/notification_service.dart';
import 'features/update_checker/update_checker_service.dart';
import 'features/preloader/instagram_preloader.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -23,9 +29,13 @@ void main() async {
final sessionManager = SessionManager();
final settingsService = SettingsService();
final screenTimeService = ScreenTimeService();
final updateChecker = UpdateCheckerService();
await sessionManager.init();
await settingsService.init();
await screenTimeService.init();
await NotificationService().init();
runApp(
@@ -33,10 +43,15 @@ void main() async {
providers: [
ChangeNotifierProvider.value(value: sessionManager),
ChangeNotifierProvider.value(value: settingsService),
ChangeNotifierProvider.value(value: screenTimeService),
ChangeNotifierProvider.value(value: updateChecker),
],
child: const FocusGramApp(),
),
);
// Fire and forget — preloads Instagram while app UI initialises.
unawaited(InstagramPreloader.start(InjectionController.iOSUserAgent));
}
class FocusGramApp extends StatelessWidget {
@@ -72,7 +87,8 @@ class FocusGramApp extends StatelessWidget {
/// 1. Onboarding (if first run)
/// 2. Cooldown Gate (if app-open cooldown active)
/// 3. Breath Gate (if enabled in settings)
/// 4. App Session Picker (always)
/// 4. If an app session is already active, resume it
/// otherwise show App Session Picker
/// 5. Main WebView
class InitialRouteHandler extends StatefulWidget {
const InitialRouteHandler({super.key});
@@ -133,11 +149,16 @@ class _InitialRouteHandlerState extends State<InitialRouteHandler> {
);
}
// Step 4: App session picker
// Step 4: App session picker / resume existing session
if (!_appSessionStarted) {
return AppSessionPickerScreen(
onSessionStarted: () => setState(() => _appSessionStarted = true),
);
if (sm.isAppSessionActive) {
// User already has an active app session — don't ask intention again.
_appSessionStarted = true;
} else {
return AppSessionPickerScreen(
onSessionStarted: () => setState(() => _appSessionStarted = true),
);
}
}
// Step 5: Main app