mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-18 02:07:43 +00:00
288 lines
9.1 KiB
Dart
288 lines
9.1 KiB
Dart
|
import 'dart:async';
|
||
|
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
|
import 'package:flutter_svg/svg.dart';
|
||
|
import 'package:stackwallet/pages/exchange_view/exchange_loading_overlay.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/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/wallets_view/wallets_view.dart';
|
||
|
import 'package:stackwallet/providers/global/notifications_provider.dart';
|
||
|
import 'package:stackwallet/providers/ui/home_view_index_provider.dart';
|
||
|
import 'package:stackwallet/providers/ui/unread_notifications_provider.dart';
|
||
|
import 'package:stackwallet/utilities/assets.dart';
|
||
|
import 'package:stackwallet/utilities/cfcolors.dart';
|
||
|
import 'package:stackwallet/utilities/constants.dart';
|
||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||
|
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||
|
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||
|
|
||
|
class HomeView extends ConsumerStatefulWidget {
|
||
|
const HomeView({Key? key}) : super(key: key);
|
||
|
|
||
|
static const routeName = "/home";
|
||
|
|
||
|
@override
|
||
|
ConsumerState<HomeView> createState() => _HomeViewState();
|
||
|
}
|
||
|
|
||
|
class _HomeViewState extends ConsumerState<HomeView> {
|
||
|
final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
|
||
|
|
||
|
late final PageController _pageController;
|
||
|
|
||
|
late final List<Widget> _children;
|
||
|
|
||
|
DateTime? _cachedTime;
|
||
|
|
||
|
bool _exitEnabled = false;
|
||
|
|
||
|
Future<bool> _onWillPop() async {
|
||
|
if (_exitEnabled) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
final now = DateTime.now();
|
||
|
const timeout = Duration(milliseconds: 1500);
|
||
|
if (_cachedTime == null || now.difference(_cachedTime!) > timeout) {
|
||
|
_cachedTime = now;
|
||
|
await showDialog<dynamic>(
|
||
|
context: context,
|
||
|
barrierDismissible: false,
|
||
|
builder: (_) => WillPopScope(
|
||
|
onWillPop: () async {
|
||
|
_exitEnabled = true;
|
||
|
return true;
|
||
|
},
|
||
|
child: const StackDialog(title: "Tap back again to exit"),
|
||
|
),
|
||
|
).timeout(
|
||
|
timeout,
|
||
|
onTimeout: () {
|
||
|
_exitEnabled = false;
|
||
|
Navigator.of(context).pop();
|
||
|
},
|
||
|
);
|
||
|
}
|
||
|
return _exitEnabled;
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void initState() {
|
||
|
_pageController = PageController();
|
||
|
_children = [
|
||
|
const WalletsView(),
|
||
|
if (Constants.enableExchange)
|
||
|
Stack(
|
||
|
children: const [
|
||
|
ExchangeView(),
|
||
|
ExchangeLoadingOverlayView(),
|
||
|
],
|
||
|
),
|
||
|
// const BuyView(),
|
||
|
];
|
||
|
|
||
|
ref.read(notificationsProvider).startCheckingWatchedNotifications();
|
||
|
|
||
|
super.initState();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
dispose() {
|
||
|
_pageController.dispose();
|
||
|
super.dispose();
|
||
|
}
|
||
|
|
||
|
DateTime _hiddenTime = DateTime.now();
|
||
|
int _hiddenCount = 0;
|
||
|
|
||
|
void _hiddenOptions() {
|
||
|
if (_hiddenCount == 5) {
|
||
|
Navigator.of(context).pushNamed(HiddenSettings.routeName);
|
||
|
}
|
||
|
final now = DateTime.now();
|
||
|
const timeout = Duration(seconds: 1);
|
||
|
if (now.difference(_hiddenTime) < timeout) {
|
||
|
_hiddenCount++;
|
||
|
} else {
|
||
|
_hiddenCount = 0;
|
||
|
}
|
||
|
_hiddenTime = now;
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
debugPrint("BUILD: $runtimeType");
|
||
|
return WillPopScope(
|
||
|
onWillPop: _onWillPop,
|
||
|
child: Scaffold(
|
||
|
key: _key,
|
||
|
appBar: AppBar(
|
||
|
automaticallyImplyLeading: false,
|
||
|
title: Row(
|
||
|
children: [
|
||
|
GestureDetector(
|
||
|
onTap: _hiddenOptions,
|
||
|
child: SvgPicture.asset(
|
||
|
Assets.svg.stackIcon,
|
||
|
// color: CFColors.stackAccent,
|
||
|
width: 24,
|
||
|
height: 24,
|
||
|
),
|
||
|
),
|
||
|
const SizedBox(
|
||
|
width: 16,
|
||
|
),
|
||
|
Text(
|
||
|
"My Stack",
|
||
|
style: STextStyles.navBarTitle,
|
||
|
)
|
||
|
],
|
||
|
),
|
||
|
actions: [
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.only(
|
||
|
top: 10,
|
||
|
bottom: 10,
|
||
|
right: 10,
|
||
|
),
|
||
|
child: AspectRatio(
|
||
|
aspectRatio: 1,
|
||
|
child: AppBarIconButton(
|
||
|
key: const Key("walletsViewAlertsButton"),
|
||
|
size: 36,
|
||
|
shadows: const [],
|
||
|
color: CFColors.almostWhite,
|
||
|
icon: SvgPicture.asset(
|
||
|
ref.watch(notificationsProvider
|
||
|
.select((value) => value.hasUnreadNotifications))
|
||
|
? Assets.svg.bellNew
|
||
|
: Assets.svg.bell,
|
||
|
width: 20,
|
||
|
height: 20,
|
||
|
),
|
||
|
onPressed: () {
|
||
|
// reset unread state
|
||
|
ref.refresh(unreadNotificationsStateProvider);
|
||
|
|
||
|
Navigator.of(context)
|
||
|
.pushNamed(NotificationsView.routeName)
|
||
|
.then((_) {
|
||
|
final Set<int> unreadNotificationIds = ref
|
||
|
.read(unreadNotificationsStateProvider.state)
|
||
|
.state;
|
||
|
if (unreadNotificationIds.isEmpty) return;
|
||
|
|
||
|
List<Future<void>> futures = [];
|
||
|
for (int i = 0;
|
||
|
i < unreadNotificationIds.length - 1;
|
||
|
i++) {
|
||
|
futures.add(ref.read(notificationsProvider).markAsRead(
|
||
|
unreadNotificationIds.elementAt(i), false));
|
||
|
}
|
||
|
|
||
|
// wait for multiple to update if any
|
||
|
Future.wait(futures).then((_) {
|
||
|
// only notify listeners once
|
||
|
ref
|
||
|
.read(notificationsProvider)
|
||
|
.markAsRead(unreadNotificationIds.last, true);
|
||
|
});
|
||
|
});
|
||
|
},
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.only(
|
||
|
top: 10,
|
||
|
bottom: 10,
|
||
|
right: 10,
|
||
|
),
|
||
|
child: AspectRatio(
|
||
|
aspectRatio: 1,
|
||
|
child: AppBarIconButton(
|
||
|
key: const Key("walletsViewSettingsButton"),
|
||
|
size: 36,
|
||
|
shadows: const [],
|
||
|
color: CFColors.almostWhite,
|
||
|
icon: SvgPicture.asset(
|
||
|
Assets.svg.gear,
|
||
|
color: CFColors.stackAccent,
|
||
|
width: 20,
|
||
|
height: 20,
|
||
|
),
|
||
|
onPressed: () {
|
||
|
debugPrint("main view settings tapped");
|
||
|
Navigator.of(context)
|
||
|
.pushNamed(GlobalSettingsView.routeName);
|
||
|
},
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
body: Container(
|
||
|
color: CFColors.almostWhite,
|
||
|
child: Column(
|
||
|
children: [
|
||
|
if (Constants.enableExchange)
|
||
|
Container(
|
||
|
decoration: const BoxDecoration(
|
||
|
color: CFColors.almostWhite,
|
||
|
boxShadow: [
|
||
|
CFColors.standardBoxShadow,
|
||
|
],
|
||
|
),
|
||
|
child: const Padding(
|
||
|
padding: EdgeInsets.only(
|
||
|
left: 16,
|
||
|
bottom: 12,
|
||
|
right: 16,
|
||
|
top: 0,
|
||
|
),
|
||
|
child: HomeViewButtonBar(),
|
||
|
),
|
||
|
),
|
||
|
Expanded(
|
||
|
child: Consumer(
|
||
|
builder: (_, _ref, __) {
|
||
|
_ref.listen(homeViewPageIndexStateProvider,
|
||
|
(previous, next) {
|
||
|
if (next is int) {
|
||
|
if (next >= 0 && next <= 1) {
|
||
|
_pageController.animateToPage(
|
||
|
next,
|
||
|
duration: const Duration(milliseconds: 300),
|
||
|
curve: Curves.decelerate,
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
return PageView(
|
||
|
controller: _pageController,
|
||
|
children: _children,
|
||
|
onPageChanged: (pageIndex) {
|
||
|
ref.read(homeViewPageIndexStateProvider.state).state =
|
||
|
pageIndex;
|
||
|
},
|
||
|
);
|
||
|
},
|
||
|
),
|
||
|
),
|
||
|
// Expanded(
|
||
|
// child: HomeStack(
|
||
|
// children: _children,
|
||
|
// ),
|
||
|
// ),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|