import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; import 'package:provider/provider.dart'; import 'package:transitioned_indexed_stack/transitioned_indexed_stack.dart'; import 'package:veilid_support/veilid_support.dart'; import '../../account_manager/account_manager.dart'; import '../../chat/chat.dart'; import '../../theme/theme.dart'; import '../../tools/tools.dart'; import 'drawer_menu/drawer_menu.dart'; import 'home_account_invalid.dart'; import 'home_account_locked.dart'; import 'home_account_missing.dart'; import 'home_account_ready/home_account_ready.dart'; import 'home_no_active.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override HomeScreenState createState() => HomeScreenState(); static HomeScreenState? of(BuildContext context) => context.findAncestorStateOfType(); } class HomeScreenState extends State with SingleTickerProviderStateMixin { @override void initState() { // Chat animation setup (open in phone mode) _chatAnimationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 250), ); _chatAnimation = Tween( begin: const Offset(1, 0), end: Offset.zero, ).animate(CurvedAnimation( parent: _chatAnimationController, curve: Curves.easeInOut, )); // Account animation setup super.initState(); } @override void dispose() { _chatAnimationController.dispose(); super.dispose(); } Widget _buildAccountReadyDeviceSpecific(BuildContext context) { if (responsiveVisibility( context: context, tablet: false, tabletLandscape: false, desktop: false)) { return BlocConsumer( listener: (context, activeChat) { final hasActiveChat = activeChat != null; if (hasActiveChat) { _chatAnimationController.forward(); } else { _chatAnimationController.reset(); } }, builder: (context, activeChat) => Stack( children: [ const HomeAccountReadyMain(), Offstage( offstage: activeChat == null, child: SlideTransition( position: _chatAnimation, child: const HomeAccountReadyChat())), ], )); } return const HomeAccountReadyMain(); } Widget _buildAccountPage( BuildContext context, TypedKey superIdentityRecordKey, PerAccountCollectionState perAccountCollectionState) { switch (perAccountCollectionState.accountInfo.status) { case AccountInfoStatus.accountInvalid: return const HomeAccountInvalid(); case AccountInfoStatus.accountLocked: return const HomeAccountLocked(); case AccountInfoStatus.accountUnlocked: // Are we ready to render? if (!perAccountCollectionState.isReady) { return waitingPage(); } // Re-export all ready blocs to the account display subtree return perAccountCollectionState.provide( child: Builder(builder: _buildAccountReadyDeviceSpecific)); } } Widget _buildAccountPageView(BuildContext context) { final localAccounts = context.watch().state; final activeLocalAccount = context.watch().state; final perAccountCollectionBlocMapState = context.watch().state; final activeIndex = localAccounts .indexWhere((x) => x.superIdentity.recordKey == activeLocalAccount); if (activeIndex == -1) { return const HomeNoActive(); } final accountPages = []; for (var i = 0; i < localAccounts.length; i++) { final superIdentityRecordKey = localAccounts[i].superIdentity.recordKey; final perAccountCollectionState = perAccountCollectionBlocMapState.get(superIdentityRecordKey); if (perAccountCollectionState == null) { return HomeAccountMissing(key: ValueKey(superIdentityRecordKey)); } final accountPage = _buildAccountPage( context, superIdentityRecordKey, perAccountCollectionState); accountPages.add(KeyedSubtree.wrap(accountPage, i)); } return SlideIndexedStack( index: activeIndex, beginSlideOffset: const Offset(1, 0), children: accountPages, ); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final scale = theme.extension()!; final gradient = LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ scale.tertiaryScale.subtleBackground, scale.tertiaryScale.appBackground, ]); return SafeArea( child: DecoratedBox( decoration: BoxDecoration(gradient: gradient), child: ZoomDrawer( controller: _zoomDrawerController, //menuBackgroundColor: Colors.transparent, menuScreen: Builder(builder: (context) { final zoomDrawer = ZoomDrawer.of(context); zoomDrawer!.stateNotifier.addListener(() { if (zoomDrawer.isOpen()) { FocusManager.instance.primaryFocus?.unfocus(); } }); return const DrawerMenu(); }), mainScreen: Provider.value( value: _zoomDrawerController, child: Builder(builder: _buildAccountPageView)), borderRadius: 24, //showShadow: false, angle: 0, drawerShadowsBackgroundColor: theme.shadowColor, mainScreenOverlayColor: theme.shadowColor.withAlpha(0x3F), openCurve: Curves.fastEaseInToSlowEaseOut, // duration: const Duration(milliseconds: 250), // reverseDuration: const Duration(milliseconds: 250), menuScreenTapClose: true, mainScreenTapClose: true, //disableDragGesture: false, mainScreenScale: .25, slideWidth: min(360, MediaQuery.of(context).size.width * 0.9), ))); } //////////////////////////////////////////////////////////////////////////// final _zoomDrawerController = ZoomDrawerController(); late final Animation _chatAnimation; late final AnimationController _chatAnimationController; }