New tab list access clients

This commit is contained in:
Juan Gilsanz Polo 2023-04-06 18:50:06 +02:00
parent 6ebde52a7f
commit 4e65f80baf
3 changed files with 170 additions and 163 deletions

View file

@ -1,10 +1,10 @@
import 'package:adguard_home_manager/constants/enums.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/settings/access_settings/clients_list.dart'; import 'package:adguard_home_manager/screens/settings/access_settings/clients_list.dart';
import 'package:adguard_home_manager/constants/enums.dart';
import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/services/http_requests.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart';
@ -72,7 +72,7 @@ class _AccessSettingsWidgetState extends State<AccessSettingsWidget> with Ticker
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final serversProvider = Provider.of<ServersProvider>(context); final serversProvider = Provider.of<ServersProvider>(context);
print(serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts.length);
return Scaffold( return Scaffold(
body: DefaultTabController( body: DefaultTabController(
length: 3, length: 3,

View file

@ -1,8 +1,5 @@
// ignore_for_file: use_build_context_synchronously // ignore_for_file: use_build_context_synchronously
import 'dart:io';
import 'package:adguard_home_manager/constants/enums.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -10,11 +7,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/settings/access_settings/add_client_modal.dart'; import 'package:adguard_home_manager/screens/settings/access_settings/add_client_modal.dart';
import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart';
import 'package:adguard_home_manager/widgets/tab_content_list.dart';
import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/snackbar.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart';
import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart';
import 'package:adguard_home_manager/constants/enums.dart';
import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/services/http_requests.dart';
import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart';
@ -209,167 +208,173 @@ class _ClientsListState extends State<ClientsList> {
} }
} }
switch (widget.loadStatus) { return CustomTabContentList(
case LoadStatus.loading: loadingGenerator: () => SizedBox(
return SizedBox( width: double.maxFinite,
width: double.maxFinite, height: MediaQuery.of(context).size.height-171,
height: MediaQuery.of(context).size.height-171, child: Column(
child: Column( mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const CircularProgressIndicator(),
const SizedBox(height: 30),
Text(
AppLocalizations.of(context)!.loadingClients,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
)
],
),
);
case LoadStatus.loaded:
return Stack(
children: [ children: [
RefreshIndicator( const CircularProgressIndicator(),
onRefresh: widget.fetchClients, const SizedBox(height: 30),
child: Column( Text(
mainAxisSize: MainAxisSize.max, AppLocalizations.of(context)!.loadingClients,
children: [ textAlign: TextAlign.center,
Padding( style: TextStyle(
padding: const EdgeInsets.all(10), fontSize: 22,
child: Card( color: Theme.of(context).colorScheme.onSurfaceVariant,
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
Icon(
Icons.info_rounded,
color: Theme.of(context).listTileTheme.iconColor,
),
const SizedBox(width: 20),
Flexible(
child: Text(
description(),
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
),
),
)
],
),
),
),
),
if (widget.data.isNotEmpty) Expanded(
child: ListView.builder(
padding: const EdgeInsets.only(top: 0),
itemCount: widget.data.length,
itemBuilder: (context, index) => ListTile(
title: Text(
widget.data[index],
style: TextStyle(
fontWeight: FontWeight.normal,
color: Theme.of(context).colorScheme.onSurface
),
),
trailing: IconButton(
onPressed: () => {
showDialog(
context: context,
builder: (context) => RemoveClientModal(
onConfirm: () => confirmRemoveItem(widget.data[index], widget.type),
)
)
},
icon: const Icon(Icons.delete_rounded)
),
)
),
),
if (widget.data.isEmpty) Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
noItems(),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 24,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 30),
TextButton.icon(
onPressed: widget.fetchClients,
icon: const Icon(Icons.refresh_rounded),
label: Text(AppLocalizations.of(context)!.refresh),
)
],
),
),
],
),
),
AnimatedPositioned(
duration: const Duration(milliseconds: 100),
curve: Curves.easeInOut,
bottom: isVisible ?
appConfigProvider.showingSnackbar
? 70 : (Platform.isIOS ? 40 : 20)
: -70,
right: 20,
child: FloatingActionButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) => AddClientModal(
type: widget.type,
onConfirm: confirmAddItem
),
backgroundColor: Colors.transparent,
isScrollControlled: true
);
},
child: const Icon(Icons.add),
), ),
) )
] ],
); ),
),
case LoadStatus.error: itemsCount: widget.data.isNotEmpty
return SizedBox( ? widget.data.length+1
width: double.maxFinite, : 0,
height: MediaQuery.of(context).size.height-101, contentWidget: (index) {
child: Column( if (index == 0) {
mainAxisAlignment: MainAxisAlignment.center, return Padding(
crossAxisAlignment: CrossAxisAlignment.center, padding: const EdgeInsets.all(10),
children: [ child: Card(
const Icon( child: Padding(
Icons.error, padding: const EdgeInsets.all(20),
color: Colors.red, child: Row(
size: 50, children: [
), Icon(
const SizedBox(height: 30), Icons.info_rounded,
Text( color: Theme.of(context).listTileTheme.iconColor,
AppLocalizations.of(context)!.clientsNotLoaded, ),
textAlign: TextAlign.center, const SizedBox(width: 20),
style: TextStyle( Flexible(
fontSize: 22, child: Text(
color: Theme.of(context).colorScheme.onSurfaceVariant, description(),
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
),
),
)
],
), ),
) ),
], ),
);
}
else {
return ListTile(
title: Text(
widget.data[index-1],
style: TextStyle(
fontWeight: FontWeight.normal,
color: Theme.of(context).colorScheme.onSurface
),
),
trailing: IconButton(
onPressed: () => {
showDialog(
context: context,
builder: (context) => RemoveClientModal(
onConfirm: () => confirmRemoveItem(widget.data[index-1], widget.type),
)
)
},
icon: const Icon(Icons.delete_rounded)
),
);
}
},
noData: Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Card(
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
Icon(
Icons.info_rounded,
color: Theme.of(context).listTileTheme.iconColor,
),
const SizedBox(width: 20),
Flexible(
child: Text(
description(),
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
),
),
)
],
),
),
),
), ),
); Expanded(
child: Column(
default: mainAxisAlignment: MainAxisAlignment.center,
return const SizedBox(); children: [
} Text(
noItems(),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 24,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 30),
TextButton.icon(
onPressed: widget.fetchClients,
icon: const Icon(Icons.refresh_rounded),
label: Text(AppLocalizations.of(context)!.refresh),
)
],
),
),
],
),
errorGenerator: () => SizedBox(
width: double.maxFinite,
height: MediaQuery.of(context).size.height-101,
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)!.clientsNotLoaded,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
)
],
),
),
loadStatus: widget.loadStatus,
onRefresh: widget.fetchClients,
refreshIndicatorOffset: 0,
fab: FloatingActionButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) => AddClientModal(
type: widget.type,
onConfirm: confirmAddItem
),
backgroundColor: Colors.transparent,
isScrollControlled: true
);
},
child: const Icon(Icons.add),
),
fabVisible: isVisible,
);
} }
} }

View file

@ -12,6 +12,7 @@ class CustomTabContentList extends StatelessWidget {
final Widget Function() errorGenerator; final Widget Function() errorGenerator;
final LoadStatus loadStatus; final LoadStatus loadStatus;
final Future<void> Function() onRefresh; final Future<void> Function() onRefresh;
final double? refreshIndicatorOffset;
final Widget? fab; final Widget? fab;
final bool? fabVisible; final bool? fabVisible;
@ -24,6 +25,7 @@ class CustomTabContentList extends StatelessWidget {
required this.errorGenerator, required this.errorGenerator,
required this.loadStatus, required this.loadStatus,
required this.onRefresh, required this.onRefresh,
this.refreshIndicatorOffset,
this.fab, this.fab,
this.fabVisible this.fabVisible
}) : super(key: key); }) : super(key: key);
@ -65,7 +67,7 @@ class CustomTabContentList extends StatelessWidget {
builder: (BuildContext context) { builder: (BuildContext context) {
return RefreshIndicator( return RefreshIndicator(
onRefresh: onRefresh, onRefresh: onRefresh,
edgeOffset: 95, edgeOffset: refreshIndicatorOffset ?? 95,
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
SliverOverlapInjector( SliverOverlapInjector(