mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 05:03:44 +02:00
fix: add NavigatorPopHandler with a custom PopHandler class for handling backarrow presses in the userstory
This commit is contained in:
parent
26d2eb150a
commit
c20a1a603c
9 changed files with 85 additions and 14 deletions
|
@ -0,0 +1,24 @@
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
|
||||||
|
///
|
||||||
|
class PopHandler {
|
||||||
|
/// Constructor
|
||||||
|
PopHandler();
|
||||||
|
|
||||||
|
final List<VoidCallback> _handlers = [];
|
||||||
|
|
||||||
|
/// Registers a new handler
|
||||||
|
void add(VoidCallback handler) {
|
||||||
|
_handlers.add(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes a handler
|
||||||
|
void remove(VoidCallback handler) {
|
||||||
|
_handlers.remove(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles the pop
|
||||||
|
void handlePop() {
|
||||||
|
_handlers.lastOrNull?.call();
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,11 +9,12 @@ import "package:flutter_availability/src/ui/widgets/base_page.dart";
|
||||||
import "package:flutter_availability/src/ui/widgets/pause_selection.dart";
|
import "package:flutter_availability/src/ui/widgets/pause_selection.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||||
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
|
|
||||||
/// Screen for modifying the availabilities for a specific daterange
|
/// Screen for modifying the availabilities for a specific daterange
|
||||||
/// There might already be availabilities for the selected period but they
|
/// There might already be availabilities for the selected period but they
|
||||||
/// will be overwritten
|
/// will be overwritten
|
||||||
class AvailabilitiesModificationScreen extends StatefulWidget {
|
class AvailabilitiesModificationScreen extends StatefulHookWidget {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
const AvailabilitiesModificationScreen({
|
const AvailabilitiesModificationScreen({
|
||||||
required this.dateRange,
|
required this.dateRange,
|
||||||
|
@ -62,6 +63,11 @@ class _AvailabilitiesModificationScreenState
|
||||||
var spacing = options.spacing;
|
var spacing = options.spacing;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
availabilityScope.popHandler.add(widget.onExit);
|
||||||
|
return () => availabilityScope.popHandler.remove(widget.onExit);
|
||||||
|
});
|
||||||
|
|
||||||
// TODO(freek): the selected period might be longer than 1 month
|
// TODO(freek): the selected period might be longer than 1 month
|
||||||
//so we need to get all the availabilites through a stream
|
//so we need to get all the availabilites through a stream
|
||||||
Future<void> onSave() async {
|
Future<void> onSave() async {
|
||||||
|
@ -180,7 +186,7 @@ class _AvailabilitiesModificationScreenState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AvailabilitiesModificationScreenLayout extends StatelessWidget {
|
class _AvailabilitiesModificationScreenLayout extends HookWidget {
|
||||||
const _AvailabilitiesModificationScreenLayout({
|
const _AvailabilitiesModificationScreenLayout({
|
||||||
required this.dateRange,
|
required this.dateRange,
|
||||||
required this.clearAvailability,
|
required this.clearAvailability,
|
||||||
|
|
|
@ -17,7 +17,7 @@ class AvailabilityOverview extends StatefulHookWidget {
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Callback for when the user gives an availability range
|
/// Callback for when the user gives an availability range
|
||||||
final void Function(
|
final Future<void> Function(
|
||||||
DateTimeRange range,
|
DateTimeRange range,
|
||||||
List<AvailabilityWithTemplate> selectedAvailabilities,
|
List<AvailabilityWithTemplate> selectedAvailabilities,
|
||||||
) onEditDateRange;
|
) onEditDateRange;
|
||||||
|
@ -49,6 +49,11 @@ class _AvailabilityOverviewState extends State<AvailabilityOverview> {
|
||||||
[_selectedDate],
|
[_selectedDate],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
availabilityScope.popHandler.add(widget.onExit);
|
||||||
|
return () => availabilityScope.popHandler.remove(widget.onExit);
|
||||||
|
});
|
||||||
|
|
||||||
var availabilitySnapshot = useStream(availabilityStream);
|
var availabilitySnapshot = useStream(availabilityStream);
|
||||||
|
|
||||||
var selectedAvailabilities = [
|
var selectedAvailabilities = [
|
||||||
|
@ -94,14 +99,16 @@ class _AvailabilityOverviewState extends State<AvailabilityOverview> {
|
||||||
|
|
||||||
VoidCallback? onButtonPress;
|
VoidCallback? onButtonPress;
|
||||||
if (_selectedRange != null) {
|
if (_selectedRange != null) {
|
||||||
onButtonPress = () {
|
onButtonPress = () async {
|
||||||
widget.onEditDateRange(
|
await widget.onEditDateRange(
|
||||||
_selectedRange!,
|
_selectedRange!,
|
||||||
selectedAvailabilities,
|
selectedAvailabilities,
|
||||||
);
|
);
|
||||||
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedRange = null;
|
_selectedRange = null;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,10 @@ import "package:flutter_availability/src/ui/widgets/template_name_input.dart";
|
||||||
import "package:flutter_availability/src/ui/widgets/template_time_break.dart";
|
import "package:flutter_availability/src/ui/widgets/template_time_break.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||||
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
|
|
||||||
/// Page for creating or editing a day template
|
/// Page for creating or editing a day template
|
||||||
class DayTemplateModificationScreen extends StatefulWidget {
|
class DayTemplateModificationScreen extends StatefulHookWidget {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
const DayTemplateModificationScreen({
|
const DayTemplateModificationScreen({
|
||||||
required this.template,
|
required this.template,
|
||||||
|
@ -50,6 +51,11 @@ class _DayTemplateModificationScreenState
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
availabilityScope.popHandler.add(widget.onExit);
|
||||||
|
return () => availabilityScope.popHandler.remove(widget.onExit);
|
||||||
|
});
|
||||||
|
|
||||||
Future<void> onDeletePressed() async {
|
Future<void> onDeletePressed() async {
|
||||||
var isConfirmed = await options.confirmationDialogBuilder(
|
var isConfirmed = await options.confirmationDialogBuilder(
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -41,6 +41,11 @@ class AvailabilityTemplateOverview extends HookWidget {
|
||||||
var dayTemplatesSnapshot = useStream(dayTemplateStream);
|
var dayTemplatesSnapshot = useStream(dayTemplateStream);
|
||||||
var weekTemplatesSnapshot = useStream(weekTemplateStream);
|
var weekTemplatesSnapshot = useStream(weekTemplateStream);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
availabilityScope.popHandler.add(onExit);
|
||||||
|
return () => availabilityScope.popHandler.remove(onExit);
|
||||||
|
});
|
||||||
|
|
||||||
var dayTemplates =
|
var dayTemplates =
|
||||||
dayTemplatesSnapshot.data ?? <AvailabilityTemplateModel>[];
|
dayTemplatesSnapshot.data ?? <AvailabilityTemplateModel>[];
|
||||||
var weekTemplates =
|
var weekTemplates =
|
||||||
|
|
|
@ -8,9 +8,10 @@ import "package:flutter_availability/src/ui/widgets/template_week_day_selection.
|
||||||
import "package:flutter_availability/src/ui/widgets/template_week_overview.dart";
|
import "package:flutter_availability/src/ui/widgets/template_week_overview.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||||
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
|
|
||||||
/// Page for creating or editing a day template
|
/// Page for creating or editing a day template
|
||||||
class WeekTemplateModificationScreen extends StatefulWidget {
|
class WeekTemplateModificationScreen extends StatefulHookWidget {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
const WeekTemplateModificationScreen({
|
const WeekTemplateModificationScreen({
|
||||||
required this.template,
|
required this.template,
|
||||||
|
@ -111,6 +112,11 @@ class _WeekTemplateModificationScreenState
|
||||||
widget.onExit();
|
widget.onExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
availabilityScope.popHandler.add(onBackPressed);
|
||||||
|
return () => availabilityScope.popHandler.remove(onBackPressed);
|
||||||
|
});
|
||||||
|
|
||||||
var canSave = _viewModel.canSave;
|
var canSave = _viewModel.canSave;
|
||||||
var nextButton = options.primaryButtonBuilder(
|
var nextButton = options.primaryButtonBuilder(
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_availability/flutter_availability.dart";
|
import "package:flutter_availability/flutter_availability.dart";
|
||||||
import "package:flutter_availability/src/service/availability_service.dart";
|
import "package:flutter_availability/src/service/availability_service.dart";
|
||||||
|
import "package:flutter_availability/src/service/pop_handler.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/break_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/break_view_model.dart";
|
||||||
import "package:flutter_availability/src/ui/widgets/generic_time_selection.dart";
|
import "package:flutter_availability/src/ui/widgets/generic_time_selection.dart";
|
||||||
import "package:flutter_availability/src/ui/widgets/input_fields.dart";
|
import "package:flutter_availability/src/ui/widgets/input_fields.dart";
|
||||||
|
@ -32,6 +33,7 @@ class PauseSelection extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
|
var popHandler = availabilityScope.popHandler;
|
||||||
|
|
||||||
Future<BreakViewModel?> openBreakDialog(
|
Future<BreakViewModel?> openBreakDialog(
|
||||||
BreakViewModel? initialBreak,
|
BreakViewModel? initialBreak,
|
||||||
|
@ -43,6 +45,7 @@ class PauseSelection extends StatelessWidget {
|
||||||
userId: availabilityScope.userId,
|
userId: availabilityScope.userId,
|
||||||
options: options,
|
options: options,
|
||||||
service: availabilityScope.service,
|
service: availabilityScope.service,
|
||||||
|
popHandler: popHandler,
|
||||||
editingTemplate: editingTemplate,
|
editingTemplate: editingTemplate,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -201,6 +204,7 @@ class AvailabilityBreakSelectionDialog extends StatefulWidget {
|
||||||
required AvailabilityOptions options,
|
required AvailabilityOptions options,
|
||||||
required String userId,
|
required String userId,
|
||||||
required AvailabilityService service,
|
required AvailabilityService service,
|
||||||
|
required PopHandler popHandler,
|
||||||
required bool editingTemplate,
|
required bool editingTemplate,
|
||||||
BreakViewModel? initialBreak,
|
BreakViewModel? initialBreak,
|
||||||
}) async =>
|
}) async =>
|
||||||
|
@ -217,6 +221,7 @@ class AvailabilityBreakSelectionDialog extends StatefulWidget {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
options: options,
|
options: options,
|
||||||
service: service,
|
service: service,
|
||||||
|
popHandler: popHandler,
|
||||||
child: AvailabilityBreakSelectionDialog(
|
child: AvailabilityBreakSelectionDialog(
|
||||||
initialBreak: initialBreak,
|
initialBreak: initialBreak,
|
||||||
editingTemplate: editingTemplate,
|
editingTemplate: editingTemplate,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import "package:flutter/material.dart";
|
||||||
import "package:flutter_availability/src/config/availability_options.dart";
|
import "package:flutter_availability/src/config/availability_options.dart";
|
||||||
import "package:flutter_availability/src/routes.dart";
|
import "package:flutter_availability/src/routes.dart";
|
||||||
import "package:flutter_availability/src/service/availability_service.dart";
|
import "package:flutter_availability/src/service/availability_service.dart";
|
||||||
|
import "package:flutter_availability/src/service/pop_handler.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
/// This pushes the availability user story to the navigator stack.
|
/// This pushes the availability user story to the navigator stack.
|
||||||
|
@ -58,16 +59,22 @@ class _AvailabilityUserStoryState extends State<AvailabilityUserStory> {
|
||||||
dataInterface: widget.options.dataInterface,
|
dataInterface: widget.options.dataInterface,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
late final PopHandler _popHandler = PopHandler();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => AvailabilityScope(
|
Widget build(BuildContext context) => AvailabilityScope(
|
||||||
userId: widget.userId,
|
userId: widget.userId,
|
||||||
options: widget.options,
|
options: widget.options,
|
||||||
service: _service,
|
service: _service,
|
||||||
|
popHandler: _popHandler,
|
||||||
|
child: NavigatorPopHandler(
|
||||||
|
onPop: _popHandler.handlePop,
|
||||||
child: Navigator(
|
child: Navigator(
|
||||||
onGenerateInitialRoutes: (state, route) => [
|
onGenerateInitialRoutes: (state, route) => [
|
||||||
homePageRoute(widget.onExit ?? () {}),
|
homePageRoute(widget.onExit ?? () {}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import "package:flutter/widgets.dart";
|
import "package:flutter/widgets.dart";
|
||||||
import "package:flutter_availability/src/config/availability_options.dart";
|
import "package:flutter_availability/src/config/availability_options.dart";
|
||||||
import "package:flutter_availability/src/service/availability_service.dart";
|
import "package:flutter_availability/src/service/availability_service.dart";
|
||||||
|
import "package:flutter_availability/src/service/pop_handler.dart";
|
||||||
|
|
||||||
///
|
///
|
||||||
class AvailabilityScope extends InheritedWidget {
|
class AvailabilityScope extends InheritedWidget {
|
||||||
|
@ -9,6 +10,7 @@ class AvailabilityScope extends InheritedWidget {
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.options,
|
required this.options,
|
||||||
required this.service,
|
required this.service,
|
||||||
|
required this.popHandler,
|
||||||
required super.child,
|
required super.child,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
@ -22,6 +24,9 @@ class AvailabilityScope extends InheritedWidget {
|
||||||
///
|
///
|
||||||
final AvailabilityService service;
|
final AvailabilityService service;
|
||||||
|
|
||||||
|
///
|
||||||
|
final PopHandler popHandler;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool updateShouldNotify(AvailabilityScope oldWidget) =>
|
bool updateShouldNotify(AvailabilityScope oldWidget) =>
|
||||||
oldWidget.userId != userId || options != options;
|
oldWidget.userId != userId || options != options;
|
||||||
|
|
Loading…
Reference in a new issue