From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <pve-devel-bounces@lists.proxmox.com> Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id B76481FF15E for <inbox@lore.proxmox.com>; Tue, 3 Jun 2025 10:10:28 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 020E311E44; Tue, 3 Jun 2025 10:10:46 +0200 (CEST) Message-ID: <e8ca22c9-df25-4552-a0bb-230a90ea44d1@proxmox.com> Date: Tue, 3 Jun 2025 10:10:41 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: Proxmox VE development discussion <pve-devel@lists.proxmox.com>, Shan Shaji <s.shaji@proxmox.com> References: <20250602133755.68431-1-s.shaji@proxmox.com> <20250602133755.68431-2-s.shaji@proxmox.com> From: =?UTF-8?Q?Michael_K=C3=B6ppl?= <m.koeppl@proxmox.com> Content-Language: en-US In-Reply-To: <20250602133755.68431-2-s.shaji@proxmox.com> X-SPAM-LEVEL: Spam detection results: 0 AWL -1.297 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy ENA_SUBJ_ODD_CASE 2.6 Subject has odd case KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: Re: [pve-devel] [PATCH pve_flutter_frontend v2 1/2] refactor: move and split the `_MobileResourceFilterSheet` widget X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com> List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe> List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/> List-Post: <mailto:pve-devel@lists.proxmox.com> List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help> List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe> Reply-To: Proxmox VE development discussion <pve-devel@lists.proxmox.com> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" <pve-devel-bounces@lists.proxmox.com> I think it's a good change. The MainLayoutSlim class is already more than big enough. On 6/2/25 15:37, Shan Shaji wrote: > This patch splits the `_MobileResourceFilterSheet` into multiple widgets > and since the `main_layout_slim.dart` file is large, the widget has been > moved to it's own file under the widgets folder. nit: commit message should not contain "This patch..." also: s/it's/its > > Signed-off-by: Shan Shaji <s.shaji@proxmox.com> > --- > > changes since v1: > * Removed all formatting changes. > * Only includes the refactoring of `_MobileResourceFilterSheet` widget. > * Moved "paused guest not showing in resources tab" bug to another patch. > > lib/pages/main_layout_slim.dart | 175 +--------------- > .../pve_mobile_resource_filter_sheet.dart | 188 ++++++++++++++++++ > 2 files changed, 190 insertions(+), 173 deletions(-) > create mode 100644 lib/widgets/pve_mobile_resource_filter_sheet.dart > > diff --git a/lib/pages/main_layout_slim.dart b/lib/pages/main_layout_slim.dart > index 3bcd83b..8d6e5ed 100644 > --- a/lib/pages/main_layout_slim.dart > +++ b/lib/pages/main_layout_slim.dart > @@ -11,6 +11,7 @@ import 'package:pve_flutter_frontend/bloc/pve_cluster_status_bloc.dart'; > import 'package:pve_flutter_frontend/bloc/pve_file_selector_bloc.dart'; > import 'package:pve_flutter_frontend/bloc/pve_resource_bloc.dart'; > import 'package:pve_flutter_frontend/bloc/pve_storage_selector_bloc.dart'; > +import 'package:pve_flutter_frontend/widgets/pve_mobile_resource_filter_sheet.dart'; > import 'package:pve_flutter_frontend/states/pve_access_management_state.dart'; > import 'package:pve_flutter_frontend/states/pve_cluster_status_state.dart'; > import 'package:pve_flutter_frontend/states/pve_file_selector_state.dart'; > @@ -606,7 +607,7 @@ class MobileResourceOverview extends StatelessWidget { > }, > child: ColoredSafeArea( > child: Scaffold( > - endDrawer: _MobileResourceFilterSheet(), > + endDrawer: PveMobileResourceFilterSheet(), > appBar: AppBar( > automaticallyImplyLeading: false, > elevation: 0, > @@ -844,178 +845,6 @@ class _AppbarSearchTextFieldState extends State<AppbarSearchTextField> { > } > } > > -class _MobileResourceFilterSheet extends StatelessWidget { > - @override > - Widget build(BuildContext context) { > - final rBloc = Provider.of<PveResourceBloc>(context); > - > - return ProxmoxStreamBuilder<PveResourceBloc, PveResourceState>( > - bloc: rBloc, > - builder: (context, state) => Drawer( > - child: SingleChildScrollView( > - child: Column( > - crossAxisAlignment: CrossAxisAlignment.start, > - children: <Widget>[ > - Padding( > - padding: const EdgeInsets.fromLTRB(8.0, 20.0, 8.0, 0), > - child: ListTile( > - title: const Text( > - 'Filter Results', > - ), > - trailing: rBloc.isFiltered > - ? TextButton( > - onPressed: () => rBloc.events.add(ResetFilter()), > - child: Text( > - 'Reset', > - style: TextStyle( > - color: Theme.of(context).colorScheme.secondary, > - ), > - ), > - ) > - : null, > - ), > - ), > - const Divider( > - indent: 0, > - endIndent: 0, > - ), > - Padding( > - padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0), > - child: Column( > - children: [ > - const ListTile( > - title: Text( > - 'Type', > - style: TextStyle(fontWeight: FontWeight.bold), > - ), > - ), > - CheckboxListTile( > - dense: true, > - title: Text( > - 'Nodes', > - style: TextStyle( > - color: Theme.of(context) > - .colorScheme > - .onSurface > - .withValues(alpha: 0.75)), > - ), > - value: state.typeFilter.contains('node'), > - onChanged: (v) => rBloc.events.add(FilterResources( > - typeFilter: addOrRemove(v!, 'node', state.typeFilter), > - )), > - ), > - CheckboxListTile( > - dense: true, > - title: Text( > - 'Qemu', > - style: TextStyle( > - color: Theme.of(context) > - .colorScheme > - .onSurface > - .withValues(alpha: 0.75)), > - ), > - value: state.typeFilter.contains('qemu'), > - onChanged: (v) => rBloc.events.add(FilterResources( > - typeFilter: addOrRemove(v!, 'qemu', state.typeFilter), > - )), > - ), > - CheckboxListTile( > - dense: true, > - title: Text( > - 'LXC', > - style: TextStyle( > - color: Theme.of(context) > - .colorScheme > - .onSurface > - .withValues(alpha: 0.75)), > - ), > - value: state.typeFilter.contains('lxc'), > - onChanged: (v) => rBloc.events.add(FilterResources( > - typeFilter: addOrRemove(v!, 'lxc', state.typeFilter), > - )), > - ), > - CheckboxListTile( > - dense: true, > - title: Text( > - 'Storage', > - style: TextStyle( > - color: Theme.of(context) > - .colorScheme > - .onSurface > - .withValues(alpha: 0.75)), > - ), > - value: state.typeFilter.contains('storage'), > - onChanged: (v) => rBloc.events.add(FilterResources( > - typeFilter: > - addOrRemove(v!, 'storage', state.typeFilter), > - )), > - ), > - ], > - ), > - ), > - Padding( > - padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0), > - child: Column( > - children: [ > - const ListTile( > - title: Text( > - 'Status', > - style: TextStyle(fontWeight: FontWeight.bold), > - ), > - ), > - CheckboxListTile( > - dense: true, > - title: Text( > - 'Online', > - style: TextStyle( > - color: Theme.of(context) > - .colorScheme > - .onSurface > - .withValues(alpha: 0.75)), > - ), > - value: state.statusFilter > - .contains(PveResourceStatusType.running), > - onChanged: (v) => rBloc.events.add(FilterResources( > - statusFilter: addOrRemove(v!, > - PveResourceStatusType.running, state.statusFilter), > - )), > - ), > - CheckboxListTile( > - dense: true, > - title: Text( > - 'Offline', > - style: TextStyle( > - color: Theme.of(context) > - .colorScheme > - .onSurface > - .withValues(alpha: 0.75)), > - ), > - value: state.statusFilter > - .contains(PveResourceStatusType.stopped), > - onChanged: (v) => rBloc.events.add(FilterResources( > - statusFilter: addOrRemove(v!, > - PveResourceStatusType.stopped, state.statusFilter), > - )), > - ), > - ], > - ), > - ) > - ], > - ), > - ), > - ), > - ); > - } > - > - BuiltSet<S> addOrRemove<S>(bool value, S element, BuiltSet<S> filter) { > - if (value) { > - return filter.rebuild((b) => b..add(element)); > - } else { > - return filter.rebuild((b) => b..remove(element)); > - } > - } > -} > - > class AppBarFilterIconButton extends StatelessWidget { > const AppBarFilterIconButton({super.key}); > > diff --git a/lib/widgets/pve_mobile_resource_filter_sheet.dart b/lib/widgets/pve_mobile_resource_filter_sheet.dart > new file mode 100644 > index 0000000..cee3a49 > --- /dev/null > +++ b/lib/widgets/pve_mobile_resource_filter_sheet.dart > @@ -0,0 +1,188 @@ > +import 'package:built_collection/built_collection.dart'; > +import 'package:flutter/material.dart'; > +import 'package:provider/provider.dart'; > +import 'package:proxmox_dart_api_client/proxmox_dart_api_client.dart'; > +import 'package:pve_flutter_frontend/bloc/pve_resource_bloc.dart'; > +import 'package:pve_flutter_frontend/states/pve_resource_state.dart'; > +import 'package:pve_flutter_frontend/widgets/proxmox_stream_builder_widget.dart'; > + > +class PveMobileResourceFilterSheet extends StatelessWidget { > + const PveMobileResourceFilterSheet({super.key}); > + > + @override > + Widget build(BuildContext context) { > + final rBloc = Provider.of<PveResourceBloc>(context); > + return ProxmoxStreamBuilder<PveResourceBloc, PveResourceState>( > + bloc: rBloc, > + builder: (context, state) => Drawer( > + child: SingleChildScrollView( > + child: Column( > + crossAxisAlignment: CrossAxisAlignment.start, > + children: [ > + Padding( > + padding: const EdgeInsets.fromLTRB(8.0, 20.0, 8.0, 0), > + child: ListTile( > + title: const Text( > + 'Filter Results', > + ), > + trailing: rBloc.isFiltered > + ? TextButton( > + onPressed: () => rBloc.events.add(ResetFilter()), > + child: Text( > + 'Reset', > + style: TextStyle( > + color: Theme.of(context).colorScheme.secondary, > + ), > + ), > + ) > + : null, > + ), > + ), > + const Divider(indent: 0, endIndent: 0), > + _PveFilterSheetSection( > + sectionTitle: 'Type', > + items: [ > + _ProxmoxResourceFilterListTile( > + title: 'Nodes', > + value: state.typeFilter.contains('node'), > + onChanged: (v) => rBloc.events.add( > + FilterResources( > + typeFilter: _addOrRemove(v!, 'node', state.typeFilter), > + ), > + ), > + ), > + _ProxmoxResourceFilterListTile( > + title: 'Qemu', > + value: state.typeFilter.contains('qemu'), > + onChanged: (v) => rBloc.events.add( > + FilterResources( > + typeFilter: _addOrRemove(v!, 'qemu', state.typeFilter), > + ), > + ), > + ), > + _ProxmoxResourceFilterListTile( > + title: 'LXC', > + value: state.typeFilter.contains('lxc'), > + onChanged: (v) => rBloc.events.add( > + FilterResources( > + typeFilter: _addOrRemove(v!, 'lxc', state.typeFilter), > + ), > + ), > + ), > + _ProxmoxResourceFilterListTile( > + title: 'Storage', > + value: state.typeFilter.contains('storage'), > + onChanged: (v) => rBloc.events.add( > + FilterResources( > + typeFilter: > + _addOrRemove(v!, 'storage', state.typeFilter), > + ), > + ), > + ), > + ], > + ), > + _PveFilterSheetSection( > + sectionTitle: 'Status', > + items: [ > + _ProxmoxResourceFilterListTile( > + title: 'Online', > + value: state.statusFilter > + .contains(PveResourceStatusType.running), > + onChanged: (v) => rBloc.events.add( > + FilterResources( > + statusFilter: _addOrRemove( > + v!, > + PveResourceStatusType.running, > + state.statusFilter, > + ), > + ), > + ), > + ), > + _ProxmoxResourceFilterListTile( > + title: 'Offline', > + value: state.statusFilter > + .contains(PveResourceStatusType.stopped), > + onChanged: (v) => rBloc.events.add( > + FilterResources( > + statusFilter: _addOrRemove( > + v!, > + PveResourceStatusType.stopped, > + state.statusFilter, > + ), > + ), > + ), > + ), > + ], > + ) > + ], > + ), > + ), > + ), > + ); > + } > + > + BuiltSet<S> _addOrRemove<S>(bool value, S element, BuiltSet<S> filter) { > + if (value) { > + return filter.rebuild((b) => b..add(element)); > + } else { > + return filter.rebuild((b) => b..remove(element)); > + } > + } > +} > + > +class _PveFilterSheetSection extends StatelessWidget { > + const _PveFilterSheetSection({ > + required this.items, > + required this.sectionTitle, > + }); > + > + final List<Widget> items; > + final String sectionTitle; > + > + @override > + Widget build(BuildContext context) { > + return Padding( > + padding: const EdgeInsets.symmetric(horizontal: 8), > + child: Column( > + children: [ > + ListTile( > + title: Text( > + sectionTitle, > + style: TextStyle(fontWeight: FontWeight.bold), > + ), > + ), > + ...items, > + ], > + ), > + ); > + } > +} > + > +class _ProxmoxResourceFilterListTile extends StatelessWidget { > + const _ProxmoxResourceFilterListTile({ > + required this.title, > + this.onChanged, > + this.value, > + }); > + > + final String title; > + final ValueChanged<bool?>? onChanged; > + final bool? value; > + > + @override > + Widget build(BuildContext context) { > + return CheckboxListTile( > + dense: true, > + title: Text( > + title, > + style: TextStyle( > + color: Theme.of(context).colorScheme.onSurface.withValues( > + alpha: 0.75, > + ), > + ), > + ), > + value: value, > + onChanged: onChanged, > + ); > + } > +} _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel