Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: url routing and deep linking support #99

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
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
15 changes: 15 additions & 0 deletions example/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,20 @@
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>FlutterDeepLinkingEnabled</key>
<true/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>myapp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
</dict>
</plist>
11 changes: 11 additions & 0 deletions example/lib/authentication_flow/authentication_flow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,24 @@ class AuthenticationFlow extends StatelessWidget {

static Route<AuthenticationState> route() {
return MaterialPageRoute(
settings: const RouteSettings(name: '/auth'),
builder: (_) => BlocProvider(
create: (_) => AuthenticationCubit(),
child: const AuthenticationFlow._(),
),
);
}

static Page<AuthenticationState> page() {
return MaterialPage(
name: '/auth',
child: BlocProvider(
create: (_) => AuthenticationCubit(),
child: const AuthenticationFlow._(),
),
);
}

@override
Widget build(BuildContext context) {
return FlowBuilder<AuthenticationState>(
Expand Down
18 changes: 15 additions & 3 deletions example/lib/location_flow/location_flow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,27 @@ List<Page<dynamic>> onGenerateLocationPages(
class LocationFlow extends StatelessWidget {
const LocationFlow._();

static Page<Location> page() => const MaterialPage(child: LocationFlow._());

static Route<Location> route() {
return MaterialPageRoute(builder: (_) => const LocationFlow._());
return MaterialPageRoute(
settings: const RouteSettings(name: '/location'),
builder: (_) => const LocationFlow._(),
);
}

@override
Widget build(BuildContext context) {
return const FlowBuilder<Location>(
state: Location(),
return FlowBuilder<Location>(
state: const Location(),
onGeneratePages: onGenerateLocationPages,
onLocationChanged: (location, state) {
return Location(
country: location.queryParameters['country'],
city: location.queryParameters['city'],
state: location.queryParameters['state'],
);
},
);
}
}
32 changes: 31 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:example/authentication_flow/authentication_flow.dart';
import 'package:example/location_flow/location_flow.dart';
import 'package:example/onboarding_flow/onboarding_flow.dart';
import 'package:example/profile_flow/profile_flow.dart';
import 'package:flow_builder/flow_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

Expand All @@ -17,14 +18,43 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return RepositoryProvider.value(
value: _locationRepository,
child: const MaterialApp(home: Home()),
child: const MaterialApp(home: UrlFlowBuilder()),
);
}
}

class UrlFlowBuilder extends StatelessWidget {
const UrlFlowBuilder({super.key});

@override
Widget build(BuildContext context) {
return FlowBuilder<Uri>(
state: Uri(path: '/'),
onGeneratePages: (uri, pages) {
if (uri.pathSegments.isEmpty) return [Home.page()];
return [
Home.page(),
if (uri.pathSegments.first == 'profile') ProfileFlow.page(),
if (uri.pathSegments.first == 'onboarding') OnboardingFlow.page(),
if (uri.pathSegments.first == 'location') LocationFlow.page(),
if (uri.pathSegments.first == 'auth') AuthenticationFlow.page(),
];
},
onLocationChanged: (location, state) => location,
onDidPop: (dynamic result) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text('$result')));
},
);
}
}

class Home extends StatefulWidget {
const Home({super.key});

static Page<void> page() => const MaterialPage<void>(name: '/', child: Home());

@override
State<Home> createState() => _HomeState();
}
Expand Down
19 changes: 16 additions & 3 deletions example/lib/onboarding_flow/onboarding_flow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ List<Page<dynamic>> onGenerateOnboardingPages(
List<Page<dynamic>> pages,
) {
switch (state) {
case OnboardingState.onboardingComplete:
case OnboardingState.usageComplete:
return [
OnboardingWelcome.page(),
Expand All @@ -27,24 +28,36 @@ List<Page<dynamic>> onGenerateOnboardingPages(
OnboardingUsage.page(),
];
case OnboardingState.initial:
case OnboardingState.onboardingComplete:
return [OnboardingWelcome.page()];
}
}

class OnboardingFlow extends StatelessWidget {
const OnboardingFlow._();

static Page<OnboardingState> page() {
return const MaterialPage(child: OnboardingFlow._());
}

static Route<OnboardingState> route() {
return MaterialPageRoute(builder: (_) => const OnboardingFlow._());
return MaterialPageRoute(
settings: const RouteSettings(name: '/onboarding/0'),
builder: (_) => const OnboardingFlow._(),
);
}

@override
Widget build(BuildContext context) {
return FlowBuilder(
return FlowBuilder<OnboardingState>(
state: OnboardingState.initial,
observers: [HeroController()],
onGeneratePages: onGenerateOnboardingPages,
onLocationChanged: (location, state) {
final index = location.pathSegments.length > 1
? int.tryParse(location.pathSegments[1]) ?? 0
: 0;
return OnboardingState.values[index];
},
);
}
}
Expand Down
46 changes: 30 additions & 16 deletions example/lib/profile_flow/profile_flow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,44 @@ import 'package:equatable/equatable.dart';
import 'package:flow_builder/flow_builder.dart';
import 'package:flutter/material.dart';

List<Page<dynamic>> onGenerateProfilePages(
Profile profile,
List<Page<dynamic>> pages,
) {
return [
const MaterialPage<void>(child: ProfileNameForm(), name: '/profile'),
if (profile.name != null) const MaterialPage<void>(child: ProfileAgeForm()),
if (profile.age != null)
const MaterialPage<void>(child: ProfileWeightForm()),
];
}

class ProfileFlow extends StatelessWidget {
const ProfileFlow._();

static Page<Profile> page() => const MaterialPage(child: ProfileFlow._());

static Route<Profile> route() {
return MaterialPageRoute(builder: (_) => const ProfileFlow._());
return MaterialPageRoute(
settings: const RouteSettings(name: '/profile'),
builder: (_) => const ProfileFlow._(),
);
}

@override
Widget build(BuildContext context) {
return const FlowBuilder<Profile>(
state: Profile(),
onGeneratePages: onGenerateProfilePages,
return FlowBuilder<Profile>(
state: const Profile(),
onGeneratePages: (Profile profile, List<Page<dynamic>> pages) {
return [
const MaterialPage<void>(child: ProfileNameForm(), name: '/profile'),
if (profile.name != null)
MaterialPage<void>(
child: const ProfileAgeForm(),
name: '/profile?name=${profile.name}',
),
if (profile.age != null)
MaterialPage<void>(
child: const ProfileWeightForm(),
name: '/profile?name=${profile.name}&age=${profile.age}',
),
];
},
onLocationChanged: (location, state) {
return Profile(
name: location.queryParameters['name'],
weight: int.tryParse(location.queryParameters['weight'] ?? ''),
age: int.tryParse(location.queryParameters['age'] ?? ''),
);
},
);
}
}
Expand Down
2 changes: 2 additions & 0 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ dependencies:
flutter:
sdk: flutter
flutter_bloc: ^8.0.0
flutter_web_plugins:
sdk: flutter

dev_dependencies:
very_good_analysis: ^3.0.1
Expand Down
Loading