Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 44 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,42 @@ DeepLinkMaterialApp(
**Path dispatcher**
```dart
..path<LoginDL>((route) => LoginPage()),

..pathRoute<LoginDL>((path) => LoginPage(),
transition: (widget) => MaterialPageRoute(builder: (_) => widget),
), // with a custom page route or a custom PageRouteBuilder that implement custom route transitions

..path<LoginDL>(
(route) => LoginPage(),
transition: (widget) => DeepLinkTransition(
type: PageTransitionType.fade,
child: widget,
),
), // with custom DeepLinkTransition, an implementation of PageRouteBuilder provided by this package

..pathRoute<LoginDL>(
(route) => LoginPage(),
transition: DeepLinkTransitions.fade(),
) // with one of the custom transition shorthand builder functions provided by this package
..
```

**Value dispatcher**
```dart
..value<Song, SongDL>((song, route) => SongPage(song: song)),

.valueRoute<Song, SongDL>(
(song, route) => SongPage(song: song),
transition: (widget) => MaterialPageRoute(builder: (_) => widget),
), // with a custom page route or a custom PageRouteBuilder that implement custom route transitions

..valueRoute<Artist, ArtistDL>(
(artist, route) => ArtistPage(artist: artist),
transition: DeepLinkTransitions.scale(
alignment: Alignment.center,
duration: Duration(milliseconds: 800),
),
) // with one of the custom transition shorthand builder functions provided by this package
```

**Sub navigation**
Expand Down Expand Up @@ -225,6 +256,10 @@ All methods internally orchestrate a native flutter navigator.
**Push a deep link**
```dart
await DeepLinkNavigator.of(context).push(ArtistDL(...));

await DeepLinkNavigator.of(context).push(
ArtistDL(...),
transition: ....); //with transition
```

**Pop a value**
Expand All @@ -242,11 +277,19 @@ DeepLinkNavigator.of(context).navigateTo([
LibraryDL(),
ArtistDL(...),
]);

DeepLinkNavigator.of(context).navigateTo([
LibraryDL(),
ArtistDL(...),
],
transition: ....); //with transition
```

**Return to default route (if any)**
```dart
DeepLinkNavigator.of(context).replaceWithDefault();

DeepLinkNavigator.of(context).replaceWithDefault(transition: ...); //with transition
```

**TODO: Throw exception to be caught by mapper**
Expand All @@ -259,18 +302,6 @@ DeepLinkNavigator.of(context).replaceWithDefault();
// TODO DeepLinkNavigator()...
```

**TODO: Page transitions**
```dart
// await DeepLinkNavigator.of(context).push(
// ArtistDL(...),
// transition: ...,
// duration: ...,
// );

// Possibly:
// await DeepLinkNavigator.of(context).fadeIn(...);
```

## Platform deep links
// TODO: serialize `List<DeepLink>`

Expand All @@ -284,8 +315,6 @@ DeepLinkNavigator.of(context).replaceWithDefault();

## What's left to do

[ ] Custom/predefined page transitions

[ ] Access deep link navigator from anywhere using static method and factory pattern

[ ] Assert `RouteNotFound` dispatcher exists by running through navigation tree
Expand All @@ -298,4 +327,4 @@ DeepLinkNavigator.of(context).replaceWithDefault();

[ ] Platform deep links example + documentation

[ ] Route changed callback for analytics, etc
[ ] Route changed callback for analytics, etc
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ packages:
path: ".."
relative: true
source: path
version: "1.3.1"
version: "1.4.0"
flutter:
dependency: transitive
description: flutter
Expand Down
133 changes: 81 additions & 52 deletions examples/multiple_base_routes/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ import 'package:multiple_base_routes/widgets/splash_page.dart';
import 'package:multiple_base_routes/widgets/user_page.dart';

void main() => runApp(
// State management of your choice
ChangeNotifierProvider<AuthenticationService>(
create: (_) => AuthenticationService(),
child: MusicApp(),
)
);
// State management of your choice
ChangeNotifierProvider<AuthenticationService>(
create: (_) => AuthenticationService(),
child: MusicApp(),
));

/// [DeepLink]s associated with the bottom navigation.
final bottomNavigationDeepLinks = [LibraryDL(), FavoritesDL(), UserDL()];
Expand All @@ -35,55 +34,85 @@ int currentIndex(List<DeepLink> currentRoute) {
class MusicApp extends StatelessWidget {
@override
Widget build(BuildContext context) => DeepLinkMaterialApp(
// This is where the magic happens
navigation: Dispatcher()
// RouteNotFound error page
..exception<RouteNotFound>((exception, route) => [ErrorDL<RouteNotFound>(exception)])
..value<RouteNotFound, ErrorDL<RouteNotFound>>((exception, route) => ErrorPage(exception))
// Unauthenticated login page
..exception<Unauthenticated>((exception, route) => [LoginDL()])
..path<LoginDL>((path) => LoginPage())
// The rest of the app
..path<LibraryDL>(
(route) => LibraryPage(),
subNavigation: Dispatcher()
..value<Artist, ArtistDL>(
(artist, route) => ArtistPage(artist: artist),
subNavigation: (artist) => Dispatcher()
..song()
// This is where the magic happens
navigation: Dispatcher()
// RouteNotFound error page
..exception<RouteNotFound>(
(exception, route) => [ErrorDL<RouteNotFound>(exception)])
..value<RouteNotFound, ErrorDL<RouteNotFound>>(
(exception, route) => ErrorPage(exception))
// Unauthenticated login page
..exception<Unauthenticated>((exception, route) => [LoginDL()])
..path<LoginDL>(
(route) => LoginPage(),
transition: (widget) => MaterialPageRoute(builder: (_) => widget),
)
// The rest of the app
..path<LibraryDL>(
(route) => LibraryPage(),
transition: (widget) => DeepLinkTransition(
type: DeepLinkTransitionType.fade,
child: widget,
),
subNavigation: Dispatcher()
..value<Artist, ArtistDL>(
(artist, route) => ArtistPage(artist: artist),
transition: DeepLinkTransitions.scale(
alignment: Alignment.center,
duration: Duration(milliseconds: 800),
),
subNavigation: (artist) => Dispatcher()..song(),
),
)
..path<FavoritesDL>((route) => FavoritesPage(),
transition: DeepLinkTransitions.rotate(
duration: Duration(milliseconds: 500),
curve: Curves.bounceInOut,
alignment: Alignment.center,
),
subNavigation: Dispatcher()..song())
..path<UserDL>(
(route) => UserPage(),
transition: DeepLinkTransitions.custom(
DeepLinkTransitionType.upToDown),
subNavigation: Dispatcher()
..path<AuthenticationDL>((route) => AuthenticationPage()),
),
)
..path<FavoritesDL>(
(route) => FavoritesPage(),
subNavigation: Dispatcher()
..song()
)
..path<UserDL>(
(route) => UserPage(),
subNavigation: Dispatcher()..path<AuthenticationDL>((route) => AuthenticationPage()),
),
defaultRoute: [LibraryDL()],
splashScreen: SplashPage(),
// Optionally specify always visible widgets
childBuilder: (BuildContext context, DeepLinkNavigator deepLinkNavigator, Widget child) => Scaffold(
body: child,
// Don't show bottom navigation while [currentRoute] is null, or any deep list is [FullScreen]
bottomNavigationBar: deepLinkNavigator.currentRoute?.any((dl) => dl is FullScreen) ?? true ? null : BottomNavigationBar(
currentIndex: currentIndex(deepLinkNavigator.currentRoute),
onTap: (int index) => deepLinkNavigator.navigateTo([bottomNavigationDeepLinks[index]]),
items: [
BottomNavigationBarItem(title: Text("Library"), icon: Icon(Icons.queue_music, key: Key("library"))),
BottomNavigationBarItem(title: Text("Favorites"), icon: Icon(Icons.favorite, key: Key("favorites"))),
BottomNavigationBarItem(title: Text("User"), icon: Icon(Icons.person, key: Key("user"))),
],
),
),
// Non-navigation related fields are still available
themeMode: ThemeMode.light,
);
defaultRoute: [LibraryDL()],
splashScreen: SplashPage(),
// Optionally specify always visible widgets
childBuilder: (BuildContext context,
DeepLinkNavigator deepLinkNavigator, Widget child) =>
Scaffold(
body: child,
// Don't show bottom navigation while [currentRoute] is null, or any deep list is [FullScreen]
bottomNavigationBar: deepLinkNavigator.currentRoute
?.any((dl) => dl is FullScreen) ??
true
? null
: BottomNavigationBar(
currentIndex: currentIndex(deepLinkNavigator.currentRoute),
onTap: (int index) => deepLinkNavigator
.navigateTo([bottomNavigationDeepLinks[index]]),
items: [
BottomNavigationBarItem(
title: Text("Library"),
icon: Icon(Icons.queue_music, key: Key("library"))),
BottomNavigationBarItem(
title: Text("Favorites"),
icon: Icon(Icons.favorite, key: Key("favorites"))),
BottomNavigationBarItem(
title: Text("User"),
icon: Icon(Icons.person, key: Key("user"))),
],
),
),
// Non-navigation related fields are still available
themeMode: ThemeMode.light,
);
}

/// Reusing code through static extension methods.
extension DispatcherExtensions on Dispatcher {
void song() => value<Song, SongDL>((song, route) => SongPage(song: song));
}
}
17 changes: 14 additions & 3 deletions examples/multiple_base_routes/lib/widgets/library_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,33 @@ class LibraryPage extends StatelessWidget {
leading: CircleAvatar(child: Icon(Icons.person)),
title: Text(artist.name),
subtitle: Text("${artist.songs.length} songs"),
onTap: () => DeepLinkNavigator.of(context).push(ArtistDL(artist)),
onTap: () => DeepLinkNavigator.of(context).push(
ArtistDL(artist),
transition: artist.name.startsWith('Ludwig')
? DeepLinkTransitions.rotate(
duration: Duration(milliseconds: 500),
curve: Curves.bounceInOut,
alignment: Alignment.center,
)
: null,
),
),
Divider(),
ListTile(
key: Key("Non-existant push"),
leading: CircleAvatar(child: Icon(Icons.bug_report)),
title: Text("Non-existant push"),
// Route doesn't exist
onTap: () => DeepLinkNavigator.of(context).push(SongDL(Data.favoriteSongs[0])),
onTap: () => DeepLinkNavigator.of(context)
.push(SongDL(Data.favoriteSongs[0])),
),
ListTile(
key: Key("Non-existant navigate"),
leading: CircleAvatar(child: Icon(Icons.bug_report)),
title: Text("Non-existant navigate"),
// Route doesn't exist
onTap: () => DeepLinkNavigator.of(context).navigateTo([LibraryDL(), SongDL(Data.favoriteSongs[1])]),
onTap: () => DeepLinkNavigator.of(context)
.navigateTo([LibraryDL(), SongDL(Data.favoriteSongs[1])]),
)
],
),
Expand Down
4 changes: 3 additions & 1 deletion lib/deep_link_navigation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ export 'src/deep_link.dart';
export 'src/deep_link_material_app.dart';
export 'src/deep_link_navigator.dart';
export 'src/dispatchers.dart';
export 'src/exceptions.dart';
export 'src/exceptions.dart';
export 'src/deep_link_transition.dart';
export 'src/deep_link_transitions.dart';
Loading