ui cleanups

This commit is contained in:
Christien Rioux 2024-06-24 23:44:08 +00:00
parent 01ba275c71
commit 8c89ce91cf
8 changed files with 175 additions and 136 deletions

View File

@ -1,37 +0,0 @@
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,4 +1,3 @@
export 'active_account_page_controller_wrapper.dart';
export 'drawer_menu/drawer_menu.dart'; export 'drawer_menu/drawer_menu.dart';
export 'home_account_invalid.dart'; export 'home_account_invalid.dart';
export 'home_account_locked.dart'; export 'home_account_locked.dart';

View File

@ -1,4 +1,5 @@
import 'package:awesome_extensions/awesome_extensions.dart'; import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_translate/flutter_translate.dart'; import 'package:flutter_translate/flutter_translate.dart';
@ -35,27 +36,32 @@ class _HomeAccountReadyMainState extends State<HomeAccountReadyMain> {
final theme = Theme.of(context); final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!; final scale = theme.extension<ScaleScheme>()!;
return Column(children: <Widget>[ return ColoredBox(
Row(children: [ color: scale.primaryScale.subtleBorder,
IconButton( child: Column(children: <Widget>[
icon: const Icon(Icons.menu), Row(children: [
color: scale.secondaryScale.borderText, IconButton(
constraints: const BoxConstraints.expand(height: 64, width: 64), icon: const Icon(Icons.menu),
style: ButtonStyle( color: scale.secondaryScale.borderText,
backgroundColor: constraints:
WidgetStateProperty.all(scale.primaryScale.hoverBorder), const BoxConstraints.expand(height: 64, width: 64),
shape: WidgetStateProperty.all(const RoundedRectangleBorder( style: ButtonStyle(
borderRadius: BorderRadius.all(Radius.circular(16))))), backgroundColor: WidgetStateProperty.all(
tooltip: translate('menu.settings_tooltip'), scale.primaryScale.hoverBorder),
onPressed: () async { shape: WidgetStateProperty.all(
final ctrl = context.read<ZoomDrawerController>(); const RoundedRectangleBorder(
await ctrl.toggle?.call(); borderRadius:
//await GoRouterHelper(context).push('/settings'); BorderRadius.all(Radius.circular(16))))),
}).paddingLTRB(0, 0, 8, 0), tooltip: translate('menu.settings_tooltip'),
ProfileWidget(profile: profile).expanded(), onPressed: () async {
]).paddingAll(8), final ctrl = context.read<ZoomDrawerController>();
const MainPager().expanded() await ctrl.toggle?.call();
]); //await GoRouterHelper(context).push('/settings');
}).paddingLTRB(0, 0, 8, 0),
ProfileWidget(profile: profile).expanded(),
]).paddingAll(8),
MainPager(key: _mainPagerKey).expanded()
]));
}); });
Widget buildPhone(BuildContext context) => Widget buildPhone(BuildContext context) =>
@ -107,4 +113,7 @@ class _HomeAccountReadyMainState extends State<HomeAccountReadyMain> {
) )
? buildTablet(context) ? buildTablet(context)
: buildPhone(context); : buildPhone(context);
////////////////////////////////////////////////////////////////////////////
final _mainPagerKey = GlobalKey(debugLabel: '_mainPagerKey');
} }

View File

@ -28,25 +28,6 @@ class MainPager extends StatefulWidget {
class MainPagerState extends State<MainPager> with TickerProviderStateMixin { class MainPagerState extends State<MainPager> with TickerProviderStateMixin {
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
var _currentPage = 0;
final pageController = PreloadPageController();
final _selectedIconList = <IconData>[Icons.person, Icons.chat];
// final _unselectedIconList = <IconData>[
// Icons.chat_outlined,
// Icons.person_outlined
// ];
final _fabIconList = <IconData>[
Icons.person_add_sharp,
Icons.add_comment_sharp,
];
final _bottomLabelList = <String>[
translate('pager.contacts'),
translate('pager.chats'),
];
//////////////////////////////////////////////////////////////////
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -124,10 +105,10 @@ class MainPagerState extends State<MainPager> with TickerProviderStateMixin {
} }
Widget _bottomSheetBuilder(BuildContext sheetContext, BuildContext context) { Widget _bottomSheetBuilder(BuildContext sheetContext, BuildContext context) {
if (_currentPage == 0) { if (currentPage == 0) {
// New contact invitation // New contact invitation
return newContactBottomSheetBuilder(sheetContext, context); return newContactBottomSheetBuilder(sheetContext, context);
} else if (_currentPage == 1) { } else if (currentPage == 1) {
// New chat // New chat
return newChatBottomSheetBuilder(sheetContext, context); return newChatBottomSheetBuilder(sheetContext, context);
} else { } else {
@ -148,11 +129,12 @@ class MainPagerState extends State<MainPager> with TickerProviderStateMixin {
body: NotificationListener<ScrollNotification>( body: NotificationListener<ScrollNotification>(
onNotification: onScrollNotification, onNotification: onScrollNotification,
child: PreloadPageView( child: PreloadPageView(
key: _pageViewKey,
controller: pageController, controller: pageController,
preloadPagesCount: 2, preloadPagesCount: 2,
onPageChanged: (index) { onPageChanged: (index) {
setState(() { setState(() {
_currentPage = index; currentPage = index;
}); });
}, },
children: const [ children: const [
@ -176,7 +158,7 @@ class MainPagerState extends State<MainPager> with TickerProviderStateMixin {
items: _buildBottomBarItems(), items: _buildBottomBarItems(),
hasNotch: true, hasNotch: true,
fabLocation: StylishBarFabLocation.end, fabLocation: StylishBarFabLocation.end,
currentIndex: _currentPage, currentIndex: currentPage,
onTap: (index) async { onTap: (index) async {
await pageController.animateToPage(index, await pageController.animateToPage(index,
duration: 250.ms, curve: Curves.easeInOut); duration: 250.ms, curve: Curves.easeInOut);
@ -189,7 +171,7 @@ class MainPagerState extends State<MainPager> with TickerProviderStateMixin {
foregroundColor: scale.secondaryScale.borderText, foregroundColor: scale.secondaryScale.borderText,
backgroundColor: scale.secondaryScale.hoverBorder, backgroundColor: scale.secondaryScale.hoverBorder,
builder: (context) => Icon( builder: (context) => Icon(
_fabIconList[_currentPage], _fabIconList[currentPage],
color: scale.secondaryScale.borderText, color: scale.secondaryScale.borderText,
), ),
bottomSheetBuilder: (sheetContext) => bottomSheetBuilder: (sheetContext) =>
@ -198,10 +180,33 @@ class MainPagerState extends State<MainPager> with TickerProviderStateMixin {
); );
} }
//////////////////////////////////////////////////////////////////
final _selectedIconList = <IconData>[Icons.person, Icons.chat];
// final _unselectedIconList = <IconData>[
// Icons.chat_outlined,
// Icons.person_outlined
// ];
final _fabIconList = <IconData>[
Icons.person_add_sharp,
Icons.add_comment_sharp,
];
final _bottomLabelList = <String>[
translate('pager.contacts'),
translate('pager.chats'),
];
final _pageViewKey = GlobalKey(debugLabel: '_pageViewKey');
// key-accessible controller
int currentPage = 0;
final pageController = PreloadPageController();
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<PreloadPageController>( properties
'pageController', pageController)); ..add(IntProperty('currentPage', currentPage))
..add(DiagnosticsProperty<PreloadPageController>(
'pageController', pageController));
} }
} }

View File

@ -1,16 +1,16 @@
import 'dart:math'; import 'dart:math';
import 'package:async_tools/async_tools.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:transitioned_indexed_stack/transitioned_indexed_stack.dart';
import 'package:veilid_support/veilid_support.dart'; import 'package:veilid_support/veilid_support.dart';
import '../../account_manager/account_manager.dart'; import '../../account_manager/account_manager.dart';
import '../../chat/chat.dart'; import '../../chat/chat.dart';
import '../../theme/theme.dart'; import '../../theme/theme.dart';
import '../../tools/tools.dart'; import '../../tools/tools.dart';
import 'active_account_page_controller_wrapper.dart';
import 'drawer_menu/drawer_menu.dart'; import 'drawer_menu/drawer_menu.dart';
import 'home_account_invalid.dart'; import 'home_account_invalid.dart';
import 'home_account_locked.dart'; import 'home_account_locked.dart';
@ -23,34 +23,71 @@ class HomeScreen extends StatefulWidget {
@override @override
HomeScreenState createState() => HomeScreenState(); HomeScreenState createState() => HomeScreenState();
static HomeScreenState? of(BuildContext context) =>
context.findAncestorStateOfType<HomeScreenState>();
} }
class HomeScreenState extends State<HomeScreen> { class HomeScreenState extends State<HomeScreen>
with SingleTickerProviderStateMixin {
@override @override
void initState() { void initState() {
// Chat animation setup (open in phone mode)
_chatAnimationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 250),
);
_chatAnimation = Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(CurvedAnimation(
parent: _chatAnimationController,
curve: Curves.easeInOut,
));
// Account animation setup
super.initState(); super.initState();
} }
@override @override
void dispose() { void dispose() {
_chatAnimationController.dispose();
super.dispose(); super.dispose();
} }
Widget _buildAccountReadyDeviceSpecific(BuildContext context) { Widget _buildAccountReadyDeviceSpecific(BuildContext context) {
final hasActiveChat = context.watch<ActiveChatCubit>().state != null;
if (responsiveVisibility( if (responsiveVisibility(
context: context, context: context,
tablet: false, tablet: false,
tabletLandscape: false, tabletLandscape: false,
desktop: false)) { desktop: false)) {
if (hasActiveChat) { return BlocConsumer<ActiveChatCubit, TypedKey?>(
return const HomeAccountReadyChat(); listener: (context, activeChat) {
} final hasActiveChat = activeChat != null;
if (hasActiveChat) {
_chatAnimationController.forward();
} else {
_chatAnimationController.reset();
}
},
builder: (context, activeChat) => Stack(
children: <Widget>[
const HomeAccountReadyMain(),
Offstage(
offstage: activeChat == null,
child: SlideTransition(
position: _chatAnimation,
child: const HomeAccountReadyChat())),
],
));
} }
return const HomeAccountReadyMain(); return const HomeAccountReadyMain();
} }
Widget _buildAccount(BuildContext context, TypedKey superIdentityRecordKey, Widget _buildAccountPage(
BuildContext context,
TypedKey superIdentityRecordKey,
PerAccountCollectionState perAccountCollectionState) { PerAccountCollectionState perAccountCollectionState) {
switch (perAccountCollectionState.accountInfo.status) { switch (perAccountCollectionState.accountInfo.status) {
case AccountInfoStatus.accountInvalid: case AccountInfoStatus.accountInvalid:
@ -81,38 +118,25 @@ class HomeScreenState extends State<HomeScreen> {
return const HomeNoActive(); return const HomeNoActive();
} }
return Provider<ActiveAccountPageControllerWrapper>( final accountPages = <Widget>[];
lazy: false,
create: (context) => for (var i = 0; i < localAccounts.length; i++) {
ActiveAccountPageControllerWrapper(context.read, activeIndex), final superIdentityRecordKey = localAccounts[i].superIdentity.recordKey;
dispose: (context, value) { final perAccountCollectionState =
value.dispose(); perAccountCollectionBlocMapState.get(superIdentityRecordKey);
}, if (perAccountCollectionState == null) {
child: Builder( return HomeAccountMissing(key: ValueKey(superIdentityRecordKey));
builder: (context) => PageView.builder( }
onPageChanged: (idx) { final accountPage = _buildAccountPage(
singleFuture(this, () async { context, superIdentityRecordKey, perAccountCollectionState);
await AccountRepository.instance.switchToAccount( accountPages.add(KeyedSubtree.wrap(accountPage, i));
localAccounts[idx].superIdentity.recordKey); }
});
}, return SlideIndexedStack(
controller: context index: activeIndex,
.read<ActiveAccountPageControllerWrapper>() beginSlideOffset: const Offset(1, 0),
.pageController, children: accountPages,
itemCount: localAccounts.length, );
itemBuilder: (context, index) {
final superIdentityRecordKey =
localAccounts[index].superIdentity.recordKey;
final perAccountCollectionState =
perAccountCollectionBlocMapState
.get(superIdentityRecordKey);
if (perAccountCollectionState == null) {
return HomeAccountMissing(
key: ValueKey(superIdentityRecordKey));
}
return _buildAccount(context, superIdentityRecordKey,
perAccountCollectionState);
})));
} }
@override @override
@ -134,15 +158,20 @@ class HomeScreenState extends State<HomeScreen> {
child: ZoomDrawer( child: ZoomDrawer(
controller: _zoomDrawerController, controller: _zoomDrawerController,
//menuBackgroundColor: Colors.transparent, //menuBackgroundColor: Colors.transparent,
menuScreen: const DrawerMenu(), menuScreen: Builder(builder: (context) {
mainScreen: DecoratedBox( final zoomDrawer = ZoomDrawer.of(context);
decoration: BoxDecoration( zoomDrawer!.stateNotifier.addListener(() {
color: scale.primaryScale.activeElementBackground), if (zoomDrawer.isOpen()) {
child: Provider<ZoomDrawerController>.value( FocusManager.instance.primaryFocus?.unfocus();
value: _zoomDrawerController, }
child: Builder(builder: _buildAccountPageView))), });
return const DrawerMenu();
}),
mainScreen: Provider<ZoomDrawerController>.value(
value: _zoomDrawerController,
child: Builder(builder: _buildAccountPageView)),
borderRadius: 24, borderRadius: 24,
showShadow: true, //showShadow: false,
angle: 0, angle: 0,
drawerShadowsBackgroundColor: theme.shadowColor, drawerShadowsBackgroundColor: theme.shadowColor,
mainScreenOverlayColor: theme.shadowColor.withAlpha(0x3F), mainScreenOverlayColor: theme.shadowColor.withAlpha(0x3F),
@ -151,10 +180,15 @@ class HomeScreenState extends State<HomeScreen> {
// reverseDuration: const Duration(milliseconds: 250), // reverseDuration: const Duration(milliseconds: 250),
menuScreenTapClose: true, menuScreenTapClose: true,
mainScreenTapClose: true, mainScreenTapClose: true,
//disableDragGesture: false,
mainScreenScale: .25, mainScreenScale: .25,
slideWidth: min(360, MediaQuery.of(context).size.width * 0.9), slideWidth: min(360, MediaQuery.of(context).size.width * 0.9),
))); )));
} }
////////////////////////////////////////////////////////////////////////////
final _zoomDrawerController = ZoomDrawerController(); final _zoomDrawerController = ZoomDrawerController();
late final Animation<Offset> _chatAnimation;
late final AnimationController _chatAnimationController;
} }

View File

@ -2,6 +2,12 @@ import 'dart:io' show Platform;
import 'package:veilid/veilid.dart'; import 'package:veilid/veilid.dart';
// ignore: do_not_use_environment
const bool _kReleaseMode = bool.fromEnvironment('dart.vm.product');
// ignore: do_not_use_environment
const bool _kProfileMode = bool.fromEnvironment('dart.vm.profile');
const bool _kDebugMode = !_kReleaseMode && !_kProfileMode;
Map<String, dynamic> getDefaultVeilidPlatformConfig( Map<String, dynamic> getDefaultVeilidPlatformConfig(
bool isWeb, String appName) { bool isWeb, String appName) {
final ignoreLogTargetsStr = final ignoreLogTargetsStr =
@ -16,7 +22,9 @@ Map<String, dynamic> getDefaultVeilidPlatformConfig(
logging: VeilidWASMConfigLogging( logging: VeilidWASMConfigLogging(
performance: VeilidWASMConfigLoggingPerformance( performance: VeilidWASMConfigLoggingPerformance(
enabled: true, enabled: true,
level: VeilidConfigLogLevel.debug, level: _kDebugMode
? VeilidConfigLogLevel.debug
: VeilidConfigLogLevel.info,
logsInTimings: true, logsInTimings: true,
logsInConsole: false, logsInConsole: false,
ignoreLogTargets: ignoreLogTargets), ignoreLogTargets: ignoreLogTargets),
@ -29,8 +37,11 @@ Map<String, dynamic> getDefaultVeilidPlatformConfig(
return VeilidFFIConfig( return VeilidFFIConfig(
logging: VeilidFFIConfigLogging( logging: VeilidFFIConfigLogging(
terminal: VeilidFFIConfigLoggingTerminal( terminal: VeilidFFIConfigLoggingTerminal(
enabled: false, enabled:
level: VeilidConfigLogLevel.debug, _kDebugMode && (Platform.isIOS || Platform.isAndroid),
level: _kDebugMode
? VeilidConfigLogLevel.debug
: VeilidConfigLogLevel.info,
ignoreLogTargets: ignoreLogTargets), ignoreLogTargets: ignoreLogTargets),
otlp: VeilidFFIConfigLoggingOtlp( otlp: VeilidFFIConfigLoggingOtlp(
enabled: false, enabled: false,

View File

@ -17,6 +17,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.4.1" version: "6.4.1"
animated_switcher_transitions:
dependency: "direct main"
description:
name: animated_switcher_transitions
sha256: "0f3ef1b46ab3f0b5efe784dcff55bbeabdc75a3b9bcbefbf2315468c9cec87c3"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
animated_theme_switcher: animated_theme_switcher:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1399,6 +1407,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.1" version: "1.0.1"
transitioned_indexed_stack:
dependency: "direct main"
description:
name: transitioned_indexed_stack
sha256: "8023abb5efe72e6d40cc3775fb03d7504c32ac918ec2ce7f9ba6804753820259"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:

View File

@ -8,6 +8,7 @@ environment:
flutter: '>=3.22.1' flutter: '>=3.22.1'
dependencies: dependencies:
animated_switcher_transitions: ^1.0.0
animated_theme_switcher: ^2.0.10 animated_theme_switcher: ^2.0.10
ansicolor: ^2.0.2 ansicolor: ^2.0.2
archive: ^3.6.1 archive: ^3.6.1
@ -83,6 +84,7 @@ dependencies:
stack_trace: ^1.11.1 stack_trace: ^1.11.1
stream_transform: ^2.1.0 stream_transform: ^2.1.0
stylish_bottom_bar: ^1.1.0 stylish_bottom_bar: ^1.1.0
transitioned_indexed_stack: ^1.0.2
uuid: ^4.4.0 uuid: ^4.4.0
veilid: veilid:
# veilid: ^0.0.1 # veilid: ^0.0.1