adguard-home-manager/lib/widgets/servers_list/servers_list.dart

430 lines
14 KiB
Dart
Raw Normal View History

2022-09-26 22:43:30 +02:00
// ignore_for_file: use_build_context_synchronously
2022-11-01 19:41:41 +01:00
import 'package:adguard_home_manager/functions/snackbar.dart';
2022-09-26 22:43:30 +02:00
import 'package:flutter/material.dart';
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/servers_list/delete_modal.dart';
import 'package:adguard_home_manager/widgets/add_server_modal.dart';
2022-09-26 22:43:30 +02:00
2022-09-30 00:24:56 +02:00
import 'package:adguard_home_manager/providers/app_config_provider.dart';
2022-11-01 19:41:41 +01:00
import 'package:adguard_home_manager/models/app_log.dart';
2022-09-26 22:43:30 +02:00
import 'package:adguard_home_manager/classes/process_modal.dart';
import 'package:adguard_home_manager/models/server.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart';
import 'package:adguard_home_manager/services/http_requests.dart';
2022-10-28 16:26:55 +02:00
class ServersList extends StatefulWidget {
2022-09-26 22:43:30 +02:00
final BuildContext context;
final List<ExpandableController> controllers;
final Function(int) onChange;
2022-10-29 19:25:58 +02:00
final ScrollController scrollController;
2022-09-26 22:43:30 +02:00
const ServersList({
Key? key,
required this.context,
required this.controllers,
2022-10-29 19:25:58 +02:00
required this.onChange,
required this.scrollController,
2022-09-26 22:43:30 +02:00
}) : super(key: key);
2022-10-28 16:26:55 +02:00
@override
State<ServersList> createState() => _ServersListState();
}
class _ServersListState extends State<ServersList> with SingleTickerProviderStateMixin {
late AnimationController animationController;
late Animation<double> animation;
@override
void initState() {
for (ExpandableController controller in widget.controllers) {
controller.addListener(() async {
await Future.delayed(const Duration(milliseconds: 200));
if (controller.value == false) {
animationController.animateTo(0);
}
else {
animationController.animateBack(1);
}
});
}
animationController = AnimationController(
duration: const Duration(milliseconds: 200),
vsync: this,
)
..addListener(() => setState(() => {}));
2022-10-28 16:26:55 +02:00
animation = Tween(
begin: 0.0,
end: 0.5,
).animate(CurvedAnimation(
parent: animationController,
curve: Curves.easeInOut
));
super.initState();
}
@override
void dispose() {
animationController.dispose();
super.dispose();
}
2022-09-26 22:43:30 +02:00
@override
// ignore: avoid_renaming_method_parameters
Widget build(BuildContext context) {
final serversProvider = Provider.of<ServersProvider>(context);
2022-09-30 00:24:56 +02:00
final appConfigProvider = Provider.of<AppConfigProvider>(context);
2022-09-26 22:43:30 +02:00
List<Server> servers = serversProvider.serversList;
void showDeleteModal(Server server) async {
await Future.delayed(const Duration(seconds: 0), () => {
showDialog(
context: context,
builder: (context) => DeleteModal(
serverToDelete: server,
),
barrierDismissible: false
)
});
}
void openAddServerBottomSheet({Server? server}) async {
await Future.delayed(const Duration(seconds: 0), (() => {
Navigator.push(context, MaterialPageRoute(
fullscreenDialog: true,
builder: (BuildContext context) => AddServerModal(server: server)
))
}));
}
void connectToServer(Server server) async {
final ProcessModal process = ProcessModal(context: context);
process.open(AppLocalizations.of(context)!.connecting);
final result = server.runningOnHa == true
? await loginHA(server)
: await login(server);
2022-09-26 22:43:30 +02:00
if (result['result'] == 'success') {
serversProvider.setSelectedServer(server);
2022-09-27 14:29:36 +02:00
serversProvider.setServerStatusLoad(0);
2022-09-27 12:43:25 +02:00
final serverStatus = await getServerStatus(server);
if (serverStatus['result'] == 'success') {
2022-09-27 14:29:36 +02:00
serversProvider.setServerStatusData(serverStatus['data']);
serversProvider.setServerStatusLoad(1);
}
else {
2022-10-03 22:41:19 +02:00
appConfigProvider.addLog(serverStatus['log']);
2022-09-27 14:29:36 +02:00
serversProvider.setServerStatusLoad(2);
}
process.close();
2022-09-26 22:43:30 +02:00
}
else {
process.close();
2022-09-30 01:23:28 +02:00
appConfigProvider.addLog(result['log']);
2022-11-01 19:41:41 +01:00
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.cannotConnect,
color: Colors.red
2022-09-26 22:43:30 +02:00
);
}
}
void setDefaultServer(Server server) async {
final result = await serversProvider.setDefaultServer(server);
2022-11-01 19:41:41 +01:00
if (result == null) {
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.connectionDefaultSuccessfully,
color: Colors.green
2022-09-26 22:43:30 +02:00
);
}
else {
2022-11-01 19:41:41 +01:00
appConfigProvider.addLog(
AppLog(
type: 'set_default_server',
dateTime: DateTime.now(),
message: result.toString()
2022-09-26 22:43:30 +02:00
)
);
2022-11-01 19:41:41 +01:00
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.connectionDefaultFailed,
color: Colors.red
);
2022-09-26 22:43:30 +02:00
}
}
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
2022-09-27 14:29:36 +02:00
? serversProvider.serverStatus.data != null
2022-09-26 22:43:30 +02:00
? Colors.green
: Colors.orange
: null,
),
SizedBox(
width: 25,
height: 25,
child: Stack(
alignment: Alignment.bottomRight,
children: [
Container(
padding: const EdgeInsets.all(1),
decoration: BoxDecoration(
2022-11-05 02:35:35 +01:00
color: Theme.of(context).floatingActionButtonTheme.backgroundColor,
2022-09-26 22:43:30 +02:00
borderRadius: BorderRadius.circular(20)
),
2022-11-04 22:56:00 +01:00
child: Icon(
2022-09-26 22:43:30 +02:00
Icons.star,
2022-11-05 02:35:35 +01:00
color: Theme.of(context).floatingActionButtonTheme.foregroundColor,
2022-09-26 22:43:30 +02:00
size: 10,
),
),
],
),
)
],
);
}
else {
return Icon(
Icons.storage_rounded,
color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id
2022-09-27 14:29:36 +02:00
? serversProvider.serverStatus.data != null
2022-09-26 22:43:30 +02:00
? Colors.green
: Colors.orange
: null,
);
}
}
Widget topRow(Server server, int index) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
2022-10-28 16:26:55 +02:00
Expanded(
2022-11-04 01:22:57 +01:00
child: Row(
2022-09-26 22:43:30 +02:00
children: [
2022-11-04 01:22:57 +01:00
Container(
margin: const EdgeInsets.only(right: 16),
child: leadingIcon(servers[index]),
2022-09-26 22:43:30 +02:00
),
2022-11-04 01:22:57 +01:00
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}",
textAlign: TextAlign.center,
2022-11-04 17:04:25 +01:00
style: TextStyle(
2022-11-04 01:22:57 +01:00
fontSize: 16,
2022-11-04 17:04:25 +01:00
fontWeight: FontWeight.w400,
color: Theme.of(context).colorScheme.onSurface
2022-11-04 01:22:57 +01:00
),
2022-09-26 22:43:30 +02:00
),
2022-11-04 01:22:57 +01:00
Column(
children: [
const SizedBox(height: 3),
Text(
servers[index].name,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
2022-11-04 17:04:25 +01:00
color: Theme.of(context).colorScheme.onSurfaceVariant
2022-11-04 01:22:57 +01:00
),
)
],
)
],
),
),
2022-09-26 22:43:30 +02:00
],
),
),
2022-11-04 01:22:57 +01:00
RotationTransition(
turns: animation,
child: const Icon(Icons.keyboard_arrow_down_rounded),
2022-09-26 22:43:30 +02:00
),
],
);
}
Widget bottomRow(Server server, int index) {
return Column(
children: [
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
PopupMenuButton(
2023-01-25 19:55:34 +01:00
// color: Theme.of(context).dialogBackgroundColor,
2022-09-26 22:43:30 +02:00
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: (() => openAddServerBottomSheet(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 == servers[index].id
? Container(
margin: const EdgeInsets.only(right: 12),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
decoration: BoxDecoration(
2022-09-27 14:29:36 +02:00
color: serversProvider.serverStatus.data != null
2022-09-26 22:43:30 +02:00
? Colors.green
: Colors.orange,
borderRadius: BorderRadius.circular(30)
),
child: Row(
children: [
Icon(
2022-09-27 14:29:36 +02:00
serversProvider.serverStatus.data != null
2022-09-26 22:43:30 +02:00
? Icons.check
: Icons.warning,
color: Colors.white,
),
const SizedBox(width: 10),
Text(
2022-09-27 14:29:36 +02:00
serversProvider.serverStatus.data != null
2022-09-26 22:43:30 +02:00
? 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(servers[index]),
child: Text(AppLocalizations.of(context)!.connect),
),
),
)
],
)
],
);
}
return servers.isNotEmpty ?
ListView.builder(
2022-10-29 19:25:58 +02:00
controller: widget.scrollController,
2022-09-26 22:43:30 +02:00
itemCount: servers.length,
itemBuilder: (context, index) => Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
2023-01-25 20:51:23 +01:00
color: Theme.of(context).colorScheme.surfaceVariant,
2022-09-26 22:43:30 +02:00
width: 1
)
)
),
child: ExpandableNotifier(
2022-10-28 16:26:55 +02:00
controller: widget.controllers[index],
2022-09-26 22:43:30 +02:00
child: Column(
children: [
Expandable(
collapsed: Material(
color: Colors.transparent,
child: InkWell(
2022-10-28 16:26:55 +02:00
onTap: () => widget.onChange(index),
2022-09-26 22:43:30 +02:00
child: Padding(
2022-11-04 22:56:00 +01:00
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
2022-09-26 22:43:30 +02:00
child: topRow(servers[index], index),
),
),
),
expanded: Material(
color: Colors.transparent,
child: InkWell(
2022-10-28 16:26:55 +02:00
onTap: () => widget.onChange(index),
2022-09-26 22:43:30 +02:00
child: Padding(
2022-11-04 22:56:00 +01:00
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
2022-09-26 22:43:30 +02:00
child: Column(
children: [
topRow(servers[index], index),
bottomRow(servers[index], index)
],
),
),
),
)
)
],
),
),
)
) : SizedBox(
height: double.maxFinite,
child: Center(
child: Text(
AppLocalizations.of(context)!.noSavedConnections,
textAlign: TextAlign.center,
2023-01-29 21:52:37 +01:00
style: TextStyle(
2022-09-26 22:43:30 +02:00
fontSize: 24,
2023-01-29 21:52:37 +01:00
color: Theme.of(context).colorScheme.onSurfaceVariant,
2022-09-26 22:43:30 +02:00
),
),
),
);
}
}