Fix deeplinking / refresh on web

Add all nested routes to the routing table
This commit is contained in:
Shawn 2024-01-09 14:54:08 -07:00
parent 74b536b366
commit 824f4a1ff1
2 changed files with 92 additions and 48 deletions

View File

@ -54,7 +54,7 @@ class AppLogic {
// Set preferred refresh rate to the max possible (the OS may ignore this) // Set preferred refresh rate to the max possible (the OS may ignore this)
if (PlatformInfo.isAndroid) { if (PlatformInfo.isAndroid) {
await FlutterDisplayMode.setHighRefreshRate(); FlutterDisplayMode.setHighRefreshRate();
} }
// Settings // Settings
@ -77,10 +77,10 @@ class AppLogic {
// Load initial view (replace empty initial view which is covered by a native splash screen) // Load initial view (replace empty initial view which is covered by a native splash screen)
bool showIntro = settingsLogic.hasCompletedOnboarding.value == false; bool showIntro = settingsLogic.hasCompletedOnboarding.value == false;
if (showIntro || true) { if (showIntro) {
appRouter.go(ScreenPaths.intro); appRouter.go(ScreenPaths.intro);
} else { } else {
appRouter.go(ScreenPaths.home); appRouter.go(initialDeeplink ?? ScreenPaths.home);
} }
} }

View File

@ -16,16 +16,54 @@ class ScreenPaths {
static String splash = '/'; static String splash = '/';
static String intro = '/welcome'; static String intro = '/welcome';
static String home = '/home'; static String home = '/home';
static String settings = '/settings'; static String settings = '/settings';
static String wonderDetails(WonderType type, {int tabIndex = 0}) => '/wonder/${type.name}?t=$tabIndex';
static String video(String id) => '/video/$id'; // editorial
static String highlights(WonderType type) => '/highlights/${type.name}'; static String wonderDetails(WonderType type, {required int tabIndex}) => '$home/wonder/${type.name}?t=$tabIndex';
// add /home/wonderType/
static String video(String id, {String? currentPath}) {
var value = '${currentPath ?? ''}/video/$id';
// if(currentPath != null) {
//
// value = '${context.go}/$value';
// }
return value;
}
static String search(WonderType type) => '/search/${type.name}'; static String search(WonderType type) => '/search/${type.name}';
static String artifact(String id) => '/artifact/$id';
static String collection(String id) => '/collection?id=$id';
static String maps(WonderType type) => '/maps/${type.name}'; static String maps(WonderType type) => '/maps/${type.name}';
// both home/timeline and /home/wonderType/timeline
static String timeline(WonderType? type) => '/timeline?type=${type?.name ?? ''}'; static String timeline(WonderType? type) => '/timeline?type=${type?.name ?? ''}';
static String wallpaperPhoto(WonderType type) => '/wallpaperPhoto/${type.name}';
// /collection, /search, /carousel, this should be a dialog... but then it can't be deep-linked?
static String artifact(String id) => '/artifact/$id';
static String collection(String id) => '/collection?id=$id';
}
// Routes that are used multiple times
AppRoute get _artifactRoute => AppRoute(
'artifact/:id',
(s) => ArtifactDetailsScreen(artifactId: s.pathParameters['id']!),
);
AppRoute get _timelineRoute {
return AppRoute(
'timeline',
(s) => TimelineScreen(type: _tryParseWonderType(s.uri.queryParameters['type']!)),
);
}
AppRoute get _collectionRoute {
return AppRoute(
'collection',
(s) => CollectionScreen(fromId: s.uri.queryParameters['id'] ?? ''),
routes: [
_artifactRoute,
],
);
} }
/// Routing table, matches string paths to UI Screens, optionally parses params from the paths /// Routing table, matches string paths to UI Screens, optionally parses params from the paths
@ -38,44 +76,45 @@ final appRouter = GoRouter(
}, },
routes: [ routes: [
AppRoute(ScreenPaths.splash, (_) => Container(color: $styles.colors.greyStrong)), // This will be hidden AppRoute(ScreenPaths.splash, (_) => Container(color: $styles.colors.greyStrong)), // This will be hidden
AppRoute(ScreenPaths.home, (_) => HomeScreen(), routes: [
AppRoute('wonder/:type', (s) {
int tab = int.tryParse(s.queryParams['t'] ?? '') ?? 0;
return WonderDetailsScreen(
type: _parseWonderType(s.params['type']),
initialTabIndex: tab,
);
}, useFade: true),
]),
AppRoute(ScreenPaths.intro, (_) => IntroScreen()), AppRoute(ScreenPaths.intro, (_) => IntroScreen()),
AppRoute('/wonder/:type', (s) { AppRoute(ScreenPaths.home, (_) => HomeScreen(), routes: [
int tab = int.tryParse(s.queryParams['t'] ?? '') ?? 0; AppRoute(
'wonder/:type',
(s) {
int tab = int.tryParse(s.uri.queryParameters['t'] ?? '') ?? 0;
return WonderDetailsScreen( return WonderDetailsScreen(
type: _parseWonderType(s.params['type']), type: _parseWonderType(s.pathParameters['type']),
initialTabIndex: tab, tabIndex: tab,
); );
}, useFade: true), },
AppRoute('/timeline', (s) { useFade: true,
return TimelineScreen(type: _tryParseWonderType(s.queryParams['type']!)); // Wonder sub-routes
routes: [
_timelineRoute,
_collectionRoute,
// Youtube Video
AppRoute('video/:id', (s) {
return FullscreenVideoViewer(id: s.pathParameters['id']!);
}), }),
AppRoute('/video/:id', (s) {
return FullscreenVideoViewer(id: s.params['id']!); // Search
}), AppRoute(
AppRoute('/highlights/:type', (s) { 'search/:type',
return ArtifactCarouselScreen(type: _parseWonderType(s.params['type'])); (s) {
}), return ArtifactSearchScreen(type: _parseWonderType(s.pathParameters['type']));
AppRoute('/search/:type', (s) { },
return ArtifactSearchScreen(type: _parseWonderType(s.params['type'])); routes: [
}), _artifactRoute,
AppRoute('/artifact/:id', (s) { ],
return ArtifactDetailsScreen(artifactId: s.params['id']!); ),
}),
AppRoute('/collection', (s) { // Maps
return CollectionScreen(fromId: s.queryParams['id'] ?? ''); AppRoute('maps/:type', (s) {
}), return FullscreenMapsViewer(type: _parseWonderType(s.pathParameters['type']));
AppRoute('/maps/:type', (s) {
return FullscreenMapsViewer(type: _parseWonderType(s.params['type']));
}), }),
],
),
]),
]), ]),
], ],
); );
@ -107,12 +146,17 @@ class AppRoute extends GoRoute {
final bool useFade; final bool useFade;
} }
String? get initialDeeplink => _initialDeeplink;
String? _initialDeeplink;
String? _handleRedirect(BuildContext context, GoRouterState state) { String? _handleRedirect(BuildContext context, GoRouterState state) {
// Prevent anyone from navigating away from `/` if app is starting up. // Prevent anyone from navigating away from `/` if app is starting up.
if (!appLogic.isBootstrapComplete && state.location != ScreenPaths.splash) { if (!appLogic.isBootstrapComplete && state.uri.path != ScreenPaths.splash) {
debugPrint('Redirecting from ${state.uri.path} to ${ScreenPaths.splash}');
_initialDeeplink ??= state.uri.toString();
return ScreenPaths.splash; return ScreenPaths.splash;
} }
debugPrint('Navigate to: ${state.location}'); debugPrint('Navigate to: ${state.uri.path}');
return null; // do nothing return null; // do nothing
} }