From b270ca2b8c75abe989328e0e688416a906d01597 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 10 Mar 2024 14:51:35 +0100 Subject: [PATCH] Added sliverappbar to more screens --- .../modals/blocked_services_screen.dart | 367 +++++++++++------- .../modals/custom_rules/add_custom_rule.dart | 94 +++-- .../custom_rules/edit_custom_rules.dart | 66 ++-- macos/Podfile.lock | 14 +- 4 files changed, 331 insertions(+), 210 deletions(-) diff --git a/lib/screens/filters/modals/blocked_services_screen.dart b/lib/screens/filters/modals/blocked_services_screen.dart index b95dd4f..f3f52ec 100644 --- a/lib/screens/filters/modals/blocked_services_screen.dart +++ b/lib/screens/filters/modals/blocked_services_screen.dart @@ -85,38 +85,130 @@ class _BlockedServicesScreenStateWidget extends State { if (widget.fullScreen == true) { return Dialog.fullscreen( - child: Scaffold( - appBar: AppBar( - leading: CloseButton(onPressed: () => Navigator.pop(context)), - title: Text(AppLocalizations.of(context)!.blockedServices), - actions: [ - IconButton( - onPressed: updateBlockedServices, - icon: const Icon( - Icons.save_rounded - ), - tooltip: AppLocalizations.of(context)!.save, - ), - const SizedBox(width: 10) - ], - ), - body: SafeArea( - child: RefreshIndicator( - onRefresh: () async { - final result = await filteringProvider.loadBlockedServices(); - if (result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.blockedServicesListNotLoaded, - color: Colors.red - ); - } - }, - child: _Content( - values: values, - updateValues: updateValues, + child: Material( + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.blockedServices), + actions: [ + IconButton( + onPressed: updateBlockedServices, + icon: const Icon( + Icons.save_rounded + ), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 10) + ], + ) ) - ), + ], + body: SafeArea( + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (filteringProvider.blockedServicesLoadStatus == LoadStatus.loading) Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingBlockedServicesList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + if (filteringProvider.blockedServicesLoadStatus == LoadStatus.loaded) SliverList.builder( + itemCount: filteringProvider.blockedServices!.services.length, + itemBuilder: (context, index) => Material( + color: Colors.transparent, + child: InkWell( + onTap: () => updateValues( + values.contains(filteringProvider.blockedServices!.services[index].id), + filteringProvider.blockedServices!.services[index] + ), + child: Padding( + padding: const EdgeInsets.only( + top: 6, + bottom: 6, + right: 12, + left: 24 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + filteringProvider.blockedServices!.services[index].name, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Checkbox( + value: values.contains(filteringProvider.blockedServices!.services[index].id), + onChanged: (value) => updateValues( + value!, + filteringProvider.blockedServices!.services[index] + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + ) + ], + ), + ), + ), + ) + ), + if (filteringProvider.blockedServicesLoadStatus == LoadStatus.error) Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.blockedServicesListNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) + ], + ), + ) + ) ), ), ); @@ -162,9 +254,105 @@ class _BlockedServicesScreenStateWidget extends State { ), ), Expanded( - child: _Content( - values: values, - updateValues: updateValues, + child: Builder( + builder: (ctx) { + switch (filteringProvider.blockedServicesLoadStatus) { + case LoadStatus.loading: + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingBlockedServicesList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + return ListView.builder( + itemCount: filteringProvider.blockedServices!.services.length, + itemBuilder: (context, index) => Material( + color: Colors.transparent, + child: InkWell( + onTap: () => updateValues( + values.contains(filteringProvider.blockedServices!.services[index].id), + filteringProvider.blockedServices!.services[index] + ), + child: Padding( + padding: const EdgeInsets.only( + top: 6, + bottom: 6, + right: 12, + left: 24 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + filteringProvider.blockedServices!.services[index].name, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Checkbox( + value: values.contains(filteringProvider.blockedServices!.services[index].id), + onChanged: (value) => updateValues( + value!, + filteringProvider.blockedServices!.services[index] + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + ) + ], + ), + ), + ), + ) + ); + + case LoadStatus.error: + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.blockedServicesListNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, ) ), ], @@ -175,117 +363,6 @@ class _BlockedServicesScreenStateWidget extends State { } } -class _Content extends StatelessWidget { - final List values; - final void Function(bool value, BlockedService item) updateValues; - - const _Content({ - required this.values, - required this.updateValues, - }); - - @override - Widget build(BuildContext context) { - final filteringProvider = Provider.of(context); - - switch (filteringProvider.blockedServicesLoadStatus) { - case LoadStatus.loading: - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingBlockedServicesList, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - return ListView.builder( - itemCount: filteringProvider.blockedServices!.services.length, - itemBuilder: (context, index) => Material( - color: Colors.transparent, - child: InkWell( - onTap: () => updateValues( - values.contains(filteringProvider.blockedServices!.services[index].id), - filteringProvider.blockedServices!.services[index] - ), - child: Padding( - padding: const EdgeInsets.only( - top: 6, - bottom: 6, - right: 12, - left: 24 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - filteringProvider.blockedServices!.services[index].name, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Checkbox( - value: values.contains(filteringProvider.blockedServices!.services[index].id), - onChanged: (value) => updateValues( - value!, - filteringProvider.blockedServices!.services[index] - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5) - ), - ) - ], - ), - ), - ), - ) - ); - - case LoadStatus.error: - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.blockedServicesListNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - } -} void openBlockedServicesModal({ required BuildContext context, diff --git a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart index 00fe303..7e6e604 100644 --- a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart +++ b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart @@ -55,44 +55,66 @@ class _AddCustomRuleState extends State { Widget build(BuildContext context) { if (widget.fullScreen == true) { return Dialog.fullscreen( - child: Scaffold( - appBar: AppBar( - leading: CloseButton(onPressed: () => Navigator.pop(context)), - title: Text(AppLocalizations.of(context)!.addCustomRule), - actions: [ - IconButton( - onPressed: _checkValidValues() == true - ? () { - Navigator.pop(context); - widget.onConfirm( - _buildRule( - domainController: _domainController, - important: _addImportant, - preset: _preset - ) - ); - } - : null, - icon: const Icon(Icons.check) - ), - const SizedBox(width: 10) - ], - ), - body: SafeArea( - child: ListView( - children: [ - _CustomRuleEditor( - domainController: _domainController, - domainError: _domainError, - important: _addImportant, - preset: _preset, - setImportant: (v) => setState(() => _addImportant = v), - setPreset: (v) => setState(() => _preset = v), - validateDomain: validateDomain + child: Material( + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.addCustomRule), + actions: [ + IconButton( + onPressed: _checkValidValues() == true + ? () { + Navigator.pop(context); + widget.onConfirm( + _buildRule( + domainController: _domainController, + important: _addImportant, + preset: _preset + ) + ); + } + : null, + icon: const Icon(Icons.check) + ), + const SizedBox(width: 10) + ], + ) ) - ] + ], + body: SafeArea( + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + _CustomRuleEditor( + domainController: _domainController, + domainError: _domainError, + important: _addImportant, + preset: _preset, + setImportant: (v) => setState(() => _addImportant = v), + setPreset: (v) => setState(() => _preset = v), + validateDomain: validateDomain + ) + ] + ) + ], + ), + ) + ) ), - ) ), ); } diff --git a/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart b/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart index ba02ab0..b063411 100644 --- a/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart +++ b/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart @@ -37,29 +37,51 @@ class _EditCustomRulesState extends State { Widget build(BuildContext context) { if (widget.fullScreen == true) { return Dialog.fullscreen( - child: Scaffold( - appBar: AppBar( - leading: CloseButton(onPressed: () => Navigator.pop(context)), - title: Text(AppLocalizations.of(context)!.editCustomRules), - actions: [ - IconButton( - onPressed: () { - Navigator.pop(context); - widget.onConfirm(_fieldController.text.split("\n")); - }, - icon: const Icon(Icons.save_rounded), - tooltip: AppLocalizations.of(context)!.save, - ), - const SizedBox(width: 10) - ], + child: Material( + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.editCustomRules), + actions: [ + IconButton( + onPressed: () { + Navigator.pop(context); + widget.onConfirm(_fieldController.text.split("\n")); + }, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 10) + ], + ) + ) + ], + body: SafeArea( + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + _CustomRulesRawEditor(fieldController: _fieldController) + ] + ) + ], + ), + ) + ) ), - body: SafeArea( - child: ListView( - children: [ - _CustomRulesRawEditor(fieldController: _fieldController) - ] - ), - ) ), ); } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 33a5a97..a7aa080 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -6,13 +6,13 @@ PODS: - FlutterMacOS (1.0.0) - package_info_plus (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.20.0): - - SentryPrivate (= 8.20.0) + - Sentry/HybridSDK (8.21.0): + - SentryPrivate (= 8.21.0) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.20.0) - - SentryPrivate (8.20.0) + - Sentry/HybridSDK (= 8.21.0) + - SentryPrivate (8.21.0) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS @@ -84,9 +84,9 @@ SPEC CHECKSUMS: dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - Sentry: a8d7b373b9f9868442b02a0c425192f693103cbf - sentry_flutter: 03e7660857a8cdb236e71456a7e8447b65c8a788 - SentryPrivate: 006b24af16828441f70e2ab6adf241bd0a8ad130 + Sentry: ebc12276bd17613a114ab359074096b6b3725203 + sentry_flutter: dff1df05dc39c83d04f9330b36360fc374574c5e + SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: 73b7fc691fdc43277614250e04d183740cb15078