diff --git a/assets/svg/connected-button.svg b/assets/svg/connected-button.svg
new file mode 100644
index 000000000..96a9970c0
--- /dev/null
+++ b/assets/svg/connected-button.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/svg/connecting-button.svg b/assets/svg/connecting-button.svg
new file mode 100644
index 000000000..1bc6e953b
--- /dev/null
+++ b/assets/svg/connecting-button.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/svg/disconnected-button.svg b/assets/svg/disconnected-button.svg
new file mode 100644
index 000000000..03a8067d7
--- /dev/null
+++ b/assets/svg/disconnected-button.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/svg/tor-circle.svg b/assets/svg/tor-circle.svg
new file mode 100644
index 000000000..8268a00f6
--- /dev/null
+++ b/assets/svg/tor-circle.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/svg/tor-synced.svg b/assets/svg/tor-synced.svg
new file mode 100644
index 000000000..20cff1f37
--- /dev/null
+++ b/assets/svg/tor-synced.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/svg/tor-syncing.svg b/assets/svg/tor-syncing.svg
new file mode 100644
index 000000000..b51803c70
--- /dev/null
+++ b/assets/svg/tor-syncing.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/svg/tor.svg b/assets/svg/tor.svg
new file mode 100644
index 000000000..a893c0907
--- /dev/null
+++ b/assets/svg/tor.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart
index c3cad7a97..759c7760d 100644
--- a/lib/pages/home_view/home_view.dart
+++ b/lib/pages/home_view/home_view.dart
@@ -17,9 +17,11 @@ import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/buy_view/buy_view.dart';
import 'package:stackwallet/pages/exchange_view/exchange_view.dart';
import 'package:stackwallet/pages/home_view/sub_widgets/home_view_button_bar.dart';
+import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart';
import 'package:stackwallet/pages/notification_views/notifications_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/global_settings_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/hidden_settings.dart';
+import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart';
import 'package:stackwallet/pages/wallets_view/wallets_view.dart';
import 'package:stackwallet/providers/global/notifications_provider.dart';
import 'package:stackwallet/providers/ui/home_view_index_provider.dart';
@@ -55,6 +57,8 @@ class _HomeViewState extends ConsumerState {
bool _exitEnabled = false;
+ late TorSyncStatus _currentSyncStatus;
+
// final _buyDataLoadingService = BuyDataLoadingService();
Future _onWillPop() async {
@@ -113,6 +117,32 @@ class _HomeViewState extends ConsumerState {
);
}
+ Widget _buildTorIcon(TorSyncStatus status) {
+ switch (status) {
+ case TorSyncStatus.unableToSync:
+ return SvgPicture.asset(
+ Assets.svg.tor,
+ color: Theme.of(context).extension()!.textSubtitle3,
+ width: 20,
+ height: 20,
+ );
+ case TorSyncStatus.synced:
+ return SvgPicture.asset(
+ Assets.svg.tor,
+ color: Theme.of(context).extension()!.accentColorGreen,
+ width: 20,
+ height: 20,
+ );
+ case TorSyncStatus.syncing:
+ return SvgPicture.asset(
+ Assets.svg.tor,
+ color: Theme.of(context).extension()!.accentColorYellow,
+ width: 20,
+ height: 20,
+ );
+ }
+ }
+
@override
void initState() {
_pageController = PageController();
@@ -125,6 +155,20 @@ class _HomeViewState extends ConsumerState {
ref.read(notificationsProvider).startCheckingWatchedNotifications();
+ /// todo change to watch tor network
+ // if (ref.read(managerProvider).isRefreshing) {
+ // _currentSyncStatus = WalletSyncStatus.syncing;
+ // _currentNodeStatus = NodeConnectionStatus.connected;
+ // } else {
+ // _currentSyncStatus = WalletSyncStatus.synced;
+ // if (ref.read(managerProvider).isConnected) {
+ // _currentNodeStatus = NodeConnectionStatus.connected;
+ // } else {
+ // _currentNodeStatus = NodeConnectionStatus.disconnected;
+ // _currentSyncStatus = WalletSyncStatus.unableToSync;
+ // }
+ // }
+
super.initState();
}
@@ -200,6 +244,31 @@ class _HomeViewState extends ConsumerState {
],
),
actions: [
+ Padding(
+ padding: const EdgeInsets.only(
+ top: 10,
+ bottom: 10,
+ right: 10,
+ ),
+ child: AspectRatio(
+ aspectRatio: 1,
+ child: AppBarIconButton(
+ semanticsLabel:
+ "Tor Settings Button. Takes To Tor Settings Page.",
+ key: const Key("walletsViewTorButton"),
+ size: 36,
+ shadows: const [],
+ color: Theme.of(context)
+ .extension()!
+ .backgroundAppBar,
+ icon: _buildTorIcon(TorSyncStatus.unableToSync),
+ onPressed: () {
+ Navigator.of(context)
+ .pushNamed(TorSettingsView.routeName);
+ },
+ ),
+ ),
+ ),
Padding(
padding: const EdgeInsets.only(
top: 10,
diff --git a/lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart b/lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart
new file mode 100644
index 000000000..87910b806
--- /dev/null
+++ b/lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart
@@ -0,0 +1,22 @@
+/*
+ * This file is part of Stack Wallet.
+ *
+ * Copyright (c) 2023 Cypher Stack
+ * All Rights Reserved.
+ * The code is distributed under GPLv3 license, see LICENSE file for details.
+ * Generated by Cypher Stack on 2023-05-26
+ *
+ */
+import 'package:stackwallet/utilities/logger.dart';
+
+enum TorSyncStatus { unableToSync, synced, syncing }
+
+class TorSyncStatusChangedEvent {
+ TorSyncStatus newStatus;
+
+ TorSyncStatusChangedEvent(this.newStatus) {
+ Logging.instance.log(
+ "TorSyncStatusChangedEvent fired with arg newStatus = $newStatus",
+ level: LogLevel.Info);
+ }
+}
diff --git a/lib/pages/settings_views/global_settings_view/global_settings_view.dart b/lib/pages/settings_views/global_settings_view/global_settings_view.dart
index 7cadc1a77..29984b928 100644
--- a/lib/pages/settings_views/global_settings_view/global_settings_view.dart
+++ b/lib/pages/settings_views/global_settings_view/global_settings_view.dart
@@ -25,6 +25,7 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/stack_back
import 'package:stackwallet/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/support_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart';
+import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart';
import 'package:stackwallet/pages/settings_views/sub_widgets/settings_list_button.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/themes/stack_colors.dart';
@@ -159,6 +160,18 @@ class GlobalSettingsView extends StatelessWidget {
const SizedBox(
height: 8,
),
+ SettingsListButton(
+ iconAssetName: Assets.svg.tor,
+ iconSize: 18,
+ title: "Tor Settings",
+ onPressed: () {
+ Navigator.of(context)
+ .pushNamed(TorSettingsView.routeName);
+ },
+ ),
+ const SizedBox(
+ height: 8,
+ ),
SettingsListButton(
iconAssetName: Assets.svg.node,
iconSize: 16,
diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart
new file mode 100644
index 000000000..8304eb851
--- /dev/null
+++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart
@@ -0,0 +1,302 @@
+/*
+ * This file is part of Stack Wallet.
+ *
+ * Copyright (c) 2023 Cypher Stack
+ * All Rights Reserved.
+ * The code is distributed under GPLv3 license, see LICENSE file for details.
+ * Generated by Cypher Stack on 2023-05-26
+ *
+ */
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart';
+import 'package:stackwallet/providers/global/prefs_provider.dart';
+import 'package:stackwallet/themes/stack_colors.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/constants.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/background.dart';
+import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+import 'package:stackwallet/widgets/stack_dialog.dart';
+
+class TorSettingsView extends ConsumerStatefulWidget {
+ const TorSettingsView({Key? key}) : super(key: key);
+
+ static const String routeName = "/torSettings";
+
+ @override
+ ConsumerState createState() => _TorSettingsViewState();
+}
+
+class _TorSettingsViewState extends ConsumerState {
+ TorSyncStatus _networkStatus = TorSyncStatus.unableToSync;
+
+ Widget _buildTorIcon(TorSyncStatus status) {
+ switch (status) {
+ case TorSyncStatus.unableToSync:
+ return Stack(
+ alignment: AlignmentDirectional.center,
+ children: [
+ SvgPicture.asset(
+ Assets.svg.tor,
+ color: Theme.of(context).extension()!.textSubtitle3,
+ width: 200,
+ height: 200,
+ ),
+ Text(
+ "CONNECT",
+ style: STextStyles.smallMed14(context).copyWith(
+ color: Theme.of(context).extension()!.popupBG),
+ )
+ ],
+ );
+ case TorSyncStatus.synced:
+ return Stack(
+ alignment: AlignmentDirectional.center,
+ children: [
+ SvgPicture.asset(
+ Assets.svg.tor,
+ color:
+ Theme.of(context).extension()!.accentColorGreen,
+ width: 200,
+ height: 200,
+ ),
+ Text(
+ "CONNECTED",
+ style: STextStyles.smallMed14(context).copyWith(
+ color: Theme.of(context).extension()!.popupBG),
+ )
+ ],
+ );
+ case TorSyncStatus.syncing:
+ return Stack(
+ alignment: AlignmentDirectional.center,
+ children: [
+ SvgPicture.asset(
+ Assets.svg.tor,
+ color:
+ Theme.of(context).extension()!.accentColorYellow,
+ width: 200,
+ height: 200,
+ ),
+ Text(
+ "CONNECTING",
+ style: STextStyles.smallMed14(context).copyWith(
+ color: Theme.of(context).extension()!.popupBG),
+ )
+ ],
+ );
+ }
+ }
+
+ Widget _buildTorStatus(TorSyncStatus status) {
+ switch (status) {
+ case TorSyncStatus.unableToSync:
+ return Text(
+ "Disconnected",
+ style: STextStyles.itemSubtitle(context).copyWith(
+ color: Theme.of(context).extension()!.textSubtitle3),
+ );
+ case TorSyncStatus.synced:
+ return Text(
+ "Connected",
+ style: STextStyles.itemSubtitle(context).copyWith(
+ color:
+ Theme.of(context).extension()!.accentColorGreen),
+ );
+ case TorSyncStatus.syncing:
+ return Text(
+ "Connecting",
+ style: STextStyles.itemSubtitle(context).copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .accentColorYellow),
+ );
+ }
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final isDesktop = Util.isDesktop;
+
+ return Background(
+ child: Scaffold(
+ backgroundColor: Colors.transparent,
+ appBar: AppBar(
+ automaticallyImplyLeading: false,
+ backgroundColor:
+ Theme.of(context).extension()!.backgroundAppBar,
+ leading: AppBarBackButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ ),
+ title: Text(
+ "Tor settings",
+ style: STextStyles.navBarTitle(context),
+ ),
+ actions: [
+ AspectRatio(
+ aspectRatio: 1,
+ child: AppBarIconButton(
+ icon: SvgPicture.asset(
+ Assets.svg.circleQuestion,
+ ),
+ onPressed: () {
+ showDialog(
+ context: context,
+ useSafeArea: false,
+ barrierDismissible: true,
+ builder: (context) {
+ return const StackDialog(
+ title: "What is Tor?",
+ message:
+ "Short for \"The Onion Router\", is an open-source software that enables internet communication"
+ " to remain anonymous by routing internet traffic through a series of layered nodes,"
+ " to obscure the origin and destination of data.",
+ rightButton: SecondaryButton(
+ label: "Close",
+ ),
+ );
+ },
+ );
+ },
+ ),
+ ),
+ ],
+ ),
+ body: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(10.0),
+ child: _buildTorIcon(_networkStatus),
+ ),
+ ],
+ ),
+ SizedBox(
+ height: 30,
+ ),
+ RoundedWhiteContainer(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 8.0),
+ child: Row(
+ children: [
+ Text(
+ "Tor status",
+ style: STextStyles.titleBold12(context),
+ ),
+ const Spacer(),
+ _buildTorStatus(_networkStatus),
+ ],
+ ),
+ ),
+ ),
+ SizedBox(
+ height: 8,
+ ),
+ RoundedWhiteContainer(
+ child: Consumer(
+ builder: (_, ref, __) {
+ return RawMaterialButton(
+ // splashColor: Theme.of(context).extension()!.highlight,
+ materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius,
+ ),
+ ),
+ onPressed: null,
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 8),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Text(
+ "Tor killswitch",
+ style: STextStyles.titleBold12(context),
+ ),
+ const SizedBox(width: 8),
+ GestureDetector(
+ onTap: () {
+ showDialog(
+ context: context,
+ useSafeArea: false,
+ barrierDismissible: true,
+ builder: (context) {
+ return const StackDialog(
+ title: "What is Tor killswitch?",
+ message:
+ "A security feature that protects your information from accidental exposure by"
+ " disconnecting your device from the Tor network if your virtual private network (VPN)"
+ " connection is disrupted or compromised.",
+ rightButton: SecondaryButton(
+ label: "Close",
+ ),
+ );
+ },
+ );
+ },
+ child: SvgPicture.asset(
+ Assets.svg.circleInfo,
+ height: 16,
+ width: 16,
+ color: Theme.of(context)
+ .extension()!
+ .infoItemLabel,
+ ),
+ ),
+ ],
+ ),
+ SizedBox(
+ height: 20,
+ width: 40,
+ child: DraggableSwitchButton(
+ isOn: ref.watch(
+ prefsChangeNotifierProvider
+ .select((value) => value.torKillswitch),
+ ),
+ onValueChanged: (newValue) {
+ ref
+ .read(prefsChangeNotifierProvider)
+ .torKillswitch = newValue;
+ },
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ },
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart
index 1a0a1f09f..b21a1d724 100644
--- a/lib/pages_desktop_specific/desktop_menu.dart
+++ b/lib/pages_desktop_specific/desktop_menu.dart
@@ -14,7 +14,9 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
+import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart';
+import 'package:stackwallet/pages_desktop_specific/settings/settings_menu.dart';
import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
@@ -57,6 +59,70 @@ class _DesktopMenuState extends ConsumerState {
// final _buyDataLoadingService = BuyDataLoadingService();
+ Widget _buildTorIcon(TorSyncStatus status) {
+ switch (status) {
+ case TorSyncStatus.unableToSync:
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ SvgPicture.asset(
+ Assets.svg.tor,
+ color: Theme.of(context).extension()!.textSubtitle3,
+ width: 20,
+ height: 20,
+ ),
+ Text(
+ "\tDisconnected",
+ style: STextStyles.smallMed12(context).copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .textSubtitle3),
+ )
+ ],
+ );
+ case TorSyncStatus.synced:
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ SvgPicture.asset(
+ Assets.svg.tor,
+ color:
+ Theme.of(context).extension()!.accentColorGreen,
+ width: 20,
+ height: 20,
+ ),
+ Text(
+ "\tConnected",
+ style: STextStyles.smallMed12(context).copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .accentColorGreen),
+ )
+ ],
+ );
+ case TorSyncStatus.syncing:
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ SvgPicture.asset(
+ Assets.svg.tor,
+ color:
+ Theme.of(context).extension()!.accentColorYellow,
+ width: 20,
+ height: 20,
+ ),
+ Text(
+ "\tConnecting",
+ style: STextStyles.smallMed12(context).copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .accentColorYellow),
+ )
+ ],
+ );
+ }
+ }
+
void updateSelectedMenuItem(DesktopMenuItemId idKey) {
widget.onSelectionWillChange?.call(idKey);
@@ -140,7 +206,22 @@ class _DesktopMenuState extends ConsumerState {
),
),
const SizedBox(
- height: 60,
+ height: 5,
+ ),
+ MouseRegion(
+ cursor: SystemMouseCursors.click,
+ child: GestureDetector(
+ onTap: () {
+ ref.read(currentDesktopMenuItemProvider.state).state =
+ DesktopMenuItemId.settings;
+ ref
+ .watch(selectedSettingsMenuItemStateProvider.state)
+ .state = 4;
+ },
+ child: _buildTorIcon(TorSyncStatus.unableToSync)),
+ ),
+ const SizedBox(
+ height: 40,
),
Expanded(
child: AnimatedContainer(
diff --git a/lib/pages_desktop_specific/settings/desktop_settings_view.dart b/lib/pages_desktop_specific/settings/desktop_settings_view.dart
index 2a8c180f9..6a785fc8a 100644
--- a/lib/pages_desktop_specific/settings/desktop_settings_view.dart
+++ b/lib/pages_desktop_specific/settings/desktop_settings_view.dart
@@ -19,6 +19,7 @@ import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/langua
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/nodes_settings.dart';
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/security_settings.dart';
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/syncing_preferences_settings.dart';
+import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@@ -56,7 +57,12 @@ class _DesktopSettingsViewState extends ConsumerState {
key: Key("settingsLanguageDesktopKey"),
onGenerateRoute: RouteGenerator.generateRoute,
initialRoute: LanguageOptionSettings.routeName,
- ), //language
+ ),
+ const Navigator(
+ key: Key("settingsTorDesktopKey"),
+ onGenerateRoute: RouteGenerator.generateRoute,
+ initialRoute: TorSettings.routeName,
+ ), //tor
const Navigator(
key: Key("settingsNodesDesktopKey"),
onGenerateRoute: RouteGenerator.generateRoute,
diff --git a/lib/pages_desktop_specific/settings/settings_menu.dart b/lib/pages_desktop_specific/settings/settings_menu.dart
index 4f3175a72..ba2c21781 100644
--- a/lib/pages_desktop_specific/settings/settings_menu.dart
+++ b/lib/pages_desktop_specific/settings/settings_menu.dart
@@ -32,6 +32,7 @@ class _SettingsMenuState extends ConsumerState {
"Security",
"Currency",
"Language",
+ "Tor settings",
"Nodes",
"Syncing preferences",
"Appearance",
diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart
new file mode 100644
index 000000000..e8d4b3f6a
--- /dev/null
+++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart
@@ -0,0 +1,316 @@
+/*
+ * This file is part of Stack Wallet.
+ *
+ * Copyright (c) 2023 Cypher Stack
+ * All Rights Reserved.
+ * The code is distributed under GPLv3 license, see LICENSE file for details.
+ * Generated by Cypher Stack on 2023-05-26
+ *
+ */
+
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+
+import '../../../../providers/global/prefs_provider.dart';
+import '../../../../themes/stack_colors.dart';
+import '../../../../widgets/custom_buttons/draggable_switch_button.dart';
+
+class TorSettings extends ConsumerStatefulWidget {
+ const TorSettings({Key? key}) : super(key: key);
+
+ static const String routeName = "/torDesktopSettings";
+
+ @override
+ ConsumerState createState() => _TorSettingsState();
+}
+
+class _TorSettingsState extends ConsumerState {
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final isDesktop = Util.isDesktop;
+
+ /// todo: redo the padding
+ return Column(
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(
+ right: 30,
+ ),
+ child: RoundedWhiteContainer(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: SvgPicture.asset(
+ Assets.svg.circleTor,
+ width: 48,
+ height: 48,
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: SvgPicture.asset(
+ Assets.svg.disconnectedButton,
+ width: 48,
+ height: 48,
+ ),
+ ),
+ ],
+ ),
+ Padding(
+ padding: const EdgeInsets.all(10),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ "Tor settings",
+ style: STextStyles.desktopTextSmall(context),
+ ),
+ RichText(
+ textAlign: TextAlign.start,
+ text: TextSpan(
+ children: [
+ TextSpan(
+ text:
+ "\nConnect to the Tor Network with one click.",
+ style: STextStyles.desktopTextExtraExtraSmall(
+ context),
+ ),
+ TextSpan(
+ text: "\tWhat is Tor?",
+ style: STextStyles.richLink(context).copyWith(
+ fontSize: 14,
+ ),
+ recognizer: TapGestureRecognizer()
+ ..onTap = () {
+ showDialog(
+ context: context,
+ useSafeArea: false,
+ barrierDismissible: true,
+ builder: (context) {
+ return DesktopDialog(
+ maxWidth: 580,
+ maxHeight: double.infinity,
+ child: Column(
+ children: [
+ Row(
+ mainAxisAlignment:
+ MainAxisAlignment.end,
+ children: [
+ DesktopDialogCloseButton(
+ onPressedOverride: () =>
+ Navigator.of(context)
+ .pop(true),
+ ),
+ ],
+ ),
+ Padding(
+ padding:
+ const EdgeInsets.all(20),
+ child: Column(
+ mainAxisSize:
+ MainAxisSize.max,
+ children: [
+ Text(
+ "What is Tor?",
+ style:
+ STextStyles.desktopH2(
+ context),
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ Text(
+ "Short for \"The Onion Router\", is an open-source software that enables internet communication"
+ " to remain anonymous by routing internet traffic through a series of layered nodes,"
+ " to obscure the origin and destination of data.",
+ style: STextStyles
+ .desktopTextMedium(
+ context)
+ .copyWith(
+ color: Theme.of(context)
+ .extension<
+ StackColors>()!
+ .textDark3,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ );
+ });
+ },
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(
+ height: 10,
+ ),
+ Padding(
+ padding: const EdgeInsets.all(10.0),
+ child: SecondaryButton(
+ label: "Disconnect from Tor",
+ width: 200,
+ buttonHeight: ButtonHeight.m,
+ onPressed: () {},
+ ),
+ ),
+ const SizedBox(
+ height: 30,
+ ),
+ Padding(
+ padding: const EdgeInsets.all(10.0),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ RichText(
+ textAlign: TextAlign.start,
+ text: TextSpan(
+ children: [
+ TextSpan(
+ text: "Tor killswitch",
+ style: STextStyles.desktopTextExtraExtraSmall(
+ context)
+ .copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .accentColorDark),
+ ),
+ TextSpan(
+ text: "\nWhat is Tor killswitch?",
+ style: STextStyles.richLink(context).copyWith(
+ fontSize: 14,
+ ),
+ recognizer: TapGestureRecognizer()
+ ..onTap = () {
+ showDialog(
+ context: context,
+ useSafeArea: false,
+ barrierDismissible: true,
+ builder: (context) {
+ return DesktopDialog(
+ maxWidth: 580,
+ maxHeight: double.infinity,
+ child: Column(
+ children: [
+ Row(
+ mainAxisAlignment:
+ MainAxisAlignment.end,
+ children: [
+ DesktopDialogCloseButton(
+ onPressedOverride: () =>
+ Navigator.of(
+ context)
+ .pop(true),
+ ),
+ ],
+ ),
+ Padding(
+ padding:
+ const EdgeInsets.all(
+ 20),
+ child: Column(
+ mainAxisSize:
+ MainAxisSize.max,
+ children: [
+ Text(
+ "What is Tor killswitch?",
+ style: STextStyles
+ .desktopH2(
+ context),
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ Text(
+ "A security feature that protects your information from accidental exposure by"
+ " disconnecting your device from the Tor network if your virtual private network (VPN)"
+ " connection is disrupted or compromised.",
+ style: STextStyles
+ .desktopTextMedium(
+ context)
+ .copyWith(
+ color: Theme.of(
+ context)
+ .extension<
+ StackColors>()!
+ .textDark3,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ );
+ });
+ },
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ Padding(
+ padding: const EdgeInsets.only(right: 8.0),
+ child: SizedBox(
+ height: 20,
+ width: 40,
+ child: DraggableSwitchButton(
+ isOn: ref.watch(
+ prefsChangeNotifierProvider
+ .select((value) => value.torKillswitch),
+ ),
+ onValueChanged: (newValue) {
+ ref
+ .read(prefsChangeNotifierProvider)
+ .torKillswitch = newValue;
+ },
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(
+ height: 10,
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/route_generator.dart b/lib/route_generator.dart
index 344eb7876..38604bc33 100644
--- a/lib/route_generator.dart
+++ b/lib/route_generator.dart
@@ -110,6 +110,7 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/support_vi
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart';
+import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_view.dart';
@@ -166,6 +167,7 @@ import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/langua
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/nodes_settings.dart';
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/security_settings.dart';
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/syncing_preferences_settings.dart';
+import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
@@ -654,6 +656,18 @@ class RouteGenerator {
builder: (_) => const LanguageSettingsView(),
settings: RouteSettings(name: settings.name));
+ case TorSettingsView.routeName:
+ return getRoute(
+ shouldUseMaterialRoute: useMaterialPageRoute,
+ builder: (_) => const TorSettingsView(),
+ settings: RouteSettings(name: settings.name));
+
+ case TorSettings.routeName:
+ return getRoute(
+ shouldUseMaterialRoute: useMaterialPageRoute,
+ builder: (_) => const TorSettings(),
+ settings: RouteSettings(name: settings.name));
+
case AboutView.routeName:
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart
index d1d7a55d8..9880e12c5 100644
--- a/lib/utilities/assets.dart
+++ b/lib/utilities/assets.dart
@@ -92,6 +92,11 @@ class _SVG {
final coinControl = const _COIN_CONTROL();
+ String get connectedButton => "assets/svg/connected-button.svg";
+ String get connectingButton => "assets/svg/connecting-button.svg";
+ String get disconnectedButton => "assets/svg/disconnected-button.svg";
+ String get circleTor => "assets/svg/tor-circle.svg";
+ String get tor => "assets/svg/tor.svg";
String get monkey => "assets/svg/monkey.svg";
String get circleSliders => "assets/svg/configuration.svg";
String get circlePlus => "assets/svg/plus-circle.svg";
diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart
index d9a2192be..8adb19ce3 100644
--- a/lib/utilities/prefs.dart
+++ b/lib/utilities/prefs.dart
@@ -44,6 +44,7 @@ class Prefs extends ChangeNotifier {
_lastUnlocked = await _getLastUnlocked();
_lastUnlockedTimeout = await _getLastUnlockedTimeout();
_showTestNetCoins = await _getShowTestNetCoins();
+ _torKillswitch = await _getTorKillswitch();
_isAutoBackupEnabled = await _getIsAutoBackupEnabled();
_autoBackupLocation = await _getAutoBackupLocation();
_backupFrequencyType = await _getBackupFrequencyType();
@@ -396,6 +397,27 @@ class Prefs extends ChangeNotifier {
0;
}
+ // tor
+
+ bool _torKillswitch = false;
+
+ bool get torKillswitch => _torKillswitch;
+
+ set torKillswitch(bool torKillswitch) {
+ if (_torKillswitch != showTestNetCoins) {
+ DB.instance.put(
+ boxName: DB.boxNamePrefs, key: "torKillswitch", value: torKillswitch);
+ _torKillswitch = torKillswitch;
+ notifyListeners();
+ }
+ }
+
+ Future _getTorKillswitch() async {
+ return await DB.instance.get(
+ boxName: DB.boxNamePrefs, key: "torKillswitch") as bool? ??
+ false;
+ }
+
// show testnet coins
bool _showTestNetCoins = false;
diff --git a/pubspec.yaml b/pubspec.yaml
index efcb1298a..f867999f9 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -346,6 +346,11 @@ flutter:
- assets/svg/send.svg
- assets/svg/ordinal.svg
- assets/svg/monkey.svg
+ - assets/svg/tor.svg
+ - assets/svg/tor-circle.svg
+ - assets/svg/connected-button.svg
+ - assets/svg/connecting-button.svg
+ - assets/svg/disconnected-button.svg
# coin control icons
- assets/svg/coin_control/