Make recipient changes explicit, prioritize verification retry, and label simulated outcomes prominently. Add shared typed analytics with bounded dummy capture, correlated service events and documented PostHog adapter contract. Validate privacy, retries, abandonment, keyboard recovery and accessibility. Related to #12.
102 lines
3.1 KiB
Dart
102 lines
3.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:sxchnge_analytics/sxchnge_analytics.dart';
|
|
|
|
import 'package:sxchnge_auth/sxchnge_auth.dart';
|
|
|
|
import 'package:sxchnge_theme/sxchnge_theme.dart';
|
|
|
|
import 'providers/locale.dart';
|
|
import 'routing/router.dart';
|
|
|
|
import 'generated/i18n/app_localizations.dart';
|
|
|
|
Future<void> main() async {
|
|
final binding = WidgetsFlutterBinding.ensureInitialized();
|
|
final locale = await LocaleProvider.load(binding.platformDispatcher.locales);
|
|
runApp(SxchngeApp(localeProvider: locale));
|
|
}
|
|
|
|
class SxchngeApp extends StatefulWidget {
|
|
const SxchngeApp({
|
|
super.key,
|
|
this.localeProvider,
|
|
this.analyticsService,
|
|
this.loginService = const DummyLoginService(),
|
|
this.signupService = const DummySignupService(),
|
|
this.verificationService = const DummyVerificationService(),
|
|
});
|
|
final LocaleProvider? localeProvider;
|
|
final AnalyticsService? analyticsService;
|
|
final LoginService loginService;
|
|
final SignupService signupService;
|
|
final VerificationService verificationService;
|
|
|
|
@override
|
|
State<SxchngeApp> createState() => _SxchngeAppState();
|
|
}
|
|
|
|
class _SxchngeAppState extends State<SxchngeApp> {
|
|
late final _locale = widget.localeProvider ?? LocaleProvider();
|
|
|
|
late final _journeys = JourneyRecorder(
|
|
widget.analyticsService ?? DummyAnalyticsService(),
|
|
);
|
|
late final _services = InstrumentedAuthServices(
|
|
recorder: _journeys,
|
|
loginService: widget.loginService,
|
|
signupService: widget.signupService,
|
|
verificationService: widget.verificationService,
|
|
);
|
|
late final _router = createAppRouter()
|
|
..routeInformationProvider.addListener(_routeChanged);
|
|
String _previousPath = '/';
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_previousPath = _router.routeInformationProvider.value.uri.path;
|
|
}
|
|
|
|
void _routeChanged() {
|
|
final path = _router.routeInformationProvider.value.uri.path;
|
|
if (path == '/' && _previousPath != '/') {
|
|
_journeys.abandon(JourneyExit.navigation);
|
|
}
|
|
_previousPath = path;
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_router.routeInformationProvider.removeListener(_routeChanged);
|
|
_router.dispose();
|
|
_journeys.dispose();
|
|
_locale.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) => MultiProvider(
|
|
providers: [
|
|
Provider<JourneyRecorder>.value(value: _journeys),
|
|
ChangeNotifierProvider.value(value: _locale),
|
|
Provider<VerificationService>.value(value: _services),
|
|
ChangeNotifierProvider(create: (_) => LoginProvider(_services)),
|
|
ChangeNotifierProvider(create: (_) => SignupProvider(_services)),
|
|
],
|
|
child: Consumer<LocaleProvider>(
|
|
builder: (context, locale, _) => MaterialApp.router(
|
|
onGenerateTitle: (context) => AppLocalizations.of(context)!.appTitle,
|
|
debugShowCheckedModeBanner: false,
|
|
theme: SxchngeTheme.light(),
|
|
locale: locale.locale,
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
routerConfig: _router,
|
|
),
|
|
),
|
|
);
|
|
}
|