mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-05-14 12:12:27 -04:00
refactor
This commit is contained in:
parent
b35b618a4d
commit
7cf44ef192
21 changed files with 338 additions and 82 deletions
40
lib/layout/home/home_account_ready/chat_only.dart
Normal file
40
lib/layout/home/home_account_ready/chat_only.dart
Normal file
|
@ -0,0 +1,40 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../chat/chat.dart';
|
||||
import '../../../tools/tools.dart';
|
||||
|
||||
class ChatOnlyPage extends StatefulWidget {
|
||||
const ChatOnlyPage({super.key});
|
||||
|
||||
@override
|
||||
ChatOnlyPageState createState() => ChatOnlyPageState();
|
||||
}
|
||||
|
||||
class ChatOnlyPageState extends State<ChatOnlyPage>
|
||||
with TickerProviderStateMixin {
|
||||
final _unfocusNode = FocusNode();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
setState(() {});
|
||||
await changeWindowSetup(
|
||||
TitleBarStyle.normal, OrientationCapability.normal);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_unfocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SafeArea(
|
||||
child: GestureDetector(
|
||||
onTap: () => FocusScope.of(context).requestFocus(_unfocusNode),
|
||||
child: buildChatComponent(),
|
||||
));
|
||||
}
|
235
lib/layout/home/home_account_ready/home_account_ready.dart
Normal file
235
lib/layout/home/home_account_ready/home_account_ready.dart
Normal file
|
@ -0,0 +1,235 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_translate/flutter_translate.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:veilid_support/veilid_support.dart';
|
||||
|
||||
import '../../../account_manager/account_manager.dart';
|
||||
import '../../../contact_invitation/contact_invitation.dart';
|
||||
import '../../../proto/proto.dart' as proto;
|
||||
import '../../../theme/theme.dart';
|
||||
import '../../../tools/tools.dart';
|
||||
|
||||
class HomeAccountReady extends StatefulWidget {
|
||||
const HomeAccountReady(
|
||||
{required IList<LocalAccount> localAccounts,
|
||||
required TypedKey activeUserLogin,
|
||||
required ActiveAccountInfo activeAccountInfo,
|
||||
required proto.Account account,
|
||||
super.key})
|
||||
: _localAccounts = localAccounts,
|
||||
_activeUserLogin = activeUserLogin,
|
||||
_activeAccountInfo = activeAccountInfo,
|
||||
_account = account;
|
||||
|
||||
final IList<LocalAccount> _localAccounts;
|
||||
final TypedKey _activeUserLogin;
|
||||
final ActiveAccountInfo _activeAccountInfo;
|
||||
final proto.Account _account;
|
||||
|
||||
@override
|
||||
HomeAccountReadyState createState() => HomeAccountReadyState();
|
||||
}
|
||||
|
||||
class HomeAccountReadyState extends State<HomeAccountReady>
|
||||
with TickerProviderStateMixin {
|
||||
//
|
||||
ContactInvitationRepository? _contactInvitationRepository;
|
||||
|
||||
//
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// Async initialize repositories for the active user
|
||||
// xxx: this should not be necessary
|
||||
// xxx: but RepositoryProvider doesn't call dispose()
|
||||
Future.delayed(Duration.zero, () async {
|
||||
//
|
||||
final cir = await ContactInvitationRepository.open(
|
||||
widget._activeAccountInfo, widget._account);
|
||||
|
||||
setState(() {
|
||||
_contactInvitationRepository = cir;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_contactInvitationRepository?.dispose();
|
||||
}
|
||||
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget buildAccountList() {
|
||||
return const Column(children: [
|
||||
Center(child: Text('Small Profile')),
|
||||
Center(child: Text('Contact invitations')),
|
||||
Center(child: Text('Contacts'))
|
||||
]);
|
||||
}
|
||||
|
||||
Widget buildUnlockAccount(
|
||||
BuildContext context,
|
||||
IList<LocalAccount> localAccounts,
|
||||
// ignore: prefer_expression_function_bodies
|
||||
) {
|
||||
return const Center(child: Text('unlock account'));
|
||||
}
|
||||
|
||||
/// We have an active, unlocked, user login
|
||||
Widget buildReadyAccount(
|
||||
BuildContext context,
|
||||
IList<LocalAccount> localAccounts,
|
||||
TypedKey activeUserLogin,
|
||||
DHTRecord accountRecord) {
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!;
|
||||
|
||||
xxx get rid of the cubit here and
|
||||
|
||||
return BlocProvider(
|
||||
create: (context) => AccountRecordCubit(record: accountRecord),
|
||||
child: Column(children: <Widget>[
|
||||
Row(children: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.settings),
|
||||
color: scale.secondaryScale.text,
|
||||
constraints: const BoxConstraints.expand(height: 64, width: 64),
|
||||
style: ButtonStyle(
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all(scale.secondaryScale.border),
|
||||
shape: MaterialStateProperty.all(
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(16))))),
|
||||
tooltip: translate('app_bar.settings_tooltip'),
|
||||
onPressed: () async {
|
||||
context.go('/home/settings');
|
||||
}).paddingLTRB(0, 0, 8, 0),
|
||||
context
|
||||
.watch<AccountRecordCubit>()
|
||||
.state
|
||||
.builder((context, account) => ProfileWidget(
|
||||
name: account.profile.name,
|
||||
pronouns: account.profile.pronouns,
|
||||
))
|
||||
.expanded(),
|
||||
]).paddingAll(8),
|
||||
context
|
||||
.watch<AccountRecordCubit>()
|
||||
.state
|
||||
.builder((context, account) => MainPager(
|
||||
localAccounts: localAccounts,
|
||||
activeUserLogin: activeUserLogin,
|
||||
account: account))
|
||||
.expanded()
|
||||
]));
|
||||
}
|
||||
|
||||
xxx get rid of this whole function
|
||||
|
||||
Widget buildUserPanel() => Builder(builder: (context) {
|
||||
final activeUserLogin = context.watch<ActiveUserLoginCubit>().state;
|
||||
final localAccounts = context.watch<LocalAccountsCubit>().state;
|
||||
|
||||
if (activeUserLogin == null) {
|
||||
// If no logged in user is active, show the loading panel
|
||||
return waitingPage(context);
|
||||
}
|
||||
|
||||
final account = AccountRepository.instance
|
||||
.getAccountInfo(accountMasterRecordKey: activeUserLogin)!;
|
||||
|
||||
switch (account.status) {
|
||||
case AccountInfoStatus.noAccount:
|
||||
Future.delayed(0.ms, () async {
|
||||
await showErrorModal(
|
||||
context,
|
||||
translate('home.missing_account_title'),
|
||||
translate('home.missing_account_text'));
|
||||
// Delete account
|
||||
await AccountRepository.instance
|
||||
.deleteLocalAccount(activeUserLogin);
|
||||
// Switch to no active user login
|
||||
await AccountRepository.instance.switchToAccount(null);
|
||||
});
|
||||
return waitingPage(context);
|
||||
case AccountInfoStatus.accountInvalid:
|
||||
Future.delayed(0.ms, () async {
|
||||
await showErrorModal(
|
||||
context,
|
||||
translate('home.invalid_account_title'),
|
||||
translate('home.invalid_account_text'));
|
||||
// Delete account
|
||||
await AccountRepository.instance
|
||||
.deleteLocalAccount(activeUserLogin);
|
||||
// Switch to no active user login
|
||||
await AccountRepository.instance.switchToAccount(null);
|
||||
});
|
||||
return waitingPage(context);
|
||||
case AccountInfoStatus.accountLocked:
|
||||
// Show unlock widget
|
||||
return buildUnlockAccount(context, localAccounts);
|
||||
case AccountInfoStatus.accountReady:
|
||||
return buildReadyAccount(
|
||||
context,
|
||||
localAccounts,
|
||||
activeUserLogin,
|
||||
account.activeAccountInfo!.accountRecord,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Widget buildPhone() =>
|
||||
Material(color: Colors.transparent, child: buildUserPanel());
|
||||
|
||||
Widget buildTabletLeftPane() =>
|
||||
Material(color: Colors.transparent, child: buildUserPanel());
|
||||
|
||||
Widget buildTabletRightPane() => buildChatComponent();
|
||||
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget buildTablet() => Builder(builder: (context) {
|
||||
final w = MediaQuery.of(context).size.width;
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!;
|
||||
|
||||
final children = [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 300, maxWidth: 300),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: w / 2),
|
||||
child: buildTabletLeftPane())),
|
||||
SizedBox(
|
||||
width: 2,
|
||||
height: double.infinity,
|
||||
child: ColoredBox(color: scale.primaryScale.hoverBorder)),
|
||||
Expanded(child: buildTabletRightPane()),
|
||||
];
|
||||
|
||||
return Row(
|
||||
children: children,
|
||||
);
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_contactInvitationRepository == null) {
|
||||
return waitingPage(context);
|
||||
}
|
||||
|
||||
return responsiveVisibility(
|
||||
context: context,
|
||||
phone: false,
|
||||
)
|
||||
? buildTablet()
|
||||
: buildPhone();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_translate/flutter_translate.dart';
|
||||
import 'package:veilid_support/veilid_support.dart';
|
||||
|
||||
import '../../../../proto/proto.dart' as proto;
|
||||
import '../../../account_manager/account_manager.dart';
|
||||
import '../../../contact_invitation/contact_invitation.dart';
|
||||
import '../../../contacts/contacts.dart';
|
||||
import '../../../theme/theme.dart';
|
||||
|
||||
class AccountPage extends StatefulWidget {
|
||||
const AccountPage({
|
||||
required this.localAccounts,
|
||||
required this.activeUserLogin,
|
||||
required this.account,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final IList<LocalAccount> localAccounts;
|
||||
final TypedKey activeUserLogin;
|
||||
final proto.Account account;
|
||||
|
||||
@override
|
||||
AccountPageState createState() => AccountPageState();
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
..add(IterableProperty<LocalAccount>('localAccounts', localAccounts))
|
||||
..add(DiagnosticsProperty<TypedKey>('activeUserLogin', activeUserLogin))
|
||||
..add(DiagnosticsProperty<proto.Account>('account', account));
|
||||
}
|
||||
}
|
||||
|
||||
class AccountPageState extends State<AccountPage> {
|
||||
final _unfocusNode = FocusNode();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_unfocusNode.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 records = widget.account.contactInvitationRecords;
|
||||
|
||||
final contactInvitationRecordList =
|
||||
ref.watch(fetchContactInvitationRecordsProvider).asData?.value ??
|
||||
const IListConst([]);
|
||||
final contactList = ref.watch(fetchContactListProvider).asData?.value ??
|
||||
const IListConst([]);
|
||||
|
||||
return SizedBox(
|
||||
child: Column(children: <Widget>[
|
||||
if (contactInvitationRecordList.isNotEmpty)
|
||||
ExpansionTile(
|
||||
tilePadding: EdgeInsets.fromLTRB(8, 0, 8, 0),
|
||||
backgroundColor: scale.primaryScale.border,
|
||||
collapsedBackgroundColor: scale.primaryScale.border,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
collapsedShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
title: Text(
|
||||
translate('account_page.contact_invitations'),
|
||||
textAlign: TextAlign.center,
|
||||
style: textTheme.titleMedium!
|
||||
.copyWith(color: scale.primaryScale.subtleText),
|
||||
),
|
||||
initiallyExpanded: true,
|
||||
children: [
|
||||
ContactInvitationListWidget(
|
||||
contactInvitationRecordList: contactInvitationRecordList)
|
||||
],
|
||||
).paddingLTRB(8, 0, 8, 8),
|
||||
ContactListWidget(contactList: contactList).expanded(),
|
||||
]));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
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,
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../proto/proto.dart' as proto;
|
||||
import '../../../account_manager/account_manager.dart';
|
||||
import '../../../tools/tools.dart';
|
||||
|
||||
class ChatsPage extends StatefulWidget {
|
||||
const ChatsPage({super.key});
|
||||
|
||||
@override
|
||||
ChatsPageState createState() => ChatsPageState();
|
||||
}
|
||||
|
||||
class ChatsPageState extends State<ChatsPage> {
|
||||
final _unfocusNode = FocusNode();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_unfocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// We have an active, unlocked, user login
|
||||
Widget buildChatList(
|
||||
BuildContext context,
|
||||
IList<LocalAccount> localAccounts,
|
||||
TypedKey activeUserLogin,
|
||||
proto.Account account,
|
||||
// ignore: prefer_expression_function_bodies
|
||||
) {
|
||||
final contactList = ref.watch(fetchContactListProvider).asData?.value ??
|
||||
const IListConst([]);
|
||||
final chatList =
|
||||
ref.watch(fetchChatListProvider).asData?.value ?? const IListConst([]);
|
||||
|
||||
return Column(children: <Widget>[
|
||||
if (chatList.isNotEmpty)
|
||||
ChatSingleContactListWidget(
|
||||
contactList: contactList, chatList: chatList)
|
||||
.expanded(),
|
||||
if (chatList.isEmpty) const EmptyChatListWidget().expanded(),
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
final localAccountsV = ref.watch(localAccountsProvider);
|
||||
final loginsV = ref.watch(loginsProvider);
|
||||
|
||||
if (!localAccountsV.hasValue || !loginsV.hasValue) {
|
||||
return waitingPage(context);
|
||||
}
|
||||
final localAccounts = localAccountsV.requireValue;
|
||||
final logins = loginsV.requireValue;
|
||||
|
||||
final activeUserLogin = logins.activeUserLogin;
|
||||
if (activeUserLogin == null) {
|
||||
// If no logged in user is active show a placeholder
|
||||
return waitingPage(context);
|
||||
}
|
||||
final accountV = ref
|
||||
.watch(fetchAccountProvider(accountMasterRecordKey: activeUserLogin));
|
||||
if (!accountV.hasValue) {
|
||||
return waitingPage(context);
|
||||
}
|
||||
final account = accountV.requireValue;
|
||||
switch (account.status) {
|
||||
case AccountInfoStatus.noAccount:
|
||||
return waitingPage(context);
|
||||
case AccountInfoStatus.accountInvalid:
|
||||
return waitingPage(context);
|
||||
case AccountInfoStatus.accountLocked:
|
||||
return waitingPage(context);
|
||||
case AccountInfoStatus.accountReady:
|
||||
return buildChatList(
|
||||
context,
|
||||
localAccounts,
|
||||
activeUserLogin,
|
||||
account.account!,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
252
lib/layout/home/home_account_ready/main_pager/main_pager.dart
Normal file
252
lib/layout/home/home_account_ready/main_pager/main_pager.dart
Normal file
|
@ -0,0 +1,252 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
import 'package:flutter/foundation.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:stylish_bottom_bar/model/bar_items.dart';
|
||||
import 'package:stylish_bottom_bar/stylish_bottom_bar.dart';
|
||||
import 'package:veilid_support/veilid_support.dart';
|
||||
|
||||
import '../../../../proto/proto.dart' as proto;
|
||||
import '../../../../tools/tools.dart';
|
||||
import '../../../account_manager/account_manager.dart';
|
||||
import '../../../contact_invitation/contact_invitation.dart';
|
||||
import '../../../theme/theme.dart';
|
||||
import 'account_page.dart';
|
||||
import 'bottom_sheet_action_button.dart';
|
||||
import 'chats_page.dart';
|
||||
|
||||
class MainPager extends StatefulWidget {
|
||||
const MainPager(
|
||||
{required this.localAccounts,
|
||||
required this.activeUserLogin,
|
||||
required this.account,
|
||||
super.key});
|
||||
|
||||
final IList<LocalAccount> localAccounts;
|
||||
final TypedKey activeUserLogin;
|
||||
final proto.Account account;
|
||||
|
||||
@override
|
||||
MainPagerState createState() => MainPagerState();
|
||||
|
||||
static MainPagerState? of(BuildContext context) =>
|
||||
context.findAncestorStateOfType<MainPagerState>();
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
..add(IterableProperty<LocalAccount>('localAccounts', localAccounts))
|
||||
..add(DiagnosticsProperty<TypedKey>('activeUserLogin', activeUserLogin))
|
||||
..add(DiagnosticsProperty<proto.Account>('account', account));
|
||||
}
|
||||
}
|
||||
|
||||
class MainPagerState extends State<MainPager> with TickerProviderStateMixin {
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
final _unfocusNode = FocusNode();
|
||||
|
||||
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.account'),
|
||||
translate('pager.chats'),
|
||||
];
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_unfocusNode.dispose();
|
||||
pageController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool onScrollNotification(ScrollNotification notification) {
|
||||
if (notification is UserScrollNotification &&
|
||||
notification.metrics.axis == Axis.vertical) {
|
||||
switch (notification.direction) {
|
||||
case ScrollDirection.forward:
|
||||
// _hideBottomBarAnimationController.reverse();
|
||||
// _fabAnimationController.forward(from: 0);
|
||||
break;
|
||||
case ScrollDirection.reverse:
|
||||
// _hideBottomBarAnimationController.forward();
|
||||
// _fabAnimationController.reverse(from: 1);
|
||||
break;
|
||||
case ScrollDirection.idle:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BottomBarItem buildBottomBarItem(int index) {
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!;
|
||||
return BottomBarItem(
|
||||
title: Text(_bottomLabelList[index]),
|
||||
icon: Icon(_selectedIconList[index], color: scale.primaryScale.text),
|
||||
selectedIcon:
|
||||
Icon(_selectedIconList[index], color: scale.primaryScale.text),
|
||||
backgroundColor: scale.primaryScale.text,
|
||||
//unSelectedColor: theme.colorScheme.primaryContainer,
|
||||
//selectedColor: theme.colorScheme.primary,
|
||||
//badge: const Text('9+'),
|
||||
//showBadge: true,
|
||||
);
|
||||
}
|
||||
|
||||
List<BottomBarItem> _buildBottomBarItems() {
|
||||
final bottomBarItems = List<BottomBarItem>.empty(growable: true);
|
||||
for (var index = 0; index < _bottomLabelList.length; index++) {
|
||||
final item = buildBottomBarItem(index);
|
||||
bottomBarItems.add(item);
|
||||
}
|
||||
return bottomBarItems;
|
||||
}
|
||||
|
||||
Future<void> scanContactInvitationDialog(BuildContext context) async {
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
// ignore: prefer_expression_function_bodies
|
||||
builder: (context) {
|
||||
return const AlertDialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
contentPadding: EdgeInsets.only(
|
||||
top: 10,
|
||||
),
|
||||
title: Text(
|
||||
'Scan Contact Invite',
|
||||
style: TextStyle(fontSize: 24),
|
||||
),
|
||||
content: ScanInviteDialog());
|
||||
});
|
||||
}
|
||||
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget _onNewChatBottomSheetBuilder(BuildContext context) {
|
||||
return const SizedBox(
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Group and custom chat functionality is not available yet')));
|
||||
}
|
||||
|
||||
Widget _bottomSheetBuilder(BuildContext context) {
|
||||
if (_currentPage == 0) {
|
||||
// New contact invitation
|
||||
return newContactInvitationBottomSheetBuilder(context);
|
||||
} else if (_currentPage == 1) {
|
||||
// New chat
|
||||
return _onNewChatBottomSheetBuilder(context);
|
||||
} else {
|
||||
// Unknown error
|
||||
return waitingPage(context);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: prefer_expression_function_bodies
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final scale = theme.extension<ScaleScheme>()!;
|
||||
|
||||
return Scaffold(
|
||||
//extendBody: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
body: NotificationListener<ScrollNotification>(
|
||||
onNotification: onScrollNotification,
|
||||
child: PreloadPageView(
|
||||
controller: pageController,
|
||||
preloadPagesCount: 2,
|
||||
onPageChanged: (index) {
|
||||
setState(() {
|
||||
_currentPage = index;
|
||||
});
|
||||
},
|
||||
children: [
|
||||
AccountPage(
|
||||
localAccounts: widget.localAccounts,
|
||||
activeUserLogin: widget.activeUserLogin,
|
||||
account: widget.account),
|
||||
const ChatsPage(),
|
||||
])),
|
||||
// appBar: AppBar(
|
||||
// toolbarHeight: 24,
|
||||
// title: Text(
|
||||
// 'C',
|
||||
// style: Theme.of(context).textTheme.headlineSmall,
|
||||
// ),
|
||||
// ),
|
||||
bottomNavigationBar: StylishBottomBar(
|
||||
backgroundColor: scale.primaryScale.hoverBorder,
|
||||
// gradient: LinearGradient(
|
||||
// begin: Alignment.topCenter,
|
||||
// end: Alignment.bottomCenter,
|
||||
// colors: <Color>[
|
||||
// theme.colorScheme.primary,
|
||||
// theme.colorScheme.primaryContainer,
|
||||
// ]),
|
||||
//borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||
option: AnimatedBarOptions(
|
||||
// iconSize: 32,
|
||||
//barAnimation: BarAnimation.fade,
|
||||
iconStyle: IconStyle.animated,
|
||||
inkEffect: true,
|
||||
inkColor: scale.primaryScale.hoverBackground,
|
||||
//opacity: 0.3,
|
||||
),
|
||||
items: _buildBottomBarItems(),
|
||||
hasNotch: true,
|
||||
fabLocation: StylishBarFabLocation.end,
|
||||
currentIndex: _currentPage,
|
||||
onTap: (index) async {
|
||||
await pageController.animateToPage(index,
|
||||
duration: 250.ms, curve: Curves.easeInOut);
|
||||
},
|
||||
),
|
||||
|
||||
floatingActionButton: BottomSheetActionButton(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(14))),
|
||||
foregroundColor: scale.secondaryScale.text,
|
||||
backgroundColor: scale.secondaryScale.hoverBorder,
|
||||
builder: (context) => Icon(
|
||||
_fabIconList[_currentPage],
|
||||
color: scale.secondaryScale.text,
|
||||
),
|
||||
bottomSheetBuilder: _bottomSheetBuilder),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DiagnosticsProperty<PreloadPageController>(
|
||||
'pageController', pageController));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue