210 lines
7.1 KiB
Dart
210 lines
7.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_web_plugins/url_strategy.dart';
|
|
|
|
import 'package:country_picker/country_picker.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 {
|
|
usePathUrlStrategy();
|
|
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.destinationService,
|
|
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 DestinationService? destinationService;
|
|
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 _authFactors =
|
|
widget.backend ?? widget.twoFactorService ?? DummyTwoFactorService();
|
|
late final _factors = _walletService is BackendWalletService
|
|
? WalletFactorService(_walletService, _authFactors)
|
|
: _authFactors;
|
|
late final _security = SecurityProvider(_factors, _analytics);
|
|
late final _identity =
|
|
widget.identityService ??
|
|
(widget.backend == null
|
|
? DummyIdentityService()
|
|
: BackendIdentityService(
|
|
baseUri: widget.backend!.baseUri,
|
|
accessToken: () => widget.backend!.session?.accessToken,
|
|
));
|
|
late final _walletService =
|
|
widget.walletService ??
|
|
(widget.backend != null
|
|
? BackendWalletService(
|
|
baseUri: widget.backend!.baseUri,
|
|
accessToken: () => widget.backend!.session?.accessToken,
|
|
)
|
|
: DummyWalletService(
|
|
_identity,
|
|
initialLocale: _locale.locale.languageCode,
|
|
factors: _authFactors,
|
|
));
|
|
late final _destinationService =
|
|
widget.destinationService ??
|
|
(_walletService.isSimulated && _walletService is DummyWalletService
|
|
? _walletService.destinations
|
|
: const UnavailableDestinationService());
|
|
late final _destinations = DestinationsProvider(_destinationService);
|
|
late final _wallet = WalletProvider(
|
|
_walletService,
|
|
_analytics,
|
|
factors: _factors,
|
|
destinations: _destinationService,
|
|
);
|
|
late final _limits =
|
|
widget.limitsService ??
|
|
(_identity is BackendIdentityService
|
|
? BackendLimitsService(_identity)
|
|
: _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 = '/';
|
|
String? _walletCustomer;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_previousPath = _router.routeInformationProvider.value.uri.path;
|
|
_walletCustomer = widget.backend?.session?.userId;
|
|
}
|
|
|
|
void _routeChanged() {
|
|
final customer = widget.backend?.session?.userId;
|
|
if (customer != _walletCustomer) {
|
|
_walletCustomer = customer;
|
|
_wallet.reset();
|
|
_destinations.reset();
|
|
}
|
|
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();
|
|
_destinations.dispose();
|
|
if (_walletService is BackendWalletService) {
|
|
_walletService.close();
|
|
}
|
|
_security.dispose();
|
|
if (_identity is BackendIdentityService) {
|
|
_identity.close();
|
|
}
|
|
_locale.dispose();
|
|
widget.backend?.close();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) => MultiProvider(
|
|
providers: [
|
|
ChangeNotifierProvider.value(value: _wallet),
|
|
ChangeNotifierProvider.value(value: _destinations),
|
|
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(create: (_) => IdentityOnboardingProvider(_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: const [
|
|
...AppLocalizations.localizationsDelegates,
|
|
CountryLocalizations.delegate,
|
|
],
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
routerConfig: _router,
|
|
),
|
|
),
|
|
);
|
|
}
|