Skip to content

Commit

Permalink
feat: add navigation observer to allow swipe back ios
Browse files Browse the repository at this point in the history
  • Loading branch information
Numoy committed Sep 21, 2023
1 parent 7f38c56 commit 847c748
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 51 deletions.
4 changes: 2 additions & 2 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class _MyAppState extends State<MyApp> {
final selectedChoice = input?.result as TextChoice?;
switch (selectedChoice?.text) {
case 'Yes':
return 'OnlyConent';
return 'OnlyContent';
case 'No':
return 'Completion';
default:
Expand Down Expand Up @@ -181,7 +181,7 @@ class _MyAppState extends State<MyApp> {
),

Step(
id: 'OnlyConent',
id: 'OnlyContent',
content: const [
TextContent(
text: 'Listen carefully!',
Expand Down
6 changes: 0 additions & 6 deletions lib/src/presenter/survey_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class SurveyState {
final StepResult? result;
final int currentStepIndex;
final int stepCount;
final bool isPreviousStep;
final SurveyResult? surveyResult;
final bool isLoading;

Expand All @@ -22,7 +21,6 @@ class SurveyState {
required this.questionResults,
this.result,
this.currentStepIndex = 0,
this.isPreviousStep = false,
this.surveyResult,
this.isLoading = false,
});
Expand All @@ -36,7 +34,6 @@ class SurveyState {
other.questionResults == questionResults &&
other.result == result &&
other.currentStepIndex == currentStepIndex &&
other.isPreviousStep == isPreviousStep &&
other.surveyResult == surveyResult &&
other.isLoading == isLoading;
@override
Expand All @@ -47,7 +44,6 @@ class SurveyState {
questionResults.hashCode ^
result.hashCode ^
currentStepIndex.hashCode ^
isPreviousStep.hashCode ^
surveyResult.hashCode ^
isLoading.hashCode;

Expand All @@ -58,7 +54,6 @@ class SurveyState {
Set<StepResult>? questionResults,
StepResult? result,
int? currentStepIndex,
bool? isPreviousStep,
SurveyResult? surveyResult,
bool? isLoading,
}) =>
Expand All @@ -69,7 +64,6 @@ class SurveyState {
questionResults: questionResults ?? this.questionResults,
result: result ?? this.result,
currentStepIndex: currentStepIndex ?? this.currentStepIndex,
isPreviousStep: isPreviousStep ?? this.isPreviousStep,
surveyResult: surveyResult ?? this.surveyResult,
isLoading: isLoading ?? this.isLoading,
);
Expand Down
12 changes: 4 additions & 8 deletions lib/src/presenter/survey_state_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,20 @@ class SurveyStateProvider extends ChangeNotifier {
if (event is StartSurvey) {
final newState = _handleInitialStep();
updateState(newState);
navigatorKey.currentState?.pushNamed(
'/',
arguments: newState,
);

return;
}
if (state != null) {
if (event is NextStep) {
final newState = _handleNextStep(event, state!);
updateState(newState);
navigatorKey.currentState?.pushNamed(
'/',
'/${newState.currentStep?.id}',
arguments: newState,
);
return;
} else if (event is StepBack) {
final newState = _handleStepBack(event, state!);
final newState = handleStepBack(event, state!);
updateState(newState);
navigatorKey.currentState?.pop();
return;
Expand Down Expand Up @@ -108,7 +105,7 @@ class SurveyStateProvider extends ChangeNotifier {
);
}

SurveyState _handleStepBack(
SurveyState handleStepBack(
StepBack event,
SurveyState currentState,
) {
Expand All @@ -127,7 +124,6 @@ class SurveyStateProvider extends ChangeNotifier {
steps: taskNavigator.task.steps,
questionResults: results,
currentStepIndex: currentStepIndex(previousStep),
isPreviousStep: true,
stepCount: countSteps,
);
}
Expand Down
84 changes: 49 additions & 35 deletions lib/src/survey_kit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:collection/collection.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart' hide Step;
import 'package:provider/provider.dart';
import 'package:survey_kit/src/survey_route_observer.dart';
import 'package:survey_kit/src/view/widget/answer/answer_view.dart';
import 'package:survey_kit/survey_kit.dart';

Expand Down Expand Up @@ -63,12 +64,20 @@ class SurveyKit extends StatefulWidget {
class _SurveyKitState extends State<SurveyKit> {
late TaskNavigator _taskNavigator;
late final GlobalKey<NavigatorState> _navigatorKey;
late final SurveyStateProvider surveyStateProvide;

@override
void initState() {
super.initState();
_taskNavigator = _createTaskNavigator();
_navigatorKey = GlobalKey<NavigatorState>();

surveyStateProvide = SurveyStateProvider(
taskNavigator: _taskNavigator,
onResult: widget.onResult,
stepShell: widget.stepShell,
navigatorKey: _navigatorKey,
);
}

TaskNavigator _createTaskNavigator() {
Expand Down Expand Up @@ -98,12 +107,7 @@ class _SurveyKitState extends State<SurveyKit> {
localizations: widget.localizations,
padding: const EdgeInsets.all(14),
child: ChangeNotifierProvider<SurveyStateProvider>(
create: (_) => SurveyStateProvider(
taskNavigator: _taskNavigator,
onResult: widget.onResult,
stepShell: widget.stepShell,
navigatorKey: _navigatorKey,
),
create: (_) => surveyStateProvide,
builder: (context, child) {
return SurveyPage(
length: widget.task.steps.length,
Expand All @@ -113,6 +117,8 @@ class _SurveyKitState extends State<SurveyKit> {
decoration: widget.decoration,
loadingState: widget.loadingState,
keepLastStateAlive: widget.keepLastStateAlive,
step: widget.task.steps.first,
surveyStateProvider: surveyStateProvide,
);
},
),
Expand All @@ -128,12 +134,16 @@ class SurveyPage extends StatefulWidget {
final BoxDecoration? decoration;
final Widget? loadingState;
final bool keepLastStateAlive;
final Step step;
final SurveyStateProvider surveyStateProvider;

const SurveyPage({
super.key,
required this.length,
required this.onResult,
required this.navigatorKey,
required this.step,
required this.surveyStateProvider,
this.appBar,
this.decoration,
this.loadingState,
Expand All @@ -144,11 +154,13 @@ class SurveyPage extends StatefulWidget {
_SurveyPageState createState() => _SurveyPageState();
}

class _SurveyPageState extends State<SurveyPage>
with SingleTickerProviderStateMixin {
class _SurveyPageState extends State<SurveyPage> {
late final SurveyRouteObserver routeObserver;

@override
void initState() {
super.initState();
routeObserver = SurveyRouteObserver(widget.surveyStateProvider);
WidgetsBinding.instance.addPostFrameCallback(
(_) => Provider.of<SurveyStateProvider>(context, listen: false).onEvent(
StartSurvey(),
Expand All @@ -162,34 +174,36 @@ class _SurveyPageState extends State<SurveyPage>
appBar: widget.appBar ?? const SurveyAppBar(),
body: Navigator(
key: widget.navigatorKey,
onGenerateRoute: (settings) => CupertinoPageRoute<Widget>(
builder: (_) {
final arg = settings.arguments;
if (arg == null || arg is! SurveyState) {
return widget.loadingState ??
const Center(
child: CircularProgressIndicator.adaptive(),
);
}
final state = settings.arguments! as SurveyState;

final step = state.currentStep;
return _SurveyView(
key: ValueKey<String>(
step!.id,
),
id: step.id,
decoration: widget.decoration,
createView: () => AnswerView(
answer: step.answerFormat,
step: step,
stepResult: state.questionResults.firstWhereOrNull(
(element) => element.id == step.id,
observers: [routeObserver],
onGenerateRoute: (settings) {
final arg = settings.arguments;
var step = widget.step;
SurveyState? surveyState;
if (arg is SurveyState) {
surveyState = settings.arguments! as SurveyState;

step = surveyState.currentStep!;
}
return CupertinoPageRoute<Widget>(
settings: settings,
builder: (_) {
return _SurveyView(
key: ValueKey<String>(
step.id,
),
),
);
},
),
id: step.id,
decoration: widget.decoration,
createView: () => AnswerView(
answer: step.answerFormat,
step: step,
stepResult: surveyState?.questionResults.firstWhereOrNull(
(element) => element.id == step.id,
),
),
);
},
);
},
),
);
}
Expand Down
20 changes: 20 additions & 0 deletions lib/src/survey_route_observer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/widgets.dart';
import 'package:survey_kit/survey_kit.dart';

/// Needed to handle navigation when the survey-controller is not used
/// e.g. Swipe-Back-iOS
class SurveyRouteObserver extends RouteObserver<ModalRoute> {
final SurveyStateProvider surveyStateProvider;

SurveyRouteObserver(this.surveyStateProvider);

@override
void didPop(Route route, Route? previousRoute) {
final state = surveyStateProvider.handleStepBack(
StepBack(null),
surveyStateProvider.state!,
);
surveyStateProvider.updateState(state);
super.didPop(route, previousRoute);
}
}

0 comments on commit 847c748

Please sign in to comment.