veilidchat/lib/layout/home/home_screen.dart

200 lines
7.1 KiB
Dart
Raw Normal View History

2024-07-24 15:20:29 -04:00
import 'dart:async';
2024-06-11 21:27:20 -04:00
import 'dart:math';
2024-07-24 15:20:29 -04:00
import 'package:flutter/gestures.dart';
2024-02-11 23:18:20 -05:00
import 'package:flutter/material.dart';
2024-07-24 15:20:29 -04:00
import 'package:flutter_translate/flutter_translate.dart';
2024-06-11 21:27:20 -04:00
import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart';
2024-02-13 22:03:26 -05:00
import 'package:provider/provider.dart';
2024-07-24 15:20:29 -04:00
import 'package:quickalert/quickalert.dart';
2024-06-24 19:44:08 -04:00
import 'package:transitioned_indexed_stack/transitioned_indexed_stack.dart';
2024-07-24 15:20:29 -04:00
import 'package:url_launcher/url_launcher_string.dart';
2024-06-15 23:29:15 -04:00
import 'package:veilid_support/veilid_support.dart';
2024-02-11 23:18:20 -05:00
2024-02-13 22:03:26 -05:00
import '../../account_manager/account_manager.dart';
2024-02-11 23:18:20 -05:00
import '../../theme/theme.dart';
2024-06-11 21:27:20 -04:00
import 'drawer_menu/drawer_menu.dart';
2024-02-13 22:03:26 -05:00
import 'home_account_invalid.dart';
import 'home_account_locked.dart';
import 'home_account_missing.dart';
2024-07-09 13:27:54 -04:00
import 'home_account_ready.dart';
2024-02-13 22:03:26 -05:00
import 'home_no_active.dart';
2024-02-11 23:18:20 -05:00
2024-06-16 22:12:24 -04:00
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
2024-02-11 23:18:20 -05:00
@override
2024-06-16 22:12:24 -04:00
HomeScreenState createState() => HomeScreenState();
2024-06-24 19:44:08 -04:00
static HomeScreenState? of(BuildContext context) =>
context.findAncestorStateOfType<HomeScreenState>();
2024-02-11 23:18:20 -05:00
}
2024-06-24 19:44:08 -04:00
class HomeScreenState extends State<HomeScreen>
with SingleTickerProviderStateMixin {
2024-02-11 23:18:20 -05:00
@override
void initState() {
2024-07-03 20:59:54 -04:00
WidgetsBinding.instance.addPostFrameCallback((_) async {
final localAccounts = context.read<LocalAccountsCubit>().state;
final activeLocalAccount = context.read<ActiveLocalAccountCubit>().state;
final activeIndex = localAccounts
.indexWhere((x) => x.superIdentity.recordKey == activeLocalAccount);
final canClose = activeIndex != -1;
2024-07-24 15:20:29 -04:00
unawaited(_doBetaDialog(context));
2024-07-03 20:59:54 -04:00
if (!canClose) {
await _zoomDrawerController.open!();
}
});
2024-02-11 23:18:20 -05:00
super.initState();
}
2024-07-24 15:20:29 -04:00
Future<void> _doBetaDialog(BuildContext context) async {
await QuickAlert.show(
context: context,
title: translate('splash.beta_title'),
widget: RichText(
textAlign: TextAlign.center,
text: TextSpan(
children: <TextSpan>[
TextSpan(
text: translate('splash.beta_text'),
style: const TextStyle(
color: Colors.black87,
),
),
TextSpan(
text: 'https://veilid.com/chat/beta',
style: const TextStyle(
color: Colors.blue,
decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap =
() => launchUrlString('https://veilid.com/chat/beta'),
),
],
),
),
type: QuickAlertType.warning);
}
2024-06-24 19:44:08 -04:00
Widget _buildAccountPage(
BuildContext context,
TypedKey superIdentityRecordKey,
2024-06-19 11:35:51 -04:00
PerAccountCollectionState perAccountCollectionState) {
switch (perAccountCollectionState.accountInfo.status) {
case AccountInfoStatus.accountInvalid:
return const HomeAccountInvalid();
case AccountInfoStatus.accountLocked:
return const HomeAccountLocked();
case AccountInfoStatus.accountUnlocked:
// Are we ready to render?
if (!perAccountCollectionState.isReady) {
return waitingPage();
}
2024-02-13 22:03:26 -05:00
2024-06-19 11:35:51 -04:00
// Re-export all ready blocs to the account display subtree
return perAccountCollectionState.provide(
2024-07-09 13:27:54 -04:00
child: const HomeAccountReady());
2024-06-19 11:35:51 -04:00
}
2024-06-15 23:29:15 -04:00
}
2024-07-06 20:09:18 -04:00
Widget _applyPageBorder(Widget child) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final scaleConfig = theme.extension<ScaleConfig>()!;
return ValueListenableBuilder(
valueListenable: _zoomDrawerController.stateNotifier!,
child: child,
builder: (context, drawerState, staticChild) => clipBorder(
clipEnabled: drawerState != DrawerState.closed,
borderEnabled:
scaleConfig.preferBorders && scaleConfig.useVisualIndicators,
borderRadius: 16 * scaleConfig.borderRadiusScale,
borderColor: scale.primaryScale.border,
child: staticChild!));
}
2024-06-16 22:12:24 -04:00
Widget _buildAccountPageView(BuildContext context) {
final localAccounts = context.watch<LocalAccountsCubit>().state;
2024-06-20 19:04:39 -04:00
final activeLocalAccount = context.watch<ActiveLocalAccountCubit>().state;
2024-06-19 11:35:51 -04:00
final perAccountCollectionBlocMapState =
context.watch<PerAccountCollectionBlocMapCubit>().state;
2024-06-16 22:12:24 -04:00
2024-06-20 19:04:39 -04:00
final activeIndex = localAccounts
.indexWhere((x) => x.superIdentity.recordKey == activeLocalAccount);
2024-06-16 22:12:24 -04:00
if (activeIndex == -1) {
2024-07-06 20:09:18 -04:00
return _applyPageBorder(const HomeNoActive());
2024-02-13 22:03:26 -05:00
}
2024-06-16 22:12:24 -04:00
2024-06-24 19:44:08 -04:00
final accountPages = <Widget>[];
for (var i = 0; i < localAccounts.length; i++) {
final superIdentityRecordKey = localAccounts[i].superIdentity.recordKey;
final perAccountCollectionState =
perAccountCollectionBlocMapState.get(superIdentityRecordKey);
if (perAccountCollectionState == null) {
return HomeAccountMissing(key: ValueKey(superIdentityRecordKey));
}
final accountPage = _buildAccountPage(
context, superIdentityRecordKey, perAccountCollectionState);
2024-07-06 20:09:18 -04:00
accountPages.add(_applyPageBorder(accountPage));
2024-06-24 19:44:08 -04:00
}
return SlideIndexedStack(
index: activeIndex,
beginSlideOffset: const Offset(1, 0),
children: accountPages,
);
2024-02-13 22:03:26 -05:00
}
2024-02-11 23:18:20 -05:00
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
2024-06-11 21:27:20 -04:00
2024-07-03 20:59:54 -04:00
final localAccounts = context.watch<LocalAccountsCubit>().state;
final activeLocalAccount = context.watch<ActiveLocalAccountCubit>().state;
final activeIndex = localAccounts
.indexWhere((x) => x.superIdentity.recordKey == activeLocalAccount);
final canClose = activeIndex != -1;
2024-02-11 23:18:20 -05:00
return SafeArea(
2024-07-06 20:09:18 -04:00
child: DefaultTextStyle(
style: theme.textTheme.bodySmall!,
2024-06-11 21:27:20 -04:00
child: ZoomDrawer(
controller: _zoomDrawerController,
//menuBackgroundColor: Colors.transparent,
2024-06-24 19:44:08 -04:00
menuScreen: Builder(builder: (context) {
final zoomDrawer = ZoomDrawer.of(context);
zoomDrawer!.stateNotifier.addListener(() {
if (zoomDrawer.isOpen()) {
FocusManager.instance.primaryFocus?.unfocus();
}
});
return const DrawerMenu();
}),
mainScreen: Provider<ZoomDrawerController>.value(
value: _zoomDrawerController,
child: Builder(builder: _buildAccountPageView)),
2024-07-06 20:09:18 -04:00
borderRadius: 0,
2024-06-11 21:27:20 -04:00
angle: 0,
2024-07-06 20:09:18 -04:00
mainScreenOverlayColor: theme.shadowColor.withAlpha(0x2F),
2024-06-11 21:27:20 -04:00
openCurve: Curves.fastEaseInToSlowEaseOut,
// duration: const Duration(milliseconds: 250),
// reverseDuration: const Duration(milliseconds: 250),
2024-07-03 20:59:54 -04:00
menuScreenTapClose: canClose,
mainScreenTapClose: canClose,
disableDragGesture: !canClose,
2024-07-06 20:09:18 -04:00
mainScreenScale: .15,
2024-06-11 21:27:20 -04:00
slideWidth: min(360, MediaQuery.of(context).size.width * 0.9),
)));
2024-02-11 23:18:20 -05:00
}
2024-06-11 21:27:20 -04:00
2024-06-24 19:44:08 -04:00
////////////////////////////////////////////////////////////////////////////
2024-06-15 23:29:15 -04:00
final _zoomDrawerController = ZoomDrawerController();
2024-02-11 23:18:20 -05:00
}