mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 05:03:44 +02:00
feat: add feature flags to enable/disable functionality
This commit is contained in:
parent
f3c8b5f473
commit
20881023ad
4 changed files with 103 additions and 54 deletions
|
@ -28,6 +28,11 @@ class AvailabilityOptions {
|
||||||
this.timePickerBuilder,
|
this.timePickerBuilder,
|
||||||
this.loadingIndicatorBuilder = DefaultLoader.builder,
|
this.loadingIndicatorBuilder = DefaultLoader.builder,
|
||||||
this.errorDisplayBuilder = DefaultErrorDisplayDialog.defaultErrorDisplay,
|
this.errorDisplayBuilder = DefaultErrorDisplayDialog.defaultErrorDisplay,
|
||||||
|
this.featureSet = const {
|
||||||
|
AvailabilityFeature.breaks,
|
||||||
|
AvailabilityFeature.customAvailability,
|
||||||
|
AvailabilityFeature.templates,
|
||||||
|
},
|
||||||
AvailabilityDataInterface? dataInterface,
|
AvailabilityDataInterface? dataInterface,
|
||||||
}) : dataInterface = dataInterface ?? LocalAvailabilityDataInterface();
|
}) : dataInterface = dataInterface ?? LocalAvailabilityDataInterface();
|
||||||
|
|
||||||
|
@ -95,6 +100,11 @@ class AvailabilityOptions {
|
||||||
/// base widget through [baseScreenBuilder].
|
/// base widget through [baseScreenBuilder].
|
||||||
final ErrorDisplayBuilder errorDisplayBuilder;
|
final ErrorDisplayBuilder errorDisplayBuilder;
|
||||||
|
|
||||||
|
/// Enabled features when using these options
|
||||||
|
///
|
||||||
|
/// Look at [AvailabilityFeature] for more information.
|
||||||
|
final Set<AvailabilityFeature> featureSet;
|
||||||
|
|
||||||
final _borderRadius = BorderRadius.circular(5);
|
final _borderRadius = BorderRadius.circular(5);
|
||||||
|
|
||||||
/// The border radius used on the individual elements
|
/// The border radius used on the individual elements
|
||||||
|
@ -233,3 +243,21 @@ typedef ErrorDisplayBuilder = Future<void> Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AvailabilityError error,
|
AvailabilityError error,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Lists all features that are toggleable
|
||||||
|
enum AvailabilityFeature {
|
||||||
|
/// Anything template related
|
||||||
|
templates,
|
||||||
|
|
||||||
|
/// Definition of breaks
|
||||||
|
breaks,
|
||||||
|
|
||||||
|
/// Definition of custom availabilities without templates
|
||||||
|
customAvailability;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extension for validating whether a feature is enabled
|
||||||
|
extension FeatureRequirement on Set<AvailabilityFeature> {
|
||||||
|
/// Whether a required feature is enabled
|
||||||
|
bool require(AvailabilityFeature feature) => contains(feature);
|
||||||
|
}
|
||||||
|
|
|
@ -241,6 +241,7 @@ class _AvailabilitiesModificationScreenLayout extends HookWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
|
var featureSet = options.featureSet;
|
||||||
|
|
||||||
return options.baseScreenBuilder(
|
return options.baseScreenBuilder(
|
||||||
context,
|
context,
|
||||||
|
@ -253,12 +254,15 @@ class _AvailabilitiesModificationScreenLayout extends HookWidget {
|
||||||
onChanged: onClearSection,
|
onChanged: onClearSection,
|
||||||
),
|
),
|
||||||
if (!viewModel.clearAvailability) ...[
|
if (!viewModel.clearAvailability) ...[
|
||||||
|
if (featureSet.require(AvailabilityFeature.templates)) ...[
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
AvailabilityTemplateSelection(
|
AvailabilityTemplateSelection(
|
||||||
selectedTemplates: selectedTemplates,
|
selectedTemplates: selectedTemplates,
|
||||||
onTemplateAdd: onTemplateSelected,
|
onTemplateAdd: onTemplateSelected,
|
||||||
onTemplatesRemoved: onTemplatesRemoved,
|
onTemplatesRemoved: onTemplatesRemoved,
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
if (featureSet.require(AvailabilityFeature.customAvailability)) ...[
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
AvailabilityTimeSelection(
|
AvailabilityTimeSelection(
|
||||||
viewModel: viewModel,
|
viewModel: viewModel,
|
||||||
|
@ -266,6 +270,7 @@ class _AvailabilitiesModificationScreenLayout extends HookWidget {
|
||||||
onStartChanged: onStartChanged,
|
onStartChanged: onStartChanged,
|
||||||
onEndChanged: onEndChanged,
|
onEndChanged: onEndChanged,
|
||||||
),
|
),
|
||||||
|
if (featureSet.require(AvailabilityFeature.breaks)) ...[
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
PauseSelection(
|
PauseSelection(
|
||||||
breaks: viewModel.breaks,
|
breaks: viewModel.breaks,
|
||||||
|
@ -274,6 +279,8 @@ class _AvailabilitiesModificationScreenLayout extends HookWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
buttons: [saveButton],
|
buttons: [saveButton],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_availability/src/config/availability_options.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";
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var colors = options.colors;
|
var colors = options.colors;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
|
var featureSet = options.featureSet;
|
||||||
|
|
||||||
var templatesLoading =
|
var templatesLoading =
|
||||||
widget.availabilities.connectionState == ConnectionState.waiting;
|
widget.availabilities.connectionState == ConnectionState.waiting;
|
||||||
|
@ -47,6 +49,11 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
|
|
||||||
var templatesVisible = templatesAvailable && _templateDrawerOpen;
|
var templatesVisible = templatesAvailable && _templateDrawerOpen;
|
||||||
|
|
||||||
|
if (!templatesAvailable &&
|
||||||
|
!featureSet.require(AvailabilityFeature.templates)) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
void onDrawerHeaderClick() {
|
void onDrawerHeaderClick() {
|
||||||
if (!templatesAvailable && !_templateDrawerOpen) {
|
if (!templatesAvailable && !_templateDrawerOpen) {
|
||||||
return;
|
return;
|
||||||
|
@ -115,6 +122,7 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
if (featureSet.require(AvailabilityFeature.templates)) ...[
|
||||||
for (var template in templates) ...[
|
for (var template in templates) ...[
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
|
@ -127,13 +135,10 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
Padding(
|
const SizedBox(height: 10),
|
||||||
padding: const EdgeInsets.only(
|
createNewTemplateButton,
|
||||||
top: 10,
|
],
|
||||||
bottom: 8,
|
const SizedBox(height: 8),
|
||||||
),
|
|
||||||
child: createNewTemplateButton,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -184,6 +189,7 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
padding: const EdgeInsets.only(right: 2),
|
padding: const EdgeInsets.only(right: 2),
|
||||||
child: body,
|
child: body,
|
||||||
),
|
),
|
||||||
|
if (featureSet.require(AvailabilityFeature.templates)) ...[
|
||||||
if (!templatesVisible) ...[
|
if (!templatesVisible) ...[
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
if (templatesLoading) ...[
|
if (templatesLoading) ...[
|
||||||
|
@ -193,6 +199,7 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_availability/src/config/availability_options.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/template_daydata_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/template_daydata_view_model.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/ui/widgets/template_time_selection.dart";
|
import "package:flutter_availability/src/ui/widgets/template_time_selection.dart";
|
||||||
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
/// Section for selecting the time and breaks for a single day
|
/// Section for selecting the time and breaks for a single day
|
||||||
class TemplateTimeAndBreakSection extends StatelessWidget {
|
class TemplateTimeAndBreakSection extends StatelessWidget {
|
||||||
|
@ -19,7 +21,9 @@ class TemplateTimeAndBreakSection extends StatelessWidget {
|
||||||
final void Function(DayTemplateDataViewModel data) onDayDataChanged;
|
final void Function(DayTemplateDataViewModel data) onDayDataChanged;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => Column(
|
Widget build(BuildContext context) {
|
||||||
|
var featureSet = AvailabilityScope.of(context).options.featureSet;
|
||||||
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
TemplateTimeSelection(
|
TemplateTimeSelection(
|
||||||
key: ValueKey([dayData.startTime, dayData.endTime]),
|
key: ValueKey([dayData.startTime, dayData.endTime]),
|
||||||
|
@ -30,6 +34,7 @@ class TemplateTimeAndBreakSection extends StatelessWidget {
|
||||||
onEndChanged: (end) =>
|
onEndChanged: (end) =>
|
||||||
onDayDataChanged(dayData.copyWith(endTime: end)),
|
onDayDataChanged(dayData.copyWith(endTime: end)),
|
||||||
),
|
),
|
||||||
|
if (featureSet.require(AvailabilityFeature.breaks)) ...[
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
PauseSelection(
|
PauseSelection(
|
||||||
editingTemplate: true,
|
editingTemplate: true,
|
||||||
|
@ -38,5 +43,7 @@ class TemplateTimeAndBreakSection extends StatelessWidget {
|
||||||
onDayDataChanged(dayData.copyWith(breaks: pauses)),
|
onDayDataChanged(dayData.copyWith(breaks: pauses)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue