mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-01-11 07:39:32 -05:00
fix slow first message
This commit is contained in:
parent
6c4b803091
commit
b0d4e35c6f
@ -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": {
|
||||
|
@ -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;
|
||||
|
@ -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'),
|
||||
|
65
lib/account_manager/views/show_recovery_key_page.dart
Normal file
65
lib/account_manager/views/show_recovery_key_page.dart
Normal 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));
|
||||
}
|
||||
}
|
35
lib/account_manager/views/switch_account_widget.dart
Normal file
35
lib/account_manager/views/switch_account_widget.dart
Normal 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: []),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
export 'new_account_page.dart';
|
||||
export 'profile_widget.dart';
|
||||
export 'show_recovery_key_page.dart';
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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':
|
||||
|
@ -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');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user