adguard-home-manager/lib/screens/settings/dhcp/dhcp.dart

909 lines
36 KiB
Dart
Raw Normal View History

2022-10-14 01:53:02 +02:00
// ignore_for_file: use_build_context_synchronously
2023-05-01 02:50:42 +02:00
import 'dart:io';
2022-10-12 03:58:17 +02:00
import 'package:flutter/material.dart';
2023-05-01 03:48:23 +02:00
import 'package:flutter_split_view/flutter_split_view.dart';
2022-10-12 03:58:17 +02:00
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
2022-10-25 21:12:00 +02:00
import 'package:adguard_home_manager/widgets/section_label.dart';
import 'package:adguard_home_manager/widgets/confirm_action_modal.dart';
2022-10-24 01:30:56 +02:00
import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_leases.dart';
2022-10-12 03:58:17 +02:00
import 'package:adguard_home_manager/screens/settings/dhcp/select_interface_modal.dart';
2022-10-14 01:53:02 +02:00
import 'package:adguard_home_manager/functions/snackbar.dart';
2023-05-24 18:22:13 +02:00
import 'package:adguard_home_manager/constants/enums.dart';
import 'package:adguard_home_manager/providers/dhcp_provider.dart';
2022-10-14 01:53:02 +02:00
import 'package:adguard_home_manager/classes/process_modal.dart';
2022-10-12 03:58:17 +02:00
import 'package:adguard_home_manager/services/http_requests.dart';
import 'package:adguard_home_manager/models/dhcp.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart';
2023-05-24 18:22:13 +02:00
class DhcpScreen extends StatefulWidget {
const DhcpScreen({Key? key}) : super(key: key);
2022-10-12 03:58:17 +02:00
@override
2023-05-24 18:22:13 +02:00
State<DhcpScreen> createState() => _DhcpScreenState();
2022-10-12 03:58:17 +02:00
}
2023-05-24 18:22:13 +02:00
class _DhcpScreenState extends State<DhcpScreen> {
2022-10-12 03:58:17 +02:00
NetworkInterface? selectedInterface;
2022-10-14 01:53:02 +02:00
bool enabled = false;
2022-10-12 03:58:17 +02:00
final TextEditingController ipv4StartRangeController = TextEditingController();
String? ipv4StartRangeError;
final TextEditingController ipv4EndRangeController = TextEditingController();
String? ipv4EndRangeError;
final TextEditingController ipv4SubnetMaskController = TextEditingController();
String? ipv4SubnetMaskError;
final TextEditingController ipv4GatewayController = TextEditingController();
String? ipv4GatewayError;
final TextEditingController ipv4LeaseTimeController = TextEditingController();
String? ipv4LeaseTimeError;
final TextEditingController ipv6StartRangeController = TextEditingController();
String? ipv6StartRangeError;
final TextEditingController ipv6EndRangeController = TextEditingController();
String? ipv6EndRangeError;
final TextEditingController ipv6LeaseTimeController = TextEditingController();
String? ipv6LeaseTimeError;
2022-10-14 01:53:02 +02:00
bool dataValid = false;
2022-10-12 03:58:17 +02:00
void loadDhcpStatus() async {
2023-05-24 18:22:13 +02:00
final serversProvider = Provider.of<ServersProvider>(context, listen: false);
final dhcpProvider = Provider.of<DhcpProvider>(context, listen: false);
dhcpProvider.setDhcpLoadStatus(LoadStatus.loading, false);
2023-05-24 18:22:13 +02:00
final result = await getDhcpData(server: serversProvider.selectedServer!);
2022-10-12 03:58:17 +02:00
if (mounted) {
if (result['result'] == 'success') {
2023-05-24 18:22:13 +02:00
dhcpProvider.setDhcpData(result['data']);
dhcpProvider.setDhcpLoadStatus(LoadStatus.loaded, true);
2022-10-12 03:58:17 +02:00
setState(() {
2022-10-14 01:53:02 +02:00
if (result['data'].dhcpStatus.interfaceName != '') {
2023-05-24 18:22:13 +02:00
selectedInterface = result['data'].networkInterfaces.firstWhere((iface) => iface.name == result['data'].dhcpStatus.interfaceName);
2022-10-14 01:53:02 +02:00
enabled = result['data'].dhcpStatus.enabled;
ipv4StartRangeController.text = result['data'].dhcpStatus.v4.rangeStart;
ipv4StartRangeController.text = result['data'].dhcpStatus.v4.rangeStart;
ipv4EndRangeController.text = result['data'].dhcpStatus.v4.rangeEnd;
ipv4SubnetMaskController.text = result['data'].dhcpStatus.v4.subnetMask;
ipv4GatewayController.text = result['data'].dhcpStatus.v4.gatewayIp;
ipv4LeaseTimeController.text = result['data'].dhcpStatus.v4.leaseDuration.toString();
}
2022-10-12 03:58:17 +02:00
});
}
else {
2023-05-24 18:22:13 +02:00
dhcpProvider.setDhcpLoadStatus(LoadStatus.error, true);
2022-10-12 03:58:17 +02:00
}
}
2022-10-14 01:53:02 +02:00
checkDataValid();
2022-10-12 03:58:17 +02:00
}
void validateIpV4(String value, String errorVar, String errorMessage) {
void setValue(String? error) {
switch (errorVar) {
case 'ipv4StartRangeError':
setState(() => ipv4StartRangeError = error);
break;
case 'ipv4EndRangeError':
setState(() => ipv4EndRangeError = error);
break;
case 'ipv4SubnetMaskError':
setState(() => ipv4SubnetMaskError = error);
break;
case 'ipv4GatewayError':
setState(() => ipv4GatewayError = error);
break;
}
}
final regex = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$');
if (regex.hasMatch(value)) {
setValue(null);
}
else {
setValue(errorMessage);
}
2022-10-14 01:53:02 +02:00
checkDataValid();
2022-10-12 03:58:17 +02:00
}
void validateIpV6(String value, String errorVar, String errorMessage) {
void setValue(String? error) {
switch (errorVar) {
case 'ipv6StartRangeError':
setState(() => ipv4StartRangeError = error);
break;
case 'ipv6EndRangeError':
setState(() => ipv4EndRangeError = error);
break;
case 'ipv6GatewayError':
setState(() => ipv4GatewayError = error);
break;
}
}
final regex = RegExp(r'^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$');
if (regex.hasMatch(value)) {
setValue(null);
}
else {
setValue(errorMessage);
}
2022-10-14 01:53:02 +02:00
checkDataValid();
}
bool checkDataValid() {
if (
ipv4StartRangeController.text != '' &&
ipv4StartRangeError == null &&
ipv4EndRangeController.text != '' &&
ipv4EndRangeError == null &&
ipv4SubnetMaskController.text != '' &&
ipv4SubnetMaskError == null &&
ipv4GatewayController.text != '' &&
ipv4GatewayError == null
) {
return true;
}
else {
return false;
}
}
void clearAll() {
setState(() {
selectedInterface = null;
enabled = false;
ipv4StartRangeController.text = '';
ipv4StartRangeError = null;
ipv4StartRangeController.text = '';
ipv4EndRangeError = null;
ipv4EndRangeController.text = '';
ipv4EndRangeError = null;
ipv4SubnetMaskController.text = '';
ipv4SubnetMaskError = null;
ipv4GatewayController.text = '';
ipv4GatewayError = null;
ipv4LeaseTimeController.text = '';
ipv4LeaseTimeError = null;
ipv6StartRangeController.text = '';
ipv6StartRangeError = null;
ipv6EndRangeController.text = '';
ipv6EndRangeError = null;
ipv6LeaseTimeController.text = '';
ipv6LeaseTimeError = null;
});
2022-10-12 03:58:17 +02:00
}
@override
void initState() {
2023-04-30 22:54:39 +02:00
if (mounted) loadDhcpStatus();
2022-10-12 03:58:17 +02:00
super.initState();
}
@override
Widget build(BuildContext context) {
2022-10-14 01:53:02 +02:00
final serversProvider = Provider.of<ServersProvider>(context);
2023-05-24 18:22:13 +02:00
final dhcpProvider = Provider.of<DhcpProvider>(context);
2022-10-14 01:53:02 +02:00
final appConfigProvider = Provider.of<AppConfigProvider>(context);
2023-05-01 02:50:42 +02:00
final width = MediaQuery.of(context).size.width;
2022-10-14 01:53:02 +02:00
void saveSettings() async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.savingSettings);
final result = await saveDhcpConfig(server: serversProvider.selectedServer!, data: {
"enabled": enabled,
"interface_name": selectedInterface!.name,
2022-10-15 00:20:31 +02:00
if (selectedInterface!.ipv4Addresses.isNotEmpty) "v4": {
2022-10-14 01:53:02 +02:00
"gateway_ip": ipv4GatewayController.text,
"subnet_mask": ipv4SubnetMaskController.text,
"range_start": ipv4StartRangeController.text,
"range_end": ipv4EndRangeController.text,
"lease_duration": ipv4LeaseTimeController.text != '' ? int.parse(ipv4LeaseTimeController.text) : null
},
if (selectedInterface!.ipv6Addresses.isNotEmpty) "v6": {
"range_start": ipv6StartRangeController.text,
"range_end": ipv6EndRangeController.text,
"lease_duration": ipv6LeaseTimeController.text != '' ? int.parse(ipv6LeaseTimeController.text) : null
}
});
processModal.close();
if (result['result'] == 'success') {
showSnacbkar(
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.settingsSaved,
color: Colors.green
);
}
else {
appConfigProvider.addLog(result['log']);
showSnacbkar(
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.settingsNotSaved,
color: Colors.red
);
}
}
void restoreConfig() async {
Future.delayed(const Duration(seconds: 0), () async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.restoringConfig);
final result = await resetDhcpConfig(server: serversProvider.selectedServer!);
processModal.close();
if (result['result'] == 'success') {
clearAll();
showSnacbkar(
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.configRestored,
color: Colors.green
);
}
else {
appConfigProvider.addLog(result['log']);
showSnacbkar(
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.configNotRestored,
color: Colors.red
);
}
});
}
2022-10-12 03:58:17 +02:00
void restoreLeases() async {
Future.delayed(const Duration(seconds: 0), () async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.restoringLeases);
final result = await restoreAllLeases(server: serversProvider.selectedServer!);
processModal.close();
if (result['result'] == 'success') {
2023-05-24 18:22:13 +02:00
DhcpModel data = dhcpProvider.dhcp!;
data.dhcpStatus.staticLeases = [];
data.dhcpStatus.leases = [];
2023-05-24 18:22:13 +02:00
dhcpProvider.setDhcpData(data);
showSnacbkar(
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.leasesRestored,
color: Colors.green
);
}
else {
appConfigProvider.addLog(result['log']);
showSnacbkar(
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.leasesNotRestored,
color: Colors.red
);
}
});
}
void askRestoreLeases() {
Future.delayed(const Duration(seconds: 0), () => {
showDialog(
context: context,
builder: (context) => ConfirmActionModal(
icon: Icons.settings_backup_restore_rounded,
title: AppLocalizations.of(context)!.restoreLeases,
message: AppLocalizations.of(context)!.restoreLeasesMessage,
onConfirm: () => restoreLeases()
)
)
});
}
void askRestoreConfig() {
Future.delayed(const Duration(seconds: 0), () => {
showDialog(
context: context,
builder: (context) => ConfirmActionModal(
icon: Icons.restore,
title: AppLocalizations.of(context)!.restoreConfiguration,
message: AppLocalizations.of(context)!.restoreConfigurationMessage,
onConfirm: () => restoreConfig()
)
)
});
}
2022-10-12 03:58:17 +02:00
void selectInterface() {
ScaffoldMessenger.of(context).clearSnackBars();
2022-10-12 03:58:17 +02:00
Future.delayed(const Duration(seconds: 0), () {
2023-05-01 02:50:42 +02:00
if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) {
showDialog(
context: context,
builder: (context) => SelectInterfaceModal(
2023-05-24 18:22:13 +02:00
interfaces: dhcpProvider.dhcp!.networkInterfaces,
2023-05-01 02:50:42 +02:00
onSelect: (interface) => setState(() {
clearAll();
selectedInterface = interface;
}),
dialog: true,
)
);
}
else {
showModalBottomSheet(
context: context,
builder: (context) => SelectInterfaceModal(
2023-05-24 18:22:13 +02:00
interfaces: dhcpProvider.dhcp!.networkInterfaces,
2023-05-01 02:50:42 +02:00
onSelect: (i) => setState(() {
clearAll();
selectedInterface = i;
}),
dialog: false,
),
2023-05-01 04:49:40 +02:00
isScrollControlled: true
2023-05-01 02:50:42 +02:00
);
}
2022-10-12 03:58:17 +02:00
});
}
Widget generateBody() {
2023-05-24 18:22:13 +02:00
switch (dhcpProvider.loadStatus) {
case LoadStatus.loading:
2022-10-12 03:58:17 +02:00
return SizedBox(
width: double.maxFinite,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const CircularProgressIndicator(),
const SizedBox(height: 30),
Text(
AppLocalizations.of(context)!.loadingDhcp,
2023-01-29 21:52:37 +01:00
style: TextStyle(
2022-10-12 03:58:17 +02:00
fontSize: 22,
2023-01-29 21:52:37 +01:00
color: Theme.of(context).colorScheme.onSurfaceVariant,
2022-10-12 03:58:17 +02:00
),
)
],
),
);
2023-05-24 18:22:13 +02:00
case LoadStatus.loaded:
2022-10-12 03:58:17 +02:00
if (selectedInterface != null) {
2023-05-01 02:50:42 +02:00
return SingleChildScrollView(
child: Wrap(
children: [
Padding(
padding: const EdgeInsets.only(
top: 10,
left: 16,
right: 16
),
child: Material(
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
2022-10-12 03:58:17 +02:00
borderRadius: BorderRadius.circular(28),
2023-05-01 02:50:42 +02:00
child: InkWell(
onTap: selectedInterface != null
? () => setState(() => enabled = !enabled)
: null,
borderRadius: BorderRadius.circular(28),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 12
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
2022-10-12 03:58:17 +02:00
Text(
2023-05-01 02:50:42 +02:00
AppLocalizations.of(context)!.enableDhcpServer,
style: TextStyle(
2023-05-01 02:50:42 +02:00
fontSize: 16,
color: Theme.of(context).colorScheme.onSurface
2022-10-12 03:58:17 +02:00
),
2023-05-01 02:50:42 +02:00
),
if (selectedInterface != null) ...[
Text(
selectedInterface!.name,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).listTileTheme.textColor
),
)
]
],
),
Switch(
value: enabled,
onChanged: selectedInterface != null
? (value) => setState(() => enabled = value)
: null,
),
],
),
2022-10-12 03:58:17 +02:00
),
),
),
),
2023-05-01 02:50:42 +02:00
if (selectedInterface!.ipv4Addresses.isNotEmpty) ...[
SectionLabel(
label: AppLocalizations.of(context)!.ipv4settings,
padding: const EdgeInsets.only(
top: 24, left: 16, right: 16, bottom: 8
)
),
FractionallySizedBox(
widthFactor: width > 900 ? 0.5 : 1,
child: Padding(
padding: width > 900
? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8)
: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: TextFormField(
controller: ipv4StartRangeController,
onChanged: (value) => validateIpV4(value, 'ipv4StartRangeError', AppLocalizations.of(context)!.ipNotValid),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.skip_previous_rounded),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10)
)
),
errorText: ipv4StartRangeError,
labelText: AppLocalizations.of(context)!.startOfRange,
),
keyboardType: TextInputType.number,
2022-10-15 00:20:31 +02:00
),
2022-10-12 03:58:17 +02:00
),
),
2023-05-01 02:50:42 +02:00
FractionallySizedBox(
widthFactor: width > 900 ? 0.5 : 1,
child: Padding(
padding: width > 900
? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16)
: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: TextFormField(
controller: ipv4EndRangeController,
onChanged: (value) => validateIpV4(value, 'ipv4EndRangeError', AppLocalizations.of(context)!.ipNotValid),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.skip_next_rounded),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10)
)
),
errorText: ipv4EndRangeError,
labelText: AppLocalizations.of(context)!.endOfRange,
),
keyboardType: TextInputType.number,
2022-10-15 00:20:31 +02:00
),
2022-10-12 03:58:17 +02:00
),
),
2023-05-01 02:50:42 +02:00
FractionallySizedBox(
widthFactor: width > 900 ? 0.5 : 1,
child: Padding(
padding: width > 900
? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8)
: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: TextFormField(
controller: ipv4SubnetMaskController,
onChanged: (value) => validateIpV4(value, 'ipv4SubnetMaskError', AppLocalizations.of(context)!.subnetMaskNotValid),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.hub_rounded),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10)
)
),
errorText: ipv4SubnetMaskError,
labelText: AppLocalizations.of(context)!.subnetMask,
),
keyboardType: TextInputType.number,
2022-10-15 00:20:31 +02:00
),
2022-10-12 03:58:17 +02:00
),
),
2023-05-01 02:50:42 +02:00
FractionallySizedBox(
widthFactor: width > 900 ? 0.5 : 1,
child: Padding(
padding: width > 900
? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16)
: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: TextFormField(
controller: ipv4GatewayController,
onChanged: (value) => validateIpV4(value, 'ipv4GatewayError', AppLocalizations.of(context)!.gatewayNotValid),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.router_rounded),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10)
)
),
errorText: ipv4GatewayError,
labelText: AppLocalizations.of(context)!.gateway,
),
keyboardType: TextInputType.number,
2022-10-15 00:20:31 +02:00
),
2022-10-12 03:58:17 +02:00
),
),
2023-05-01 02:50:42 +02:00
FractionallySizedBox(
widthFactor: 1,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: TextFormField(
controller: ipv4LeaseTimeController,
onChanged: (value) {
if (int.tryParse(value).runtimeType == int) {
setState(() => ipv4LeaseTimeError = null);
}
else {
setState(() => ipv4LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid);
}
},
decoration: InputDecoration(
prefixIcon: const Icon(Icons.timer),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10)
)
),
errorText: ipv4LeaseTimeError,
labelText: AppLocalizations.of(context)!.leaseTime,
),
keyboardType: TextInputType.number,
2022-10-15 00:20:31 +02:00
),
2022-10-12 03:58:17 +02:00
),
),
2023-05-01 02:50:42 +02:00
],
if (selectedInterface!.ipv6Addresses.isNotEmpty) ...[
SectionLabel(
label: AppLocalizations.of(context)!.ipv6settings,
padding: const EdgeInsets.all(16)
),
FractionallySizedBox(
widthFactor: width > 900 ? 0.5 : 1,
child: Padding(
padding: width > 900
? const EdgeInsets.only(top: 8, bottom: 12, left: 16, right: 8)
: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: TextFormField(
controller: ipv6StartRangeController,
onChanged: (value) => validateIpV4(value, 'ipv6StartRangeError', AppLocalizations.of(context)!.ipNotValid),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.skip_next_rounded),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10)
)
),
errorText: ipv6StartRangeError,
labelText: AppLocalizations.of(context)!.startOfRange,
),
keyboardType: TextInputType.number,
2022-10-12 03:58:17 +02:00
),
),
),
2023-05-01 02:50:42 +02:00
FractionallySizedBox(
widthFactor: width > 900 ? 0.5 : 1,
child: Padding(
padding: width > 900
? const EdgeInsets.only(top: 8, bottom: 12, left: 8, right: 16)
: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: TextFormField(
controller: ipv6EndRangeController,
onChanged: (value) => validateIpV4(value, 'ipv6EndRangeError', AppLocalizations.of(context)!.ipNotValid),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.skip_previous_rounded),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10)
)
),
errorText: ipv6EndRangeError,
labelText: AppLocalizations.of(context)!.endOfRange,
),
keyboardType: TextInputType.number,
),
),
),
FractionallySizedBox(
widthFactor: 1,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: TextFormField(
controller: ipv6LeaseTimeController,
onChanged: (value) {
if (int.tryParse(value).runtimeType == int) {
setState(() => ipv6LeaseTimeError = null);
}
else {
setState(() => ipv6LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid);
}
},
decoration: InputDecoration(
prefixIcon: const Icon(Icons.timer),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10)
)
),
errorText: ipv6LeaseTimeError,
labelText: AppLocalizations.of(context)!.leaseTime,
),
keyboardType: TextInputType.number,
2022-10-12 03:58:17 +02:00
),
),
),
2023-05-01 02:50:42 +02:00
],
const SizedBox(height: 20),
SectionLabel(
label: AppLocalizations.of(context)!.dhcpLeases,
padding: const EdgeInsets.all(16),
2022-10-12 03:58:17 +02:00
),
2023-05-01 02:50:42 +02:00
if (width <= 900) Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => DhcpLeases(
2023-05-24 18:22:13 +02:00
items: dhcpProvider.dhcp!.dhcpStatus.leases,
2023-05-01 02:50:42 +02:00
staticLeases: false,
2022-10-12 03:58:17 +02:00
)
2023-05-01 02:50:42 +02:00
));
},
child: Container(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
AppLocalizations.of(context)!.dhcpLeases,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurface,
),
),
Icon(
Icons.arrow_forward_rounded,
color: Theme.of(context).colorScheme.onSurface,
)
],
2022-10-12 03:58:17 +02:00
),
),
),
),
2023-05-01 02:50:42 +02:00
if (width <= 900) Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => DhcpLeases(
2023-05-24 18:22:13 +02:00
items: dhcpProvider.dhcp!.dhcpStatus.staticLeases,
2023-05-01 02:50:42 +02:00
staticLeases: true,
2022-11-05 01:09:09 +01:00
)
2023-05-01 02:50:42 +02:00
));
},
child: Container(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
AppLocalizations.of(context)!.dhcpStatic,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurface,
),
),
Icon(
Icons.arrow_forward_rounded,
color: Theme.of(context).colorScheme.onSurface,
)
],
),
2022-10-24 01:30:56 +02:00
),
2022-10-15 14:01:11 +02:00
),
),
2023-05-01 02:50:42 +02:00
if (width > 900) Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
2023-05-01 03:48:23 +02:00
onPressed: () {
if (!(Platform.isAndroid || Platform.isIOS)) {
SplitView.of(context).push(
DhcpLeases(
2023-05-24 18:22:13 +02:00
items: dhcpProvider.dhcp!.dhcpStatus.leases,
2023-05-01 03:48:23 +02:00
staticLeases: false,
)
);
}
else {
Navigator.push(context, MaterialPageRoute(
builder: (context) => DhcpLeases(
2023-05-24 18:22:13 +02:00
items: dhcpProvider.dhcp!.dhcpStatus.leases,
2023-05-01 03:48:23 +02:00
staticLeases: false,
)
));
}
},
2023-05-01 02:50:42 +02:00
child: Row(
children: [
Text(AppLocalizations.of(context)!.dhcpLeases),
const SizedBox(width: 8),
const Icon(Icons.arrow_forward_rounded)
],
)
2023-05-01 02:50:42 +02:00
),
ElevatedButton(
2023-05-01 03:48:23 +02:00
onPressed: () {
if (!(Platform.isAndroid || Platform.isIOS)) {
SplitView.of(context).push(
DhcpLeases(
2023-05-24 18:22:13 +02:00
items: dhcpProvider.dhcp!.dhcpStatus.staticLeases,
2023-05-01 03:48:23 +02:00
staticLeases: true,
)
);
}
else {
Navigator.push(context, MaterialPageRoute(
builder: (context) => DhcpLeases(
2023-05-24 18:22:13 +02:00
items: dhcpProvider.dhcp!.dhcpStatus.staticLeases,
2023-05-01 03:48:23 +02:00
staticLeases: true,
)
));
}
},
2023-05-01 02:50:42 +02:00
child: Row(
children: [
Text(AppLocalizations.of(context)!.dhcpStatic),
const SizedBox(width: 8),
const Icon(Icons.arrow_forward_rounded)
],
)
),
2023-05-01 02:50:42 +02:00
],
),
2023-05-01 02:50:42 +02:00
const SizedBox(height: 10)
],
),
2022-10-12 03:58:17 +02:00
);
}
else {
2023-05-01 02:50:42 +02:00
return Row(
2022-10-12 03:58:17 +02:00
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Text(
AppLocalizations.of(context)!.neededSelectInterface,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22,
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5)
),
2023-05-01 02:50:42 +02:00
),
),
const SizedBox(height: 30),
ElevatedButton(
onPressed: selectInterface,
child: Text(AppLocalizations.of(context)!.selectInterface)
),
],
),
),
2022-10-12 03:58:17 +02:00
],
);
}
2023-05-24 18:22:13 +02:00
case LoadStatus.error:
2022-10-12 03:58:17 +02:00
return SizedBox(
width: double.maxFinite,
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)!.dhcpSettingsNotLoaded,
2023-01-29 21:52:37 +01:00
style: TextStyle(
2022-10-12 03:58:17 +02:00
fontSize: 22,
2023-01-29 21:52:37 +01:00
color: Theme.of(context).colorScheme.onSurfaceVariant,
2022-10-12 03:58:17 +02:00
),
)
],
),
);
default:
return const SizedBox();
}
}
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.dhcpSettings),
2023-03-16 23:29:18 +01:00
centerTitle: false,
2022-10-12 03:58:17 +02:00
actions: selectedInterface != null ? [
IconButton(
2022-10-14 01:53:02 +02:00
onPressed: checkDataValid() == true
? () => saveSettings()
: null,
2022-10-12 03:58:17 +02:00
icon: const Icon(Icons.save_rounded),
tooltip: AppLocalizations.of(context)!.save,
),
PopupMenuButton(
itemBuilder: (context) => [
PopupMenuItem(
onTap: selectInterface,
child: Row(
children: [
const Icon(Icons.swap_horiz_rounded),
const SizedBox(width: 10),
Text(AppLocalizations.of(context)!.changeInterface)
],
)
),
PopupMenuItem(
onTap: askRestoreLeases,
child: Row(
children: [
const Icon(Icons.settings_backup_restore_rounded),
const SizedBox(width: 10),
Text(AppLocalizations.of(context)!.restoreLeases)
],
)
),
2022-10-12 03:58:17 +02:00
PopupMenuItem(
onTap: askRestoreConfig,
2022-10-12 03:58:17 +02:00
child: Row(
children: [
const Icon(Icons.restore),
const SizedBox(width: 10),
Text(AppLocalizations.of(context)!.restoreConfiguration)
],
)
),
2022-10-12 03:58:17 +02:00
]
),
const SizedBox(width: 10)
] : null,
),
body: generateBody(),
);
}
}