mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-05-28 10:42:24 -04:00
refactor and cleanup in prep for profile changing
This commit is contained in:
parent
87bb1657c7
commit
56d65442f4
49 changed files with 967 additions and 655 deletions
|
@ -1,3 +1,4 @@
|
|||
import 'package:async_tools/async_tools.dart';
|
||||
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
@ -9,6 +10,7 @@ import 'package:veilid_support/veilid_support.dart';
|
|||
import '../../../account_manager/account_manager.dart';
|
||||
import '../../../theme/theme.dart';
|
||||
import '../../../tools/tools.dart';
|
||||
import '../../../veilid_processor/veilid_processor.dart';
|
||||
import 'menu_item_widget.dart';
|
||||
|
||||
class DrawerMenu extends StatefulWidget {
|
||||
|
@ -29,8 +31,10 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
void _doLoginClick(TypedKey superIdentityRecordKey) {
|
||||
//
|
||||
void _doSwitchClick(TypedKey superIdentityRecordKey) {
|
||||
singleFuture(this, () async {
|
||||
await AccountRepository.instance.switchToAccount(superIdentityRecordKey);
|
||||
});
|
||||
}
|
||||
|
||||
void _doEditClick(TypedKey superIdentityRecordKey) {
|
||||
|
@ -47,10 +51,12 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
|
||||
Widget _makeAccountWidget(
|
||||
{required String name,
|
||||
required bool selected,
|
||||
required ScaleColor scale,
|
||||
required bool loggedIn,
|
||||
required void Function() clickHandler}) {
|
||||
required void Function()? callback,
|
||||
required void Function()? footerCallback}) {
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!.tertiaryScale;
|
||||
final abbrev = name.split(' ').map((s) => s.isEmpty ? '' : s[0]).join();
|
||||
late final String shortname;
|
||||
if (abbrev.length >= 3) {
|
||||
|
@ -65,30 +71,36 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
foregroundColor: loggedIn ? scale.primaryText : scale.subtleText,
|
||||
child: Text(shortname, style: theme.textTheme.titleLarge));
|
||||
|
||||
return MenuItemWidget(
|
||||
title: name,
|
||||
headerWidget: avatar,
|
||||
titleStyle: theme.textTheme.titleLarge!,
|
||||
foregroundColor: scale.primary,
|
||||
backgroundColor: scale.elementBackground,
|
||||
backgroundHoverColor: scale.hoverElementBackground,
|
||||
backgroundFocusColor: scale.activeElementBackground,
|
||||
borderColor: scale.border,
|
||||
borderHoverColor: scale.hoverBorder,
|
||||
borderFocusColor: scale.primary,
|
||||
footerButtonIcon: loggedIn ? Icons.edit_outlined : Icons.login_outlined,
|
||||
footerCallback: clickHandler,
|
||||
footerButtonIconColor: scale.border,
|
||||
footerButtonIconHoverColor: scale.hoverElementBackground,
|
||||
footerButtonIconFocusColor: scale.activeElementBackground,
|
||||
);
|
||||
return AnimatedPadding(
|
||||
padding: EdgeInsets.fromLTRB(selected ? 0 : 0, 0, selected ? 0 : 8, 0),
|
||||
duration: const Duration(milliseconds: 50),
|
||||
child: MenuItemWidget(
|
||||
title: name,
|
||||
headerWidget: avatar,
|
||||
titleStyle: theme.textTheme.titleLarge!,
|
||||
foregroundColor: scale.primary,
|
||||
backgroundColor: selected
|
||||
? scale.activeElementBackground
|
||||
: scale.elementBackground,
|
||||
backgroundHoverColor: scale.hoverElementBackground,
|
||||
backgroundFocusColor: scale.activeElementBackground,
|
||||
borderColor: scale.border,
|
||||
borderHoverColor: scale.hoverBorder,
|
||||
borderFocusColor: scale.primary,
|
||||
callback: callback,
|
||||
footerButtonIcon: loggedIn ? Icons.edit_outlined : null,
|
||||
footerCallback: footerCallback,
|
||||
footerButtonIconColor: scale.border,
|
||||
footerButtonIconHoverColor: scale.hoverElementBackground,
|
||||
footerButtonIconFocusColor: scale.activeElementBackground,
|
||||
));
|
||||
}
|
||||
|
||||
Widget _getAccountList(
|
||||
{required TypedKey? activeLocalAccount,
|
||||
required AccountRecordsBlocMapState accountRecords}) {
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!;
|
||||
final scaleScheme = theme.extension<ScaleScheme>()!;
|
||||
|
||||
final accountRepo = AccountRepository.instance;
|
||||
final localAccounts = accountRepo.getLocalAccounts();
|
||||
|
@ -104,28 +116,38 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
final acctRecord = accountRecords.get(superIdentityRecordKey);
|
||||
if (acctRecord != null) {
|
||||
// Account is logged in
|
||||
final scale = theme.extension<ScaleScheme>()!.tertiaryScale;
|
||||
final loggedInAccount = acctRecord.when(
|
||||
data: (value) => _makeAccountWidget(
|
||||
name: value.profile.name,
|
||||
scale: scale,
|
||||
selected: superIdentityRecordKey == activeLocalAccount,
|
||||
loggedIn: true,
|
||||
clickHandler: () {
|
||||
callback: () {
|
||||
_doSwitchClick(superIdentityRecordKey);
|
||||
},
|
||||
footerCallback: () {
|
||||
_doEditClick(superIdentityRecordKey);
|
||||
}),
|
||||
loading: () => _wrapInBox(
|
||||
child: buildProgressIndicator(),
|
||||
color: scale.grayScale.subtleBorder),
|
||||
color: scaleScheme.grayScale.subtleBorder),
|
||||
error: (err, st) => _wrapInBox(
|
||||
child: errorPage(err, st), color: scale.errorScale.subtleBorder),
|
||||
child: errorPage(err, st),
|
||||
color: scaleScheme.errorScale.subtleBorder),
|
||||
);
|
||||
loggedInAccounts.add(loggedInAccount);
|
||||
loggedInAccounts.add(loggedInAccount.paddingLTRB(0, 0, 0, 8));
|
||||
} else {
|
||||
// Account is not logged in
|
||||
final scale = theme.extension<ScaleScheme>()!.grayScale;
|
||||
final loggedOutAccount = _makeAccountWidget(
|
||||
name: la.name,
|
||||
loggedIn: false,
|
||||
clickHandler: () {
|
||||
_doLoginClick(superIdentityRecordKey);
|
||||
});
|
||||
name: la.name,
|
||||
scale: scale,
|
||||
selected: superIdentityRecordKey == activeLocalAccount,
|
||||
loggedIn: false,
|
||||
callback: () => {_doSwitchClick(superIdentityRecordKey)},
|
||||
footerCallback: null,
|
||||
);
|
||||
loggedOutAccounts.add(loggedOutAccount);
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +230,7 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
final scale = theme.extension<ScaleScheme>()!;
|
||||
//final textTheme = theme.textTheme;
|
||||
final accountRecords = context.watch<AccountRecordsBlocMapCubit>().state;
|
||||
final activeLocalAccount = context.watch<ActiveLocalAccountCubit>().state;
|
||||
final activeLocalAccount = context.watch<ActiveAccountInfoCubit>().state;
|
||||
final gradient = LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
|
@ -249,13 +271,21 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
])),
|
||||
const Spacer(),
|
||||
_getAccountList(
|
||||
activeLocalAccount: activeLocalAccount,
|
||||
activeLocalAccount:
|
||||
activeLocalAccount.unlockedAccountInfo?.superIdentityRecordKey,
|
||||
accountRecords: accountRecords),
|
||||
_getBottomButtons(),
|
||||
const Spacer(),
|
||||
Text('Version $packageInfoVersion',
|
||||
style: theme.textTheme.labelMedium!
|
||||
.copyWith(color: scale.tertiaryScale.hoverBorder))
|
||||
Row(children: [
|
||||
Text('Version $packageInfoVersion',
|
||||
style: theme.textTheme.labelMedium!
|
||||
.copyWith(color: scale.tertiaryScale.hoverBorder)),
|
||||
const Spacer(),
|
||||
SignalStrengthMeterWidget(
|
||||
color: scale.tertiaryScale.hoverBorder,
|
||||
inactiveColor: scale.tertiaryScale.border,
|
||||
),
|
||||
])
|
||||
]).paddingAll(16),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ class MenuItemWidget extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) => TextButton(
|
||||
onPressed: () => callback,
|
||||
onPressed: callback,
|
||||
style: TextButton.styleFrom(foregroundColor: foregroundColor).copyWith(
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
if (states.contains(WidgetState.hovered)) {
|
||||
|
|
|
@ -44,7 +44,7 @@ class _HomeAccountReadyMainState extends State<HomeAccountReadyMain> {
|
|||
WidgetStateProperty.all(scale.primaryScale.hoverBorder),
|
||||
shape: WidgetStateProperty.all(const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(16))))),
|
||||
tooltip: translate('app_bar.settings_tooltip'),
|
||||
tooltip: translate('menu.settings_tooltip'),
|
||||
onPressed: () async {
|
||||
final ctrl = context.read<ZoomDrawerController>();
|
||||
await ctrl.toggle?.call();
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import 'package:async_tools/async_tools.dart';
|
||||
import 'package:bloc_advanced_tools/bloc_advanced_tools.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:veilid_support/veilid_support.dart';
|
||||
|
||||
import '../../../account_manager/account_manager.dart';
|
||||
import '../../../chat/chat.dart';
|
||||
import '../../../chat_list/chat_list.dart';
|
||||
import '../../../contact_invitation/contact_invitation.dart';
|
||||
import '../../../contacts/contacts.dart';
|
||||
import '../../../conversation/conversation.dart';
|
||||
import '../../../router/router.dart';
|
||||
import '../../../theme/theme.dart';
|
||||
|
||||
|
@ -18,20 +17,17 @@ class HomeAccountReadyShell extends StatefulWidget {
|
|||
{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 activeLocalAccount = context.read<ActiveLocalAccountCubit>().state!;
|
||||
final activeAccountInfo = context.read<ActiveAccountInfo>();
|
||||
final unlockedAccountInfo = context.watch<UnlockedAccountInfo>();
|
||||
final routerCubit = context.read<RouterCubit>();
|
||||
|
||||
return HomeAccountReadyShell._(
|
||||
activeLocalAccount: activeLocalAccount,
|
||||
activeAccountInfo: activeAccountInfo,
|
||||
unlockedAccountInfo: unlockedAccountInfo,
|
||||
routerCubit: routerCubit,
|
||||
key: key,
|
||||
child: child);
|
||||
}
|
||||
const HomeAccountReadyShell._(
|
||||
{required this.activeLocalAccount,
|
||||
required this.activeAccountInfo,
|
||||
{required this.unlockedAccountInfo,
|
||||
required this.routerCubit,
|
||||
required this.child,
|
||||
super.key});
|
||||
|
@ -40,18 +36,15 @@ class HomeAccountReadyShell extends StatefulWidget {
|
|||
HomeAccountReadyShellState createState() => HomeAccountReadyShellState();
|
||||
|
||||
final Widget child;
|
||||
final TypedKey activeLocalAccount;
|
||||
final ActiveAccountInfo activeAccountInfo;
|
||||
final UnlockedAccountInfo unlockedAccountInfo;
|
||||
final RouterCubit routerCubit;
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
..add(DiagnosticsProperty<TypedKey>(
|
||||
'activeLocalAccount', activeLocalAccount))
|
||||
..add(DiagnosticsProperty<ActiveAccountInfo>(
|
||||
'activeAccountInfo', activeAccountInfo))
|
||||
..add(DiagnosticsProperty<UnlockedAccountInfo>(
|
||||
'unlockedAccountInfo', unlockedAccountInfo))
|
||||
..add(DiagnosticsProperty<RouterCubit>('routerCubit', routerCubit));
|
||||
}
|
||||
}
|
||||
|
@ -115,39 +108,41 @@ class HomeAccountReadyShellState extends State<HomeAccountReadyShell> {
|
|||
}
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
// Contact Cubits
|
||||
BlocProvider(
|
||||
create: (context) => ContactInvitationListCubit(
|
||||
activeAccountInfo: widget.activeAccountInfo,
|
||||
unlockedAccountInfo: widget.unlockedAccountInfo,
|
||||
account: account)),
|
||||
BlocProvider(
|
||||
create: (context) => ContactListCubit(
|
||||
activeAccountInfo: widget.activeAccountInfo,
|
||||
unlockedAccountInfo: widget.unlockedAccountInfo,
|
||||
account: account)),
|
||||
BlocProvider(
|
||||
create: (context) => ActiveChatCubit(null)
|
||||
..withStateListen((event) {
|
||||
widget.routerCubit.setHasActiveChat(event != null);
|
||||
})),
|
||||
BlocProvider(
|
||||
create: (context) => ChatListCubit(
|
||||
activeAccountInfo: widget.activeAccountInfo,
|
||||
activeChatCubit: context.read<ActiveChatCubit>(),
|
||||
account: account)),
|
||||
BlocProvider(
|
||||
create: (context) => ActiveConversationsBlocMapCubit(
|
||||
activeAccountInfo: widget.activeAccountInfo,
|
||||
contactListCubit: context.read<ContactListCubit>())
|
||||
..follow(context.read<ChatListCubit>())),
|
||||
BlocProvider(
|
||||
create: (context) => ActiveSingleContactChatBlocMapCubit(
|
||||
activeAccountInfo: widget.activeAccountInfo,
|
||||
contactListCubit: context.read<ContactListCubit>(),
|
||||
chatListCubit: context.read<ChatListCubit>())
|
||||
..follow(context.read<ActiveConversationsBlocMapCubit>())),
|
||||
BlocProvider(
|
||||
create: (context) => WaitingInvitationsBlocMapCubit(
|
||||
activeAccountInfo: widget.activeAccountInfo, account: account)
|
||||
..follow(context.read<ContactInvitationListCubit>()))
|
||||
unlockedAccountInfo: widget.unlockedAccountInfo,
|
||||
account: account)
|
||||
..follow(context.watch<ContactInvitationListCubit>())),
|
||||
// Chat Cubits
|
||||
BlocProvider(
|
||||
create: (context) => ActiveChatCubit(null,
|
||||
routerCubit: context.watch<RouterCubit>())),
|
||||
BlocProvider(
|
||||
create: (context) => ChatListCubit(
|
||||
unlockedAccountInfo: widget.unlockedAccountInfo,
|
||||
activeChatCubit: context.watch<ActiveChatCubit>(),
|
||||
account: account)),
|
||||
// Conversation Cubits
|
||||
BlocProvider(
|
||||
create: (context) => ActiveConversationsBlocMapCubit(
|
||||
unlockedAccountInfo: widget.unlockedAccountInfo,
|
||||
contactListCubit: context.watch<ContactListCubit>())
|
||||
..follow(context.watch<ChatListCubit>())),
|
||||
BlocProvider(
|
||||
create: (context) => ActiveSingleContactChatBlocMapCubit(
|
||||
unlockedAccountInfo: widget.unlockedAccountInfo,
|
||||
contactListCubit: context.watch<ContactListCubit>(),
|
||||
chatListCubit: context.watch<ChatListCubit>())
|
||||
..follow(context.watch<ActiveConversationsBlocMapCubit>())),
|
||||
],
|
||||
child: MultiBlocListener(listeners: [
|
||||
BlocListener<WaitingInvitationsBlocMapCubit,
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||
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';
|
||||
|
||||
|
@ -35,17 +33,19 @@ class HomeShellState extends State<HomeShell> {
|
|||
}
|
||||
|
||||
Widget buildWithLogin(BuildContext context) {
|
||||
final activeLocalAccount = context.watch<ActiveLocalAccountCubit>().state;
|
||||
final accountInfo = context.watch<ActiveAccountInfoCubit>().state;
|
||||
final accountRecordsCubit = context.watch<AccountRecordsBlocMapCubit>();
|
||||
if (activeLocalAccount == null) {
|
||||
if (!accountInfo.active) {
|
||||
// If no logged in user is active, show the loading panel
|
||||
return const HomeNoActive();
|
||||
}
|
||||
|
||||
final accountInfo =
|
||||
AccountRepository.instance.getAccountInfo(activeLocalAccount);
|
||||
final activeCubit =
|
||||
accountRecordsCubit.tryOperate(activeLocalAccount, closure: (c) => c);
|
||||
final superIdentityRecordKey =
|
||||
accountInfo.unlockedAccountInfo?.superIdentityRecordKey;
|
||||
final activeCubit = superIdentityRecordKey == null
|
||||
? null
|
||||
: accountRecordsCubit.tryOperate(superIdentityRecordKey,
|
||||
closure: (c) => c);
|
||||
if (activeCubit == null) {
|
||||
return waitingPage();
|
||||
}
|
||||
|
@ -59,8 +59,8 @@ class HomeShellState extends State<HomeShell> {
|
|||
return const HomeAccountLocked();
|
||||
case AccountInfoStatus.accountReady:
|
||||
return MultiProvider(providers: [
|
||||
Provider<ActiveAccountInfo>.value(
|
||||
value: accountInfo.activeAccountInfo!,
|
||||
Provider<UnlockedAccountInfo>.value(
|
||||
value: accountInfo.unlockedAccountInfo!,
|
||||
),
|
||||
Provider<AccountRecordCubit>.value(value: activeCubit),
|
||||
Provider<ZoomDrawerController>.value(value: _zoomDrawerController),
|
||||
|
@ -101,6 +101,7 @@ class HomeShellState extends State<HomeShell> {
|
|||
// duration: const Duration(milliseconds: 250),
|
||||
// reverseDuration: const Duration(milliseconds: 250),
|
||||
menuScreenTapClose: true,
|
||||
mainScreenTapClose: true,
|
||||
mainScreenScale: .25,
|
||||
slideWidth: min(360, MediaQuery.of(context).size.width * 0.9),
|
||||
)));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue