refactor some more

This commit is contained in:
Christien Rioux 2023-12-27 22:56:24 -05:00
parent 2adc958128
commit c516323e7d
91 changed files with 1237 additions and 748 deletions

View file

@ -1,13 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:signal_strength_indicator/signal_strength_indicator.dart';
import 'package:go_router/go_router.dart';
import 'package:veilid_support/veilid_support.dart';
import '../providers/connection_state.dart';
import '../tools/tools.dart';
import '../veilid_support/veilid_support.dart';
class SignalStrengthMeterWidget extends ConsumerWidget {
xxx move to feature level
class SignalStrengthMeterWidget extends Widget {
const SignalStrengthMeterWidget({super.key});
@override

View file

@ -1,53 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'preferences.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$LockPreferenceImpl _$$LockPreferenceImplFromJson(Map<String, dynamic> json) =>
_$LockPreferenceImpl(
inactivityLockSecs: json['inactivity_lock_secs'] as int,
lockWhenSwitching: json['lock_when_switching'] as bool,
lockWithSystemLock: json['lock_with_system_lock'] as bool,
);
Map<String, dynamic> _$$LockPreferenceImplToJson(
_$LockPreferenceImpl instance) =>
<String, dynamic>{
'inactivity_lock_secs': instance.inactivityLockSecs,
'lock_when_switching': instance.lockWhenSwitching,
'lock_with_system_lock': instance.lockWithSystemLock,
};
_$ThemePreferencesImpl _$$ThemePreferencesImplFromJson(
Map<String, dynamic> json) =>
_$ThemePreferencesImpl(
brightnessPreference:
BrightnessPreference.fromJson(json['brightness_preference']),
colorPreference: ColorPreference.fromJson(json['color_preference']),
displayScale: (json['display_scale'] as num).toDouble(),
);
Map<String, dynamic> _$$ThemePreferencesImplToJson(
_$ThemePreferencesImpl instance) =>
<String, dynamic>{
'brightness_preference': instance.brightnessPreference.toJson(),
'color_preference': instance.colorPreference.toJson(),
'display_scale': instance.displayScale,
};
_$PreferencesImpl _$$PreferencesImplFromJson(Map<String, dynamic> json) =>
_$PreferencesImpl(
themePreferences: ThemePreferences.fromJson(json['theme_preferences']),
language: LanguagePreference.fromJson(json['language']),
locking: LockPreference.fromJson(json['locking']),
);
Map<String, dynamic> _$$PreferencesImplToJson(_$PreferencesImpl instance) =>
<String, dynamic>{
'theme_preferences': instance.themePreferences.toJson(),
'language': instance.language.toJson(),
'locking': instance.locking.toJson(),
};

View file

@ -14,7 +14,7 @@ import 'package:quickalert/quickalert.dart';
import 'package:xterm/xterm.dart';
import '../../tools/tools.dart';
import '../../veilid_support/veilid_support.dart';
import '../../../packages/veilid_support/veilid_support.dart';
final globalDebugTerminal = Terminal(
maxLines: 50000,

View file

@ -18,7 +18,7 @@ import '../../local_accounts/local_accounts.dart';
import '../providers/logins.dart';
import '../providers/window_control.dart';
import '../../tools/tools.dart';
import '../../veilid_support/veilid_support.dart';
import '../../../packages/veilid_support/veilid_support.dart';
import 'main_pager/main_pager.dart';
class HomePage extends StatefulWidget {

View file

@ -15,7 +15,7 @@ import '../../providers/contact.dart';
import '../../providers/contact_invite.dart';
import '../../../theme/theme.dart';
import '../../../tools/tools.dart';
import '../../../veilid_support/veilid_support.dart';
import '../../../../packages/veilid_support/veilid_support.dart';
class AccountPage extends ConsumerStatefulWidget {
const AccountPage({

View file

@ -13,7 +13,7 @@ import '../../providers/contact.dart';
import '../../../local_accounts/local_accounts.dart';
import '../../providers/logins.dart';
import '../../../tools/tools.dart';
import '../../../veilid_support/veilid_support.dart';
import '../../../../packages/veilid_support/veilid_support.dart';
class ChatsPage extends ConsumerStatefulWidget {
const ChatsPage({super.key});

View file

@ -20,7 +20,7 @@ import '../../../components/send_invite_dialog.dart';
import '../../../entities/local_account.dart';
import '../../../proto/proto.dart' as proto;
import '../../../tools/tools.dart';
import '../../../veilid_support/veilid_support.dart';
import '../../../../packages/veilid_support/veilid_support.dart';
import 'account.dart';
import 'chats.dart';

View file

@ -1,175 +0,0 @@
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_translate/flutter_translate.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:go_router/go_router.dart';
import '../../components/default_app_bar.dart';
import '../../components/signal_strength_meter.dart';
import '../../entities/entities.dart';
import '../../local_accounts/local_accounts.dart';
import '../providers/logins.dart';
import '../providers/window_control.dart';
import '../../tools/tools.dart';
import '../../veilid_support/veilid_support.dart';
class NewAccountPage extends StatefulWidget {
const NewAccountPage({super.key});
@override
NewAccountPageState createState() => NewAccountPageState();
}
class NewAccountPageState extends ConsumerState<NewAccountPage> {
final _formKey = GlobalKey<FormBuilderState>();
late bool isInAsyncCall = false;
static const String formFieldName = 'name';
static const String formFieldPronouns = 'pronouns';
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
setState(() {});
await ref.read(windowControlProvider.notifier).changeWindowSetup(
TitleBarStyle.normal, OrientationCapability.portraitOnly);
});
}
/// Creates a new master identity, an account associated with the master
/// identity, stores the account in the identity key and then logs into
/// that account with no password set at this time
Future<void> createAccount() async {
final localAccounts = ref.read(localAccountsProvider.notifier);
final logins = ref.read(loginsProvider.notifier);
final name = _formKey.currentState!.fields[formFieldName]!.value as String;
final pronouns =
_formKey.currentState!.fields[formFieldPronouns]!.value as String? ??
'';
final imws = await IdentityMasterWithSecrets.create();
try {
final localAccount = await localAccounts.newLocalAccount(
identityMaster: imws.identityMaster,
identitySecret: imws.identitySecret,
name: name,
pronouns: pronouns);
// Log in the new account by default with no pin
final ok = await logins.login(localAccount.identityMaster.masterRecordKey,
EncryptionKeyType.none, '');
assert(ok, 'login with none should never fail');
} on Exception catch (_) {
await imws.delete();
rethrow;
}
}
Widget _newAccountForm(BuildContext context,
{required Future<void> Function(GlobalKey<FormBuilderState>)
onSubmit}) =>
FormBuilder(
key: _formKey,
child: ListView(
children: [
Text(translate('new_account_page.header'))
.textStyle(context.headlineSmall)
.paddingSymmetric(vertical: 16),
FormBuilderTextField(
autofocus: true,
name: formFieldName,
decoration:
InputDecoration(labelText: translate('account.form_name')),
maxLength: 64,
// The validator receives the text that the user has entered.
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
]),
),
FormBuilderTextField(
name: formFieldPronouns,
maxLength: 64,
decoration: InputDecoration(
labelText: translate('account.form_pronouns')),
),
Row(children: [
const Spacer(),
Text(translate('new_account_page.instructions'))
.toCenter()
.flexible(flex: 6),
const Spacer(),
]).paddingSymmetric(vertical: 4),
ElevatedButton(
onPressed: () async {
if (_formKey.currentState?.saveAndValidate() ?? false) {
setState(() {
isInAsyncCall = true;
});
try {
await onSubmit(_formKey);
} finally {
if (mounted) {
setState(() {
isInAsyncCall = false;
});
}
}
}
},
child: Text(translate('new_account_page.create')),
).paddingSymmetric(vertical: 4).alignAtCenterRight(),
],
),
);
@override
Widget build(BuildContext context) {
ref.watch(windowControlProvider);
final localAccounts = ref.watch(localAccountsProvider);
final logins = ref.watch(loginsProvider);
final displayModalHUD =
isInAsyncCall || !localAccounts.hasValue || !logins.hasValue;
return Scaffold(
// resizeToAvoidBottomInset: false,
appBar: DefaultAppBar(
title: Text(translate('new_account_page.titlebar')),
actions: [
const SignalStrengthMeterWidget(),
IconButton(
icon: const Icon(Icons.settings),
tooltip: translate('app_bar.settings_tooltip'),
onPressed: () async {
context.go('/new_account/settings');
})
]),
body: _newAccountForm(
context,
onSubmit: (formKey) async {
FocusScope.of(context).unfocus();
try {
await createAccount();
} on Exception catch (e) {
if (context.mounted) {
await showErrorModal(context, translate('new_account_page.error'),
'Exception: $e');
}
}
},
).paddingSymmetric(horizontal: 24, vertical: 8),
).withModalHUD(context, displayModalHUD);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<bool>('isInAsyncCall', isInAsyncCall));
}
}

View file

@ -4,7 +4,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../entities/local_account.dart';
import '../../entities/user_login.dart';
import '../../proto/proto.dart' as proto;
import '../../veilid_support/veilid_support.dart';
import '../../../packages/veilid_support/veilid_support.dart';
import '../../local_accounts/local_accounts.dart';
import 'logins.dart';

View file

@ -4,7 +4,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../proto/proto.dart' as proto;
import '../../veilid_support/veilid_support.dart';
import '../../../packages/veilid_support/veilid_support.dart';
import 'account.dart';
part 'chat.g.dart';

View file

@ -1,7 +1,7 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import '../../veilid_support/veilid_support.dart';
import '../../../packages/veilid_support/veilid_support.dart';
part 'connection_state.freezed.dart';

View file

@ -30,8 +30,6 @@ abstract class $ConnectionStateCopyWith<$Res> {
_$ConnectionStateCopyWithImpl<$Res, ConnectionState>;
@useResult
$Res call({VeilidStateAttachment attachment});
$VeilidStateAttachmentCopyWith<$Res> get attachment;
}
/// @nodoc
@ -47,23 +45,15 @@ class _$ConnectionStateCopyWithImpl<$Res, $Val extends ConnectionState>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? attachment = null,
Object? attachment = freezed,
}) {
return _then(_value.copyWith(
attachment: null == attachment
attachment: freezed == attachment
? _value.attachment
: attachment // ignore: cast_nullable_to_non_nullable
as VeilidStateAttachment,
) as $Val);
}
@override
@pragma('vm:prefer-inline')
$VeilidStateAttachmentCopyWith<$Res> get attachment {
return $VeilidStateAttachmentCopyWith<$Res>(_value.attachment, (value) {
return _then(_value.copyWith(attachment: value) as $Val);
});
}
}
/// @nodoc
@ -75,9 +65,6 @@ abstract class _$$ConnectionStateImplCopyWith<$Res>
@override
@useResult
$Res call({VeilidStateAttachment attachment});
@override
$VeilidStateAttachmentCopyWith<$Res> get attachment;
}
/// @nodoc
@ -91,10 +78,10 @@ class __$$ConnectionStateImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? attachment = null,
Object? attachment = freezed,
}) {
return _then(_$ConnectionStateImpl(
attachment: null == attachment
attachment: freezed == attachment
? _value.attachment
: attachment // ignore: cast_nullable_to_non_nullable
as VeilidStateAttachment,
@ -120,12 +107,13 @@ class _$ConnectionStateImpl extends _ConnectionState {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ConnectionStateImpl &&
(identical(other.attachment, attachment) ||
other.attachment == attachment));
const DeepCollectionEquality()
.equals(other.attachment, attachment));
}
@override
int get hashCode => Object.hash(runtimeType, attachment);
int get hashCode =>
Object.hash(runtimeType, const DeepCollectionEquality().hash(attachment));
@JsonKey(ignore: true)
@override

View file

@ -5,7 +5,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../proto/proto.dart' as proto;
import '../../veilid_support/veilid_support.dart';
import '../../../packages/veilid_support/veilid_support.dart';
import '../../tools/tools.dart';
import 'account.dart';
import 'chat.dart';

View file

@ -7,7 +7,7 @@ import 'package:mutex/mutex.dart';
import '../../entities/entities.dart';
import '../../proto/proto.dart' as proto;
import '../../tools/tools.dart';
import '../../veilid_support/veilid_support.dart';
import '../../../packages/veilid_support/veilid_support.dart';
import 'account.dart';
part 'contact_invitation_list_manager.g.dart';
@ -115,11 +115,11 @@ class ContactInvitationListManager extends _$ContactInvitationListManager {
final conversationWriter = _activeAccountInfo.getConversationWriter();
// Encrypt the writer secret with the encryption key
final encryptedSecret = await encryptSecretToBytes(
final encryptedSecret = await encryptionKeyType.encryptSecretToBytes(
secret: contactRequestWriter.secret,
cryptoKind: cs.kind(),
encryptionKey: encryptionKey,
encryptionKeyType: encryptionKeyType);
);
// Create local chat DHT record with the account record key as its parent
// Do not set the encryption of this key yet as it will not yet be written

View file

@ -7,7 +7,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../entities/local_account.dart';
import '../../proto/proto.dart' as proto;
import '../../tools/tools.dart';
import '../../veilid_support/veilid_support.dart';
import '../../../packages/veilid_support/veilid_support.dart';
import 'account.dart';
import 'conversation.dart';

View file

@ -11,7 +11,7 @@ import '../../proto/proto.dart' as proto;
import '../../tools/tools.dart';
import '../../init.dart';
import '../../veilid_support/veilid_support.dart';
import '../../../packages/veilid_support/veilid_support.dart';
import 'account.dart';
import 'chat.dart';
import 'contact.dart';

View file

@ -1,83 +0,0 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:window_manager/window_manager.dart';
import '../../tools/responsive.dart';
export 'package:window_manager/window_manager.dart' show TitleBarStyle;
part 'window_control.g.dart';
enum OrientationCapability {
normal,
portraitOnly,
landscapeOnly,
}
// Window Control
@riverpod
class WindowControl extends _$WindowControl {
/// Change window control
@override
FutureOr<bool> build() async {
await _doWindowSetup(TitleBarStyle.hidden, OrientationCapability.normal);
return true;
}
static Future<void> initialize() async {
if (isDesktop) {
await windowManager.ensureInitialized();
const windowOptions = WindowOptions(
size: Size(768, 1024),
//minimumSize: Size(480, 480),
center: true,
backgroundColor: Colors.transparent,
skipTaskbar: false,
);
await windowManager.waitUntilReadyToShow(windowOptions, () async {
await windowManager.show();
await windowManager.focus();
});
}
}
Future<void> _doWindowSetup(TitleBarStyle titleBarStyle,
OrientationCapability orientationCapability) async {
if (isDesktop) {
await windowManager.setTitleBarStyle(titleBarStyle);
} else {
switch (orientationCapability) {
case OrientationCapability.normal:
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
case OrientationCapability.portraitOnly:
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
case OrientationCapability.landscapeOnly:
await SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
}
}
}
//////////////////////////////////////////////////////////////
/// Mutators and Selectors
/// Reorder accounts
Future<void> changeWindowSetup(TitleBarStyle titleBarStyle,
OrientationCapability orientationCapability) async {
state = const AsyncValue.loading();
await _doWindowSetup(titleBarStyle, orientationCapability);
state = const AsyncValue.data(true);
}
}