mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-06-29 00:27:13 -04:00
account management update
This commit is contained in:
parent
01c6490ec4
commit
5e4f47d5a1
42 changed files with 1663 additions and 831 deletions
|
@ -40,10 +40,10 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
}
|
||||
|
||||
void _doEditClick(TypedKey superIdentityRecordKey,
|
||||
proto.Profile existingProfile, OwnedDHTRecordPointer accountRecord) {
|
||||
proto.Account existingAccount, OwnedDHTRecordPointer accountRecord) {
|
||||
singleFuture(this, () async {
|
||||
await GoRouterHelper(context).push('/edit_account',
|
||||
extra: [superIdentityRecordKey, existingProfile, accountRecord]);
|
||||
extra: [superIdentityRecordKey, existingAccount, accountRecord]);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,45 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
borderRadius: BorderRadius.circular(borderRadius))),
|
||||
child: child);
|
||||
|
||||
Widget _makeAvatarWidget({
|
||||
required String name,
|
||||
required double size,
|
||||
required Color borderColor,
|
||||
required Color foregroundColor,
|
||||
required Color backgroundColor,
|
||||
required ScaleConfig scaleConfig,
|
||||
required TextStyle textStyle,
|
||||
ImageProvider<Object>? imageProvider,
|
||||
}) {
|
||||
final abbrev = name.split(' ').map((s) => s.isEmpty ? '' : s[0]).join();
|
||||
late final String shortname;
|
||||
if (abbrev.length >= 3) {
|
||||
shortname = abbrev[0] + abbrev[1] + abbrev[abbrev.length - 1];
|
||||
} else {
|
||||
shortname = abbrev;
|
||||
}
|
||||
|
||||
return Container(
|
||||
height: size,
|
||||
width: size,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: scaleConfig.preferBorders
|
||||
? Border.all(
|
||||
color: borderColor,
|
||||
width: 2 * (size ~/ 32 + 1),
|
||||
strokeAlign: BorderSide.strokeAlignOutside)
|
||||
: null,
|
||||
color: Colors.blue,
|
||||
),
|
||||
child: AvatarImage(
|
||||
//size: 32,
|
||||
backgroundImage: imageProvider,
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
child: Text(shortname, style: textStyle)));
|
||||
}
|
||||
|
||||
Widget _makeAccountWidget(
|
||||
{required String name,
|
||||
required bool selected,
|
||||
|
@ -67,13 +106,6 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
required void Function()? callback,
|
||||
required void Function()? footerCallback}) {
|
||||
final theme = Theme.of(context);
|
||||
final abbrev = name.split(' ').map((s) => s.isEmpty ? '' : s[0]).join();
|
||||
late final String shortname;
|
||||
if (abbrev.length >= 3) {
|
||||
shortname = abbrev[0] + abbrev[1] + abbrev[abbrev.length - 1];
|
||||
} else {
|
||||
shortname = abbrev;
|
||||
}
|
||||
|
||||
late final Color background;
|
||||
late final Color hoverBackground;
|
||||
|
@ -99,24 +131,15 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
activeBorder = scale.primary;
|
||||
}
|
||||
|
||||
final avatar = Container(
|
||||
height: 34,
|
||||
width: 34,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: scaleConfig.preferBorders
|
||||
? Border.all(
|
||||
color: border,
|
||||
width: 2,
|
||||
strokeAlign: BorderSide.strokeAlignOutside)
|
||||
: null,
|
||||
color: Colors.blue,
|
||||
),
|
||||
child: AvatarImage(
|
||||
//size: 32,
|
||||
backgroundColor: loggedIn ? scale.primary : scale.elementBackground,
|
||||
foregroundColor: loggedIn ? scale.primaryText : scale.subtleText,
|
||||
child: Text(shortname, style: theme.textTheme.titleLarge)));
|
||||
final avatar = AvatarWidget(
|
||||
name: name,
|
||||
size: 34,
|
||||
borderColor: border,
|
||||
foregroundColor: loggedIn ? scale.primaryText : scale.subtleText,
|
||||
backgroundColor: loggedIn ? scale.primary : scale.elementBackground,
|
||||
scaleConfig: scaleConfig,
|
||||
textStyle: theme.textTheme.titleLarge!,
|
||||
);
|
||||
|
||||
return AnimatedPadding(
|
||||
padding: EdgeInsets.fromLTRB(selected ? 0 : 8, selected ? 0 : 2,
|
||||
|
@ -190,7 +213,7 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||
footerCallback: () {
|
||||
_doEditClick(
|
||||
superIdentityRecordKey,
|
||||
value.profile,
|
||||
value,
|
||||
perAccountState.accountInfo.userLogin!.accountRecordInfo
|
||||
.accountRecord);
|
||||
}),
|
||||
|
|
|
@ -6,9 +6,10 @@ import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart';
|
|||
|
||||
import '../../account_manager/account_manager.dart';
|
||||
import '../../chat/chat.dart';
|
||||
import '../../chat_list/chat_list.dart';
|
||||
import '../../contacts/contacts.dart';
|
||||
import '../../proto/proto.dart' as proto;
|
||||
import '../../theme/theme.dart';
|
||||
import 'main_pager/main_pager.dart';
|
||||
|
||||
class HomeAccountReady extends StatefulWidget {
|
||||
const HomeAccountReady({super.key});
|
||||
|
@ -23,6 +24,75 @@ class _HomeAccountReadyState extends State<HomeAccountReady> {
|
|||
super.initState();
|
||||
}
|
||||
|
||||
Widget buildMenuButton() => Builder(builder: (context) {
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!;
|
||||
final scaleConfig = theme.extension<ScaleConfig>()!;
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.menu),
|
||||
color: scaleConfig.preferBorders
|
||||
? scale.primaryScale.border
|
||||
: scale.primaryScale.borderText,
|
||||
constraints: const BoxConstraints.expand(height: 48, width: 48),
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(
|
||||
scaleConfig.preferBorders
|
||||
? scale.primaryScale.hoverElementBackground
|
||||
: scale.primaryScale.hoverBorder),
|
||||
shape: WidgetStateProperty.all(
|
||||
RoundedRectangleBorder(
|
||||
side: !scaleConfig.useVisualIndicators
|
||||
? BorderSide.none
|
||||
: BorderSide(
|
||||
strokeAlign: BorderSide.strokeAlignCenter,
|
||||
color: scaleConfig.preferBorders
|
||||
? scale.primaryScale.border
|
||||
: scale.primaryScale.borderText,
|
||||
width: 2),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(12 * scaleConfig.borderRadiusScale))),
|
||||
)),
|
||||
tooltip: translate('menu.accounts_menu_tooltip'),
|
||||
onPressed: () async {
|
||||
final ctrl = context.read<ZoomDrawerController>();
|
||||
await ctrl.toggle?.call();
|
||||
});
|
||||
});
|
||||
|
||||
Widget buildContactsButton() => Builder(builder: (context) {
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!;
|
||||
final scaleConfig = theme.extension<ScaleConfig>()!;
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.contacts),
|
||||
color: scaleConfig.preferBorders
|
||||
? scale.primaryScale.border
|
||||
: scale.primaryScale.borderText,
|
||||
constraints: const BoxConstraints.expand(height: 48, width: 48),
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(
|
||||
scaleConfig.preferBorders
|
||||
? scale.primaryScale.hoverElementBackground
|
||||
: scale.primaryScale.hoverBorder),
|
||||
shape: WidgetStateProperty.all(
|
||||
RoundedRectangleBorder(
|
||||
side: !scaleConfig.useVisualIndicators
|
||||
? BorderSide.none
|
||||
: BorderSide(
|
||||
strokeAlign: BorderSide.strokeAlignCenter,
|
||||
color: scaleConfig.preferBorders
|
||||
? scale.primaryScale.border
|
||||
: scale.primaryScale.borderText,
|
||||
width: 2),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(12 * scaleConfig.borderRadiusScale))),
|
||||
)),
|
||||
tooltip: translate('menu.contacts_tooltip'),
|
||||
onPressed: () async {
|
||||
await ContactsDialog.show(context);
|
||||
});
|
||||
});
|
||||
|
||||
Widget buildUserPanel() => Builder(builder: (context) {
|
||||
final profile = context.select<AccountRecordCubit, proto.Profile>(
|
||||
(c) => c.state.asData!.value.profile);
|
||||
|
@ -36,43 +106,14 @@ class _HomeAccountReadyState extends State<HomeAccountReady> {
|
|||
: scale.primaryScale.subtleBorder,
|
||||
child: Column(children: <Widget>[
|
||||
Row(children: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.menu),
|
||||
color: scaleConfig.preferBorders
|
||||
? scale.primaryScale.border
|
||||
: scale.primaryScale.borderText,
|
||||
constraints:
|
||||
const BoxConstraints.expand(height: 48, width: 48),
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(
|
||||
scaleConfig.preferBorders
|
||||
? scale.primaryScale.hoverElementBackground
|
||||
: scale.primaryScale.hoverBorder),
|
||||
shape: WidgetStateProperty.all(
|
||||
RoundedRectangleBorder(
|
||||
side: !scaleConfig.useVisualIndicators
|
||||
? BorderSide.none
|
||||
: BorderSide(
|
||||
strokeAlign: BorderSide.strokeAlignCenter,
|
||||
color: scaleConfig.preferBorders
|
||||
? scale.primaryScale.border
|
||||
: scale.primaryScale.borderText,
|
||||
width: 2),
|
||||
borderRadius: BorderRadius.all(Radius.circular(
|
||||
12 * scaleConfig.borderRadiusScale))),
|
||||
)),
|
||||
tooltip: translate('menu.settings_tooltip'),
|
||||
onPressed: () async {
|
||||
final ctrl = context.read<ZoomDrawerController>();
|
||||
await ctrl.toggle?.call();
|
||||
//await GoRouterHelper(context).push('/settings');
|
||||
}).paddingLTRB(0, 0, 8, 0),
|
||||
buildMenuButton().paddingLTRB(0, 0, 8, 0),
|
||||
ProfileWidget(
|
||||
profile: profile,
|
||||
showPronouns: false,
|
||||
).expanded(),
|
||||
buildContactsButton().paddingLTRB(8, 0, 0, 0),
|
||||
]).paddingAll(8),
|
||||
MainPager(key: _mainPagerKey).expanded()
|
||||
const ChatListWidget().expanded()
|
||||
]));
|
||||
});
|
||||
|
||||
|
@ -156,7 +197,4 @@ class _HomeAccountReadyState extends State<HomeAccountReady> {
|
|||
]);
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
final _mainPagerKey = GlobalKey(debugLabel: '_mainPagerKey');
|
||||
}
|
||||
|
|
|
@ -132,7 +132,14 @@ class HomeScreenState extends State<HomeScreen>
|
|||
|
||||
// Re-export all ready blocs to the account display subtree
|
||||
return perAccountCollectionState.provide(
|
||||
child: const HomeAccountReady());
|
||||
child: Navigator(
|
||||
onPopPage: (route, result) {
|
||||
if (!route.didPop(result)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
pages: const [MaterialPage(child: HomeAccountReady())]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BottomSheetActionButton extends StatefulWidget {
|
||||
const BottomSheetActionButton(
|
||||
{required this.bottomSheetBuilder,
|
||||
required this.builder,
|
||||
this.foregroundColor,
|
||||
this.backgroundColor,
|
||||
this.shape,
|
||||
super.key});
|
||||
final Color? foregroundColor;
|
||||
final Color? backgroundColor;
|
||||
final ShapeBorder? shape;
|
||||
final Widget Function(BuildContext) builder;
|
||||
final Widget Function(BuildContext) bottomSheetBuilder;
|
||||
|
||||
@override
|
||||
BottomSheetActionButtonState createState() => BottomSheetActionButtonState();
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
..add(ObjectFlagProperty<Widget Function(BuildContext p1)>.has(
|
||||
'bottomSheetBuilder', bottomSheetBuilder))
|
||||
..add(ColorProperty('foregroundColor', foregroundColor))
|
||||
..add(ColorProperty('backgroundColor', backgroundColor))
|
||||
..add(DiagnosticsProperty<ShapeBorder?>('shape', shape))
|
||||
..add(ObjectFlagProperty<Widget? Function(BuildContext p1)>.has(
|
||||
'builder', builder));
|
||||
}
|
||||
}
|
||||
|
||||
class BottomSheetActionButtonState extends State<BottomSheetActionButton> {
|
||||
bool _showFab = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
//
|
||||
return _showFab
|
||||
? FloatingActionButton(
|
||||
elevation: 0,
|
||||
heroTag: this,
|
||||
hoverElevation: 0,
|
||||
shape: widget.shape,
|
||||
foregroundColor: widget.foregroundColor,
|
||||
backgroundColor: widget.backgroundColor,
|
||||
child: widget.builder(context),
|
||||
onPressed: () async {
|
||||
await showModalBottomSheet<void>(
|
||||
context: context, builder: widget.bottomSheetBuilder);
|
||||
},
|
||||
)
|
||||
: Container();
|
||||
}
|
||||
|
||||
void showFloatingActionButton(bool value) {
|
||||
setState(() {
|
||||
_showFab = value;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../chat_list/chat_list.dart';
|
||||
|
||||
class ChatsPage extends StatefulWidget {
|
||||
const ChatsPage({super.key});
|
||||
|
||||
@override
|
||||
ChatsPageState createState() => ChatsPageState();
|
||||
}
|
||||
|
||||
class ChatsPageState extends State<ChatsPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
return const ChatListWidget();
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
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 '../../../contact_invitation/contact_invitation.dart';
|
||||
import '../../../contacts/contacts.dart';
|
||||
|
||||
class ContactsPage extends StatefulWidget {
|
||||
const ContactsPage({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
ContactsPageState createState() => ContactsPageState();
|
||||
}
|
||||
|
||||
class ContactsPageState extends State<ContactsPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
// final theme = Theme.of(context);
|
||||
// final textTheme = theme.textTheme;
|
||||
// final scale = theme.extension<ScaleScheme>()!;
|
||||
// final scaleConfig = theme.extension<ScaleConfig>()!;
|
||||
|
||||
final cilState = context.watch<ContactInvitationListCubit>().state;
|
||||
final cilBusy = cilState.busy;
|
||||
final contactInvitationRecordList =
|
||||
cilState.state.asData?.value.map((x) => x.value).toIList() ??
|
||||
const IListConst([]);
|
||||
|
||||
final ciState = context.watch<ContactListCubit>().state;
|
||||
final ciBusy = ciState.busy;
|
||||
final contactList =
|
||||
ciState.state.asData?.value.map((x) => x.value).toIList();
|
||||
|
||||
return CustomScrollView(slivers: [
|
||||
if (contactInvitationRecordList.isNotEmpty)
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
sliver: ContactInvitationListWidget(
|
||||
contactInvitationRecordList: contactInvitationRecordList,
|
||||
disabled: cilBusy)),
|
||||
ContactListWidget(contactList: contactList, disabled: ciBusy)
|
||||
]).paddingLTRB(8, 0, 8, 8);
|
||||
}
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:animated_bottom_navigation_bar/'
|
||||
'animated_bottom_navigation_bar.dart';
|
||||
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
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 '../../../chat/chat.dart';
|
||||
import '../../../contact_invitation/contact_invitation.dart';
|
||||
import '../../../theme/theme.dart';
|
||||
import 'bottom_sheet_action_button.dart';
|
||||
import 'chats_page.dart';
|
||||
import 'contacts_page.dart';
|
||||
|
||||
class MainPager extends StatefulWidget {
|
||||
const MainPager({super.key});
|
||||
|
||||
@override
|
||||
MainPagerState createState() => MainPagerState();
|
||||
|
||||
static MainPagerState? of(BuildContext context) =>
|
||||
context.findAncestorStateOfType<MainPagerState>();
|
||||
}
|
||||
|
||||
class MainPagerState extends State<MainPager> with TickerProviderStateMixin {
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
pageController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> scanContactInvitationDialog(BuildContext context) async {
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
// ignore: prefer_expression_function_bodies
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
contentPadding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
),
|
||||
title: const Text(
|
||||
'Scan Contact Invite',
|
||||
style: TextStyle(fontSize: 24),
|
||||
),
|
||||
content: ScanInvitationDialog(
|
||||
locator: context.read,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildBottomBarItem(int index, bool isActive) {
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!;
|
||||
final scaleConfig = theme.extension<ScaleConfig>()!;
|
||||
|
||||
final color = scaleConfig.useVisualIndicators
|
||||
? (scaleConfig.preferBorders
|
||||
? scale.primaryScale.border
|
||||
: scale.primaryScale.borderText)
|
||||
: (isActive
|
||||
? (scaleConfig.preferBorders
|
||||
? scale.primaryScale.border
|
||||
: scale.primaryScale.borderText)
|
||||
: (scaleConfig.preferBorders
|
||||
? scale.primaryScale.subtleBorder
|
||||
: scale.primaryScale.borderText.withAlpha(0x80)));
|
||||
|
||||
final item = Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
_selectedIconList[index],
|
||||
size: 24,
|
||||
color: color,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Text(
|
||||
_bottomLabelList[index],
|
||||
style: theme.textTheme.labelMedium!.copyWith(
|
||||
fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
|
||||
color: color),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
if (scaleConfig.useVisualIndicators && isActive) {
|
||||
return DecoratedBox(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
14 * scaleConfig.borderRadiusScale),
|
||||
side: BorderSide(
|
||||
width: 2,
|
||||
color: scaleConfig.preferBorders
|
||||
? scale.primaryScale.border
|
||||
: scale.primaryScale.borderText))),
|
||||
child: item)
|
||||
.paddingLTRB(8, 0, 8, 6);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
Widget _bottomSheetBuilder(BuildContext sheetContext, BuildContext context) {
|
||||
if (currentPage == 0) {
|
||||
// New contact invitation
|
||||
return newContactBottomSheetBuilder(sheetContext, context);
|
||||
} else if (currentPage == 1) {
|
||||
// New chat
|
||||
return newChatBottomSheetBuilder(sheetContext, context);
|
||||
} else {
|
||||
// Unknown error
|
||||
return debugPage('unknown page');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!;
|
||||
final scaleConfig = theme.extension<ScaleConfig>()!;
|
||||
|
||||
return Scaffold(
|
||||
//extendBody: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
body: PreloadPageView(
|
||||
key: _pageViewKey,
|
||||
controller: pageController,
|
||||
preloadPagesCount: 2,
|
||||
onPageChanged: (index) {
|
||||
setState(() {
|
||||
currentPage = index;
|
||||
});
|
||||
},
|
||||
children: const [
|
||||
ContactsPage(),
|
||||
ChatsPage(),
|
||||
]),
|
||||
// appBar: AppBar(
|
||||
// toolbarHeight: 24,
|
||||
// title: Text(
|
||||
// 'C',
|
||||
// style: Theme.of(context).textTheme.headlineSmall,
|
||||
// ),
|
||||
// ),
|
||||
bottomNavigationBar: AnimatedBottomNavigationBar.builder(
|
||||
itemCount: 2,
|
||||
height: 64,
|
||||
tabBuilder: _buildBottomBarItem,
|
||||
activeIndex: currentPage,
|
||||
gapLocation: GapLocation.end,
|
||||
gapWidth: 90,
|
||||
notchSmoothness: NotchSmoothness.defaultEdge,
|
||||
notchMargin: 4,
|
||||
backgroundColor: scaleConfig.preferBorders
|
||||
? scale.primaryScale.hoverElementBackground
|
||||
: scale.primaryScale.hoverBorder,
|
||||
elevation: 0,
|
||||
onTap: (index) async {
|
||||
await pageController.animateToPage(index,
|
||||
duration: 250.ms, curve: Curves.easeInOut);
|
||||
},
|
||||
),
|
||||
floatingActionButton: BottomSheetActionButton(
|
||||
shape: CircleBorder(
|
||||
side: !scaleConfig.useVisualIndicators
|
||||
? BorderSide.none
|
||||
: BorderSide(
|
||||
strokeAlign: BorderSide.strokeAlignCenter,
|
||||
color: scaleConfig.preferBorders
|
||||
? scale.secondaryScale.border
|
||||
: scale.secondaryScale.borderText,
|
||||
width: 2),
|
||||
),
|
||||
foregroundColor: scaleConfig.preferBorders
|
||||
? scale.secondaryScale.border
|
||||
: scale.secondaryScale.borderText,
|
||||
backgroundColor: scaleConfig.preferBorders
|
||||
? scale.secondaryScale.hoverElementBackground
|
||||
: scale.secondaryScale.hoverBorder,
|
||||
builder: (context) => Icon(
|
||||
_fabIconList[currentPage],
|
||||
color: scaleConfig.preferBorders
|
||||
? scale.secondaryScale.border
|
||||
: scale.secondaryScale.borderText,
|
||||
),
|
||||
bottomSheetBuilder: (sheetContext) =>
|
||||
_bottomSheetBuilder(sheetContext, context)),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
|
||||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
final _selectedIconList = <IconData>[Icons.person, Icons.chat];
|
||||
// final _unselectedIconList = <IconData>[
|
||||
// Icons.chat_outlined,
|
||||
// Icons.person_outlined
|
||||
// ];
|
||||
final _fabIconList = <IconData>[
|
||||
Icons.person_add_sharp,
|
||||
Icons.chat,
|
||||
];
|
||||
final _bottomLabelList = <String>[
|
||||
translate('pager.contacts'),
|
||||
translate('pager.chats'),
|
||||
];
|
||||
final _pageViewKey = GlobalKey(debugLabel: '_pageViewKey');
|
||||
|
||||
// key-accessible controller
|
||||
int currentPage = 0;
|
||||
final pageController = PreloadPageController();
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
..add(IntProperty('currentPage', currentPage))
|
||||
..add(DiagnosticsProperty<PreloadPageController>(
|
||||
'pageController', pageController));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue