diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 987d406..0012259 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -1,6 +1,9 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -15,6 +18,8 @@ class AdvancedSettings extends StatelessWidget { @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; Future updateSslCheck(bool newStatus) async { final result = await appConfigProvider.setOverrideSslCheck(newStatus); @@ -64,11 +69,16 @@ class AdvancedSettings extends StatelessWidget { title: AppLocalizations.of(context)!.logs, subtitle: AppLocalizations.of(context)!.checkAppLogs, onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const AppLogs() + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push(const AppLogs()) + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const AppLogs() + ) ) - ) + } }, padding: const EdgeInsets.only( top: 10, diff --git a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart index 53bc3b2..6ac5ee6 100644 --- a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart @@ -7,10 +7,12 @@ import 'package:adguard_home_manager/models/rewrite_rules.dart'; class AddDnsRewriteModal extends StatefulWidget { final void Function(RewriteRulesData) onConfirm; + final bool dialog; const AddDnsRewriteModal({ Key? key, - required this.onConfirm + required this.onConfirm, + required this.dialog }) : super(key: key); @override @@ -50,118 +52,143 @@ class _AddDnsRewriteModalState extends State { @override Widget build(BuildContext context) { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - height: Platform.isIOS ? 416 : 400, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.add, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.addDnsRewrite, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, bottom: 12 + ), + child: TextFormField( + controller: domainController, + onChanged: validateDomain, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: domainError, + labelText: AppLocalizations.of(context)!.domain, + ), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, top: 12 + ), + child: TextFormField( + controller: answerController, + onChanged: (_) => checkValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.system_update_alt_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.answer, + ), + ), + ), + ], + ), ), - color: Theme.of(context).dialogBackgroundColor, - ), - child: Column( - children: [ - Expanded( - child: ListView( - physics: (Platform.isIOS ? 426 : 410) < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.add, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.addDnsRewrite, - textAlign: TextAlign.center, + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel), + ), + const SizedBox(width: 20), + TextButton( + onPressed: validData == true + ? () { + Navigator.pop(context); + widget.onConfirm( + RewriteRulesData( + domain: domainController.text, + answer: answerController.text + ) + ); + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface + color: validData == true + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) ), ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: domainController, - onChanged: validateDomain, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: domainError, - labelText: AppLocalizations.of(context)!.domain, - ), - ), - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: answerController, - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.system_update_alt_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.answer, - ), - ), - ), - ], - ), + ), + ], ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel), - ), - const SizedBox(width: 20), - TextButton( - onPressed: validData == true - ? () { - Navigator.pop(context); - widget.onConfirm( - RewriteRulesData( - domain: domainController.text, - answer: answerController.text - ) - ); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: validData == true - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - ), - ), - ), - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: content() ), - ), - ); + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor, + ), + child: content() + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 119da4c..d9fe68f 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -70,6 +72,8 @@ class _DnsRewritesWidgetState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void deleteDnsRewrite(RewriteRulesData rule) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deleting); @@ -288,14 +292,26 @@ class _DnsRewritesWidgetState extends State { body: generateBody(), floatingActionButton: FloatingActionButton( onPressed: () => { - showModalBottomSheet( - context: context, - builder: (context) => AddDnsRewriteModal( - onConfirm: addDnsRewrite, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ) + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => AddDnsRewriteModal( + onConfirm: addDnsRewrite, + dialog: true, + ), + ) + } + else { + showModalBottomSheet( + context: context, + builder: (context) => AddDnsRewriteModal( + onConfirm: addDnsRewrite, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ) + } }, child: const Icon(Icons.add), ), diff --git a/lib/screens/settings/encryption/custom_text_field.dart b/lib/screens/settings/encryption/custom_text_field.dart index c149873..6a1cac8 100644 --- a/lib/screens/settings/encryption/custom_text_field.dart +++ b/lib/screens/settings/encryption/custom_text_field.dart @@ -26,8 +26,12 @@ class EncryptionTextField extends StatelessWidget { @override Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: width > 900 + ? const EdgeInsets.symmetric(horizontal: 8) + : const EdgeInsets.symmetric(horizontal: 16), child: ConstrainedBox( constraints: const BoxConstraints( maxHeight: 200 diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index e1f3686..2392287 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -234,6 +234,8 @@ class _EncryptionSettingsWidgetState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void saveData() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); @@ -343,43 +345,59 @@ class _EncryptionSettingsWidgetState extends State { disabled: !enabled, ), const SizedBox(height: 10), - EncryptionTextField( - enabled: enabled, - controller: httpsPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => httpsPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: httpsPortError, - label: AppLocalizations.of(context)!.httpsPort, - keyboardType: TextInputType.number, - ), - const SizedBox(height: 30), - EncryptionTextField( - enabled: enabled, - controller: tlsPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => tlsPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: tlsPortError, - label: AppLocalizations.of(context)!.tlsPort, - keyboardType: TextInputType.number, - ), - const SizedBox(height: 30), - EncryptionTextField( - enabled: enabled, - controller: dnsOverQuicPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => dnsOverQuicPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: dnsOverQuicPortError, - label: AppLocalizations.of(context)!.dnsOverQuicPort, - keyboardType: TextInputType.number, + Wrap( + children: [ + FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: httpsPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => httpsPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: httpsPortError, + label: AppLocalizations.of(context)!.httpsPort, + keyboardType: TextInputType.number, + ), + ), + Padding( + padding: width <= 900 + ? const EdgeInsets.symmetric(vertical: 24) + : const EdgeInsets.all(0), + child: FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: tlsPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => tlsPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: tlsPortError, + label: AppLocalizations.of(context)!.tlsPort, + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: dnsOverQuicPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => dnsOverQuicPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: dnsOverQuicPortError, + label: AppLocalizations.of(context)!.dnsOverQuicPort, + keyboardType: TextInputType.number, + ), + ), + ], ), SectionLabel( label: AppLocalizations.of(context)!.certificates, diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index eef0b7f..8981f86 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -34,7 +34,9 @@ class Settings extends StatelessWidget { @override Widget build(BuildContext context) { - if (!(Platform.isAndroid || Platform.isIOS)) { + final width = MediaQuery.of(context).size.width; + + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { return const SplitView.material( breakpoint: 900, child: SettingsWidget(), diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index 5fa898e..f92292a 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -65,16 +65,18 @@ class UpdateScreen extends StatelessWidget { Widget headerPortrait() { return Column( children: [ + const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - IconButton( + if (Navigator.canPop(context)) IconButton( icon: Icon( Icons.arrow_back, color: Theme.of(context).colorScheme.onSurfaceVariant, ), onPressed: () => Navigator.pop(context), ), + if (!Navigator.canPop(context)) const SizedBox(), IconButton( icon: Icon( Icons.refresh_rounded, @@ -170,120 +172,6 @@ class UpdateScreen extends StatelessWidget { ); } - Widget headerLandscape() { - return Column( - mainAxisSize: MainAxisSize.max, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - IconButton( - icon: Icon( - Icons.arrow_back, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - onPressed: () => Navigator.pop(context), - ), - IconButton( - icon: Icon( - Icons.refresh_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - tooltip: AppLocalizations.of(context)!.checkUpdates, - onPressed: () => serversProvider.checkServerUpdatesAvailable(serversProvider.selectedServer!) - ), - ], - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only( - top: 8, bottom: 16, left: 16, right: 16 - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? Column( - children: const [ - CircularProgressIndicator(), - SizedBox(height: 4) - ], - ) - : Icon( - serversProvider.updateAvailable.data!.updateAvailable != null - ? serversProvider.updateAvailable.data!.updateAvailable == true - ? Icons.system_update_rounded - : Icons.system_security_update_good_rounded - : Icons.system_security_update_warning_rounded, - size: 40, - color: Theme.of(context).colorScheme.primary, - ), - const SizedBox(height: 16), - Text( - serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? AppLocalizations.of(context)!.checkingUpdates - : serversProvider.updateAvailable.data!.updateAvailable != null - ? serversProvider.updateAvailable.data!.updateAvailable == true - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.serverUpdated - : AppLocalizations.of(context)!.unknownStatus, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400 - ), - ), - const SizedBox(height: 40), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (serversProvider.updateAvailable.loadStatus == LoadStatus.loaded) Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true - ? AppLocalizations.of(context)!.newVersion - : AppLocalizations.of(context)!.currentVersion, - style: const TextStyle( - fontSize: 16, - ), - ), - const SizedBox(height: 4), - Text( - serversProvider.updateAvailable.data!.updateAvailable != null - ? serversProvider.updateAvailable.data!.updateAvailable == true - ? serversProvider.updateAvailable.data!.newVersion ?? 'N/A' - : serversProvider.updateAvailable.data!.currentVersion - : "N/A", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w700, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ) - ], - ), - if (serversProvider.updateAvailable.loadStatus != LoadStatus.loaded) const SizedBox(), - FilledButton.icon( - icon: const Icon(Icons.download_rounded), - label: Text(AppLocalizations.of(context)!.updateNow), - onPressed: serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true - ? serversProvider.updateAvailable.data!.canAutoupdate == true - ? () => update() - : () => showAutoUpdateUnavailableModal() - : null - ) - ], - ), - ), - ], - ), - ), - ), - ], - ); - } - final changelog = serversProvider.updateAvailable.loadStatus == LoadStatus.loaded && serversProvider.updateAvailable.data!.changelog != null ? ListView( children: [ @@ -313,51 +201,20 @@ class UpdateScreen extends StatelessWidget { : null; return Scaffold( - body: MediaQuery.of(context).size.width > 700 - ? Row( - children: [ - Expanded( - flex: 2, - child: Container( - color: Theme.of(context).colorScheme.surfaceVariant, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Container( - height: MediaQuery.of(context).size.height, - padding: EdgeInsets.only( - top: MediaQuery.of(context).viewPadding.top - ), - child: headerLandscape(), - ) - ], - ), - ), - ), - Expanded( - flex: 3, - child: SafeArea( - child: SizedBox( - width: MediaQuery.of(context).size.width*0.6, - child: changelog ?? const SizedBox(), - ), - ), - ) - ], - ) - : Column( - children: [ - Container( - color: Theme.of(context).colorScheme.surfaceVariant, - child: SafeArea( - child: headerPortrait() - ) - ), - changelog != null - ? Expanded(child: changelog) - : const SizedBox(), - ] - ) + body: Column( + children: [ + Container( + color: Theme.of(context).colorScheme.surfaceVariant, + child: SafeArea( + child: headerPortrait() + ) + ), + const SizedBox(height: 16), + changelog != null + ? Expanded(child: changelog) + : const SizedBox(), + ] + ) ); } } \ No newline at end of file