diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..7e7e7f6 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1 @@ +extensions: diff --git a/lib/screens/filters/selection/selection_screen.dart b/lib/screens/filters/selection/selection_screen.dart index cde1f1d..11539b2 100644 --- a/lib/screens/filters/selection/selection_screen.dart +++ b/lib/screens/filters/selection/selection_screen.dart @@ -339,19 +339,28 @@ class _Tab extends StatelessWidget { Text(text), const SizedBox(width: 8), Container( - width: 18, - height: 18, + height: 22, + padding: const EdgeInsets.symmetric( + horizontal: 2 + ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Theme.of(context).colorScheme.primaryContainer ), - child: Text( - quantity.toString(), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w700, - color: Theme.of(context).colorScheme.onPrimaryContainer + child: ConstrainedBox( + constraints: const BoxConstraints( + minWidth: 18 + ), + child: Center( + child: Text( + quantity.toString(), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + color: Theme.of(context).colorScheme.onPrimaryContainer + ), + ), ), ), ) diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index d3149c1..47ca6fe 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -5,18 +5,9 @@ import 'package:expandable/expandable.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; -import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; +import 'package:adguard_home_manager/widgets/servers_list/server_tile_functions.dart'; -import 'package:adguard_home_manager/models/server_status.dart'; -import 'package:adguard_home_manager/services/api_client.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/models/app_log.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -27,12 +18,12 @@ class ServersListItem extends StatefulWidget { final void Function(int) onChange; const ServersListItem({ - Key? key, + super.key, required this.expandableController, required this.server, required this.index, required this.onChange - }) : super(key: key); + }); @override State createState() => _ServersListItemState(); @@ -71,293 +62,8 @@ class _ServersListItemState extends State with SingleTickerProv @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - final width = MediaQuery.of(context).size.width; - void showDeleteModal(Server server) async { - await Future.delayed(const Duration(seconds: 0), () => { - showDialog( - context: context, - builder: (context) => DeleteModal( - serverToDelete: server, - ), - barrierDismissible: false - ) - }); - } - - void openServerModal({Server? server}) async { - await Future.delayed(const Duration(seconds: 0), (() => { - openServerFormModal(context: context, width: width, server: server) - })); - } - - void connectToServer(Server server) async { - final ProcessModal process = ProcessModal(); - process.open(AppLocalizations.of(context)!.connecting); - - final result = server.runningOnHa == true - ? await loginHA(server) - : await login(server); - - if (result['result'] == 'success') { - final ApiClientV2 apiClient2 = ApiClientV2(server: server); - serversProvider.setApiClient2(apiClient2); - serversProvider.setSelectedServer(server); - - statusProvider.setServerStatusLoad(LoadStatus.loading); - final serverStatus = await apiClient2.getServerStatus(); - if (serverStatus.successful == true) { - statusProvider.setServerStatusData( - data: serverStatus.content as ServerStatus - ); - serversProvider.checkServerUpdatesAvailable( - server: server, - ); - statusProvider.setServerStatusLoad(LoadStatus.loaded); - } - - process.close(); - } - else { - process.close(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.cannotConnect, - color: Colors.red - ); - } - } - - void setDefaultServer(Server server) async { - final result = await serversProvider.setDefaultServer(server); - if (result == null) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, - color: Colors.green - ); - } - else { - appConfigProvider.addLog( - AppLog( - type: 'set_default_server', - dateTime: DateTime.now(), - message: result.toString() - ) - ); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionDefaultFailed, - color: Colors.red - ); - } - } - - Widget leadingIcon(Server server) { - if (server.defaultServer == true) { - return Stack( - alignment: Alignment.center, - children: [ - Icon( - Icons.storage_rounded, - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? statusProvider.serverStatus != null - ? Colors.green - : Colors.orange - : null, - ), - SizedBox( - width: 25, - height: 25, - child: Stack( - alignment: Alignment.bottomRight, - children: [ - Container( - padding: const EdgeInsets.all(1), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primaryContainer, - borderRadius: BorderRadius.circular(20) - ), - child: Icon( - Icons.star, - color: Theme.of(context).colorScheme.onPrimaryContainer, - size: 10, - ), - ), - ], - ), - ) - ], - ); - } - else { - return Icon( - Icons.storage_rounded, - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? statusProvider.serverStatus != null - ? Colors.green - : Colors.orange - : null, - ); - } - } - - Widget topRow(Server server, int index) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Row( - children: [ - Container( - margin: const EdgeInsets.only(right: 16), - child: leadingIcon(server), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Column( - children: [ - const SizedBox(height: 3), - Text( - server.name, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ) - ], - ) - ], - ), - ), - ], - ), - ), - RotationTransition( - turns: animation, - child: const Icon(Icons.keyboard_arrow_down_rounded), - ), - ], - ); - } - - Widget bottomRow(Server server, int index) { - return Column( - children: [ - const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - PopupMenuButton( - // color: Theme.of(context).dialogBackgroundColor, - itemBuilder: (context) => [ - PopupMenuItem( - enabled: server.defaultServer == false - ? true - : false, - onTap: server.defaultServer == false - ? (() => setDefaultServer(server)) - : null, - child: SizedBox( - child: Row( - children: [ - const Icon(Icons.star), - const SizedBox(width: 15), - Text( - server.defaultServer == true - ? AppLocalizations.of(context)!.defaultConnection - : AppLocalizations.of(context)!.setDefault, - ) - ], - ), - ) - ), - PopupMenuItem( - onTap: (() => openServerModal(server: server)), - child: Row( - children: [ - const Icon(Icons.edit), - const SizedBox(width: 15), - Text(AppLocalizations.of(context)!.edit) - ], - ) - ), - PopupMenuItem( - onTap: (() => showDeleteModal(server)), - child: Row( - children: [ - const Icon(Icons.delete), - const SizedBox(width: 15), - Text(AppLocalizations.of(context)!.delete) - ], - ) - ), - ] - ), - SizedBox( - child: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? Container( - margin: const EdgeInsets.only(right: 12), - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), - decoration: BoxDecoration( - color: statusProvider.serverStatus != null - ? Colors.green - : Colors.orange, - borderRadius: BorderRadius.circular(30) - ), - child: Row( - children: [ - Icon( - statusProvider.serverStatus != null - ? Icons.check - : Icons.warning, - color: Colors.white, - ), - const SizedBox(width: 10), - Text( - statusProvider.serverStatus != null - ? AppLocalizations.of(context)!.connected - : AppLocalizations.of(context)!.selectedDisconnected, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ) - ], - ), - ) - : Container( - margin: const EdgeInsets.only(right: 10), - child: TextButton( - onPressed: () => connectToServer(server), - child: Text(AppLocalizations.of(context)!.connect), - ), - ), - ) - ], - ) - ], - ); - } - return Container( decoration: BoxDecoration( border: Border( @@ -378,7 +84,7 @@ class _ServersListItemState extends State with SingleTickerProv onTap: () => widget.onChange(widget.index), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: topRow(widget.server, widget.index), + child: _TopRow(server: widget.server, animation: animation) ), ), ), @@ -390,8 +96,14 @@ class _ServersListItemState extends State with SingleTickerProv padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Column( children: [ - topRow(widget.server, widget.index), - bottomRow(widget.server, widget.index) + _TopRow(server: widget.server, animation: animation), + _BottomRow( + server: widget.server, + connectToServer: (s) => connectToServer(context: context, server: s), + openServerModal: (s) => openServerModal(context: context, server: s, width: width), + setDefaultServer: (s) => setDefaultServer(context: context, server: s), + showDeleteModal: (s) => showDeleteModal(context: context, server: s), + ) ], ), ), @@ -403,4 +115,247 @@ class _ServersListItemState extends State with SingleTickerProv ), ); } +} + +class _TopRow extends StatelessWidget { + final Server server; + final Animation animation; + + const _TopRow({ + required this.server, + required this.animation, + }); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 16), + child: _LeadingIcon(server: server), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Column( + children: [ + const SizedBox(height: 3), + Text( + server.name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ) + ], + ), + ), + ], + ), + ), + RotationTransition( + turns: animation, + child: const Icon(Icons.keyboard_arrow_down_rounded), + ), + ], + ); + } +} + +class _LeadingIcon extends StatelessWidget { + final Server server; + + const _LeadingIcon({ + required this.server, + }); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + + if (server.defaultServer == true) { + return Stack( + alignment: Alignment.center, + children: [ + Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? statusProvider.serverStatus != null + ? Colors.green + : Colors.orange + : null, + ), + SizedBox( + width: 25, + height: 25, + child: Stack( + alignment: Alignment.bottomRight, + children: [ + Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(20) + ), + child: Icon( + Icons.star, + color: Theme.of(context).colorScheme.onPrimaryContainer, + size: 10, + ), + ), + ], + ), + ) + ], + ); + } + else { + return Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? statusProvider.serverStatus != null + ? Colors.green + : Colors.orange + : null, + ); + } + } +} + +class _BottomRow extends StatelessWidget { + final Server server; + final void Function(Server) setDefaultServer; + final void Function(Server) openServerModal; + final void Function(Server) showDeleteModal; + final void Function(Server) connectToServer; + + const _BottomRow({ + required this.server, + required this.setDefaultServer, + required this.openServerModal, + required this.showDeleteModal, + required this.connectToServer, + }); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + + return Column( + children: [ + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + PopupMenuButton( + // color: Theme.of(context).dialogBackgroundColor, + itemBuilder: (context) => [ + PopupMenuItem( + enabled: server.defaultServer == false + ? true + : false, + onTap: server.defaultServer == false + ? (() => setDefaultServer(server)) + : null, + child: SizedBox( + child: Row( + children: [ + const Icon(Icons.star), + const SizedBox(width: 15), + Text( + server.defaultServer == true + ? AppLocalizations.of(context)!.defaultConnection + : AppLocalizations.of(context)!.setDefault, + ) + ], + ), + ) + ), + PopupMenuItem( + onTap: (() => openServerModal(server)), + child: Row( + children: [ + const Icon(Icons.edit), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.edit) + ], + ) + ), + PopupMenuItem( + onTap: (() => showDeleteModal(server)), + child: Row( + children: [ + const Icon(Icons.delete), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.delete) + ], + ) + ), + ] + ), + SizedBox( + child: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? Container( + margin: const EdgeInsets.only(right: 12), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + decoration: BoxDecoration( + color: statusProvider.serverStatus != null + ? Colors.green + : Colors.orange, + borderRadius: BorderRadius.circular(30) + ), + child: Row( + children: [ + Icon( + statusProvider.serverStatus != null + ? Icons.check + : Icons.warning, + color: Colors.white, + ), + const SizedBox(width: 10), + Text( + statusProvider.serverStatus != null + ? AppLocalizations.of(context)!.connected + : AppLocalizations.of(context)!.selectedDisconnected, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w500 + ), + ) + ], + ), + ) + : Container( + margin: const EdgeInsets.only(right: 10), + child: TextButton( + onPressed: () => connectToServer(server), + child: Text(AppLocalizations.of(context)!.connect), + ), + ), + ) + ], + ) + ], + ); + } } \ No newline at end of file