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
|
|
|
}
|