This commit is contained in:
Christien Rioux 2024-06-16 22:12:24 -04:00
parent 2ccad50f9a
commit 360ba436f8
29 changed files with 501 additions and 317 deletions

View file

@ -0,0 +1,37 @@
import 'dart:async';
import 'package:async_tools/async_tools.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:veilid_support/veilid_support.dart';
import '../../account_manager/account_manager.dart';
class ActiveAccountPageControllerWrapper {
ActiveAccountPageControllerWrapper(Locator locator, int initialPage) {
pageController = PageController(initialPage: initialPage, keepPage: false);
final activeLocalAccountCubit = locator<ActiveLocalAccountCubit>();
_subscription =
activeLocalAccountCubit.stream.listen((activeLocalAccountRecordKey) {
singleFuture(this, () async {
final localAccounts = locator<LocalAccountsCubit>().state;
final activeIndex = localAccounts.indexWhere(
(x) => x.superIdentity.recordKey == activeLocalAccountRecordKey);
if (pageController.page == activeIndex) {
return;
}
await pageController.animateToPage(activeIndex,
duration: const Duration(milliseconds: 250),
curve: Curves.fastOutSlowIn);
});
});
}
void dispose() {
unawaited(_subscription.cancel());
}
late PageController pageController;
late StreamSubscription<TypedKey?> _subscription;
}

View file

@ -1,5 +1,6 @@
import 'package:async_tools/async_tools.dart';
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
@ -102,15 +103,12 @@ class _DrawerMenuState extends State<DrawerMenu> {
}
Widget _getAccountList(
{required TypedKey? activeLocalAccount,
{required IList<LocalAccount> localAccounts,
required TypedKey? activeLocalAccount,
required AccountRecordsBlocMapState accountRecords}) {
final theme = Theme.of(context);
final scaleScheme = theme.extension<ScaleScheme>()!;
final accountRepo = AccountRepository.instance;
final localAccounts = accountRepo.getLocalAccounts();
//final userLogins = accountRepo.getUserLogins();
final loggedInAccounts = <Widget>[];
final loggedOutAccounts = <Widget>[];
@ -234,8 +232,9 @@ class _DrawerMenuState extends State<DrawerMenu> {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
//final textTheme = theme.textTheme;
final localAccounts = context.watch<LocalAccountsCubit>().state;
final accountRecords = context.watch<AccountRecordsBlocMapCubit>().state;
final activeLocalAccount = context.watch<ActiveAccountInfoCubit>().state;
final activeLocalAccount = context.watch<ActiveLocalAccountCubit>().state;
final gradient = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
@ -276,8 +275,8 @@ class _DrawerMenuState extends State<DrawerMenu> {
])),
const Spacer(),
_getAccountList(
activeLocalAccount:
activeLocalAccount.unlockedAccountInfo?.superIdentityRecordKey,
localAccounts: localAccounts,
activeLocalAccount: activeLocalAccount,
accountRecords: accountRecords),
_getBottomButtons(),
const Spacer(),

View file

@ -1,7 +1,8 @@
export 'active_account_page_controller_wrapper.dart';
export 'drawer_menu/drawer_menu.dart';
export 'home_account_invalid.dart';
export 'home_account_locked.dart';
export 'home_account_missing.dart';
export 'home_account_ready/home_account_ready.dart';
export 'home_no_active.dart';
export 'home_shell.dart';
export 'home_screen.dart';

View file

@ -5,6 +5,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:flutter_translate/flutter_translate.dart';
import 'package:preload_page_view/preload_page_view.dart';
import 'package:provider/provider.dart';
import 'package:stylish_bottom_bar/stylish_bottom_bar.dart';
import '../../../../chat/chat.dart';
@ -117,7 +118,7 @@ class MainPagerState extends State<MainPager> with TickerProviderStateMixin {
style: TextStyle(fontSize: 24),
),
content: ScanInvitationDialog(
modalContext: context,
locator: context.read,
));
});
}

View file

@ -14,24 +14,24 @@ import '../../contact_invitation/contact_invitation.dart';
import '../../contacts/contacts.dart';
import '../../conversation/conversation.dart';
import '../../proto/proto.dart' as proto;
import '../../router/router.dart';
import '../../theme/theme.dart';
import '../../tools/tools.dart';
import 'active_account_page_controller_wrapper.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 HomeShell extends StatefulWidget {
const HomeShell({required this.child, super.key});
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
HomeShellState createState() => HomeShellState();
final Widget child;
HomeScreenState createState() => HomeScreenState();
}
class HomeShellState extends State<HomeShell> {
class HomeScreenState extends State<HomeScreen> {
@override
void initState() {
super.initState();
@ -84,8 +84,22 @@ class HomeShellState extends State<HomeShell> {
});
}
Widget _buildActiveAccount(BuildContext context) {
final accountRecordKey = context.select<ActiveAccountInfoCubit, TypedKey>(
Widget _buildAccountReadyDeviceSpecific(BuildContext context) {
final hasActiveChat = context.watch<ActiveChatCubit>().state != null;
if (responsiveVisibility(
context: context,
tablet: false,
tabletLandscape: false,
desktop: false)) {
if (hasActiveChat) {
return const HomeAccountReadyChat();
}
}
return const HomeAccountReadyMain();
}
Widget _buildUnlockedAccount(BuildContext context) {
final accountRecordKey = context.select<AccountInfoCubit, TypedKey>(
(c) => c.state.unlockedAccountInfo!.accountRecordKey);
final contactListRecordPointer =
context.select<AccountRecordCubit, OwnedDHTRecordPointer?>(
@ -124,8 +138,9 @@ class HomeShellState extends State<HomeShell> {
)),
// Chat Cubits
BlocProvider(
create: (context) => ActiveChatCubit(null,
routerCubit: context.read<RouterCubit>())),
create: (context) => ActiveChatCubit(
null,
)),
BlocProvider(
create: (context) => ChatListCubit(
locator: context.read,
@ -146,27 +161,21 @@ class HomeShellState extends State<HomeShell> {
WaitingInvitationsBlocMapState>(
listener: _invitationStatusListener,
)
], child: widget.child));
], child: Builder(builder: _buildAccountReadyDeviceSpecific)));
}
Widget _buildWithLogin(BuildContext context) {
Widget _buildAccount(BuildContext context) {
// Get active account info status
final (
accountInfoStatus,
accountInfoActive,
superIdentityRecordKey
) = context
.select<ActiveAccountInfoCubit, (AccountInfoStatus, bool, TypedKey?)>(
(c) => (
c.state.status,
c.state.active,
c.state.unlockedAccountInfo?.superIdentityRecordKey
));
if (!accountInfoActive) {
// If no logged in user is active, show the loading panel
return const HomeNoActive();
}
.select<AccountInfoCubit, (AccountInfoStatus, bool, TypedKey?)>((c) => (
c.state.status,
c.state.active,
c.state.unlockedAccountInfo?.superIdentityRecordKey
));
switch (accountInfoStatus) {
case AccountInfoStatus.noAccount:
@ -175,7 +184,7 @@ class HomeShellState extends State<HomeShell> {
return const HomeAccountInvalid();
case AccountInfoStatus.accountLocked:
return const HomeAccountLocked();
case AccountInfoStatus.accountReady:
case AccountInfoStatus.accountUnlocked:
// Get the current active account record cubit
final activeAccountRecordCubit =
@ -190,10 +199,50 @@ class HomeShellState extends State<HomeShell> {
return MultiBlocProvider(providers: [
BlocProvider<AccountRecordCubit>.value(
value: activeAccountRecordCubit),
], child: Builder(builder: _buildActiveAccount));
], child: Builder(builder: _buildUnlockedAccount));
}
}
Widget _buildAccountPageView(BuildContext context) {
final localAccounts = context.watch<LocalAccountsCubit>().state;
final activeLocalAccountCubit = context.read<ActiveLocalAccountCubit>();
final activeIndex = localAccounts.indexWhere(
(x) => x.superIdentity.recordKey == activeLocalAccountCubit.state);
if (activeIndex == -1) {
return const HomeNoActive();
}
return Provider<ActiveAccountPageControllerWrapper>(
lazy: false,
create: (context) =>
ActiveAccountPageControllerWrapper(context.read, activeIndex),
dispose: (context, value) {
value.dispose();
},
child: Builder(
builder: (context) => PageView.builder(
itemCount: localAccounts.length,
onPageChanged: (idx) {
singleFuture(this, () async {
await AccountRepository.instance.switchToAccount(
localAccounts[idx].superIdentity.recordKey);
});
},
controller: context
.read<ActiveAccountPageControllerWrapper>()
.pageController,
itemBuilder: (context, index) {
final localAccount = localAccounts[index];
return BlocProvider<AccountInfoCubit>(
key: ValueKey(localAccount.superIdentity.recordKey),
create: (context) => AccountInfoCubit(
AccountRepository.instance,
localAccount.superIdentity.recordKey),
child: Builder(builder: _buildAccount));
})));
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
@ -219,7 +268,7 @@ class HomeShellState extends State<HomeShell> {
color: scale.primaryScale.activeElementBackground),
child: Provider<ZoomDrawerController>.value(
value: _zoomDrawerController,
child: Builder(builder: _buildWithLogin))),
child: Builder(builder: _buildAccountPageView))),
borderRadius: 24,
showShadow: true,
angle: 0,
@ -239,50 +288,3 @@ class HomeShellState extends State<HomeShell> {
final _singleInvitationStatusProcessor =
SingleStateProcessor<WaitingInvitationsBlocMapState>();
}
// class HomeAccountReadyShell extends StatefulWidget {
// factory HomeAccountReadyShell(
// {required BuildContext context, required Widget child, Key? key}) {
// // These must exist in order for the account to
// // be considered 'ready' for this widget subtree
// final unlockedAccountInfo = context.watch<UnlockedAccountInfo>();
// final routerCubit = context.read<RouterCubit>();
// return HomeAccountReadyShell._(
// unlockedAccountInfo: unlockedAccountInfo,
// routerCubit: routerCubit,
// key: key,
// child: child);
// }
// const HomeAccountReadyShell._(
// {required this.unlockedAccountInfo,
// required this.routerCubit,
// required this.child,
// super.key});
// @override
// HomeAccountReadyShellState createState() => HomeAccountReadyShellState();
// final Widget child;
// final UnlockedAccountInfo unlockedAccountInfo;
// final RouterCubit routerCubit;
// @override
// void debugFillProperties(DiagnosticPropertiesBuilder properties) {
// super.debugFillProperties(properties);
// properties
// ..add(DiagnosticsProperty<UnlockedAccountInfo>(
// 'unlockedAccountInfo', unlockedAccountInfo))
// ..add(DiagnosticsProperty<RouterCubit>('routerCubit', routerCubit));
// }
// }
// class HomeAccountReadyShellState extends State<HomeAccountReadyShell> {
// final SingleStateProcessor<WaitingInvitationsBlocMapState>
// _singleInvitationStatusProcessor = SingleStateProcessor();
// @override
// void initState() {
// super.initState();
// }
// }