Skip to content

Commit

Permalink
feat!: remove controller from builder (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
felangel authored Oct 14, 2020
1 parent d5f5007 commit 924a8f2
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 184 deletions.
211 changes: 40 additions & 171 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'package:equatable/equatable.dart';
import 'package:example/onboarding_flow.dart';
import 'package:example/profile_flow.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flow_builder/flow_builder.dart';

void main() {
EquatableConfig.stringify = kDebugMode;
Expand All @@ -17,178 +18,46 @@ class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Center(
child: Builder(
builder: (context) {
return RaisedButton(
onPressed: () async {
final profile = await Navigator.of(context).push(
ProfileFlow.route(),
);
Scaffold.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text('$profile')));
},
child: const Text('Start'),
);
},
),
),
);
}
}

class ProfileFlow extends StatelessWidget {
static Route<Profile> route() {
return MaterialPageRoute(builder: (_) => ProfileFlow());
}

@override
Widget build(BuildContext context) {
return FlowBuilder<Profile>(
state: const Profile(),
builder: (context, profile, controller) {
return [
MaterialPage<void>(child: ProfileNameForm()),
if (profile.name != null) MaterialPage<void>(child: ProfileAgeForm()),
if (profile.age != null)
MaterialPage<void>(child: ProfileWeightForm()),
];
},
);
}
}

class ProfileNameForm extends StatefulWidget {
@override
_ProfileNameFormState createState() => _ProfileNameFormState();
}

class _ProfileNameFormState extends State<ProfileNameForm> {
var _name = '';

void _continuePressed() {
context.flow<Profile>().update((profile) => profile.copyWith(name: _name));
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Name')),
body: Center(
child: Column(
children: <Widget>[
TextField(
onChanged: (value) => setState(() => _name = value),
decoration: const InputDecoration(
labelText: 'Name',
hintText: 'John Doe',
),
),
RaisedButton(
child: const Text('Continue'),
onPressed: _name.isNotEmpty ? _continuePressed : null,
)
],
),
),
);
}
}

class ProfileAgeForm extends StatefulWidget {
@override
_ProfileAgeFormState createState() => _ProfileAgeFormState();
}

class _ProfileAgeFormState extends State<ProfileAgeForm> {
int _age;

void _continuePressed() {
context.flow<Profile>().update((profile) => profile.copyWith(age: _age));
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Age')),
body: Center(
child: Column(
children: <Widget>[
TextField(
onChanged: (value) => setState(() => _age = int.parse(value)),
decoration: const InputDecoration(
labelText: 'Age',
hintText: '42',
),
keyboardType: TextInputType.number,
),
RaisedButton(
child: const Text('Continue'),
onPressed: _age != null ? _continuePressed : null,
)
],
),
),
);
}
}

class ProfileWeightForm extends StatefulWidget {
@override
_ProfileWeightFormState createState() => _ProfileWeightFormState();
}

class _ProfileWeightFormState extends State<ProfileWeightForm> {
int _weight;

void _continuePressed() {
context
.flow<Profile>()
.complete((profile) => profile.copyWith(weight: _weight));
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Weight')),
body: Center(
child: Column(
children: <Widget>[
TextField(
onChanged: (value) => setState(() => _weight = int.parse(value)),
decoration: const InputDecoration(
labelText: 'Weight (lbs)',
hintText: '170',
body: Builder(
builder: (context) {
return ListView(
children: [
ListTile(
leading: const Icon(Icons.help_outline),
title: const Text('Onboarding Flow'),
trailing: const Icon(Icons.chevron_right),
onTap: () async {
await Navigator.of(context).push(OnboardingFlow.route());
Scaffold.of(context)
..hideCurrentSnackBar()
..showSnackBar(
const SnackBar(
content: Text('Onboarding Flow Complete!'),
),
);
},
),
keyboardType: TextInputType.number,
),
RaisedButton(
child: const Text('Continue'),
onPressed: _weight != null ? _continuePressed : null,
)
],
),
ListTile(
leading: const Icon(Icons.person_outline),
title: const Text('Profile Flow'),
trailing: const Icon(Icons.chevron_right),
onTap: () async {
final profile = await Navigator.of(context).push(
ProfileFlow.route(),
);
Scaffold.of(context)
..hideCurrentSnackBar()
..showSnackBar(
SnackBar(
content: Text('Profile Flow Complete! $profile'),
),
);
},
)
],
);
},
),
);
}
}

class Profile extends Equatable {
const Profile({this.name, this.age, this.weight});

final String name;
final int age;
final int weight;

Profile copyWith({String name, int age, int weight}) {
return Profile(
name: name ?? this.name,
age: age ?? this.age,
weight: weight ?? this.weight,
);
}

@override
List<Object> get props => [name, age, weight];
}
112 changes: 112 additions & 0 deletions example/lib/onboarding_flow.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import 'package:flutter/material.dart';
import 'package:flow_builder/flow_builder.dart';

enum OnboardingState { step1, step2, step3 }

class OnboardingFlow extends StatelessWidget {
static Route<void> route() {
return MaterialPageRoute(builder: (_) => OnboardingFlow());
}

@override
Widget build(BuildContext context) {
return FlowBuilder<OnboardingState>(
state: OnboardingState.step1,
builder: (context, state) {
return [
MaterialPage<void>(
child: Scaffold(
appBar: AppBar(),
body: const Center(child: Text('Onboarding Step 1')),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
FloatingActionButton(
heroTag: 0,
onPressed: () {
context.flow<OnboardingState>().complete((_) => null);
},
child: const Icon(Icons.clear),
),
const SizedBox(width: 8),
FloatingActionButton(
heroTag: 1,
onPressed: () {
context
.flow<OnboardingState>()
.update((_) => OnboardingState.step2);
},
child: const Icon(Icons.arrow_forward_ios_rounded),
),
],
),
),
),
if (state.index >= 1)
MaterialPage<void>(
child: Scaffold(
appBar: AppBar(),
body: const Center(child: Text('Onboarding Step 2')),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
FloatingActionButton(
heroTag: 2,
onPressed: () {
context
.flow<OnboardingState>()
.update((_) => OnboardingState.step1);
},
child: const Icon(Icons.arrow_back_ios_rounded),
),
const SizedBox(width: 8),
FloatingActionButton(
heroTag: 3,
onPressed: () {
context
.flow<OnboardingState>()
.update((_) => OnboardingState.step3);
},
child: const Icon(Icons.arrow_forward_ios_rounded),
),
],
),
),
),
if (state.index >= 2)
MaterialPage<void>(
child: Scaffold(
appBar: AppBar(),
body: const Center(child: Text('Onboarding Step 3')),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
FloatingActionButton(
heroTag: 4,
onPressed: () {
context
.flow<OnboardingState>()
.update((_) => OnboardingState.step2);
},
child: const Icon(Icons.arrow_back_ios_rounded),
),
const SizedBox(width: 8),
FloatingActionButton(
heroTag: 5,
onPressed: () {
context.flow<OnboardingState>().complete((_) => null);
},
child: const Icon(Icons.check),
),
],
),
),
),
];
},
);
}
}
Loading

0 comments on commit 924a8f2

Please sign in to comment.