Files
sxchnge/frontend/app/lib/routing/router.dart
T

140 lines
4.6 KiB
Dart

import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart';
import 'package:sxchnge_wallet/sxchnge_wallet.dart';
import '../auth/page.dart';
import '../kyc/page.dart';
import '../verification/page.dart';
import '../workspace/accounts.dart';
import '../workspace/activity.dart';
import '../workspace/limits.dart';
import '../workspace/operation.dart';
import '../workspace/settings.dart';
import '../workspace/shell.dart';
import '../workspace/transfer.dart';
import 'routes.dart';
GoRouter createAppRouter() {
final topUpKey = GlobalKey<TransferPageState>();
final exchangeKey = GlobalKey<TransferPageState>();
final payoutKey = GlobalKey<TransferPageState>();
final identityKey = GlobalKey<IdentityPageState>();
return GoRouter(
// Signup email is an in-memory navigation extra, never browser-history data.
extraCodec: const _TransientExtras(),
routes: [
ShellRoute(
builder: (context, state, child) =>
WorkspaceShell(path: state.uri.path, child: child),
routes: [
GoRoute(
path: '/accounts',
builder: (context, state) => const AccountsPage(),
routes: [
GoRoute(
path: ':accountId',
builder: (context, state) =>
AccountsPage(accountId: state.pathParameters['accountId']),
),
],
),
GoRoute(
path: '/activity',
builder: (context, state) => const ActivityPage(),
routes: [
GoRoute(
path: ':operationId',
builder: (context, state) =>
OperationPage(id: state.pathParameters['operationId']!),
),
],
),
GoRoute(
path: '/limits',
builder: (context, state) => const LimitsPage(),
),
GoRoute(
path: '/settings',
builder: (context, state) => const SettingsPage(),
),
GoRoute(
path: '/top-up',
builder: (context, state) => TransferPage(
key: topUpKey,
kind: TransferKind.topUp,
source: state.extra is String ? state.extra as String : null,
),
onExit: (context, state) async =>
await topUpKey.currentState?.allowExit() ?? true,
),
GoRoute(
path: '/exchange',
builder: (context, state) => TransferPage(
key: exchangeKey,
kind: TransferKind.exchange,
source: state.extra is String ? state.extra as String : null,
),
onExit: (context, state) async =>
await exchangeKey.currentState?.allowExit() ?? true,
),
GoRoute(
path: '/payout',
builder: (context, state) => TransferPage(
key: payoutKey,
kind: TransferKind.payout,
source: state.extra is String ? state.extra as String : null,
),
onExit: (context, state) async =>
await payoutKey.currentState?.allowExit() ?? true,
),
GoRoute(
path: '/identity',
name: AppRoutes.identity,
builder: (context, state) => IdentityPage(key: identityKey),
onExit: (context, state) async =>
await identityKey.currentState?.allowExit() ?? true,
),
],
),
GoRoute(
path: '/',
name: AppRoutes.login,
builder: (context, state) => const AuthPage(),
),
GoRoute(
path: '/verification-sent',
name: AppRoutes.verificationSent,
builder: (context, state) => VerificationPage(
email: state.extra is String ? state.extra as String : null,
),
),
GoRoute(
path: '/verify-email',
name: AppRoutes.verifyEmail,
builder: (context, state) =>
VerificationPage(token: state.uri.queryParameters['token'] ?? ''),
),
],
// Preserve the existing fallback, and keep the visible URL canonical.
onException: (context, state, router) => router.goNamed(AppRoutes.login),
);
}
class _TransientExtras extends Codec<Object?, Object?> {
const _TransientExtras();
@override
Converter<Object?, Object?> get encoder => const _DiscardExtra();
@override
Converter<Object?, Object?> get decoder => const _DiscardExtra();
}
class _DiscardExtra extends Converter<Object?, Object?> {
const _DiscardExtra();
@override
Object? convert(Object? input) => null;
}