mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-04-22 14:59:12 +00:00
Added servers list and edit server
This commit is contained in:
parent
3acfc7c5a5
commit
59e9917a4b
12 changed files with 777 additions and 14 deletions
|
@ -22,9 +22,11 @@ class _BaseState extends State<Base> {
|
|||
Widget build(BuildContext context) {
|
||||
final serversProvider = Provider.of<ServersProvider>(context);
|
||||
|
||||
List<AppScreen> screens = serversProvider.selectedServer != null
|
||||
? screensServerConnected
|
||||
: screensSelectServer;
|
||||
// List<AppScreen> screens = serversProvider.selectedServer != null
|
||||
// ? screensServerConnected
|
||||
// : screensSelectServer;
|
||||
|
||||
List<AppScreen> screens = screensSelectServer;
|
||||
|
||||
if (selectedScreen > screens.length-1) {
|
||||
setState(() => selectedScreen = 0);
|
||||
|
|
31
lib/classes/process_modal.dart
Normal file
31
lib/classes/process_modal.dart
Normal file
|
@ -0,0 +1,31 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:adguard_home_manager/widgets/process_dialog.dart';
|
||||
|
||||
class ProcessModal {
|
||||
late BuildContext context;
|
||||
|
||||
ProcessModal({
|
||||
required this.context
|
||||
});
|
||||
|
||||
void open(String message) async {
|
||||
await Future.delayed(const Duration(seconds: 0), () => {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (c) {
|
||||
context = c;
|
||||
return ProcessDialog(
|
||||
message: message,
|
||||
);
|
||||
},
|
||||
barrierDismissible: false,
|
||||
useSafeArea: true,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
void close() {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
|
@ -26,5 +26,22 @@
|
|||
"sslError": "SSL error",
|
||||
"unknownError": "Unknown error",
|
||||
"connectionNotCreated": "Connection couldn't be created",
|
||||
"connecting": "Connecting..."
|
||||
"connecting": "Connecting...",
|
||||
"connected": "Connected",
|
||||
"selectedDisconnected": "Selected but disconnected",
|
||||
"connectionDefaultSuccessfully": "Connection set as default successfully.",
|
||||
"connectionDefaultFailed": "Connection could not be set as default.",
|
||||
"noSavedConnections": "No saved connections",
|
||||
"cannotConnect": "Cannot connect to the server",
|
||||
"connectionRemoved": "Connection removed successfully",
|
||||
"connectionCannotBeRemoved": "Connection cannot be removed.",
|
||||
"remove": "Remove",
|
||||
"removeWarning": "Are you sure you want to remove the connection with this AdGuard Home server?",
|
||||
"cancel": "Cancel",
|
||||
"defaultConnection": "Default connection",
|
||||
"setDefault": "Set default",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"save": "Save",
|
||||
"connectionNotUpdated": "Connection not updated"
|
||||
}
|
|
@ -26,5 +26,22 @@
|
|||
"sslError": "Error de SSL",
|
||||
"unknownError": "Error desconocido",
|
||||
"connectionNotCreated": "No se pudo crear la conexión",
|
||||
"connecting": "Conectando..."
|
||||
"connecting": "Conectando...",
|
||||
"connected": "Conectado",
|
||||
"selectedDisconnected": "Seleccionado pero desconectado",
|
||||
"connectionDefaultSuccessfully": "Conexión definida como por defecto.",
|
||||
"connectionDefaultFailed": "No se ha podido definir como conexión por defecto.",
|
||||
"noSavedConnections": "No hay conexiones guardadas",
|
||||
"cannotConnect": "No se puede conectar con el servidor",
|
||||
"connectionRemoved": "Conexión eliminada satisfactoriamente.",
|
||||
"connectionCannotBeRemoved": "No se ha podido eliminar la conexión.",
|
||||
"remove": "Eliminar",
|
||||
"removeWarning": "¿Estás seguro de que deseas eliminar la conexión con este servidor?",
|
||||
"cancel": "Cancelar",
|
||||
"defaultConnection": "Conexión por defecto",
|
||||
"setDefault": "Seleccionar por defecto",
|
||||
"edit": "Editar",
|
||||
"delete": "Eliminar",
|
||||
"save": "Guardar",
|
||||
"connectionNotUpdated": "Conexión no actualizada"
|
||||
}
|
|
@ -9,6 +9,7 @@ class ServersProvider with ChangeNotifier {
|
|||
|
||||
List<Server> _serversList = [];
|
||||
Server? _selectedServer;
|
||||
bool? _isServerConnected;
|
||||
|
||||
List<Server> get serversList {
|
||||
return _serversList;
|
||||
|
@ -18,6 +19,10 @@ class ServersProvider with ChangeNotifier {
|
|||
return _selectedServer;
|
||||
}
|
||||
|
||||
bool? get isServerConnected {
|
||||
return _isServerConnected;
|
||||
}
|
||||
|
||||
void setDbInstance(Database db) {
|
||||
_dbInstance = db;
|
||||
}
|
||||
|
@ -27,6 +32,16 @@ class ServersProvider with ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
void setSelectedServer(Server server) {
|
||||
_selectedServer = server;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setIsServerConnected(bool status) {
|
||||
_isServerConnected = status;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<bool> createServer(Server server) async {
|
||||
final saved = await saveServerIntoDb(server);
|
||||
if (saved == true) {
|
||||
|
@ -74,11 +89,71 @@ class ServersProvider with ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
Future<bool> editServer(Server server) async {
|
||||
final result = await editServerDb(server);
|
||||
if (result == true) {
|
||||
List<Server> newServers = _serversList.map((s) {
|
||||
if (s.id == server.id) {
|
||||
return server;
|
||||
}
|
||||
else {
|
||||
return s;
|
||||
}
|
||||
}).toList();
|
||||
_serversList = newServers;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> removeServer(Server server) async {
|
||||
final result = await removeFromDb(server.id);
|
||||
if (result == true) {
|
||||
_selectedServer = null;
|
||||
List<Server> newServers = _serversList.where((s) => s.id != server.id).toList();
|
||||
_serversList = newServers;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> saveServerIntoDb(Server server) async {
|
||||
try {
|
||||
return await _dbInstance!.transaction((txn) async {
|
||||
await txn.rawInsert(
|
||||
'INSERT INTO servers (id, name, connectionMethod, domain, path, port, user, password, defaultServer) VALUES ("${server.id}", "${server.name}", "${server.connectionMethod}", "${server.domain}", "${server.path}", ${server.port}, "${server.user}", "${server.password}", 0)',
|
||||
'INSERT INTO servers (id, name, connectionMethod, domain, path, port, user, password, defaultServer) VALUES ("${server.id}", "${server.name}", "${server.connectionMethod}", "${server.domain}", ${server.path != null ? "${server.path}" : null}, ${server.port}, "${server.user}", "${server.password}", 0)',
|
||||
);
|
||||
return true;
|
||||
});
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> editServerDb(Server server) async {
|
||||
try {
|
||||
return await _dbInstance!.transaction((txn) async {
|
||||
await txn.rawUpdate(
|
||||
'UPDATE servers SET name = "${server.name}", connectionMethod = "${server.connectionMethod}", domain = "${server.domain}", path = ${server.path != null ? "${server.path}" : null}, port = ${server.port}, user = "${server.user}", password = "${server.password}" WHERE id = "${server.id}"',
|
||||
);
|
||||
return true;
|
||||
});
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> removeFromDb(String id) async {
|
||||
try {
|
||||
return await _dbInstance!.transaction((txn) async {
|
||||
await txn.rawDelete(
|
||||
'DELETE FROM servers WHERE id = "$id"',
|
||||
);
|
||||
return true;
|
||||
});
|
||||
|
|
|
@ -1,15 +1,37 @@
|
|||
import 'package:expandable/expandable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:adguard_home_manager/widgets/servers_list/servers_list.dart';
|
||||
|
||||
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||
|
||||
class Connect extends StatelessWidget {
|
||||
class Connect extends StatefulWidget {
|
||||
const Connect({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Connect> createState() => _ConnectState();
|
||||
}
|
||||
|
||||
class _ConnectState extends State<Connect> {
|
||||
List<ExpandableController> expandableControllerList = [];
|
||||
|
||||
void expandOrContract(int index) async {
|
||||
expandableControllerList[index].expanded = !expandableControllerList[index].expanded;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final serversProvider = Provider.of<ServersProvider>(context);
|
||||
|
||||
return Container();
|
||||
for (var i = 0; i < serversProvider.serversList.length; i++) {
|
||||
expandableControllerList.add(ExpandableController());
|
||||
}
|
||||
|
||||
return ServersList(
|
||||
context: context,
|
||||
controllers: expandableControllerList,
|
||||
onChange: expandOrContract
|
||||
);
|
||||
}
|
||||
}
|
|
@ -13,7 +13,12 @@ import 'package:adguard_home_manager/models/server.dart';
|
|||
import 'package:adguard_home_manager/config/system_overlay_style.dart';
|
||||
|
||||
class AddServerModal extends StatefulWidget {
|
||||
const AddServerModal({Key? key}) : super(key: key);
|
||||
final Server? server;
|
||||
|
||||
const AddServerModal({
|
||||
Key? key,
|
||||
this.server,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AddServerModal> createState() => _AddServerModalState();
|
||||
|
@ -178,6 +183,22 @@ class _AddServerModalState extends State<AddServerModal> {
|
|||
checkDataValid();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
if (widget.server != null) {
|
||||
nameController.text = widget.server!.name;
|
||||
connectionType = widget.server!.connectionMethod;
|
||||
ipDomainController.text = widget.server!.domain;
|
||||
pathController.text = widget.server!.path ?? '';
|
||||
portController.text = widget.server!.port != null ? widget.server!.port.toString() : "";
|
||||
userController.text = widget.server!.user;
|
||||
passwordController.text = widget.server!.password;
|
||||
defaultServer = widget.server!.defaultServer;
|
||||
}
|
||||
checkDataValid();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final serversProvider = Provider.of<ServersProvider>(context, listen: false);
|
||||
|
@ -195,7 +216,9 @@ class _AddServerModalState extends State<AddServerModal> {
|
|||
password: passwordController.text,
|
||||
defaultServer: defaultServer
|
||||
);
|
||||
setState(() => isConnecting = true);
|
||||
final result = await login(serverObj);
|
||||
setState(() => isConnecting = false);
|
||||
if (result['result'] == 'success') {
|
||||
final serverCreated = await serversProvider.createServer(serverObj);
|
||||
if (serverCreated == true) {
|
||||
|
@ -252,6 +275,74 @@ class _AddServerModalState extends State<AddServerModal> {
|
|||
}
|
||||
}
|
||||
|
||||
void edit() async {
|
||||
final Server serverObj = Server(
|
||||
id: widget.server!.id,
|
||||
name: nameController.text,
|
||||
connectionMethod: connectionType,
|
||||
domain: ipDomainController.text,
|
||||
port: int.parse(portController.text),
|
||||
user: userController.text,
|
||||
password: passwordController.text,
|
||||
defaultServer: defaultServer
|
||||
);
|
||||
final result = await login(serverObj);
|
||||
if (result['result'] == 'success') {
|
||||
final serverSaved = await serversProvider.editServer(serverObj);
|
||||
if (serverSaved == true) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.connectionNotUpdated),
|
||||
backgroundColor: Colors.red,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (result['result'] == 'error' && result['message'] == 'invalid_username_password') {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.invalidUsernamePassword),
|
||||
backgroundColor: Colors.red,
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (result['result'] == 'error' && result['message'] == 'many_attempts') {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.tooManyAttempts),
|
||||
backgroundColor: Colors.red,
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (result['result'] == 'error' && result['message'] == 'no_connection') {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.cantReachServer),
|
||||
backgroundColor: Colors.red,
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (result['result'] == 'error' && result['message'] == 'ssl_error') {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.sslError),
|
||||
backgroundColor: Colors.red,
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.unknownError),
|
||||
backgroundColor: Colors.red,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
Scaffold(
|
||||
|
@ -264,11 +355,19 @@ class _AddServerModalState extends State<AddServerModal> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: IconButton(
|
||||
tooltip: AppLocalizations.of(context)!.connect,
|
||||
tooltip: widget.server == null
|
||||
? AppLocalizations.of(context)!.connect
|
||||
: AppLocalizations.of(context)!.save,
|
||||
onPressed: allDataValid == true
|
||||
? () => connect()
|
||||
? widget.server == null
|
||||
? () => connect()
|
||||
: () => edit()
|
||||
: null,
|
||||
icon: const Icon(Icons.login_rounded)
|
||||
icon: Icon(
|
||||
widget.server == null
|
||||
? Icons.login_rounded
|
||||
: Icons.save_rounded
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -349,7 +448,9 @@ class _AddServerModalState extends State<AddServerModal> {
|
|||
Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => setState(() => defaultServer = !defaultServer),
|
||||
onTap: widget.server == null
|
||||
? () => setState(() => defaultServer = !defaultServer)
|
||||
: null,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Row(
|
||||
|
@ -363,7 +464,9 @@ class _AddServerModalState extends State<AddServerModal> {
|
|||
),
|
||||
Switch(
|
||||
value: defaultServer,
|
||||
onChanged: (value) => setState(() => defaultServer = value),
|
||||
onChanged: widget.server == null
|
||||
? (value) => setState(() => defaultServer = value)
|
||||
: null,
|
||||
activeColor: Theme.of(context).primaryColor,
|
||||
)
|
||||
],
|
||||
|
|
33
lib/widgets/process_dialog.dart
Normal file
33
lib/widgets/process_dialog.dart
Normal file
|
@ -0,0 +1,33 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class ProcessDialog extends StatelessWidget {
|
||||
final String message;
|
||||
|
||||
const ProcessDialog({
|
||||
Key? key,
|
||||
required this.message,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: Dialog(
|
||||
backgroundColor: Theme.of(context).dialogBackgroundColor,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 30,
|
||||
horizontal: 30
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(width: 40),
|
||||
Text(message)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
98
lib/widgets/servers_list/delete_modal.dart
Normal file
98
lib/widgets/servers_list/delete_modal.dart
Normal file
|
@ -0,0 +1,98 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import 'package:adguard_home_manager/models/server.dart';
|
||||
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||
|
||||
class DeleteModal extends StatelessWidget {
|
||||
final Server serverToDelete;
|
||||
|
||||
const DeleteModal({
|
||||
Key? key,
|
||||
required this.serverToDelete,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final serversProvider = Provider.of<ServersProvider>(context);
|
||||
|
||||
void removeServer() async {
|
||||
final deleted = await serversProvider.removeServer(serverToDelete);
|
||||
Navigator.pop(context);
|
||||
if (deleted == true) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.connectionRemoved),
|
||||
backgroundColor: Colors.green,
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.connectionCannotBeRemoved),
|
||||
backgroundColor: Colors.red,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return AlertDialog(
|
||||
title: Column(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.delete,
|
||||
size: 26,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.remove,
|
||||
style: const TextStyle(
|
||||
fontSize: 24
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
AppLocalizations.of(context)!.removeWarning,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Center(
|
||||
child: Text(
|
||||
"${serverToDelete.connectionMethod}://${serverToDelete.domain}${serverToDelete.path ?? ""}${serverToDelete.port != null ? ':${serverToDelete.port}' : ""}",
|
||||
style: const TextStyle(
|
||||
fontStyle: FontStyle.italic
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => {
|
||||
Navigator.pop(context)
|
||||
},
|
||||
child: Text(AppLocalizations.of(context)!.cancel)
|
||||
),
|
||||
TextButton(
|
||||
onPressed: removeServer,
|
||||
child: Text(AppLocalizations.of(context)!.remove),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
357
lib/widgets/servers_list/servers_list.dart
Normal file
357
lib/widgets/servers_list/servers_list.dart
Normal file
|
@ -0,0 +1,357 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
import 'package:adguard_home_manager/widgets/add_server_modal.dart';
|
||||
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/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';
|
||||
|
||||
class ServersList extends StatelessWidget {
|
||||
final BuildContext context;
|
||||
final List<ExpandableController> controllers;
|
||||
final Function(int) onChange;
|
||||
|
||||
const ServersList({
|
||||
Key? key,
|
||||
required this.context,
|
||||
required this.controllers,
|
||||
required this.onChange
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
// ignore: avoid_renaming_method_parameters
|
||||
Widget build(BuildContext context) {
|
||||
final serversProvider = Provider.of<ServersProvider>(context);
|
||||
List<Server> servers = serversProvider.serversList;
|
||||
|
||||
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 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 {
|
||||
Future connectSuccess(result) async {
|
||||
serversProvider.setSelectedServer(server);
|
||||
}
|
||||
|
||||
final ProcessModal process = ProcessModal(context: context);
|
||||
process.open(AppLocalizations.of(context)!.connecting);
|
||||
|
||||
final result = await login(server);
|
||||
|
||||
process.close();
|
||||
|
||||
if (result['result'] == 'success') {
|
||||
await connectSuccess(result);
|
||||
}
|
||||
else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.cannotConnect),
|
||||
backgroundColor: Colors.red,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void setDefaultServer(Server server) async {
|
||||
final result = await serversProvider.setDefaultServer(server);
|
||||
if (result == true) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.connectionDefaultSuccessfully),
|
||||
backgroundColor: Colors.green,
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.connectionDefaultFailed),
|
||||
backgroundColor: 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
|
||||
? serversProvider.isServerConnected == true
|
||||
? 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).primaryColor,
|
||||
borderRadius: BorderRadius.circular(20)
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.star,
|
||||
color: Colors.white,
|
||||
size: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
else {
|
||||
return Icon(
|
||||
Icons.storage_rounded,
|
||||
color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id
|
||||
? serversProvider.isServerConnected == true
|
||||
? Colors.green
|
||||
: Colors.orange
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget topRow(Server server, int index) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
width: 48,
|
||||
margin: const EdgeInsets.only(right: 12),
|
||||
child: leadingIcon(servers[index]),
|
||||
),
|
||||
SizedBox(
|
||||
width: width-168,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
servers[index].name,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontStyle: FontStyle.italic
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => onChange(index),
|
||||
icon: const Icon(Icons.arrow_drop_down),
|
||||
splashRadius: 20,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
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: (() => 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(
|
||||
color: serversProvider.isServerConnected == true
|
||||
? Colors.green
|
||||
: Colors.orange,
|
||||
borderRadius: BorderRadius.circular(30)
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
serversProvider.isServerConnected == true
|
||||
? Icons.check
|
||||
: Icons.warning,
|
||||
color: Colors.white,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
serversProvider.isServerConnected == true
|
||||
? 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(
|
||||
itemCount: servers.length,
|
||||
itemBuilder: (context, index) => Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1
|
||||
)
|
||||
)
|
||||
),
|
||||
child: ExpandableNotifier(
|
||||
controller: controllers[index],
|
||||
child: Column(
|
||||
children: [
|
||||
Expandable(
|
||||
collapsed: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => onChange(index),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: topRow(servers[index], index),
|
||||
),
|
||||
),
|
||||
),
|
||||
expanded: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => onChange(index),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
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,
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
color: Colors.grey,
|
||||
fontWeight: FontWeight.w500
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -106,6 +106,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.4"
|
||||
expandable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: expandable
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -43,6 +43,7 @@ dependencies:
|
|||
animations: ^2.0.5
|
||||
device_info_plus: ^4.1.2
|
||||
uuid: ^3.0.6
|
||||
expandable: ^5.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Add table
Reference in a new issue