diff --git a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart index d399c6f1..389d10e0 100644 --- a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart +++ b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart @@ -270,7 +270,7 @@ class BrowserBottomAppBar extends HookConsumerWidget { await TorProxyRoute().push(context); }, leadingIcon: const Icon(TorIcons.onionAlt), - child: const Text('Tor'), + child: const Text('Tor™ Proxy'), ), const Divider(), MenuItemButton( diff --git a/app/lib/features/tor/presentation/screens/tor_proxy.dart b/app/lib/features/tor/presentation/screens/tor_proxy.dart index 97d3c26f..c2abab94 100644 --- a/app/lib/features/tor/presentation/screens/tor_proxy.dart +++ b/app/lib/features/tor/presentation/screens/tor_proxy.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_material_design_icons/flutter_material_design_icons.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:weblibre/features/settings/presentation/controllers/save_settings.dart'; import 'package:weblibre/features/tor/domain/services/tor_proxy.dart'; import 'package:weblibre/features/user/data/models/general_settings.dart'; import 'package:weblibre/features/user/domain/repositories/general_settings.dart'; import 'package:weblibre/presentation/hooks/on_initialization.dart'; +import 'package:weblibre/presentation/icons/tor_icons.dart'; class TorProxyScreen extends HookConsumerWidget { const TorProxyScreen(); @@ -25,161 +25,177 @@ class TorProxyScreen extends HookConsumerWidget { }); return Scaffold( - appBar: AppBar(title: const Text('Tor Proxy')), - body: ColoredBox( - color: const Color(0xFF7D4698), - child: Column( - children: [ - Flexible( - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SvgPicture.asset('assets/images/tor_white.svg', width: 200), - const SizedBox(height: 16), - ListTileTheme( - iconColor: Colors.white, - textColor: Colors.white, - child: SwitchListTile.adaptive( - inactiveThumbColor: Colors.white, - activeColor: const Color(0xFF68B030), - trackColor: WidgetStateProperty.resolveWith(( - Set states, - ) { - if (states.isEmpty) { - return const Color(0xFF333A41); - } - return null; // Use the default color. - }), - trackOutlineColor: - WidgetStateProperty.resolveWith(( - Set states, - ) { - if (states.isEmpty) { - return Colors.white; - } - return null; // Use the default color. - }), - thumbIcon: WidgetStateProperty.resolveWith(( - Set states, - ) { - if (states.contains(WidgetState.selected)) { - return const Icon(MdiIcons.axisArrowLock); - } - return null; // Use the default color. - }), - value: torProxyPort.valueOrNull != null, - title: const Text('Tor Proxy'), - secondary: const Icon(MdiIcons.power), - onChanged: torProxyPort.isLoading - ? null - : (value) async { - if (value) { - await ref - .read(torProxyServiceProvider.notifier) - .connect(); - } else { - await ref - .read(torProxyServiceProvider.notifier) - .disconnect(); + appBar: AppBar(title: const Text('Tor™ Proxy')), + body: SafeArea( + child: ColoredBox( + color: const Color(0xFF7D4698), + child: Column( + children: [ + Flexible( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const Icon(TorIcons.onionAlt, size: 84), + const SizedBox(height: 16), + ListTileTheme( + iconColor: Colors.white, + textColor: Colors.white, + child: SwitchListTile.adaptive( + inactiveThumbColor: Colors.white, + activeColor: const Color(0xFF68B030), + trackColor: WidgetStateProperty.resolveWith(( + Set states, + ) { + if (states.isEmpty) { + return const Color(0xFF333A41); + } + return null; // Use the default color. + }), + trackOutlineColor: + WidgetStateProperty.resolveWith(( + Set states, + ) { + if (states.isEmpty) { + return Colors.white; } - }, - ), - ), - ListTileTheme( - iconColor: Colors.white, - textColor: Colors.white, - child: SwitchListTile.adaptive( - inactiveThumbColor: Colors.white, - activeColor: const Color(0xFF68B030), - trackColor: WidgetStateProperty.resolveWith(( - Set states, - ) { - if (states.isEmpty) { - return const Color(0xFF333A41); - } - return null; // Use the default color. - }), - trackOutlineColor: - WidgetStateProperty.resolveWith(( - Set states, - ) { - if (states.isEmpty) { - return Colors.white; - } - return null; // Use the default color. - }), - thumbIcon: WidgetStateProperty.resolveWith(( - Set states, - ) { - if (states.contains(WidgetState.selected)) { - return const Icon(MdiIcons.incognito); - } - return null; // Use the default color. - }), - value: proxyPrivateTabsTor, - title: const Text('Proxy Private Tabs'), - subtitle: const Text( - 'When enabled, all Private Tabs will be tunneled through Tor', + return null; // Use the default color. + }), + thumbIcon: WidgetStateProperty.resolveWith(( + Set states, + ) { + if (states.contains(WidgetState.selected)) { + return const Icon(MdiIcons.axisArrowLock); + } + return null; // Use the default color. + }), + value: torProxyPort.valueOrNull != null, + title: const Text('Tor™ Proxy'), + secondary: const Icon(MdiIcons.power), + onChanged: torProxyPort.isLoading + ? null + : (value) async { + if (value) { + await ref + .read(torProxyServiceProvider.notifier) + .connect(); + } else { + await ref + .read(torProxyServiceProvider.notifier) + .disconnect(); + } + }, ), - secondary: const Icon(MdiIcons.arrowDecision), - onChanged: (value) async { - await ref - .read( - saveGeneralSettingsControllerProvider.notifier, - ) - .save( - (currentSettings) => currentSettings.copyWith - .proxyPrivateTabsTor(value), - ); - }, ), - ), - ], + ListTileTheme( + iconColor: Colors.white, + textColor: Colors.white, + child: SwitchListTile.adaptive( + inactiveThumbColor: Colors.white, + activeColor: const Color(0xFF68B030), + trackColor: WidgetStateProperty.resolveWith(( + Set states, + ) { + if (states.isEmpty) { + return const Color(0xFF333A41); + } + return null; // Use the default color. + }), + trackOutlineColor: + WidgetStateProperty.resolveWith(( + Set states, + ) { + if (states.isEmpty) { + return Colors.white; + } + return null; // Use the default color. + }), + thumbIcon: WidgetStateProperty.resolveWith(( + Set states, + ) { + if (states.contains(WidgetState.selected)) { + return const Icon(MdiIcons.incognito); + } + return null; // Use the default color. + }), + value: proxyPrivateTabsTor, + title: const Text('Proxy Private Tabs'), + subtitle: const Text( + 'When enabled, all Private Tabs will be tunneled through Tor', + ), + secondary: const Icon(MdiIcons.arrowDecision), + onChanged: (value) async { + await ref + .read( + saveGeneralSettingsControllerProvider.notifier, + ) + .save( + (currentSettings) => currentSettings.copyWith + .proxyPrivateTabsTor(value), + ); + }, + ), + ), + ], + ), ), - ), - Flexible( - child: Column( - children: [ - if (torProxyPort.isLoading) - const Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox(height: 8), - LinearProgressIndicator( - backgroundColor: Color(0xFF333A41), - color: Color(0xFF68B030), - ), - SizedBox(height: 8), - Text( - 'Establishing connection...', - style: TextStyle(color: Colors.white), - ), - ], - ), - if (torProxyPort.valueOrNull != null) - Padding( - padding: const EdgeInsets.only(top: 24.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, + Flexible( + child: Column( + children: [ + if (torProxyPort.isLoading) + const Column( + mainAxisSize: MainAxisSize.min, children: [ - const Icon( - MdiIcons.shieldLockOutline, + SizedBox(height: 8), + LinearProgressIndicator( + backgroundColor: Color(0xFF333A41), color: Color(0xFF68B030), - size: 32, ), - const SizedBox(width: 12), + SizedBox(height: 8), Text( - 'Connected to the Tor Network', - style: Theme.of(context).textTheme.titleMedium - ?.copyWith(color: const Color(0xFF68B030)), + 'Establishing connection...', + style: TextStyle(color: Colors.white), ), ], ), - ), - ], + if (torProxyPort.valueOrNull != null) + Padding( + padding: const EdgeInsets.only(top: 24.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + MdiIcons.shieldLockOutline, + color: Color(0xFF68B030), + size: 32, + ), + const SizedBox(width: 12), + Text( + 'Connected to the Tor Network', + style: Theme.of(context).textTheme.titleMedium + ?.copyWith(color: const Color(0xFF68B030)), + ), + ], + ), + ), + ], + ), ), - ), - ], + Padding( + padding: const EdgeInsets.only( + right: 8.0, + left: 8.0, + bottom: 8.0, + ), + child: Text( + 'Tor is a trademark of The Tor Project; all rights reserved. WebLibre is not endorsed or sponsored by, or affiliated with, the Tor Project.', + textAlign: TextAlign.center, + style: Theme.of( + context, + ).textTheme.bodySmall?.copyWith(fontStyle: FontStyle.italic), + ), + ), + ], + ), ), ), ); diff --git a/app/lib/features/tor/presentation/widgets/tor_dialog.dart b/app/lib/features/tor/presentation/widgets/tor_dialog.dart index b6414fe4..dd2c903e 100644 --- a/app/lib/features/tor/presentation/widgets/tor_dialog.dart +++ b/app/lib/features/tor/presentation/widgets/tor_dialog.dart @@ -7,7 +7,7 @@ class TorDialog extends StatelessWidget { Widget build(BuildContext context) { return AlertDialog( icon: const Icon(TorIcons.onionAlt, color: Color(0xFF7D4698)), - title: const Text('Tor Proxy'), + title: const Text('Tor™ Proxy'), content: const Text( 'This container requires a Tor proxy for secure connections, which is not currently running.', ),