mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 09:47:37 +00:00
extract desktop tor status button into its own widget and animate it when collapsing/expanding the desktop menu
This commit is contained in:
parent
dea3be904e
commit
596f917a0f
2 changed files with 213 additions and 134 deletions
|
@ -8,10 +8,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
@ -19,15 +17,12 @@ import 'package:flutter_svg/flutter_svg.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/services/event_bus/events/global/tor_connection_status_changed_event.dart';
|
||||
import 'package:stackwallet/services/tor_service.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_tor_status_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/living_stack_icon.dart';
|
||||
|
||||
import '../services/event_bus/global_event_bus.dart';
|
||||
|
||||
enum DesktopMenuItemId {
|
||||
myStack,
|
||||
exchange,
|
||||
|
@ -59,86 +54,10 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
|
|||
|
||||
final Duration duration = const Duration(milliseconds: 250);
|
||||
late final List<DMIController> controllers;
|
||||
late final DMIController torButtonController;
|
||||
|
||||
double _width = expandedWidth;
|
||||
|
||||
// final _buyDataLoadingService = BuyDataLoadingService();
|
||||
|
||||
/// The global event bus.
|
||||
late final EventBus eventBus;
|
||||
|
||||
/// The subscription to the TorConnectionStatusChangedEvent.
|
||||
late StreamSubscription<TorConnectionStatusChangedEvent>
|
||||
_torConnectionStatusSubscription;
|
||||
|
||||
/// The current status of the Tor connection.
|
||||
late TorConnectionStatus _torConnectionStatus;
|
||||
|
||||
/// Builds the tor icon based on the current status.
|
||||
Widget _buildTorIcon(TorConnectionStatus status) {
|
||||
switch (status) {
|
||||
case TorConnectionStatus.disconnected:
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.tor,
|
||||
color: Theme.of(context).extension<StackColors>()!.textSubtitle3,
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
"\tDisconnected",
|
||||
style: STextStyles.smallMed12(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textSubtitle3),
|
||||
)
|
||||
],
|
||||
);
|
||||
case TorConnectionStatus.connecting:
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.tor,
|
||||
color:
|
||||
Theme.of(context).extension<StackColors>()!.accentColorYellow,
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
"\tConnecting",
|
||||
style: STextStyles.smallMed12(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorYellow),
|
||||
)
|
||||
],
|
||||
);
|
||||
case TorConnectionStatus.connected:
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.tor,
|
||||
color:
|
||||
Theme.of(context).extension<StackColors>()!.accentColorGreen,
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
"\tConnected",
|
||||
style: STextStyles.smallMed12(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorGreen),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void updateSelectedMenuItem(DesktopMenuItemId idKey) {
|
||||
widget.onSelectionWillChange?.call(idKey);
|
||||
|
||||
|
@ -154,6 +73,8 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
|
|||
e.toggle?.call();
|
||||
}
|
||||
|
||||
torButtonController.toggle?.call();
|
||||
|
||||
setState(() {
|
||||
_width = expanded ? minimizedWidth : expandedWidth;
|
||||
});
|
||||
|
@ -173,43 +94,7 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
|
|||
DMIController(),
|
||||
];
|
||||
|
||||
// Initialize the global event bus.
|
||||
eventBus = GlobalEventBus.instance;
|
||||
|
||||
// Initialize the TorConnectionStatus.
|
||||
_torConnectionStatus = ref.read(pTorService).enabled
|
||||
? TorConnectionStatus.connected
|
||||
: TorConnectionStatus.disconnected;
|
||||
|
||||
// Subscribe to the TorConnectionStatusChangedEvent.
|
||||
_torConnectionStatusSubscription =
|
||||
eventBus.on<TorConnectionStatusChangedEvent>().listen(
|
||||
(event) async {
|
||||
// Rebuild the widget.
|
||||
setState(() {
|
||||
_torConnectionStatus = event.newStatus;
|
||||
});
|
||||
|
||||
// TODO implement spinner or animations and control from here
|
||||
// switch (event.newStatus) {
|
||||
// case TorConnectionStatus.disconnected:
|
||||
// // if (_spinController.hasLoadedAnimation) {
|
||||
// // _spinController.stop?.call();
|
||||
// // }
|
||||
// break;
|
||||
// case TorConnectionStatus.connecting:
|
||||
// // if (_spinController.hasLoadedAnimation) {
|
||||
// // _spinController.repeat?.call();
|
||||
// // }
|
||||
// break;
|
||||
// case TorConnectionStatus.connected:
|
||||
// // if (_spinController.hasLoadedAnimation) {
|
||||
// // _spinController.stop?.call();
|
||||
// // }
|
||||
// break;
|
||||
// }
|
||||
},
|
||||
);
|
||||
torButtonController = DMIController();
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
@ -219,9 +104,7 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
|
|||
for (var e in controllers) {
|
||||
e.dispose();
|
||||
}
|
||||
|
||||
// Clean up the subscription to the TorConnectionStatusChangedEvent.
|
||||
_torConnectionStatusSubscription.cancel();
|
||||
torButtonController.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
@ -266,17 +149,21 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
|
|||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
ref.read(currentDesktopMenuItemProvider.state).state =
|
||||
DesktopMenuItemId.settings;
|
||||
ref
|
||||
.watch(selectedSettingsMenuItemStateProvider.state)
|
||||
.state = 4;
|
||||
},
|
||||
child: _buildTorIcon(_torConnectionStatus)),
|
||||
AnimatedContainer(
|
||||
duration: duration,
|
||||
width: _width == expandedWidth
|
||||
? _width - 32 // 16 padding on either side
|
||||
: _width - 16, // 8 padding on either side
|
||||
child: DesktopTorStatusButton(
|
||||
transitionDuration: duration,
|
||||
controller: torButtonController,
|
||||
onPressed: () {
|
||||
ref.read(currentDesktopMenuItemProvider.state).state =
|
||||
DesktopMenuItemId.settings;
|
||||
ref.watch(selectedSettingsMenuItemStateProvider.state).state =
|
||||
4;
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
|
|
192
lib/widgets/desktop/desktop_tor_status_button.dart
Normal file
192
lib/widgets/desktop/desktop_tor_status_button.dart
Normal file
|
@ -0,0 +1,192 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_native_splash/cli_commands.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart';
|
||||
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
|
||||
import 'package:stackwallet/services/tor_service.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
|
||||
class DesktopTorStatusButton extends ConsumerStatefulWidget {
|
||||
const DesktopTorStatusButton({
|
||||
super.key,
|
||||
this.onPressed,
|
||||
required this.transitionDuration,
|
||||
this.controller,
|
||||
this.labelLength = 125,
|
||||
});
|
||||
|
||||
final VoidCallback? onPressed;
|
||||
final Duration transitionDuration;
|
||||
final DMIController? controller;
|
||||
final double labelLength;
|
||||
|
||||
@override
|
||||
ConsumerState<DesktopTorStatusButton> createState() =>
|
||||
_DesktopTorStatusButtonState();
|
||||
}
|
||||
|
||||
class _DesktopTorStatusButtonState extends ConsumerState<DesktopTorStatusButton>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final AnimationController animationController;
|
||||
late final DMIController? controller;
|
||||
late final double labelLength;
|
||||
|
||||
/// The global event bus.
|
||||
late final EventBus eventBus;
|
||||
|
||||
/// The subscription to the TorConnectionStatusChangedEvent.
|
||||
late final StreamSubscription<TorConnectionStatusChangedEvent>
|
||||
_torConnectionStatusSubscription;
|
||||
|
||||
/// The current status of the Tor connection.
|
||||
late TorConnectionStatus _torConnectionStatus;
|
||||
|
||||
Color _color(TorConnectionStatus status) {
|
||||
switch (status) {
|
||||
case TorConnectionStatus.disconnected:
|
||||
return Theme.of(context).extension<StackColors>()!.textSubtitle3;
|
||||
case TorConnectionStatus.connecting:
|
||||
return Theme.of(context).extension<StackColors>()!.accentColorYellow;
|
||||
case TorConnectionStatus.connected:
|
||||
return Theme.of(context).extension<StackColors>()!.accentColorGreen;
|
||||
}
|
||||
}
|
||||
|
||||
bool _iconOnly = false;
|
||||
|
||||
void toggle() {
|
||||
setState(() {
|
||||
_iconOnly = !_iconOnly;
|
||||
});
|
||||
if (_iconOnly) {
|
||||
animationController.reverse();
|
||||
} else {
|
||||
animationController.forward();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
labelLength = widget.labelLength;
|
||||
controller = widget.controller;
|
||||
|
||||
// Initialize the global event bus.
|
||||
eventBus = GlobalEventBus.instance;
|
||||
|
||||
// Initialize the TorConnectionStatus.
|
||||
_torConnectionStatus = ref.read(pTorService).enabled
|
||||
? TorConnectionStatus.connected
|
||||
: TorConnectionStatus.disconnected;
|
||||
|
||||
// Subscribe to the TorConnectionStatusChangedEvent.
|
||||
_torConnectionStatusSubscription =
|
||||
eventBus.on<TorConnectionStatusChangedEvent>().listen(
|
||||
(event) async {
|
||||
// Rebuild the widget.
|
||||
setState(() {
|
||||
_torConnectionStatus = event.newStatus;
|
||||
});
|
||||
|
||||
// TODO implement spinner or animations and control from here
|
||||
// switch (event.newStatus) {
|
||||
// case TorConnectionStatus.disconnected:
|
||||
// // if (_spinController.hasLoadedAnimation) {
|
||||
// // _spinController.stop?.call();
|
||||
// // }
|
||||
// break;
|
||||
// case TorConnectionStatus.connecting:
|
||||
// // if (_spinController.hasLoadedAnimation) {
|
||||
// // _spinController.repeat?.call();
|
||||
// // }
|
||||
// break;
|
||||
// case TorConnectionStatus.connected:
|
||||
// // if (_spinController.hasLoadedAnimation) {
|
||||
// // _spinController.stop?.call();
|
||||
// // }
|
||||
// break;
|
||||
// }
|
||||
},
|
||||
);
|
||||
|
||||
controller?.toggle = toggle;
|
||||
animationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: widget.transitionDuration,
|
||||
)..forward();
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// Clean up the subscription to the TorConnectionStatusChangedEvent.
|
||||
_torConnectionStatusSubscription.cancel();
|
||||
|
||||
|
||||
controller?.dispose();
|
||||
animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getDesktopMenuButtonStyle(context),
|
||||
onPressed: widget.onPressed,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
AnimatedContainer(
|
||||
duration: widget.transitionDuration,
|
||||
width: _iconOnly ? 0 : 16,
|
||||
),
|
||||
SvgPicture.asset(
|
||||
Assets.svg.tor,
|
||||
color: _color(_torConnectionStatus),
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
AnimatedOpacity(
|
||||
duration: widget.transitionDuration,
|
||||
opacity: _iconOnly ? 0 : 1.0,
|
||||
child: SizeTransition(
|
||||
sizeFactor: animationController,
|
||||
axis: Axis.horizontal,
|
||||
axisAlignment: -1,
|
||||
child: SizedBox(
|
||||
width: labelLength,
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Text(
|
||||
_torConnectionStatus.name.capitalize(),
|
||||
style: STextStyles.smallMed12(context).copyWith(
|
||||
color: _color(_torConnectionStatus),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue