mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2024-10-01 06:55:46 -04:00
cleanup
This commit is contained in:
parent
8c89ce91cf
commit
9dfb8c3f71
@ -37,11 +37,17 @@
|
|||||||
"pronouns": "Pronouns",
|
"pronouns": "Pronouns",
|
||||||
"remove_account": "Remove Account",
|
"remove_account": "Remove Account",
|
||||||
"delete_identity": "Delete Identity",
|
"delete_identity": "Delete Identity",
|
||||||
"remove_account_confirm": "Confirm Account Removal?",
|
"remove_account_confirm": "Confirm Account Removal",
|
||||||
"remove_account_description": "Remove account from this device only",
|
"remove_account_description": "Remove account from this device only",
|
||||||
"delete_identity_description": "Delete identity and all messages completely",
|
"remove_account_confirm_message": " • Your account will be removed from this device ONLY\n • Your identity will remain recoverable with the recovery key\n • Your messages and contacts will remain available on other devices\n",
|
||||||
"delete_identity_confirm_message": "This action is PERMANENT, and your identity will no longer be recoverable with the recovery key. This will not remove your messages you have sent from other people's devices.",
|
"delete_identity_description": "Delete identity from all devices everywhere",
|
||||||
"confirm_are_you_sure": "Are you sure you want to do this?"
|
"delete_identity_confirm_message": "This action is PERMANENT, and your identity will no longer be recoverable with the recovery key. Restoring from backups will not recover your account!",
|
||||||
|
"delete_identity_confirm_message_details": "You will lose access to:\n • Your entire message history\n • Your contacts\n • This will not remove your messages you have sent from other people's devices\n",
|
||||||
|
"confirm_are_you_sure": "Are you sure you want to do this?",
|
||||||
|
"failed_to_remove": "Failed to remove account.\n\nTry again when you have a more stable network connection.",
|
||||||
|
"failed_to_delete": "Failed to delete identity.\n\nTry again when you have a more stable network connection.",
|
||||||
|
"account_removed": "Account removed successfully",
|
||||||
|
"identity_deleted": "Identity deleted successfully"
|
||||||
},
|
},
|
||||||
"show_recovery_key_page": {
|
"show_recovery_key_page": {
|
||||||
"titlebar": "Save Recovery Key",
|
"titlebar": "Save Recovery Key",
|
||||||
@ -58,6 +64,8 @@
|
|||||||
"accept": "Accept",
|
"accept": "Accept",
|
||||||
"reject": "Reject",
|
"reject": "Reject",
|
||||||
"finish": "Finish",
|
"finish": "Finish",
|
||||||
|
"yes_proceed": "Yes, proceed",
|
||||||
|
"no_cancel": "No, cancel",
|
||||||
"waiting_for_network": "Waiting For Network"
|
"waiting_for_network": "Waiting For Network"
|
||||||
},
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
|
@ -168,7 +168,15 @@ class AccountRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Remove an account and wipe the messages for this account from this device
|
/// Remove an account and wipe the messages for this account from this device
|
||||||
Future<bool> deleteLocalAccount(TypedKey superIdentityRecordKey) async {
|
Future<bool> deleteLocalAccount(TypedKey superIdentityRecordKey,
|
||||||
|
OwnedDHTRecordPointer? accountRecord) async {
|
||||||
|
// Delete the account record locally which causes a deep delete
|
||||||
|
// of all the contacts, invites, chats, and messages in the dht record
|
||||||
|
// pool
|
||||||
|
if (accountRecord != null) {
|
||||||
|
await DHTRecordPool.instance.deleteRecord(accountRecord.recordKey);
|
||||||
|
}
|
||||||
|
|
||||||
await logout(superIdentityRecordKey);
|
await logout(superIdentityRecordKey);
|
||||||
|
|
||||||
final localAccounts = await _localAccounts.get();
|
final localAccounts = await _localAccounts.get();
|
||||||
@ -178,8 +186,6 @@ class AccountRepository {
|
|||||||
await _localAccounts.set(newLocalAccounts);
|
await _localAccounts.set(newLocalAccounts);
|
||||||
_streamController.add(AccountRepositoryChange.localAccounts);
|
_streamController.add(AccountRepositoryChange.localAccounts);
|
||||||
|
|
||||||
// TO DO: wipe messages
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,6 +373,11 @@ class AccountRepository {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (logoutUser == activeLocalAccount) {
|
||||||
|
await switchToAccount(
|
||||||
|
_localAccounts.value.firstOrNull?.superIdentity.recordKey);
|
||||||
|
}
|
||||||
|
|
||||||
final logoutUserLogin = fetchUserLogin(logoutUser);
|
final logoutUserLogin = fetchUserLogin(logoutUser);
|
||||||
if (logoutUserLogin == null) {
|
if (logoutUserLogin == null) {
|
||||||
// Already logged out
|
// Already logged out
|
||||||
|
@ -20,6 +20,7 @@ class EditAccountPage extends StatefulWidget {
|
|||||||
const EditAccountPage(
|
const EditAccountPage(
|
||||||
{required this.superIdentityRecordKey,
|
{required this.superIdentityRecordKey,
|
||||||
required this.existingProfile,
|
required this.existingProfile,
|
||||||
|
required this.accountRecord,
|
||||||
super.key});
|
super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -27,6 +28,7 @@ class EditAccountPage extends StatefulWidget {
|
|||||||
|
|
||||||
final TypedKey superIdentityRecordKey;
|
final TypedKey superIdentityRecordKey;
|
||||||
final proto.Profile existingProfile;
|
final proto.Profile existingProfile;
|
||||||
|
final OwnedDHTRecordPointer accountRecord;
|
||||||
@override
|
@override
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
super.debugFillProperties(properties);
|
super.debugFillProperties(properties);
|
||||||
@ -34,7 +36,9 @@ class EditAccountPage extends StatefulWidget {
|
|||||||
..add(DiagnosticsProperty<TypedKey>(
|
..add(DiagnosticsProperty<TypedKey>(
|
||||||
'superIdentityRecordKey', superIdentityRecordKey))
|
'superIdentityRecordKey', superIdentityRecordKey))
|
||||||
..add(DiagnosticsProperty<proto.Profile>(
|
..add(DiagnosticsProperty<proto.Profile>(
|
||||||
'existingProfile', existingProfile));
|
'existingProfile', existingProfile))
|
||||||
|
..add(DiagnosticsProperty<OwnedDHTRecordPointer>(
|
||||||
|
'accountRecord', accountRecord));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,92 +71,179 @@ class _EditAccountPageState extends State<EditAccountPage> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Future<void> _onRemoveAccount() async {
|
||||||
|
final confirmed = await StyledDialog.show<bool>(
|
||||||
|
context: context,
|
||||||
|
title: translate('edit_account_page.remove_account_confirm'),
|
||||||
|
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
|
Text(translate('edit_account_page.remove_account_confirm_message'))
|
||||||
|
.paddingLTRB(24, 24, 24, 0),
|
||||||
|
Text(translate('edit_account_page.confirm_are_you_sure'))
|
||||||
|
.paddingAll(8),
|
||||||
|
Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(false);
|
||||||
|
},
|
||||||
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
|
const Icon(Icons.cancel, size: 16).paddingLTRB(0, 0, 4, 0),
|
||||||
|
Text(translate('button.no_cancel')).paddingLTRB(0, 0, 4, 0)
|
||||||
|
])),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
|
const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0),
|
||||||
|
Text(translate('button.yes_proceed')).paddingLTRB(0, 0, 4, 0)
|
||||||
|
]))
|
||||||
|
]).paddingAll(24)
|
||||||
|
]));
|
||||||
|
if (confirmed != null && confirmed && mounted) {
|
||||||
|
// dismiss the keyboard by unfocusing the textfield
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
|
||||||
|
try {
|
||||||
|
setState(() {
|
||||||
|
_isInAsyncCall = true;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
final success = await AccountRepository.instance.deleteLocalAccount(
|
||||||
|
widget.superIdentityRecordKey, widget.accountRecord);
|
||||||
|
if (success && mounted) {
|
||||||
|
showInfoToast(
|
||||||
|
context, translate('edit_account_page.account_removed'));
|
||||||
|
GoRouterHelper(context).pop();
|
||||||
|
} else if (mounted) {
|
||||||
|
showErrorToast(
|
||||||
|
context, translate('edit_account_page.failed_to_remove'));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isInAsyncCall = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} on Exception catch (e) {
|
||||||
|
if (mounted) {
|
||||||
|
await showErrorModal(
|
||||||
|
context, translate('new_account_page.error'), 'Exception: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onDeleteIdentity() async {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onSubmit(GlobalKey<FormBuilderState> formKey) async {
|
||||||
|
// dismiss the keyboard by unfocusing the textfield
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final name = formKey
|
||||||
|
.currentState!.fields[EditProfileForm.formFieldName]!.value as String;
|
||||||
|
final pronouns = formKey.currentState!
|
||||||
|
.fields[EditProfileForm.formFieldPronouns]!.value as String? ??
|
||||||
|
'';
|
||||||
|
final newProfile = widget.existingProfile.deepCopy()
|
||||||
|
..name = name
|
||||||
|
..pronouns = pronouns
|
||||||
|
..timestamp = Veilid.instance.now().toInt64();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isInAsyncCall = true;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
// Look up account cubit for this specific account
|
||||||
|
final perAccountCollectionBlocMapCubit =
|
||||||
|
context.read<PerAccountCollectionBlocMapCubit>();
|
||||||
|
final accountRecordCubit = await perAccountCollectionBlocMapCubit
|
||||||
|
.operate(widget.superIdentityRecordKey,
|
||||||
|
closure: (c) async => c.accountRecordCubit);
|
||||||
|
if (accountRecordCubit == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update account profile DHT record
|
||||||
|
// This triggers ConversationCubits to update
|
||||||
|
await accountRecordCubit.updateProfile(newProfile);
|
||||||
|
|
||||||
|
// Update local account profile
|
||||||
|
await AccountRepository.instance
|
||||||
|
.editAccountProfile(widget.superIdentityRecordKey, newProfile);
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.canPop(context)
|
||||||
|
? GoRouterHelper(context).pop()
|
||||||
|
: GoRouterHelper(context).go('/');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isInAsyncCall = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} on Exception catch (e) {
|
||||||
|
if (mounted) {
|
||||||
|
await showErrorModal(
|
||||||
|
context, translate('edit_account_page.error'), 'Exception: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final displayModalHUD = _isInAsyncCall;
|
final displayModalHUD = _isInAsyncCall;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
// resizeToAvoidBottomInset: false,
|
// resizeToAvoidBottomInset: false,
|
||||||
appBar: DefaultAppBar(
|
appBar: DefaultAppBar(
|
||||||
title: Text(translate('edit_account_page.titlebar')),
|
title: Text(translate('edit_account_page.titlebar')),
|
||||||
leading: Navigator.canPop(context)
|
leading: Navigator.canPop(context)
|
||||||
? IconButton(
|
? IconButton(
|
||||||
icon: const Icon(Icons.arrow_back),
|
icon: const Icon(Icons.arrow_back),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
actions: [
|
actions: [
|
||||||
const SignalStrengthMeterWidget(),
|
const SignalStrengthMeterWidget(),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.settings),
|
icon: const Icon(Icons.settings),
|
||||||
tooltip: translate('menu.settings_tooltip'),
|
tooltip: translate('menu.settings_tooltip'),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await GoRouterHelper(context).push('/settings');
|
await GoRouterHelper(context).push('/settings');
|
||||||
})
|
})
|
||||||
]),
|
]),
|
||||||
body: _editAccountForm(
|
body: Column(children: [
|
||||||
context,
|
_editAccountForm(
|
||||||
onSubmit: (formKey) async {
|
context,
|
||||||
// dismiss the keyboard by unfocusing the textfield
|
onSubmit: _onSubmit,
|
||||||
FocusScope.of(context).unfocus();
|
).expanded(),
|
||||||
|
Text(translate('edit_account_page.remove_account_description')),
|
||||||
try {
|
ElevatedButton(
|
||||||
final name = formKey.currentState!
|
onPressed: _onRemoveAccount,
|
||||||
.fields[EditProfileForm.formFieldName]!.value as String;
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
final pronouns = formKey
|
const Icon(Icons.person_remove_alt_1, size: 16)
|
||||||
.currentState!
|
.paddingLTRB(0, 0, 4, 0),
|
||||||
.fields[EditProfileForm.formFieldPronouns]!
|
Text(translate('edit_account_page.remove_account'))
|
||||||
.value as String? ??
|
.paddingLTRB(0, 0, 4, 0)
|
||||||
'';
|
])).paddingLTRB(0, 8, 0, 24),
|
||||||
final newProfile = widget.existingProfile.deepCopy()
|
Text(translate('edit_account_page.delete_identity_description')),
|
||||||
..name = name
|
ElevatedButton(
|
||||||
..pronouns = pronouns
|
onPressed: _onDeleteIdentity,
|
||||||
..timestamp = Veilid.instance.now().toInt64();
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
|
const Icon(Icons.person_off, size: 16)
|
||||||
setState(() {
|
.paddingLTRB(0, 0, 4, 0),
|
||||||
_isInAsyncCall = true;
|
Text(translate('edit_account_page.delete_identity'))
|
||||||
});
|
.paddingLTRB(0, 0, 4, 0)
|
||||||
try {
|
])).paddingLTRB(0, 8, 0, 24)
|
||||||
// Look up account cubit for this specific account
|
]).paddingSymmetric(horizontal: 24, vertical: 8))
|
||||||
final perAccountCollectionBlocMapCubit =
|
.withModalHUD(context, displayModalHUD);
|
||||||
context.read<PerAccountCollectionBlocMapCubit>();
|
|
||||||
final accountRecordCubit = await perAccountCollectionBlocMapCubit
|
|
||||||
.operate(widget.superIdentityRecordKey,
|
|
||||||
closure: (c) async => c.accountRecordCubit);
|
|
||||||
if (accountRecordCubit == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update account profile DHT record
|
|
||||||
// This triggers ConversationCubits to update
|
|
||||||
await accountRecordCubit.updateProfile(newProfile);
|
|
||||||
|
|
||||||
// Update local account profile
|
|
||||||
await AccountRepository.instance.editAccountProfile(
|
|
||||||
widget.superIdentityRecordKey, newProfile);
|
|
||||||
|
|
||||||
if (context.mounted) {
|
|
||||||
Navigator.canPop(context)
|
|
||||||
? GoRouterHelper(context).pop()
|
|
||||||
: GoRouterHelper(context).go('/');
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
_isInAsyncCall = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} on Exception catch (e) {
|
|
||||||
if (context.mounted) {
|
|
||||||
await showErrorModal(context,
|
|
||||||
translate('edit_account_page.error'), 'Exception: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).paddingSymmetric(horizontal: 24, vertical: 8),
|
|
||||||
).withModalHUD(context, displayModalHUD);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,43 @@ class _NewAccountPageState extends State<NewAccountPage> {
|
|||||||
onSubmit: !canSubmit ? null : onSubmit);
|
onSubmit: !canSubmit ? null : onSubmit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _onSubmit(GlobalKey<FormBuilderState> formKey) async {
|
||||||
|
// dismiss the keyboard by unfocusing the textfield
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final name = formKey
|
||||||
|
.currentState!.fields[EditProfileForm.formFieldName]!.value as String;
|
||||||
|
final pronouns = formKey.currentState!
|
||||||
|
.fields[EditProfileForm.formFieldPronouns]!.value as String? ??
|
||||||
|
'';
|
||||||
|
final newProfile = proto.Profile()
|
||||||
|
..name = name
|
||||||
|
..pronouns = pronouns;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isInAsyncCall = true;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
final superSecret = await AccountRepository.instance
|
||||||
|
.createWithNewSuperIdentity(newProfile);
|
||||||
|
GoRouterHelper(context)
|
||||||
|
.pushReplacement('/new_account/recovery_key', extra: superSecret);
|
||||||
|
} finally {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isInAsyncCall = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} on Exception catch (e) {
|
||||||
|
if (mounted) {
|
||||||
|
await showErrorModal(
|
||||||
|
context, translate('new_account_page.error'), 'Exception: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final displayModalHUD = _isInAsyncCall;
|
final displayModalHUD = _isInAsyncCall;
|
||||||
@ -79,45 +116,7 @@ class _NewAccountPageState extends State<NewAccountPage> {
|
|||||||
]),
|
]),
|
||||||
body: _newAccountForm(
|
body: _newAccountForm(
|
||||||
context,
|
context,
|
||||||
onSubmit: (formKey) async {
|
onSubmit: _onSubmit,
|
||||||
// dismiss the keyboard by unfocusing the textfield
|
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
|
|
||||||
try {
|
|
||||||
final name = formKey.currentState!
|
|
||||||
.fields[EditProfileForm.formFieldName]!.value as String;
|
|
||||||
final pronouns = formKey
|
|
||||||
.currentState!
|
|
||||||
.fields[EditProfileForm.formFieldPronouns]!
|
|
||||||
.value as String? ??
|
|
||||||
'';
|
|
||||||
final newProfile = proto.Profile()
|
|
||||||
..name = name
|
|
||||||
..pronouns = pronouns;
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_isInAsyncCall = true;
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
final superSecret = await AccountRepository.instance
|
|
||||||
.createWithNewSuperIdentity(newProfile);
|
|
||||||
GoRouterHelper(context).pushReplacement(
|
|
||||||
'/new_account/recovery_key',
|
|
||||||
extra: superSecret);
|
|
||||||
} finally {
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
_isInAsyncCall = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} on Exception catch (e) {
|
|
||||||
if (context.mounted) {
|
|
||||||
await showErrorModal(context, translate('new_account_page.error'),
|
|
||||||
'Exception: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).paddingSymmetric(horizontal: 24, vertical: 8),
|
).paddingSymmetric(horizontal: 24, vertical: 8),
|
||||||
).withModalHUD(context, displayModalHUD);
|
).withModalHUD(context, displayModalHUD);
|
||||||
}
|
}
|
||||||
|
@ -99,9 +99,13 @@ class _EditProfileFormState extends State<EditProfileForm> {
|
|||||||
await widget.onSubmit!(_formKey);
|
await widget.onSubmit!(_formKey);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text((widget.onSubmit == null)
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
? widget.submitDisabledText
|
const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0),
|
||||||
: widget.submitText),
|
Text((widget.onSubmit == null)
|
||||||
|
? widget.submitDisabledText
|
||||||
|
: widget.submitText)
|
||||||
|
.paddingLTRB(0, 0, 4, 0)
|
||||||
|
]),
|
||||||
).paddingSymmetric(vertical: 4).alignAtCenterRight(),
|
).paddingSymmetric(vertical: 4).alignAtCenterRight(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -15,7 +15,7 @@ class VeilidChatGlobalInit {
|
|||||||
Future<void> _initializeVeilid() async {
|
Future<void> _initializeVeilid() async {
|
||||||
// Init Veilid
|
// Init Veilid
|
||||||
Veilid.instance.initializeVeilidCore(
|
Veilid.instance.initializeVeilidCore(
|
||||||
getDefaultVeilidPlatformConfig(kIsWeb, VeilidChatApp.name));
|
await getDefaultVeilidPlatformConfig(kIsWeb, VeilidChatApp.name));
|
||||||
|
|
||||||
// Veilid logging
|
// Veilid logging
|
||||||
initVeilidLog(kDebugMode);
|
initVeilidLog(kDebugMode);
|
||||||
|
@ -39,11 +39,11 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _doEditClick(
|
void _doEditClick(TypedKey superIdentityRecordKey,
|
||||||
TypedKey superIdentityRecordKey, proto.Profile existingProfile) {
|
proto.Profile existingProfile, OwnedDHTRecordPointer accountRecord) {
|
||||||
singleFuture(this, () async {
|
singleFuture(this, () async {
|
||||||
await GoRouterHelper(context).push('/edit_account',
|
await GoRouterHelper(context).push('/edit_account',
|
||||||
extra: [superIdentityRecordKey, existingProfile]);
|
extra: [superIdentityRecordKey, existingProfile, accountRecord]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,10 +128,10 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||||||
final superIdentityRecordKey = la.superIdentity.recordKey;
|
final superIdentityRecordKey = la.superIdentity.recordKey;
|
||||||
|
|
||||||
// See if this account is logged in
|
// See if this account is logged in
|
||||||
final avAccountRecordState = perAccountCollectionBlocMapState
|
final perAccountState =
|
||||||
.get(superIdentityRecordKey)
|
perAccountCollectionBlocMapState.get(superIdentityRecordKey);
|
||||||
?.avAccountRecordState;
|
final avAccountRecordState = perAccountState?.avAccountRecordState;
|
||||||
if (avAccountRecordState != null) {
|
if (perAccountState != null && avAccountRecordState != null) {
|
||||||
// Account is logged in
|
// Account is logged in
|
||||||
final scale = theme.extension<ScaleScheme>()!.tertiaryScale;
|
final scale = theme.extension<ScaleScheme>()!.tertiaryScale;
|
||||||
final loggedInAccount = avAccountRecordState.when(
|
final loggedInAccount = avAccountRecordState.when(
|
||||||
@ -144,7 +144,11 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||||||
_doSwitchClick(superIdentityRecordKey);
|
_doSwitchClick(superIdentityRecordKey);
|
||||||
},
|
},
|
||||||
footerCallback: () {
|
footerCallback: () {
|
||||||
_doEditClick(superIdentityRecordKey, value.profile);
|
_doEditClick(
|
||||||
|
superIdentityRecordKey,
|
||||||
|
value.profile,
|
||||||
|
perAccountState.accountInfo.userLogin!.accountRecordInfo
|
||||||
|
.accountRecord);
|
||||||
}),
|
}),
|
||||||
loading: () => _wrapInBox(
|
loading: () => _wrapInBox(
|
||||||
child: buildProgressIndicator(),
|
child: buildProgressIndicator(),
|
||||||
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../../chat/chat.dart';
|
import '../../../chat/chat.dart';
|
||||||
import '../../../tools/tools.dart';
|
|
||||||
|
|
||||||
class HomeAccountReadyChat extends StatefulWidget {
|
class HomeAccountReadyChat extends StatefulWidget {
|
||||||
const HomeAccountReadyChat({super.key});
|
const HomeAccountReadyChat({super.key});
|
||||||
@ -15,11 +14,6 @@ class HomeAccountReadyChatState extends State<HomeAccountReadyChat> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
|
||||||
await changeWindowSetup(
|
|
||||||
TitleBarStyle.normal, OrientationCapability.normal);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -23,11 +23,6 @@ class _HomeAccountReadyMainState extends State<HomeAccountReadyMain> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
|
||||||
await changeWindowSetup(
|
|
||||||
TitleBarStyle.normal, OrientationCapability.normal);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildUserPanel() => Builder(builder: (context) {
|
Widget buildUserPanel() => Builder(builder: (context) {
|
||||||
|
@ -45,8 +45,20 @@ class HomeScreenState extends State<HomeScreen>
|
|||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Account animation setup
|
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;
|
||||||
|
|
||||||
|
await changeWindowSetup(
|
||||||
|
TitleBarStyle.normal, OrientationCapability.normal);
|
||||||
|
|
||||||
|
if (!canClose) {
|
||||||
|
await _zoomDrawerController.open!();
|
||||||
|
}
|
||||||
|
});
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +164,12 @@ class HomeScreenState extends State<HomeScreen>
|
|||||||
scale.tertiaryScale.appBackground,
|
scale.tertiaryScale.appBackground,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: DecoratedBox(
|
child: DecoratedBox(
|
||||||
decoration: BoxDecoration(gradient: gradient),
|
decoration: BoxDecoration(gradient: gradient),
|
||||||
@ -178,9 +196,9 @@ class HomeScreenState extends State<HomeScreen>
|
|||||||
openCurve: Curves.fastEaseInToSlowEaseOut,
|
openCurve: Curves.fastEaseInToSlowEaseOut,
|
||||||
// duration: const Duration(milliseconds: 250),
|
// duration: const Duration(milliseconds: 250),
|
||||||
// reverseDuration: const Duration(milliseconds: 250),
|
// reverseDuration: const Duration(milliseconds: 250),
|
||||||
menuScreenTapClose: true,
|
menuScreenTapClose: canClose,
|
||||||
mainScreenTapClose: true,
|
mainScreenTapClose: canClose,
|
||||||
//disableDragGesture: false,
|
disableDragGesture: !canClose,
|
||||||
mainScreenScale: .25,
|
mainScreenScale: .25,
|
||||||
slideWidth: min(360, MediaQuery.of(context).size.width * 0.9),
|
slideWidth: min(360, MediaQuery.of(context).size.width * 0.9),
|
||||||
)));
|
)));
|
||||||
|
@ -69,6 +69,7 @@ class RouterCubit extends Cubit<RouterState> {
|
|||||||
return EditAccountPage(
|
return EditAccountPage(
|
||||||
superIdentityRecordKey: extra[0]! as TypedKey,
|
superIdentityRecordKey: extra[0]! as TypedKey,
|
||||||
existingProfile: extra[1]! as proto.Profile,
|
existingProfile: extra[1]! as proto.Profile,
|
||||||
|
accountRecord: extra[2]! as OwnedDHTRecordPointer,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,6 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
|||||||
|
|
||||||
import '../src/veilid_log.dart';
|
import '../src/veilid_log.dart';
|
||||||
import '../veilid_support.dart';
|
import '../veilid_support.dart';
|
||||||
import 'exceptions.dart';
|
|
||||||
|
|
||||||
part 'identity_instance.freezed.dart';
|
part 'identity_instance.freezed.dart';
|
||||||
part 'identity_instance.g.dart';
|
part 'identity_instance.g.dart';
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'dart:io' show Platform;
|
import 'dart:io' show Platform;
|
||||||
|
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:veilid/veilid.dart';
|
import 'package:veilid/veilid.dart';
|
||||||
|
|
||||||
// ignore: do_not_use_environment
|
// ignore: do_not_use_environment
|
||||||
@ -8,8 +10,8 @@ const bool _kReleaseMode = bool.fromEnvironment('dart.vm.product');
|
|||||||
const bool _kProfileMode = bool.fromEnvironment('dart.vm.profile');
|
const bool _kProfileMode = bool.fromEnvironment('dart.vm.profile');
|
||||||
const bool _kDebugMode = !_kReleaseMode && !_kProfileMode;
|
const bool _kDebugMode = !_kReleaseMode && !_kProfileMode;
|
||||||
|
|
||||||
Map<String, dynamic> getDefaultVeilidPlatformConfig(
|
Future<Map<String, dynamic>> getDefaultVeilidPlatformConfig(
|
||||||
bool isWeb, String appName) {
|
bool isWeb, String appName) async {
|
||||||
final ignoreLogTargetsStr =
|
final ignoreLogTargetsStr =
|
||||||
// ignore: do_not_use_environment
|
// ignore: do_not_use_environment
|
||||||
const String.fromEnvironment('IGNORE_LOG_TARGETS').trim();
|
const String.fromEnvironment('IGNORE_LOG_TARGETS').trim();
|
||||||
@ -17,6 +19,16 @@ Map<String, dynamic> getDefaultVeilidPlatformConfig(
|
|||||||
? <String>[]
|
? <String>[]
|
||||||
: ignoreLogTargetsStr.split(',').map((e) => e.trim()).toList();
|
: ignoreLogTargetsStr.split(',').map((e) => e.trim()).toList();
|
||||||
|
|
||||||
|
// ignore: do_not_use_environment
|
||||||
|
var flamePathStr = const String.fromEnvironment('FLAME').trim();
|
||||||
|
if (flamePathStr == '1') {
|
||||||
|
flamePathStr = p.join(
|
||||||
|
(await getApplicationSupportDirectory()).absolute.path,
|
||||||
|
'$appName.folded');
|
||||||
|
// ignore: avoid_print
|
||||||
|
print('Flame data logged to $flamePathStr');
|
||||||
|
}
|
||||||
|
|
||||||
if (isWeb) {
|
if (isWeb) {
|
||||||
return VeilidWASMConfig(
|
return VeilidWASMConfig(
|
||||||
logging: VeilidWASMConfigLogging(
|
logging: VeilidWASMConfigLogging(
|
||||||
@ -52,7 +64,9 @@ Map<String, dynamic> getDefaultVeilidPlatformConfig(
|
|||||||
api: VeilidFFIConfigLoggingApi(
|
api: VeilidFFIConfigLoggingApi(
|
||||||
enabled: true,
|
enabled: true,
|
||||||
level: VeilidConfigLogLevel.info,
|
level: VeilidConfigLogLevel.info,
|
||||||
ignoreLogTargets: ignoreLogTargets)))
|
ignoreLogTargets: ignoreLogTargets),
|
||||||
|
flame: VeilidFFIConfigLoggingFlame(
|
||||||
|
enabled: flamePathStr.isNotEmpty, path: flamePathStr)))
|
||||||
.toJson();
|
.toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +428,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||||
@ -436,7 +436,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.9.0"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
|
sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
|
||||||
|
@ -19,6 +19,8 @@ dependencies:
|
|||||||
loggy: ^2.0.3
|
loggy: ^2.0.3
|
||||||
meta: ^1.12.0
|
meta: ^1.12.0
|
||||||
|
|
||||||
|
path: ^1.9.0
|
||||||
|
path_provider: ^2.1.3
|
||||||
protobuf: ^3.1.0
|
protobuf: ^3.1.0
|
||||||
veilid:
|
veilid:
|
||||||
# veilid: ^0.0.1
|
# veilid: ^0.0.1
|
||||||
|
3
process_flame.sh
Executable file
3
process_flame.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cat "/Users/$USER/Library/Containers/com.veilid.veilidchat/Data/Library/Application Support/com.veilid.veilidchat/VeilidChat.folded" | inferno-flamegraph -c purple --fontsize 8 --height 24 --title "VeilidChat" --factor 0.000000001 --countname secs > /tmp/veilidchat.svg
|
||||||
|
cat "/Users/$USER/Library/Containers/com.veilid.veilidchat/Data/Library/Application Support/com.veilid.veilidchat/VeilidChat.folded" | inferno-flamegraph --reverse -c aqua --fontsize 8 --height 24 --title "VeilidChat Reverse" --factor 0.000000001 --countname secs > /tmp/veilidchat-reverse.svg
|
Loading…
Reference in New Issue
Block a user