fix slow first message

This commit is contained in:
Christien Rioux 2024-06-10 10:04:03 -04:00
parent 6c4b803091
commit b0d4e35c6f
9 changed files with 141 additions and 5 deletions

View File

@ -18,7 +18,7 @@
"lock_type_password": "password"
},
"new_account_page": {
"titlebar": "Create a new account",
"titlebar": "Create A New Account",
"header": "Account Profile",
"create": "Create",
"instructions": "This information will be shared with the people you invite to connect with you on VeilidChat.",
@ -26,12 +26,21 @@
"name": "Name",
"pronouns": "Pronouns"
},
"show_recovery_key_page": {
"titlebar": "Save Recovery Key",
"instructions": "You must save this recovery key somewhere safe. This key is the ONLY way to recover your VeilidChat account in the event of a forgotton password or a lost, stolen, or compromised device.",
"instructions_options": "Here are some options for your recovery key:",
"instructions_print": "Print the recovery key and keep it somewhere safe",
"instructions_write": "View the recovery key and write it down on paper",
"instructions_send": "Send the recovery key to another app to save it"
},
"button": {
"ok": "Ok",
"cancel": "Cancel",
"delete": "Delete",
"accept": "Accept",
"reject": "Reject",
"finish": "Finish",
"waiting_for_network": "Waiting For Network"
},
"toast": {

View File

@ -168,7 +168,8 @@ class AccountRepository {
/// Creates a new super identity, an identity instance, an account associated
/// with the identity instance, stores the account in the identity key and
/// then logs into that account with no password set at this time
Future<void> createWithNewSuperIdentity(NewProfileSpec newProfileSpec) async {
Future<SecretKey> createWithNewSuperIdentity(
NewProfileSpec newProfileSpec) async {
log.debug('Creating super identity');
final wsi = await WritableSuperIdentity.create();
try {
@ -181,6 +182,8 @@ class AccountRepository {
final ok = await login(
localAccount.superIdentity.recordKey, EncryptionKeyType.none, '');
assert(ok, 'login with none should never fail');
return wsi.superSecret;
} on Exception catch (_) {
await wsi.delete();
rethrow;

View File

@ -140,8 +140,11 @@ class NewAccountPageState extends State<NewAccountPage> {
final newProfileSpec =
NewProfileSpec(name: name, pronouns: pronouns);
await AccountRepository.instance
final superSecret = await AccountRepository.instance
.createWithNewSuperIdentity(newProfileSpec);
GoRouterHelper(context).pushReplacement('/new_account/recovery_key',
extra: superSecret);
} on Exception catch (e) {
if (context.mounted) {
await showErrorModal(context, translate('new_account_page.error'),

View File

@ -0,0 +1,65 @@
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.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 'package:veilid_support/veilid_support.dart';
import '../../layout/default_app_bar.dart';
import '../../theme/theme.dart';
import '../../tools/tools.dart';
import '../../veilid_processor/veilid_processor.dart';
import '../account_manager.dart';
class ShowRecoveryKeyPage extends StatefulWidget {
const ShowRecoveryKeyPage({required SecretKey secretKey, super.key})
: _secretKey = secretKey;
@override
ShowRecoveryKeyPageState createState() => ShowRecoveryKeyPageState();
final SecretKey _secretKey;
}
class ShowRecoveryKeyPageState extends State<ShowRecoveryKeyPage> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
await changeWindowSetup(
TitleBarStyle.normal, OrientationCapability.portraitOnly);
});
}
@override
// ignore: prefer_expression_function_bodies
Widget build(BuildContext context) {
final secretKey = widget._secretKey;
return Scaffold(
// resizeToAvoidBottomInset: false,
appBar: DefaultAppBar(
title: Text(translate('show_recovery_key_page.titlebar')),
actions: [
const SignalStrengthMeterWidget(),
IconButton(
icon: const Icon(Icons.settings),
tooltip: translate('app_bar.settings_tooltip'),
onPressed: () async {
await GoRouterHelper(context).push('/settings');
})
]),
body: Column(children: [
Text('ASS: $secretKey'),
ElevatedButton(
onPressed: () {
GoRouterHelper(context).go('/');
},
child: Text(translate('button.finish')))
]).paddingSymmetric(horizontal: 24, vertical: 8));
}
}

View File

@ -0,0 +1,35 @@
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/material.dart';
import '../../proto/proto.dart' as proto;
import '../../theme/theme.dart';
import '../account_manager.dart';
class SwitchAccountWidget extends StatelessWidget {
const SwitchAccountWidget({
super.key,
});
//
@override
// ignore: prefer_expression_function_bodies
Widget build(BuildContext context) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final textTheme = theme.textTheme;
final accountRepo = AccountRepository.instance;
final localAccounts = accountRepo.getLocalAccounts();
for (final la in localAccounts) {
//
}
return DecoratedBox(
decoration: ShapeDecoration(
color: scale.primaryScale.border,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))),
child: Column(children: []),
);
}
}

View File

@ -1,2 +1,3 @@
export 'new_account_page.dart';
export 'profile_widget.dart';
export 'show_recovery_key_page.dart';

View File

@ -3,6 +3,7 @@ import 'package:veilid_support/veilid_support.dart';
import '../../../proto/proto.dart' as proto;
import '../../../tools/tools.dart';
import 'author_input_source.dart';
import 'message_integrity.dart';
import 'output_position.dart';
@ -84,6 +85,8 @@ class AuthorInputQueue {
if (_lastMessage != null) {
// Ensure the timestamp is not moving backward
if (nextMessage.value.timestamp < _lastMessage!.timestamp) {
log.warning('timestamp backward: ${nextMessage.value.timestamp}'
' < ${_lastMessage!.timestamp}');
continue;
}
}
@ -91,11 +94,14 @@ class AuthorInputQueue {
// Verify the id chain for the message
final matchId = await _messageIntegrity.generateMessageId(_lastMessage);
if (matchId.compare(nextMessage.value.idBytes) != 0) {
log.warning(
'id chain invalid: $matchId != ${nextMessage.value.idBytes}');
continue;
}
// Verify the signature for the message
if (!await _messageIntegrity.verifyMessage(nextMessage.value)) {
log.warning('invalid message signature: ${nextMessage.value}');
continue;
}

View File

@ -7,6 +7,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:go_router/go_router.dart';
import 'package:stream_transform/stream_transform.dart';
import 'package:veilid_support/veilid_support.dart';
import '../../../account_manager/account_manager.dart';
import '../../layout/layout.dart';
@ -83,6 +84,11 @@ class RouterCubit extends Cubit<RouterState> {
path: '/new_account',
builder: (context, state) => const NewAccountPage(),
),
GoRoute(
path: '/new_account/recovery_key',
builder: (context, state) =>
ShowRecoveryKeyPage(secretKey: state.extra! as SecretKey),
),
GoRoute(
path: '/settings',
builder: (context, state) => const SettingsPage(),
@ -98,8 +104,6 @@ class RouterCubit extends Cubit<RouterState> {
// No matter where we are, if there's not
switch (goRouterState.matchedLocation) {
case '/new_account':
return state.hasAnyAccount ? '/' : null;
case '/':
if (!state.hasAnyAccount) {
return '/new_account';
@ -130,6 +134,10 @@ class RouterCubit extends Cubit<RouterState> {
return '/';
}
return null;
case '/new_account':
return null;
case '/new_account/recovery_key':
return null;
case '/settings':
return null;
case '/developer':

View File

@ -71,6 +71,12 @@ class _DHTLogSpine {
// Write new spine head record to the network
await spine.operate((spine) async {
// Write first empty subkey
final subkeyData = _makeEmptySubkey();
final existingSubkeyData =
await spineRecord.tryWriteBytes(subkeyData, subkey: 1);
assert(existingSubkeyData == null, 'Should never conflict on create');
final success = await spine.writeSpineHead();
assert(success, 'false return should never happen on create');
});