Files
sxchnge/frontend/app/lib/main.dart

159 lines
5.3 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_kyc/sxchnge_kyc.dart';
import 'package:sxchnge_theme/sxchnge_theme.dart';
import 'package:sxchnge_wallet/sxchnge_wallet.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);
const apiUrl = String.fromEnvironment('SXCHNGE_API_URL');
const clientId = String.fromEnvironment('SXCHNGE_CLIENT_ID');
final backend = apiUrl.isEmpty
? null
: BackendAuthServices(baseUri: Uri.parse(apiUrl), clientId: clientId);
runApp(SxchngeApp(localeProvider: locale, backend: backend));
}
class SxchngeApp extends StatefulWidget {
const SxchngeApp({
super.key,
this.localeProvider,
this.backend,
this.analyticsService,
this.identityService,
this.limitsService,
this.walletService,
this.twoFactorService,
this.photoService = const FilePhotoService(),
this.loginService = const DummyLoginService(),
this.signupService = const DummySignupService(),
this.verificationService = const DummyVerificationService(),
});
final LocaleProvider? localeProvider;
final BackendAuthServices? backend;
final AnalyticsService? analyticsService;
final IdentityService? identityService;
final LimitsService? limitsService;
final WalletService? walletService;
final TwoFactorService? twoFactorService;
final PhotoService photoService;
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 _analytics = widget.analyticsService ?? DummyAnalyticsService();
late final _factors =
widget.backend ?? widget.twoFactorService ?? DummyTwoFactorService();
late final _security = SecurityProvider(_factors, _analytics);
late final _identity = widget.identityService ?? DummyIdentityService();
late final _walletService =
widget.walletService ??
DummyWalletService(
_identity,
initialLocale: _locale.locale.languageCode,
factors: _factors,
);
late final _wallet = WalletProvider(
_walletService,
_analytics,
factors: _factors,
);
late final _limits =
widget.limitsService ??
(_walletService is DummyWalletService
? WalletLimitsService(_walletService)
: DummyLimitsService(_identity));
late final _journeys = JourneyRecorder(_analytics);
late final _services = InstrumentedAuthServices(
recorder: _journeys,
loginService: GuardedLoginService(
widget.backend ?? widget.loginService,
_factors,
),
signupService: widget.backend ?? widget.signupService,
verificationService: widget.backend ?? widget.verificationService,
);
late final _router = createAppRouter(
authenticated: widget.backend == null
? null
: () => widget.backend!.session != null,
)..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 != '/' && _previousPath != '/two-factor') {
_journeys.abandon(JourneyExit.navigation);
}
_previousPath = path;
}
@override
void dispose() {
_router.routeInformationProvider.removeListener(_routeChanged);
_router.dispose();
_journeys.dispose();
_wallet.dispose();
_security.dispose();
_locale.dispose();
widget.backend?.close();
super.dispose();
}
@override
Widget build(BuildContext context) => MultiProvider(
providers: [
ChangeNotifierProvider.value(value: _wallet),
ChangeNotifierProvider.value(value: _security),
Provider<TwoFactorService>.value(value: _factors),
Provider<JourneyRecorder>.value(value: _journeys),
Provider<AnalyticsService>.value(value: _analytics),
Provider<IdentityService>.value(value: _identity),
Provider<LimitsService>.value(value: _limits),
Provider<PhotoService>.value(value: widget.photoService),
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,
),
),
);
}