From 41906366e6d94dd515b2b0c1a42f046111ff0d0d Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Fri, 7 Jul 2023 19:33:28 -0400 Subject: [PATCH] protoc and localization --- assets/i18n/en.json | 27 + lib/app.dart | 23 +- lib/entities/dht.dart | 28 - lib/entities/entities.dart | 249 -------- lib/entities/entities.freezed.dart | 739 ------------------------ lib/entities/entities.g.dart | 62 -- lib/entities/identity.dart | 50 ++ lib/entities/identity.freezed.dart | 370 ++++++++++++ lib/entities/identity.g.dart | 38 ++ lib/entities/local_account.dart | 53 ++ lib/entities/local_account.freezed.dart | 275 +++++++++ lib/entities/local_account.g.dart | 29 + lib/entities/preferences.dart | 92 +++ lib/entities/preferences.freezed.dart | 437 ++++++++++++++ lib/entities/preferences.g.dart | 39 ++ lib/main.dart | 13 +- proto/veilidchat.proto | 195 +++++++ pubspec.lock | 37 ++ pubspec.yaml | 5 + setup_linux.sh | 34 +- setup_macos.sh | 32 +- 21 files changed, 1717 insertions(+), 1110 deletions(-) create mode 100644 assets/i18n/en.json delete mode 100644 lib/entities/dht.dart delete mode 100644 lib/entities/entities.dart delete mode 100644 lib/entities/entities.freezed.dart delete mode 100644 lib/entities/entities.g.dart create mode 100644 lib/entities/identity.dart create mode 100644 lib/entities/identity.freezed.dart create mode 100644 lib/entities/identity.g.dart create mode 100644 lib/entities/local_account.dart create mode 100644 lib/entities/local_account.freezed.dart create mode 100644 lib/entities/local_account.g.dart create mode 100644 lib/entities/preferences.dart create mode 100644 lib/entities/preferences.freezed.dart create mode 100644 lib/entities/preferences.g.dart create mode 100644 proto/veilidchat.proto diff --git a/assets/i18n/en.json b/assets/i18n/en.json new file mode 100644 index 0000000..65041d0 --- /dev/null +++ b/assets/i18n/en.json @@ -0,0 +1,27 @@ +{ + "app_bar": { + "title": "VeilidChat" + }, + "button": { + "cancel": "Cancel", + "change_language": "Change Language" + }, + "language": { + "name": { + "en": "English" + }, + "selected_message": "Currently selected language is {language}", + "selection": { + "message": "Please select a language from the list", + "title": "Language Selection" + } + }, + "plural": { + "demo": { + "zero": "Please start pushing the 'plus' button.", + "one": "You have pushed the button one time.", + "two": "You have pushed the button two times.", + "other": "You have pushed the button {{value}} times." + } + } +} \ No newline at end of file diff --git a/lib/app.dart b/lib/app.dart index 1f4aa17..21937dd 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:animated_theme_switcher/animated_theme_switcher.dart'; import 'router/router.dart'; +import 'package:flutter_translate/flutter_translate.dart'; class VeilidChatApp extends ConsumerWidget { const VeilidChatApp({ @@ -15,14 +17,25 @@ class VeilidChatApp extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final router = ref.watch(routerProvider); + var localizationDelegate = LocalizedApp.of(context).delegate; + return ThemeProvider( initTheme: theme, builder: (_, theme) { - return MaterialApp.router( - routerConfig: router, - title: 'VeilidChat', - theme: theme, - ); + return LocalizationProvider( + state: LocalizationProvider.of(context).state, + child: MaterialApp.router( + routerConfig: router, + title: 'VeilidChat', + theme: theme, + localizationsDelegates: [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + localizationDelegate + ], + supportedLocales: localizationDelegate.supportedLocales, + locale: localizationDelegate.currentLocale, + )); }, ); } diff --git a/lib/entities/dht.dart b/lib/entities/dht.dart deleted file mode 100644 index f5609c7..0000000 --- a/lib/entities/dht.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'dart:typed_data'; - -import 'package:change_case/change_case.dart'; -import 'package:flutter/material.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:uuid/uuid.dart'; -import 'package:veilid/veilid.dart'; - -part 'dht.freezed.dart'; -part 'dht.g.dart'; - -// Header in subkey 0 for Fixed DHT Data -// Subkeys 1..=stride on the first key are concatenated chunks -// Subkeys 0..stride on the 'keys' keys are concatenated chunks -@freezed -class DHTData with _$DHTData { - const factory DHTData({ - // Other keys to concatenate - required List keys, - // Total data size - required int size, - // Chunk size per subkey - required int chunk, - // Subkeys per key - required int stride, - }) = _DHTData; - factory DHTData.fromJson(Map json) => _$DHTData(json); -} diff --git a/lib/entities/entities.dart b/lib/entities/entities.dart deleted file mode 100644 index 55c490a..0000000 --- a/lib/entities/entities.dart +++ /dev/null @@ -1,249 +0,0 @@ -import 'dart:typed_data'; - -import 'package:change_case/change_case.dart'; -import 'package:flutter/material.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:uuid/uuid.dart'; -import 'package:veilid/veilid.dart'; - -part 'entities.freezed.dart'; -part 'entities.g.dart'; - -// A record of a chunk of messages as reconciled from a conversation -// -// DHT Key (Private): messagesKey -// DHT Secret: messagesSecret -// Encryption: Symmetric(messagesSecret) - -@freezed -class Messages with _$Messages { - const factory Messages( - {required Profile profile, - required Identity identity, - required bool available}) = _Messages; - - factory Messages.fromJson(Map json) => - _$MessagesFromJson(json); -} - -// A record of a 1-1 chat that is synchronized between -// two users. Backed up on a DHT key. Visible and encrypted -// for the other party -// -// DHT Key (UnicastOutbox): conversationPublicKey -// DHT Secret: conversationSecret -// Encryption: DH(IdentityA, IdentityB) - -@freezed -class Conversation with _$Conversation { - const factory Conversation( - {required Profile profile, - required Identity identity, - required bool available}) = _Contact; - - factory Conversation.fromJson(Map json) => - _$ConversationFromJson(json); -} - -// A record of a contact that has accepted a contact invitation -// Contains a copy of the most recent remote profile as well as -// a locally edited profile. -// Contains a copy of the most recent identity from the contact's -// Master identity dht key -// Contains -@freezed -class Contact with _$Contact { - const factory Contact({ - // Profile as locally edited - required Profile localProfile, - // Profile from remote conversation - required Profile remoteProfile, - // Identity from remote conversation - required Identity identity, - // xxx - required bool available, - }) = _Contact; - - factory Contact.fromJson(Map json) => - _$ContactFromJson(json); -} - -// Publicly shared profile information for both contacts and accounts -// Contains: -// Name - Friendly name -// Title - Title of user -// Icon - Little picture to represent user in contact list -// -// DHT Key: None -// Encryption: None -@freezed -class Profile with _$Profile { - const factory Profile({ - // Friendy name - required String name, - // Title of user - required String title, - // Status/away message - required String status, - // Icon DHTData - required TypedKey icon, - }) = _Profile; - factory Profile.fromJson(Map json) => - _$ProfileFromJson(json); -} - -// A linked list of DHT subvalues - -// A record of an individual account -// DHT Key (Private): accountPublicKey -// DHT Secret: accountSecretKey -@freezed -class Account with _$Account { - const factory Account({ - // The user's profile that gets shared with contacts - required Profile profile, - // Invisibility makes you always look 'Offline' - required bool invisible, - // Auto-away sets 'away' mode after an inactivity time - required autoAwayTimeoutSec, - // The contacts for this account - required DHTListRef contacts, - }) = _Account; - - factory Account.fromJson(Map json) => - _$AccountFromJson(json); -} - -// Identity Key points to accounts associated with this identity -// accounts field has a map of service name or uuid to account key pairs -// DHT Key (Private): identityPublicKey -// DHT Secret: identitySecretKey (stored encrypted with unlock code in local table store) -@freezed -class Identity with _$Identity { - const factory Identity({ - // Top level account data key - required TypedKey accountPublicKey, - // Top level account data secret - required SecretKey accountSecretKey, - }) = _Identity; - - factory Identity.fromJson(Map json) => - _$IdentityFromJson(json); -} - -// Identity Master key structure for created account -// Master key allows for regeneration of identity DHT record -// Bidirectional Master<->Identity signature allows for -// chain of identity ownership for account recovery process -// -// Backed by a DHT key at masterPublicKey, the secret is kept -// completely offline and only written to upon account recovery -// -// DHT Key (Public): masterPublicKey -// DHT Secret: masterSecretKey (kept offline) -// Encryption: None -@freezed -class IdentityMaster with _$IdentityMaster { - const factory IdentityMaster( - {required TypedKey identityPublicKey, - required TypedKey masterPublicKey, - required Signature identitySignature, - required Signature masterSignature}) = _IdentityMaster; - - factory IdentityMaster.fromJson(Map json) => - _$IdentityMasterFromJson(json); -} - -// Local account identitySecretKey is potentially encrypted with a key -// using the following mechanisms -// * None : no key, bytes are unencrypted -// * Pin : Code is a numeric pin (4-256 numeric digits) hashed with Argon2 -// * Password: Code is a UTF-8 string that is hashed with Argon2 -enum EncryptionKeyType { - none, - pin, - password; - - String toJson() => name.toPascalCase(); - factory EncryptionKeyType.fromJson(String j) => - EncryptionKeyType.values.byName(j.toCamelCase()); -} - -// Local Accounts are stored in a table locally and not backed by a DHT key -// and represents the accounts that have been added/imported -// on the current device. -// Stores a copy of the IdentityMaster associated with the account -// and the identitySecretKey optionally encrypted by an unlock code -// This is the root of the account information tree for VeilidChat -// -@freezed -class LocalAccount with _$LocalAccount { - const factory LocalAccount({ - // The master key record for the account, containing the identityPublicKey - required IdentityMaster identityMaster, - // The encrypted identity secret that goes with the identityPublicKey - required Uint8List identitySecretKeyBytes, - // The kind of encryption input used on the account - required EncryptionKeyType encryptionKeyType, - // If account is not hidden, password can be retrieved via - required bool biometricsEnabled, - // Keep account hidden unless account password is entered - // (tries all hidden accounts with auth method (no biometrics)) - required bool hiddenAccount, - }) = _LocalAccount; - - factory LocalAccount.fromJson(Map json) => - _$LocalAccountFromJson(json); -} - -// Each theme supports light and dark mode, optionally selected by the -// operating system -enum DarkModePreference { - system, - light, - dark; - - String toJson() => name.toPascalCase(); - factory DarkModePreference.fromJson(String j) => - DarkModePreference.values.byName(j.toCamelCase()); -} - -// Lock preference changes how frequently the messenger locks its -// interface and requires the identitySecretKey to be entered (pin/password/etc) -@freezed -class LockPreference with _$LockPreference { - const factory LockPreference({ - required int inactivityLockSecs, - required bool lockWhenSwitching, - required bool lockWithSystemLock, - }) = _LockPreference; - - factory LockPreference.fromJson(Map json) => - _$LockPreferenceFromJson(json); -} - -// Preferences are stored in a table locally and globally affect all -// accounts imported/added and the app in general -@freezed -class Preferences with _$Preferences { - const factory Preferences({ - required DarkModePreference darkMode, - required Uuid activeTheme, - required LockPreference locking, - }) = _Preferences; - - factory Preferences.fromJson(Map json) => - _$PreferencesFromJson(json); -} - -// Themes are stored in a table locally and referenced by their UUID -@freezed -class Theme with _$Theme { - const factory Theme({ - required Uuid uuid, - required String name, - required Map modeData, - }) = _Theme; - - factory Theme.fromJson(Map json) => _$ThemeFromJson(json); -} diff --git a/lib/entities/entities.freezed.dart b/lib/entities/entities.freezed.dart deleted file mode 100644 index effea21..0000000 --- a/lib/entities/entities.freezed.dart +++ /dev/null @@ -1,739 +0,0 @@ -// coverage:ignore-file -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'entities.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -T _$identity(T value) => value; - -final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); - -Account _$AccountFromJson(Map json) { - return _Account.fromJson(json); -} - -/// @nodoc -mixin _$Account { - Profile get profile => throw _privateConstructorUsedError; - Identity get identity => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $AccountCopyWith get copyWith => throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $AccountCopyWith<$Res> { - factory $AccountCopyWith(Account value, $Res Function(Account) then) = - _$AccountCopyWithImpl<$Res, Account>; - @useResult - $Res call({Profile profile, Identity identity}); - - $ProfileCopyWith<$Res> get profile; - $IdentityCopyWith<$Res> get identity; -} - -/// @nodoc -class _$AccountCopyWithImpl<$Res, $Val extends Account> - implements $AccountCopyWith<$Res> { - _$AccountCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? profile = null, - Object? identity = null, - }) { - return _then(_value.copyWith( - profile: null == profile - ? _value.profile - : profile // ignore: cast_nullable_to_non_nullable - as Profile, - identity: null == identity - ? _value.identity - : identity // ignore: cast_nullable_to_non_nullable - as Identity, - ) as $Val); - } - - @override - @pragma('vm:prefer-inline') - $ProfileCopyWith<$Res> get profile { - return $ProfileCopyWith<$Res>(_value.profile, (value) { - return _then(_value.copyWith(profile: value) as $Val); - }); - } - - @override - @pragma('vm:prefer-inline') - $IdentityCopyWith<$Res> get identity { - return $IdentityCopyWith<$Res>(_value.identity, (value) { - return _then(_value.copyWith(identity: value) as $Val); - }); - } -} - -/// @nodoc -abstract class _$$_AccountCopyWith<$Res> implements $AccountCopyWith<$Res> { - factory _$$_AccountCopyWith( - _$_Account value, $Res Function(_$_Account) then) = - __$$_AccountCopyWithImpl<$Res>; - @override - @useResult - $Res call({Profile profile, Identity identity}); - - @override - $ProfileCopyWith<$Res> get profile; - @override - $IdentityCopyWith<$Res> get identity; -} - -/// @nodoc -class __$$_AccountCopyWithImpl<$Res> - extends _$AccountCopyWithImpl<$Res, _$_Account> - implements _$$_AccountCopyWith<$Res> { - __$$_AccountCopyWithImpl(_$_Account _value, $Res Function(_$_Account) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? profile = null, - Object? identity = null, - }) { - return _then(_$_Account( - profile: null == profile - ? _value.profile - : profile // ignore: cast_nullable_to_non_nullable - as Profile, - identity: null == identity - ? _value.identity - : identity // ignore: cast_nullable_to_non_nullable - as Identity, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$_Account implements _Account { - const _$_Account({required this.profile, required this.identity}); - - factory _$_Account.fromJson(Map json) => - _$$_AccountFromJson(json); - - @override - final Profile profile; - @override - final Identity identity; - - @override - String toString() { - return 'Account(profile: $profile, identity: $identity)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_Account && - (identical(other.profile, profile) || other.profile == profile) && - (identical(other.identity, identity) || - other.identity == identity)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash(runtimeType, profile, identity); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_AccountCopyWith<_$_Account> get copyWith => - __$$_AccountCopyWithImpl<_$_Account>(this, _$identity); - - @override - Map toJson() { - return _$$_AccountToJson( - this, - ); - } -} - -abstract class _Account implements Account { - const factory _Account( - {required final Profile profile, - required final Identity identity}) = _$_Account; - - factory _Account.fromJson(Map json) = _$_Account.fromJson; - - @override - Profile get profile; - @override - Identity get identity; - @override - @JsonKey(ignore: true) - _$$_AccountCopyWith<_$_Account> get copyWith => - throw _privateConstructorUsedError; -} - -Contact _$ContactFromJson(Map json) { - return _Contact.fromJson(json); -} - -/// @nodoc -mixin _$Contact { - String get name => throw _privateConstructorUsedError; - Typed get publicKey => - throw _privateConstructorUsedError; - bool get available => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $ContactCopyWith get copyWith => throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $ContactCopyWith<$Res> { - factory $ContactCopyWith(Contact value, $Res Function(Contact) then) = - _$ContactCopyWithImpl<$Res, Contact>; - @useResult - $Res call( - {String name, Typed publicKey, bool available}); -} - -/// @nodoc -class _$ContactCopyWithImpl<$Res, $Val extends Contact> - implements $ContactCopyWith<$Res> { - _$ContactCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? name = null, - Object? publicKey = null, - Object? available = null, - }) { - return _then(_value.copyWith( - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, - publicKey: null == publicKey - ? _value.publicKey - : publicKey // ignore: cast_nullable_to_non_nullable - as Typed, - available: null == available - ? _value.available - : available // ignore: cast_nullable_to_non_nullable - as bool, - ) as $Val); - } -} - -/// @nodoc -abstract class _$$_ContactCopyWith<$Res> implements $ContactCopyWith<$Res> { - factory _$$_ContactCopyWith( - _$_Contact value, $Res Function(_$_Contact) then) = - __$$_ContactCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {String name, Typed publicKey, bool available}); -} - -/// @nodoc -class __$$_ContactCopyWithImpl<$Res> - extends _$ContactCopyWithImpl<$Res, _$_Contact> - implements _$$_ContactCopyWith<$Res> { - __$$_ContactCopyWithImpl(_$_Contact _value, $Res Function(_$_Contact) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? name = null, - Object? publicKey = null, - Object? available = null, - }) { - return _then(_$_Contact( - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, - publicKey: null == publicKey - ? _value.publicKey - : publicKey // ignore: cast_nullable_to_non_nullable - as Typed, - available: null == available - ? _value.available - : available // ignore: cast_nullable_to_non_nullable - as bool, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$_Contact implements _Contact { - const _$_Contact( - {required this.name, required this.publicKey, required this.available}); - - factory _$_Contact.fromJson(Map json) => - _$$_ContactFromJson(json); - - @override - final String name; - @override - final Typed publicKey; - @override - final bool available; - - @override - String toString() { - return 'Contact(name: $name, publicKey: $publicKey, available: $available)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_Contact && - (identical(other.name, name) || other.name == name) && - (identical(other.publicKey, publicKey) || - other.publicKey == publicKey) && - (identical(other.available, available) || - other.available == available)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash(runtimeType, name, publicKey, available); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_ContactCopyWith<_$_Contact> get copyWith => - __$$_ContactCopyWithImpl<_$_Contact>(this, _$identity); - - @override - Map toJson() { - return _$$_ContactToJson( - this, - ); - } -} - -abstract class _Contact implements Contact { - const factory _Contact( - {required final String name, - required final Typed publicKey, - required final bool available}) = _$_Contact; - - factory _Contact.fromJson(Map json) = _$_Contact.fromJson; - - @override - String get name; - @override - Typed get publicKey; - @override - bool get available; - @override - @JsonKey(ignore: true) - _$$_ContactCopyWith<_$_Contact> get copyWith => - throw _privateConstructorUsedError; -} - -Identity _$IdentityFromJson(Map json) { - return _Identity.fromJson(json); -} - -/// @nodoc -mixin _$Identity { - Typed get identityPublicKey => - throw _privateConstructorUsedError; - Typed get masterPublicKey => - throw _privateConstructorUsedError; - FixedEncodedString86 get identitySignature => - throw _privateConstructorUsedError; - FixedEncodedString86 get masterSignature => - throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $IdentityCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $IdentityCopyWith<$Res> { - factory $IdentityCopyWith(Identity value, $Res Function(Identity) then) = - _$IdentityCopyWithImpl<$Res, Identity>; - @useResult - $Res call( - {Typed identityPublicKey, - Typed masterPublicKey, - FixedEncodedString86 identitySignature, - FixedEncodedString86 masterSignature}); -} - -/// @nodoc -class _$IdentityCopyWithImpl<$Res, $Val extends Identity> - implements $IdentityCopyWith<$Res> { - _$IdentityCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? identityPublicKey = null, - Object? masterPublicKey = null, - Object? identitySignature = null, - Object? masterSignature = null, - }) { - return _then(_value.copyWith( - identityPublicKey: null == identityPublicKey - ? _value.identityPublicKey - : identityPublicKey // ignore: cast_nullable_to_non_nullable - as Typed, - masterPublicKey: null == masterPublicKey - ? _value.masterPublicKey - : masterPublicKey // ignore: cast_nullable_to_non_nullable - as Typed, - identitySignature: null == identitySignature - ? _value.identitySignature - : identitySignature // ignore: cast_nullable_to_non_nullable - as FixedEncodedString86, - masterSignature: null == masterSignature - ? _value.masterSignature - : masterSignature // ignore: cast_nullable_to_non_nullable - as FixedEncodedString86, - ) as $Val); - } -} - -/// @nodoc -abstract class _$$_IdentityCopyWith<$Res> implements $IdentityCopyWith<$Res> { - factory _$$_IdentityCopyWith( - _$_Identity value, $Res Function(_$_Identity) then) = - __$$_IdentityCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {Typed identityPublicKey, - Typed masterPublicKey, - FixedEncodedString86 identitySignature, - FixedEncodedString86 masterSignature}); -} - -/// @nodoc -class __$$_IdentityCopyWithImpl<$Res> - extends _$IdentityCopyWithImpl<$Res, _$_Identity> - implements _$$_IdentityCopyWith<$Res> { - __$$_IdentityCopyWithImpl( - _$_Identity _value, $Res Function(_$_Identity) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? identityPublicKey = null, - Object? masterPublicKey = null, - Object? identitySignature = null, - Object? masterSignature = null, - }) { - return _then(_$_Identity( - identityPublicKey: null == identityPublicKey - ? _value.identityPublicKey - : identityPublicKey // ignore: cast_nullable_to_non_nullable - as Typed, - masterPublicKey: null == masterPublicKey - ? _value.masterPublicKey - : masterPublicKey // ignore: cast_nullable_to_non_nullable - as Typed, - identitySignature: null == identitySignature - ? _value.identitySignature - : identitySignature // ignore: cast_nullable_to_non_nullable - as FixedEncodedString86, - masterSignature: null == masterSignature - ? _value.masterSignature - : masterSignature // ignore: cast_nullable_to_non_nullable - as FixedEncodedString86, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$_Identity implements _Identity { - const _$_Identity( - {required this.identityPublicKey, - required this.masterPublicKey, - required this.identitySignature, - required this.masterSignature}); - - factory _$_Identity.fromJson(Map json) => - _$$_IdentityFromJson(json); - - @override - final Typed identityPublicKey; - @override - final Typed masterPublicKey; - @override - final FixedEncodedString86 identitySignature; - @override - final FixedEncodedString86 masterSignature; - - @override - String toString() { - return 'Identity(identityPublicKey: $identityPublicKey, masterPublicKey: $masterPublicKey, identitySignature: $identitySignature, masterSignature: $masterSignature)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_Identity && - (identical(other.identityPublicKey, identityPublicKey) || - other.identityPublicKey == identityPublicKey) && - (identical(other.masterPublicKey, masterPublicKey) || - other.masterPublicKey == masterPublicKey) && - (identical(other.identitySignature, identitySignature) || - other.identitySignature == identitySignature) && - (identical(other.masterSignature, masterSignature) || - other.masterSignature == masterSignature)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash(runtimeType, identityPublicKey, - masterPublicKey, identitySignature, masterSignature); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_IdentityCopyWith<_$_Identity> get copyWith => - __$$_IdentityCopyWithImpl<_$_Identity>(this, _$identity); - - @override - Map toJson() { - return _$$_IdentityToJson( - this, - ); - } -} - -abstract class _Identity implements Identity { - const factory _Identity( - {required final Typed identityPublicKey, - required final Typed masterPublicKey, - required final FixedEncodedString86 identitySignature, - required final FixedEncodedString86 masterSignature}) = _$_Identity; - - factory _Identity.fromJson(Map json) = _$_Identity.fromJson; - - @override - Typed get identityPublicKey; - @override - Typed get masterPublicKey; - @override - FixedEncodedString86 get identitySignature; - @override - FixedEncodedString86 get masterSignature; - @override - @JsonKey(ignore: true) - _$$_IdentityCopyWith<_$_Identity> get copyWith => - throw _privateConstructorUsedError; -} - -Profile _$ProfileFromJson(Map json) { - return _Profile.fromJson(json); -} - -/// @nodoc -mixin _$Profile { - String get name => throw _privateConstructorUsedError; - Typed get publicKey => - throw _privateConstructorUsedError; - bool get invisible => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $ProfileCopyWith get copyWith => throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $ProfileCopyWith<$Res> { - factory $ProfileCopyWith(Profile value, $Res Function(Profile) then) = - _$ProfileCopyWithImpl<$Res, Profile>; - @useResult - $Res call( - {String name, Typed publicKey, bool invisible}); -} - -/// @nodoc -class _$ProfileCopyWithImpl<$Res, $Val extends Profile> - implements $ProfileCopyWith<$Res> { - _$ProfileCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? name = null, - Object? publicKey = null, - Object? invisible = null, - }) { - return _then(_value.copyWith( - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, - publicKey: null == publicKey - ? _value.publicKey - : publicKey // ignore: cast_nullable_to_non_nullable - as Typed, - invisible: null == invisible - ? _value.invisible - : invisible // ignore: cast_nullable_to_non_nullable - as bool, - ) as $Val); - } -} - -/// @nodoc -abstract class _$$_ProfileCopyWith<$Res> implements $ProfileCopyWith<$Res> { - factory _$$_ProfileCopyWith( - _$_Profile value, $Res Function(_$_Profile) then) = - __$$_ProfileCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {String name, Typed publicKey, bool invisible}); -} - -/// @nodoc -class __$$_ProfileCopyWithImpl<$Res> - extends _$ProfileCopyWithImpl<$Res, _$_Profile> - implements _$$_ProfileCopyWith<$Res> { - __$$_ProfileCopyWithImpl(_$_Profile _value, $Res Function(_$_Profile) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? name = null, - Object? publicKey = null, - Object? invisible = null, - }) { - return _then(_$_Profile( - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, - publicKey: null == publicKey - ? _value.publicKey - : publicKey // ignore: cast_nullable_to_non_nullable - as Typed, - invisible: null == invisible - ? _value.invisible - : invisible // ignore: cast_nullable_to_non_nullable - as bool, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$_Profile implements _Profile { - const _$_Profile( - {required this.name, required this.publicKey, required this.invisible}); - - factory _$_Profile.fromJson(Map json) => - _$$_ProfileFromJson(json); - - @override - final String name; - @override - final Typed publicKey; - @override - final bool invisible; - - @override - String toString() { - return 'Profile(name: $name, publicKey: $publicKey, invisible: $invisible)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_Profile && - (identical(other.name, name) || other.name == name) && - (identical(other.publicKey, publicKey) || - other.publicKey == publicKey) && - (identical(other.invisible, invisible) || - other.invisible == invisible)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash(runtimeType, name, publicKey, invisible); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_ProfileCopyWith<_$_Profile> get copyWith => - __$$_ProfileCopyWithImpl<_$_Profile>(this, _$identity); - - @override - Map toJson() { - return _$$_ProfileToJson( - this, - ); - } -} - -abstract class _Profile implements Profile { - const factory _Profile( - {required final String name, - required final Typed publicKey, - required final bool invisible}) = _$_Profile; - - factory _Profile.fromJson(Map json) = _$_Profile.fromJson; - - @override - String get name; - @override - Typed get publicKey; - @override - bool get invisible; - @override - @JsonKey(ignore: true) - _$$_ProfileCopyWith<_$_Profile> get copyWith => - throw _privateConstructorUsedError; -} diff --git a/lib/entities/entities.g.dart b/lib/entities/entities.g.dart deleted file mode 100644 index 7a2137d..0000000 --- a/lib/entities/entities.g.dart +++ /dev/null @@ -1,62 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'entities.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -_$_Account _$$_AccountFromJson(Map json) => _$_Account( - profile: Profile.fromJson(json['profile'] as Map), - identity: Identity.fromJson(json['identity'] as Map), - ); - -Map _$$_AccountToJson(_$_Account instance) => - { - 'profile': instance.profile.toJson(), - 'identity': instance.identity.toJson(), - }; - -_$_Contact _$$_ContactFromJson(Map json) => _$_Contact( - name: json['name'] as String, - publicKey: Typed.fromJson(json['public_key']), - available: json['available'] as bool, - ); - -Map _$$_ContactToJson(_$_Contact instance) => - { - 'name': instance.name, - 'public_key': instance.publicKey.toJson(), - 'available': instance.available, - }; - -_$_Identity _$$_IdentityFromJson(Map json) => _$_Identity( - identityPublicKey: - Typed.fromJson(json['identity_public_key']), - masterPublicKey: - Typed.fromJson(json['master_public_key']), - identitySignature: - FixedEncodedString86.fromJson(json['identity_signature']), - masterSignature: FixedEncodedString86.fromJson(json['master_signature']), - ); - -Map _$$_IdentityToJson(_$_Identity instance) => - { - 'identity_public_key': instance.identityPublicKey.toJson(), - 'master_public_key': instance.masterPublicKey.toJson(), - 'identity_signature': instance.identitySignature.toJson(), - 'master_signature': instance.masterSignature.toJson(), - }; - -_$_Profile _$$_ProfileFromJson(Map json) => _$_Profile( - name: json['name'] as String, - publicKey: Typed.fromJson(json['public_key']), - invisible: json['invisible'] as bool, - ); - -Map _$$_ProfileToJson(_$_Profile instance) => - { - 'name': instance.name, - 'public_key': instance.publicKey.toJson(), - 'invisible': instance.invisible, - }; diff --git a/lib/entities/identity.dart b/lib/entities/identity.dart new file mode 100644 index 0000000..c7df3aa --- /dev/null +++ b/lib/entities/identity.dart @@ -0,0 +1,50 @@ +import 'dart:typed_data'; + +import 'package:change_case/change_case.dart'; +import 'package:flutter/material.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:uuid/uuid.dart'; +import 'package:veilid/veilid.dart'; + +part 'identity.freezed.dart'; +part 'identity.g.dart'; + +// Identity Key points to accounts associated with this identity +// accounts field has a map of service name or uuid to account key pairs +// DHT Schema: DFLT(1) +// DHT Key (Private): identityPublicKey +// DHT Secret: identitySecretKey (stored encrypted with unlock code in local table store) +@freezed +class Identity with _$Identity { + const factory Identity({ + // Top level account keys and secrets + required Map accountKeyPairs, + }) = _Identity; + + factory Identity.fromJson(Map json) => + _$IdentityFromJson(json); +} + +// Identity Master key structure for created account +// Master key allows for regeneration of identity DHT record +// Bidirectional Master<->Identity signature allows for +// chain of identity ownership for account recovery process +// +// Backed by a DHT key at masterPublicKey, the secret is kept +// completely offline and only written to upon account recovery +// +// DHT Schema: DFLT(1) +// DHT Key (Public): masterPublicKey +// DHT Secret: masterSecretKey (kept offline) +// Encryption: None +@freezed +class IdentityMaster with _$IdentityMaster { + const factory IdentityMaster( + {required TypedKey identityPublicKey, + required TypedKey masterPublicKey, + required Signature identitySignature, + required Signature masterSignature}) = _IdentityMaster; + + factory IdentityMaster.fromJson(Map json) => + _$IdentityMasterFromJson(json); +} diff --git a/lib/entities/identity.freezed.dart b/lib/entities/identity.freezed.dart new file mode 100644 index 0000000..fbaccd1 --- /dev/null +++ b/lib/entities/identity.freezed.dart @@ -0,0 +1,370 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'identity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +Identity _$IdentityFromJson(Map json) { + return _Identity.fromJson(json); +} + +/// @nodoc +mixin _$Identity { +// Top level account keys and secrets + Map get accountKeyPairs => + throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $IdentityCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $IdentityCopyWith<$Res> { + factory $IdentityCopyWith(Identity value, $Res Function(Identity) then) = + _$IdentityCopyWithImpl<$Res, Identity>; + @useResult + $Res call({Map accountKeyPairs}); +} + +/// @nodoc +class _$IdentityCopyWithImpl<$Res, $Val extends Identity> + implements $IdentityCopyWith<$Res> { + _$IdentityCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? accountKeyPairs = null, + }) { + return _then(_value.copyWith( + accountKeyPairs: null == accountKeyPairs + ? _value.accountKeyPairs + : accountKeyPairs // ignore: cast_nullable_to_non_nullable + as Map, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_IdentityCopyWith<$Res> implements $IdentityCopyWith<$Res> { + factory _$$_IdentityCopyWith( + _$_Identity value, $Res Function(_$_Identity) then) = + __$$_IdentityCopyWithImpl<$Res>; + @override + @useResult + $Res call({Map accountKeyPairs}); +} + +/// @nodoc +class __$$_IdentityCopyWithImpl<$Res> + extends _$IdentityCopyWithImpl<$Res, _$_Identity> + implements _$$_IdentityCopyWith<$Res> { + __$$_IdentityCopyWithImpl( + _$_Identity _value, $Res Function(_$_Identity) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? accountKeyPairs = null, + }) { + return _then(_$_Identity( + accountKeyPairs: null == accountKeyPairs + ? _value._accountKeyPairs + : accountKeyPairs // ignore: cast_nullable_to_non_nullable + as Map, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_Identity implements _Identity { + const _$_Identity({required final Map accountKeyPairs}) + : _accountKeyPairs = accountKeyPairs; + + factory _$_Identity.fromJson(Map json) => + _$$_IdentityFromJson(json); + +// Top level account keys and secrets + final Map _accountKeyPairs; +// Top level account keys and secrets + @override + Map get accountKeyPairs { + if (_accountKeyPairs is EqualUnmodifiableMapView) return _accountKeyPairs; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_accountKeyPairs); + } + + @override + String toString() { + return 'Identity(accountKeyPairs: $accountKeyPairs)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_Identity && + const DeepCollectionEquality() + .equals(other._accountKeyPairs, _accountKeyPairs)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash( + runtimeType, const DeepCollectionEquality().hash(_accountKeyPairs)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_IdentityCopyWith<_$_Identity> get copyWith => + __$$_IdentityCopyWithImpl<_$_Identity>(this, _$identity); + + @override + Map toJson() { + return _$$_IdentityToJson( + this, + ); + } +} + +abstract class _Identity implements Identity { + const factory _Identity( + {required final Map accountKeyPairs}) = _$_Identity; + + factory _Identity.fromJson(Map json) = _$_Identity.fromJson; + + @override // Top level account keys and secrets + Map get accountKeyPairs; + @override + @JsonKey(ignore: true) + _$$_IdentityCopyWith<_$_Identity> get copyWith => + throw _privateConstructorUsedError; +} + +IdentityMaster _$IdentityMasterFromJson(Map json) { + return _IdentityMaster.fromJson(json); +} + +/// @nodoc +mixin _$IdentityMaster { + Typed get identityPublicKey => + throw _privateConstructorUsedError; + Typed get masterPublicKey => + throw _privateConstructorUsedError; + FixedEncodedString86 get identitySignature => + throw _privateConstructorUsedError; + FixedEncodedString86 get masterSignature => + throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $IdentityMasterCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $IdentityMasterCopyWith<$Res> { + factory $IdentityMasterCopyWith( + IdentityMaster value, $Res Function(IdentityMaster) then) = + _$IdentityMasterCopyWithImpl<$Res, IdentityMaster>; + @useResult + $Res call( + {Typed identityPublicKey, + Typed masterPublicKey, + FixedEncodedString86 identitySignature, + FixedEncodedString86 masterSignature}); +} + +/// @nodoc +class _$IdentityMasterCopyWithImpl<$Res, $Val extends IdentityMaster> + implements $IdentityMasterCopyWith<$Res> { + _$IdentityMasterCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? identityPublicKey = null, + Object? masterPublicKey = null, + Object? identitySignature = null, + Object? masterSignature = null, + }) { + return _then(_value.copyWith( + identityPublicKey: null == identityPublicKey + ? _value.identityPublicKey + : identityPublicKey // ignore: cast_nullable_to_non_nullable + as Typed, + masterPublicKey: null == masterPublicKey + ? _value.masterPublicKey + : masterPublicKey // ignore: cast_nullable_to_non_nullable + as Typed, + identitySignature: null == identitySignature + ? _value.identitySignature + : identitySignature // ignore: cast_nullable_to_non_nullable + as FixedEncodedString86, + masterSignature: null == masterSignature + ? _value.masterSignature + : masterSignature // ignore: cast_nullable_to_non_nullable + as FixedEncodedString86, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_IdentityMasterCopyWith<$Res> + implements $IdentityMasterCopyWith<$Res> { + factory _$$_IdentityMasterCopyWith( + _$_IdentityMaster value, $Res Function(_$_IdentityMaster) then) = + __$$_IdentityMasterCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {Typed identityPublicKey, + Typed masterPublicKey, + FixedEncodedString86 identitySignature, + FixedEncodedString86 masterSignature}); +} + +/// @nodoc +class __$$_IdentityMasterCopyWithImpl<$Res> + extends _$IdentityMasterCopyWithImpl<$Res, _$_IdentityMaster> + implements _$$_IdentityMasterCopyWith<$Res> { + __$$_IdentityMasterCopyWithImpl( + _$_IdentityMaster _value, $Res Function(_$_IdentityMaster) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? identityPublicKey = null, + Object? masterPublicKey = null, + Object? identitySignature = null, + Object? masterSignature = null, + }) { + return _then(_$_IdentityMaster( + identityPublicKey: null == identityPublicKey + ? _value.identityPublicKey + : identityPublicKey // ignore: cast_nullable_to_non_nullable + as Typed, + masterPublicKey: null == masterPublicKey + ? _value.masterPublicKey + : masterPublicKey // ignore: cast_nullable_to_non_nullable + as Typed, + identitySignature: null == identitySignature + ? _value.identitySignature + : identitySignature // ignore: cast_nullable_to_non_nullable + as FixedEncodedString86, + masterSignature: null == masterSignature + ? _value.masterSignature + : masterSignature // ignore: cast_nullable_to_non_nullable + as FixedEncodedString86, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_IdentityMaster implements _IdentityMaster { + const _$_IdentityMaster( + {required this.identityPublicKey, + required this.masterPublicKey, + required this.identitySignature, + required this.masterSignature}); + + factory _$_IdentityMaster.fromJson(Map json) => + _$$_IdentityMasterFromJson(json); + + @override + final Typed identityPublicKey; + @override + final Typed masterPublicKey; + @override + final FixedEncodedString86 identitySignature; + @override + final FixedEncodedString86 masterSignature; + + @override + String toString() { + return 'IdentityMaster(identityPublicKey: $identityPublicKey, masterPublicKey: $masterPublicKey, identitySignature: $identitySignature, masterSignature: $masterSignature)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_IdentityMaster && + (identical(other.identityPublicKey, identityPublicKey) || + other.identityPublicKey == identityPublicKey) && + (identical(other.masterPublicKey, masterPublicKey) || + other.masterPublicKey == masterPublicKey) && + (identical(other.identitySignature, identitySignature) || + other.identitySignature == identitySignature) && + (identical(other.masterSignature, masterSignature) || + other.masterSignature == masterSignature)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, identityPublicKey, + masterPublicKey, identitySignature, masterSignature); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_IdentityMasterCopyWith<_$_IdentityMaster> get copyWith => + __$$_IdentityMasterCopyWithImpl<_$_IdentityMaster>(this, _$identity); + + @override + Map toJson() { + return _$$_IdentityMasterToJson( + this, + ); + } +} + +abstract class _IdentityMaster implements IdentityMaster { + const factory _IdentityMaster( + {required final Typed identityPublicKey, + required final Typed masterPublicKey, + required final FixedEncodedString86 identitySignature, + required final FixedEncodedString86 masterSignature}) = _$_IdentityMaster; + + factory _IdentityMaster.fromJson(Map json) = + _$_IdentityMaster.fromJson; + + @override + Typed get identityPublicKey; + @override + Typed get masterPublicKey; + @override + FixedEncodedString86 get identitySignature; + @override + FixedEncodedString86 get masterSignature; + @override + @JsonKey(ignore: true) + _$$_IdentityMasterCopyWith<_$_IdentityMaster> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/entities/identity.g.dart b/lib/entities/identity.g.dart new file mode 100644 index 0000000..f7cceed --- /dev/null +++ b/lib/entities/identity.g.dart @@ -0,0 +1,38 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'identity.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_Identity _$$_IdentityFromJson(Map json) => _$_Identity( + accountKeyPairs: (json['account_key_pairs'] as Map).map( + (k, e) => MapEntry(k, TypedKeyPair.fromJson(e)), + ), + ); + +Map _$$_IdentityToJson(_$_Identity instance) => + { + 'account_key_pairs': + instance.accountKeyPairs.map((k, e) => MapEntry(k, e.toJson())), + }; + +_$_IdentityMaster _$$_IdentityMasterFromJson(Map json) => + _$_IdentityMaster( + identityPublicKey: + Typed.fromJson(json['identity_public_key']), + masterPublicKey: + Typed.fromJson(json['master_public_key']), + identitySignature: + FixedEncodedString86.fromJson(json['identity_signature']), + masterSignature: FixedEncodedString86.fromJson(json['master_signature']), + ); + +Map _$$_IdentityMasterToJson(_$_IdentityMaster instance) => + { + 'identity_public_key': instance.identityPublicKey.toJson(), + 'master_public_key': instance.masterPublicKey.toJson(), + 'identity_signature': instance.identitySignature.toJson(), + 'master_signature': instance.masterSignature.toJson(), + }; diff --git a/lib/entities/local_account.dart b/lib/entities/local_account.dart new file mode 100644 index 0000000..fa7f6c3 --- /dev/null +++ b/lib/entities/local_account.dart @@ -0,0 +1,53 @@ +import 'dart:typed_data'; + +import 'package:change_case/change_case.dart'; +import 'package:flutter/material.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:uuid/uuid.dart'; +import 'package:veilid/veilid.dart'; +import 'identity.dart'; + +part 'local_account.freezed.dart'; +part 'local_account.g.dart'; + +// Local account identitySecretKey is potentially encrypted with a key +// using the following mechanisms +// * None : no key, bytes are unencrypted +// * Pin : Code is a numeric pin (4-256 numeric digits) hashed with Argon2 +// * Password: Code is a UTF-8 string that is hashed with Argon2 +enum EncryptionKeyType { + none, + pin, + password; + + String toJson() => name.toPascalCase(); + factory EncryptionKeyType.fromJson(String j) => + EncryptionKeyType.values.byName(j.toCamelCase()); +} + +// Local Accounts are stored in a table locally and not backed by a DHT key +// and represents the accounts that have been added/imported +// on the current device. +// Stores a copy of the IdentityMaster associated with the account +// and the identitySecretKey optionally encrypted by an unlock code +// This is the root of the account information tree for VeilidChat +// +@freezed +class LocalAccount with _$LocalAccount { + const factory LocalAccount({ + // The master key record for the account, containing the identityPublicKey + required IdentityMaster identityMaster, + // The encrypted identity secret that goes with the identityPublicKey + @Uint8ListJsonConverter() required Uint8List identitySecretKeyBytes, + // The kind of encryption input used on the account + required EncryptionKeyType encryptionKeyType, + // If account is not hidden, password can be retrieved via + required bool biometricsEnabled, + // Keep account hidden unless account password is entered + // (tries all hidden accounts with auth method (no biometrics)) + required bool hiddenAccount, + }) = _LocalAccount; + + factory LocalAccount.fromJson(Map json) => + _$LocalAccountFromJson(json); +} diff --git a/lib/entities/local_account.freezed.dart b/lib/entities/local_account.freezed.dart new file mode 100644 index 0000000..1788ac1 --- /dev/null +++ b/lib/entities/local_account.freezed.dart @@ -0,0 +1,275 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'local_account.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +LocalAccount _$LocalAccountFromJson(Map json) { + return _LocalAccount.fromJson(json); +} + +/// @nodoc +mixin _$LocalAccount { +// The master key record for the account, containing the identityPublicKey + IdentityMaster get identityMaster => + throw _privateConstructorUsedError; // The encrypted identity secret that goes with the identityPublicKey + @Uint8ListJsonConverter() + Uint8List get identitySecretKeyBytes => + throw _privateConstructorUsedError; // The kind of encryption input used on the account + EncryptionKeyType get encryptionKeyType => + throw _privateConstructorUsedError; // If account is not hidden, password can be retrieved via + bool get biometricsEnabled => + throw _privateConstructorUsedError; // Keep account hidden unless account password is entered +// (tries all hidden accounts with auth method (no biometrics)) + bool get hiddenAccount => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $LocalAccountCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LocalAccountCopyWith<$Res> { + factory $LocalAccountCopyWith( + LocalAccount value, $Res Function(LocalAccount) then) = + _$LocalAccountCopyWithImpl<$Res, LocalAccount>; + @useResult + $Res call( + {IdentityMaster identityMaster, + @Uint8ListJsonConverter() Uint8List identitySecretKeyBytes, + EncryptionKeyType encryptionKeyType, + bool biometricsEnabled, + bool hiddenAccount}); + + $IdentityMasterCopyWith<$Res> get identityMaster; +} + +/// @nodoc +class _$LocalAccountCopyWithImpl<$Res, $Val extends LocalAccount> + implements $LocalAccountCopyWith<$Res> { + _$LocalAccountCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? identityMaster = null, + Object? identitySecretKeyBytes = null, + Object? encryptionKeyType = null, + Object? biometricsEnabled = null, + Object? hiddenAccount = null, + }) { + return _then(_value.copyWith( + identityMaster: null == identityMaster + ? _value.identityMaster + : identityMaster // ignore: cast_nullable_to_non_nullable + as IdentityMaster, + identitySecretKeyBytes: null == identitySecretKeyBytes + ? _value.identitySecretKeyBytes + : identitySecretKeyBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + encryptionKeyType: null == encryptionKeyType + ? _value.encryptionKeyType + : encryptionKeyType // ignore: cast_nullable_to_non_nullable + as EncryptionKeyType, + biometricsEnabled: null == biometricsEnabled + ? _value.biometricsEnabled + : biometricsEnabled // ignore: cast_nullable_to_non_nullable + as bool, + hiddenAccount: null == hiddenAccount + ? _value.hiddenAccount + : hiddenAccount // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } + + @override + @pragma('vm:prefer-inline') + $IdentityMasterCopyWith<$Res> get identityMaster { + return $IdentityMasterCopyWith<$Res>(_value.identityMaster, (value) { + return _then(_value.copyWith(identityMaster: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$_LocalAccountCopyWith<$Res> + implements $LocalAccountCopyWith<$Res> { + factory _$$_LocalAccountCopyWith( + _$_LocalAccount value, $Res Function(_$_LocalAccount) then) = + __$$_LocalAccountCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {IdentityMaster identityMaster, + @Uint8ListJsonConverter() Uint8List identitySecretKeyBytes, + EncryptionKeyType encryptionKeyType, + bool biometricsEnabled, + bool hiddenAccount}); + + @override + $IdentityMasterCopyWith<$Res> get identityMaster; +} + +/// @nodoc +class __$$_LocalAccountCopyWithImpl<$Res> + extends _$LocalAccountCopyWithImpl<$Res, _$_LocalAccount> + implements _$$_LocalAccountCopyWith<$Res> { + __$$_LocalAccountCopyWithImpl( + _$_LocalAccount _value, $Res Function(_$_LocalAccount) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? identityMaster = null, + Object? identitySecretKeyBytes = null, + Object? encryptionKeyType = null, + Object? biometricsEnabled = null, + Object? hiddenAccount = null, + }) { + return _then(_$_LocalAccount( + identityMaster: null == identityMaster + ? _value.identityMaster + : identityMaster // ignore: cast_nullable_to_non_nullable + as IdentityMaster, + identitySecretKeyBytes: null == identitySecretKeyBytes + ? _value.identitySecretKeyBytes + : identitySecretKeyBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + encryptionKeyType: null == encryptionKeyType + ? _value.encryptionKeyType + : encryptionKeyType // ignore: cast_nullable_to_non_nullable + as EncryptionKeyType, + biometricsEnabled: null == biometricsEnabled + ? _value.biometricsEnabled + : biometricsEnabled // ignore: cast_nullable_to_non_nullable + as bool, + hiddenAccount: null == hiddenAccount + ? _value.hiddenAccount + : hiddenAccount // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_LocalAccount implements _LocalAccount { + const _$_LocalAccount( + {required this.identityMaster, + @Uint8ListJsonConverter() required this.identitySecretKeyBytes, + required this.encryptionKeyType, + required this.biometricsEnabled, + required this.hiddenAccount}); + + factory _$_LocalAccount.fromJson(Map json) => + _$$_LocalAccountFromJson(json); + +// The master key record for the account, containing the identityPublicKey + @override + final IdentityMaster identityMaster; +// The encrypted identity secret that goes with the identityPublicKey + @override + @Uint8ListJsonConverter() + final Uint8List identitySecretKeyBytes; +// The kind of encryption input used on the account + @override + final EncryptionKeyType encryptionKeyType; +// If account is not hidden, password can be retrieved via + @override + final bool biometricsEnabled; +// Keep account hidden unless account password is entered +// (tries all hidden accounts with auth method (no biometrics)) + @override + final bool hiddenAccount; + + @override + String toString() { + return 'LocalAccount(identityMaster: $identityMaster, identitySecretKeyBytes: $identitySecretKeyBytes, encryptionKeyType: $encryptionKeyType, biometricsEnabled: $biometricsEnabled, hiddenAccount: $hiddenAccount)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_LocalAccount && + (identical(other.identityMaster, identityMaster) || + other.identityMaster == identityMaster) && + const DeepCollectionEquality() + .equals(other.identitySecretKeyBytes, identitySecretKeyBytes) && + (identical(other.encryptionKeyType, encryptionKeyType) || + other.encryptionKeyType == encryptionKeyType) && + (identical(other.biometricsEnabled, biometricsEnabled) || + other.biometricsEnabled == biometricsEnabled) && + (identical(other.hiddenAccount, hiddenAccount) || + other.hiddenAccount == hiddenAccount)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash( + runtimeType, + identityMaster, + const DeepCollectionEquality().hash(identitySecretKeyBytes), + encryptionKeyType, + biometricsEnabled, + hiddenAccount); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_LocalAccountCopyWith<_$_LocalAccount> get copyWith => + __$$_LocalAccountCopyWithImpl<_$_LocalAccount>(this, _$identity); + + @override + Map toJson() { + return _$$_LocalAccountToJson( + this, + ); + } +} + +abstract class _LocalAccount implements LocalAccount { + const factory _LocalAccount( + {required final IdentityMaster identityMaster, + @Uint8ListJsonConverter() required final Uint8List identitySecretKeyBytes, + required final EncryptionKeyType encryptionKeyType, + required final bool biometricsEnabled, + required final bool hiddenAccount}) = _$_LocalAccount; + + factory _LocalAccount.fromJson(Map json) = + _$_LocalAccount.fromJson; + + @override // The master key record for the account, containing the identityPublicKey + IdentityMaster get identityMaster; + @override // The encrypted identity secret that goes with the identityPublicKey + @Uint8ListJsonConverter() + Uint8List get identitySecretKeyBytes; + @override // The kind of encryption input used on the account + EncryptionKeyType get encryptionKeyType; + @override // If account is not hidden, password can be retrieved via + bool get biometricsEnabled; + @override // Keep account hidden unless account password is entered +// (tries all hidden accounts with auth method (no biometrics)) + bool get hiddenAccount; + @override + @JsonKey(ignore: true) + _$$_LocalAccountCopyWith<_$_LocalAccount> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/entities/local_account.g.dart b/lib/entities/local_account.g.dart new file mode 100644 index 0000000..04ba81b --- /dev/null +++ b/lib/entities/local_account.g.dart @@ -0,0 +1,29 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'local_account.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_LocalAccount _$$_LocalAccountFromJson(Map json) => + _$_LocalAccount( + identityMaster: IdentityMaster.fromJson( + json['identity_master'] as Map), + identitySecretKeyBytes: const Uint8ListJsonConverter() + .fromJson(json['identity_secret_key_bytes'] as String), + encryptionKeyType: + EncryptionKeyType.fromJson(json['encryption_key_type'] as String), + biometricsEnabled: json['biometrics_enabled'] as bool, + hiddenAccount: json['hidden_account'] as bool, + ); + +Map _$$_LocalAccountToJson(_$_LocalAccount instance) => + { + 'identity_master': instance.identityMaster.toJson(), + 'identity_secret_key_bytes': const Uint8ListJsonConverter() + .toJson(instance.identitySecretKeyBytes), + 'encryption_key_type': instance.encryptionKeyType.toJson(), + 'biometrics_enabled': instance.biometricsEnabled, + 'hidden_account': instance.hiddenAccount, + }; diff --git a/lib/entities/preferences.dart b/lib/entities/preferences.dart new file mode 100644 index 0000000..ec53006 --- /dev/null +++ b/lib/entities/preferences.dart @@ -0,0 +1,92 @@ +import 'package:change_case/change_case.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'preferences.freezed.dart'; +part 'preferences.g.dart'; + +// Theme supports light and dark mode, optionally selected by the +// operating system +enum DarkModePreference { + system, + light, + dark; + + String toJson() => name.toPascalCase(); + factory DarkModePreference.fromJson(String j) => + DarkModePreference.values.byName(j.toCamelCase()); +} + +// Lock preference changes how frequently the messenger locks its +// interface and requires the identitySecretKey to be entered (pin/password/etc) +@freezed +class LockPreference with _$LockPreference { + const factory LockPreference({ + required int inactivityLockSecs, + required bool lockWhenSwitching, + required bool lockWithSystemLock, + }) = _LockPreference; + + factory LockPreference.fromJson(Map json) => + _$LockPreferenceFromJson(json); +} + +// Theme supports multiple color variants based on 'Radix' +enum ColorPreference { + amber, + blue, + bronze, + brown, + crimson, + cyan, + gold, + grass, + gray, + green, + indigo, + lime, + mauve, + mint, + olive, + orange, + pink, + plum, + purple, + red, + sage, + sand, + sky, + slate, + teal, + tomato, + violet, + yellow; + + String toJson() => name.toPascalCase(); + factory ColorPreference.fromJson(String j) => + ColorPreference.values.byName(j.toCamelCase()); +} + +// Theme supports multiple translations +enum LanguagePreference { + englishUS; + + String toJson() => name.toPascalCase(); + factory LanguagePreference.fromJson(String j) => + LanguagePreference.values.byName(j.toCamelCase()); +} + +// Preferences are stored in a table locally and globally affect all +// accounts imported/added and the app in general +@freezed +class Preferences with _$Preferences { + const factory Preferences({ + required DarkModePreference darkMode, + required ColorPreference themeColor, + required LanguagePreference language, + required int displayScale, + required LockPreference locking, + }) = _Preferences; + + factory Preferences.fromJson(Map json) => + _$PreferencesFromJson(json); +} diff --git a/lib/entities/preferences.freezed.dart b/lib/entities/preferences.freezed.dart new file mode 100644 index 0000000..353ffee --- /dev/null +++ b/lib/entities/preferences.freezed.dart @@ -0,0 +1,437 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'preferences.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +LockPreference _$LockPreferenceFromJson(Map json) { + return _LockPreference.fromJson(json); +} + +/// @nodoc +mixin _$LockPreference { + int get inactivityLockSecs => throw _privateConstructorUsedError; + bool get lockWhenSwitching => throw _privateConstructorUsedError; + bool get lockWithSystemLock => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $LockPreferenceCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LockPreferenceCopyWith<$Res> { + factory $LockPreferenceCopyWith( + LockPreference value, $Res Function(LockPreference) then) = + _$LockPreferenceCopyWithImpl<$Res, LockPreference>; + @useResult + $Res call( + {int inactivityLockSecs, + bool lockWhenSwitching, + bool lockWithSystemLock}); +} + +/// @nodoc +class _$LockPreferenceCopyWithImpl<$Res, $Val extends LockPreference> + implements $LockPreferenceCopyWith<$Res> { + _$LockPreferenceCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? inactivityLockSecs = null, + Object? lockWhenSwitching = null, + Object? lockWithSystemLock = null, + }) { + return _then(_value.copyWith( + inactivityLockSecs: null == inactivityLockSecs + ? _value.inactivityLockSecs + : inactivityLockSecs // ignore: cast_nullable_to_non_nullable + as int, + lockWhenSwitching: null == lockWhenSwitching + ? _value.lockWhenSwitching + : lockWhenSwitching // ignore: cast_nullable_to_non_nullable + as bool, + lockWithSystemLock: null == lockWithSystemLock + ? _value.lockWithSystemLock + : lockWithSystemLock // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_LockPreferenceCopyWith<$Res> + implements $LockPreferenceCopyWith<$Res> { + factory _$$_LockPreferenceCopyWith( + _$_LockPreference value, $Res Function(_$_LockPreference) then) = + __$$_LockPreferenceCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {int inactivityLockSecs, + bool lockWhenSwitching, + bool lockWithSystemLock}); +} + +/// @nodoc +class __$$_LockPreferenceCopyWithImpl<$Res> + extends _$LockPreferenceCopyWithImpl<$Res, _$_LockPreference> + implements _$$_LockPreferenceCopyWith<$Res> { + __$$_LockPreferenceCopyWithImpl( + _$_LockPreference _value, $Res Function(_$_LockPreference) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? inactivityLockSecs = null, + Object? lockWhenSwitching = null, + Object? lockWithSystemLock = null, + }) { + return _then(_$_LockPreference( + inactivityLockSecs: null == inactivityLockSecs + ? _value.inactivityLockSecs + : inactivityLockSecs // ignore: cast_nullable_to_non_nullable + as int, + lockWhenSwitching: null == lockWhenSwitching + ? _value.lockWhenSwitching + : lockWhenSwitching // ignore: cast_nullable_to_non_nullable + as bool, + lockWithSystemLock: null == lockWithSystemLock + ? _value.lockWithSystemLock + : lockWithSystemLock // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_LockPreference implements _LockPreference { + const _$_LockPreference( + {required this.inactivityLockSecs, + required this.lockWhenSwitching, + required this.lockWithSystemLock}); + + factory _$_LockPreference.fromJson(Map json) => + _$$_LockPreferenceFromJson(json); + + @override + final int inactivityLockSecs; + @override + final bool lockWhenSwitching; + @override + final bool lockWithSystemLock; + + @override + String toString() { + return 'LockPreference(inactivityLockSecs: $inactivityLockSecs, lockWhenSwitching: $lockWhenSwitching, lockWithSystemLock: $lockWithSystemLock)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_LockPreference && + (identical(other.inactivityLockSecs, inactivityLockSecs) || + other.inactivityLockSecs == inactivityLockSecs) && + (identical(other.lockWhenSwitching, lockWhenSwitching) || + other.lockWhenSwitching == lockWhenSwitching) && + (identical(other.lockWithSystemLock, lockWithSystemLock) || + other.lockWithSystemLock == lockWithSystemLock)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash( + runtimeType, inactivityLockSecs, lockWhenSwitching, lockWithSystemLock); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_LockPreferenceCopyWith<_$_LockPreference> get copyWith => + __$$_LockPreferenceCopyWithImpl<_$_LockPreference>(this, _$identity); + + @override + Map toJson() { + return _$$_LockPreferenceToJson( + this, + ); + } +} + +abstract class _LockPreference implements LockPreference { + const factory _LockPreference( + {required final int inactivityLockSecs, + required final bool lockWhenSwitching, + required final bool lockWithSystemLock}) = _$_LockPreference; + + factory _LockPreference.fromJson(Map json) = + _$_LockPreference.fromJson; + + @override + int get inactivityLockSecs; + @override + bool get lockWhenSwitching; + @override + bool get lockWithSystemLock; + @override + @JsonKey(ignore: true) + _$$_LockPreferenceCopyWith<_$_LockPreference> get copyWith => + throw _privateConstructorUsedError; +} + +Preferences _$PreferencesFromJson(Map json) { + return _Preferences.fromJson(json); +} + +/// @nodoc +mixin _$Preferences { + DarkModePreference get darkMode => throw _privateConstructorUsedError; + ColorPreference get themeColor => throw _privateConstructorUsedError; + LanguagePreference get language => throw _privateConstructorUsedError; + int get displayScale => throw _privateConstructorUsedError; + LockPreference get locking => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $PreferencesCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PreferencesCopyWith<$Res> { + factory $PreferencesCopyWith( + Preferences value, $Res Function(Preferences) then) = + _$PreferencesCopyWithImpl<$Res, Preferences>; + @useResult + $Res call( + {DarkModePreference darkMode, + ColorPreference themeColor, + LanguagePreference language, + int displayScale, + LockPreference locking}); + + $LockPreferenceCopyWith<$Res> get locking; +} + +/// @nodoc +class _$PreferencesCopyWithImpl<$Res, $Val extends Preferences> + implements $PreferencesCopyWith<$Res> { + _$PreferencesCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? darkMode = null, + Object? themeColor = null, + Object? language = null, + Object? displayScale = null, + Object? locking = null, + }) { + return _then(_value.copyWith( + darkMode: null == darkMode + ? _value.darkMode + : darkMode // ignore: cast_nullable_to_non_nullable + as DarkModePreference, + themeColor: null == themeColor + ? _value.themeColor + : themeColor // ignore: cast_nullable_to_non_nullable + as ColorPreference, + language: null == language + ? _value.language + : language // ignore: cast_nullable_to_non_nullable + as LanguagePreference, + displayScale: null == displayScale + ? _value.displayScale + : displayScale // ignore: cast_nullable_to_non_nullable + as int, + locking: null == locking + ? _value.locking + : locking // ignore: cast_nullable_to_non_nullable + as LockPreference, + ) as $Val); + } + + @override + @pragma('vm:prefer-inline') + $LockPreferenceCopyWith<$Res> get locking { + return $LockPreferenceCopyWith<$Res>(_value.locking, (value) { + return _then(_value.copyWith(locking: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$_PreferencesCopyWith<$Res> + implements $PreferencesCopyWith<$Res> { + factory _$$_PreferencesCopyWith( + _$_Preferences value, $Res Function(_$_Preferences) then) = + __$$_PreferencesCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {DarkModePreference darkMode, + ColorPreference themeColor, + LanguagePreference language, + int displayScale, + LockPreference locking}); + + @override + $LockPreferenceCopyWith<$Res> get locking; +} + +/// @nodoc +class __$$_PreferencesCopyWithImpl<$Res> + extends _$PreferencesCopyWithImpl<$Res, _$_Preferences> + implements _$$_PreferencesCopyWith<$Res> { + __$$_PreferencesCopyWithImpl( + _$_Preferences _value, $Res Function(_$_Preferences) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? darkMode = null, + Object? themeColor = null, + Object? language = null, + Object? displayScale = null, + Object? locking = null, + }) { + return _then(_$_Preferences( + darkMode: null == darkMode + ? _value.darkMode + : darkMode // ignore: cast_nullable_to_non_nullable + as DarkModePreference, + themeColor: null == themeColor + ? _value.themeColor + : themeColor // ignore: cast_nullable_to_non_nullable + as ColorPreference, + language: null == language + ? _value.language + : language // ignore: cast_nullable_to_non_nullable + as LanguagePreference, + displayScale: null == displayScale + ? _value.displayScale + : displayScale // ignore: cast_nullable_to_non_nullable + as int, + locking: null == locking + ? _value.locking + : locking // ignore: cast_nullable_to_non_nullable + as LockPreference, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_Preferences implements _Preferences { + const _$_Preferences( + {required this.darkMode, + required this.themeColor, + required this.language, + required this.displayScale, + required this.locking}); + + factory _$_Preferences.fromJson(Map json) => + _$$_PreferencesFromJson(json); + + @override + final DarkModePreference darkMode; + @override + final ColorPreference themeColor; + @override + final LanguagePreference language; + @override + final int displayScale; + @override + final LockPreference locking; + + @override + String toString() { + return 'Preferences(darkMode: $darkMode, themeColor: $themeColor, language: $language, displayScale: $displayScale, locking: $locking)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_Preferences && + (identical(other.darkMode, darkMode) || + other.darkMode == darkMode) && + (identical(other.themeColor, themeColor) || + other.themeColor == themeColor) && + (identical(other.language, language) || + other.language == language) && + (identical(other.displayScale, displayScale) || + other.displayScale == displayScale) && + (identical(other.locking, locking) || other.locking == locking)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash( + runtimeType, darkMode, themeColor, language, displayScale, locking); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_PreferencesCopyWith<_$_Preferences> get copyWith => + __$$_PreferencesCopyWithImpl<_$_Preferences>(this, _$identity); + + @override + Map toJson() { + return _$$_PreferencesToJson( + this, + ); + } +} + +abstract class _Preferences implements Preferences { + const factory _Preferences( + {required final DarkModePreference darkMode, + required final ColorPreference themeColor, + required final LanguagePreference language, + required final int displayScale, + required final LockPreference locking}) = _$_Preferences; + + factory _Preferences.fromJson(Map json) = + _$_Preferences.fromJson; + + @override + DarkModePreference get darkMode; + @override + ColorPreference get themeColor; + @override + LanguagePreference get language; + @override + int get displayScale; + @override + LockPreference get locking; + @override + @JsonKey(ignore: true) + _$$_PreferencesCopyWith<_$_Preferences> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/entities/preferences.g.dart b/lib/entities/preferences.g.dart new file mode 100644 index 0000000..08bd24c --- /dev/null +++ b/lib/entities/preferences.g.dart @@ -0,0 +1,39 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'preferences.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_LockPreference _$$_LockPreferenceFromJson(Map json) => + _$_LockPreference( + inactivityLockSecs: json['inactivity_lock_secs'] as int, + lockWhenSwitching: json['lock_when_switching'] as bool, + lockWithSystemLock: json['lock_with_system_lock'] as bool, + ); + +Map _$$_LockPreferenceToJson(_$_LockPreference instance) => + { + 'inactivity_lock_secs': instance.inactivityLockSecs, + 'lock_when_switching': instance.lockWhenSwitching, + 'lock_with_system_lock': instance.lockWithSystemLock, + }; + +_$_Preferences _$$_PreferencesFromJson(Map json) => + _$_Preferences( + darkMode: DarkModePreference.fromJson(json['dark_mode'] as String), + themeColor: ColorPreference.fromJson(json['theme_color'] as String), + language: LanguagePreference.fromJson(json['language'] as String), + displayScale: json['display_scale'] as int, + locking: LockPreference.fromJson(json['locking'] as Map), + ); + +Map _$$_PreferencesToJson(_$_Preferences instance) => + { + 'dark_mode': instance.darkMode.toJson(), + 'theme_color': instance.themeColor.toJson(), + 'language': instance.language.toJson(), + 'display_scale': instance.displayScale, + 'locking': instance.locking.toJson(), + }; diff --git a/lib/main.dart b/lib/main.dart index fe89401..90458b8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,6 +8,7 @@ import 'veilid_support/veilid_support.dart'; import 'theming/theming.dart'; import 'app.dart'; import 'dart:io'; +import 'package:flutter_translate/flutter_translate.dart'; void main() async { // Disable all debugprints in release mode @@ -31,11 +32,13 @@ void main() async { // Start up Veilid and Veilid processor in the background unawaited(initializeVeilid()); + // Make localization delegate + var delegate = await LocalizationDelegate.create( + fallbackLocale: 'en_US', supportedLocales: ['en_US']); + // Run the app // Hot reloads will only restart this part, not Veilid - runApp( - ProviderScope( - observers: const [StateLogger()], - child: VeilidChatApp(theme: initTheme)), - ); + runApp(ProviderScope( + observers: const [StateLogger()], + child: LocalizedApp(delegate, VeilidChatApp(theme: initTheme)))); } diff --git a/proto/veilidchat.proto b/proto/veilidchat.proto new file mode 100644 index 0000000..fd33772 --- /dev/null +++ b/proto/veilidchat.proto @@ -0,0 +1,195 @@ + +// import 'dart:typed_data'; + +// import 'package:change_case/change_case.dart'; +// import 'package:flutter/material.dart'; +// import 'package:freezed_annotation/freezed_annotation.dart'; +// import 'package:uuid/uuid.dart'; +// import 'package:veilid/veilid.dart'; + +// part 'dht.freezed.dart'; +// part 'dht.g.dart'; + +// // DHTData - represents chunked blob data in the DHT +// // Header in subkey 0 follows this structure +// // +// // Subkeys 1..=stride on the first key are concatenated chunks +// // Subkeys 0..stride on the 'keys' keys are concatenated chunks +// // +// // Keys must use writable schema in order to make this data mutable +// @freezed +// class DHTData with _$DHTData { +// const factory DHTData({ +// // Other keys to concatenate +// required List keys, +// // Hash of reassembled data to verify contents +// required TypedHashDigest hash, +// // Subkeys per key +// required int stride, +// // Chunk size per subkey +// required int chunk, +// // Total data size +// required int size, +// }) = _DHTData; +// factory DHTData.fromJson(Map json) => _$DHTData(json); +// } + +// // DHTList - represents an ordered collection of individual elements +// // Header in subkey 0 follows this structure +// // +// // Subkeys 1..=stride on the first key are individual elements +// // Subkeys 0..stride on the 'keys' keys are also individual elements +// // +// // Keys must use writable schema in order to make this list mutable +// @freezed +// class DHTList with _$DHTList { +// const factory DHTList({ +// // Other keys to concatenate +// required List keys, +// // Subkeys per key +// required int stride, +// // Item position index +// // Actual item location is: +// // idx = index[n] + 1 (offset for header at idx 0) +// // key = idx / stride +// // subkey = idx % stride +// required List index, +// }) = _DHTList; +// factory DHTList.fromJson(Map json) => _$DHTList(json); +// } + + +// // A single message as part of a series of messages +// @freezed +// class Message with _$Message { +// const factory Message( +// { +// // Identity public key of the message author +// required TypedKey author, +// // Identity signature of all of the message fields +// required Signature sig, +// // Time the message was sent (ms since epoch) +// required int ts, +// // Text of the message +// required String text}) = _Message; + +// factory Message.fromJson(Map json) => +// _$MessageFromJson(json); +// } + +// // A record of a chunk of messages as reconciled from a conversation +// // Element of a DHTList of messages +// // DHT Key (Private): messagesKey +// // DHT Secret: messagesSecret +// // Encryption: Symmetric(messagesSecret) +// // * for Conversation messagesSecret is: DH(IdentityA, IdentityB) + +// @freezed +// class Messages with _$Messages { +// const factory Messages( +// {required Profile profile, +// required Identity identity, +// required bool available}) = _Messages; + +// factory Messages.fromJson(Map json) => +// _$MessagesFromJson(json); +// } + +// // A record of a 1-1 chat that is synchronized between +// // two users. Backed up on a DHT key. Visible and encrypted +// // for the other party +// // +// // DHT Schema: SMPL(0,1,[identityPublicKey]) +// // DHT Key (UnicastOutbox): localConversation +// // DHT Secret: None +// // Encryption: DH(IdentityA, IdentityB) + +// @freezed +// class Conversation with _$Conversation { +// const factory Conversation( +// { +// // Profile to publish to friend +// required Profile profile, +// // Identity to publish to friend +// required Identity identity, +// // Messages DHTList +// required TypedKey}) = _Contact; + +// factory Conversation.fromJson(Map json) => +// _$ConversationFromJson(json); +// } + +// // A record of a contact that has accepted a contact invitation +// // Contains a copy of the most recent remote profile as well as +// // a locally edited profile. +// // Contains a copy of the most recent identity from the contact's +// // Master identity dht key +// // +// // Stored in ContactList DHTList +// // + +// @freezed +// class Contact with _$Contact { +// const factory Contact({ +// // Friend's profile as locally edited +// required Profile editedProfile, +// // Copy of friend's profile from remote conversation +// required Profile remoteProfile, +// // Copy of friend's identity from remote conversation +// required Identity remoteIdentity, +// // Remote conversation key to sync from friend +// required TypedKey remoteConversation, +// // Our conversation key for friend to sync +// required TypedKey localConversation, +// }) = _Contact; + +// factory Contact.fromJson(Map json) => +// _$ContactFromJson(json); +// } + +// // Publicly shared profile information for both contacts and accounts +// // Contains: +// // Name - Friendly name +// // Title - Title of user +// // Icon - Little picture to represent user in contact list +// // +// // DHT Key: None +// // Encryption: None +// @freezed +// class Profile with _$Profile { +// const factory Profile({ +// // Friendy name +// required String name, +// // Title of user +// required String title, +// // Status/away message +// required String status, +// // Icon DHTData +// required TypedKey icon, +// }) = _Profile; +// factory Profile.fromJson(Map json) => +// _$ProfileFromJson(json); +// } + +// // A record of an individual account +// // +// // DHT Schema: DFLT(1) +// // DHT Key (Private): accountPublicKey +// // DHT Secret: accountSecretKey +// @freezed +// class Account with _$Account { +// const factory Account({ +// // The user's profile that gets shared with contacts +// required Profile profile, +// // Invisibility makes you always look 'Offline' +// required bool invisible, +// // Auto-away sets 'away' mode after an inactivity time +// required autoAwayTimeoutSec, +// // The contacts DHTList for this account +// // Schema: SMPL(0,64,[accountPublicKey]) Encryption: accountSecretKey +// required TypedKey contactList, +// }) = _Account; + +// factory Account.fromJson(Map json) => +// _$AccountFromJson(json); +// } diff --git a/pubspec.lock b/pubspec.lock index a1f9493..fe334c2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -326,6 +326,11 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_riverpod: dependency: "direct main" description: @@ -339,6 +344,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_translate: + dependency: "direct main" + description: + name: flutter_translate + sha256: "8b1c449bf6d17753e6f188185f735ebc0a328d21d745878a43be66857de8ebb3" + url: "https://pub.dev" + source: hosted + version: "4.0.4" flutter_web_plugins: dependency: transitive description: flutter @@ -424,6 +437,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + intl: + dependency: "direct main" + description: + name: intl + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + url: "https://pub.dev" + source: hosted + version: "0.18.0" io: dependency: transitive description: @@ -624,6 +645,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.3" + radix_colors: + dependency: "direct main" + description: + name: radix_colors + sha256: c56a4b2e80f6165d5386992fdb5b20aa2431410efb85a7d8a944330713b8b950 + url: "https://pub.dev" + source: hosted + version: "1.0.4" riverpod: dependency: transitive description: @@ -845,6 +874,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" + source: hosted + version: "2.2.2" uuid: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 782f5d6..979901e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,6 +10,8 @@ environment: dependencies: flutter: sdk: flutter + flutter_localizations: + sdk: flutter flutter_hooks: ^0.18.0 hooks_riverpod: ^2.1.3 flutter_riverpod: ^2.1.3 @@ -31,6 +33,9 @@ dependencies: json_annotation: ^4.8.1 equatable: ^2.0.5 change_case: ^1.1.0 + radix_colors: ^1.0.4 + flutter_translate: ^4.0.4 + intl: ^0.18.0 dev_dependencies: flutter_test: diff --git a/setup_linux.sh b/setup_linux.sh index 83772c1..ea651ea 100755 --- a/setup_linux.sh +++ b/setup_linux.sh @@ -12,13 +12,29 @@ if [ "$(lsb_release -d | grep -qEi 'debian|buntu|mint')" ]; then exit 1 fi -# # ensure unzip is installed -# if command -v unzip &> /dev/null; then -# echo '[X] unzip is available in the path' -# else -# echo 'unzip is not available in the path' -# exit 1 -# fi + +# run setup for veilid +$VEILIDDIR/setup_linux.sh +# run setup for veilid_flutter +$VEILIDDIR/veilid-flutter/setup_flutter.sh + + +# ensure protoc is installed +if command -v protoc &> /dev/null; then + echo '[X] protoc is available in the path' +else + echo 'protoc is not available in the path' + exit 1 +fi + +# Install protoc-gen-dart +dart pub global activate protoc_plugin +if command -v protoc-gen-dart &> /dev/null; then + echo '[X] protoc-gen-dart is available in the path' +else + echo 'protoc-gen-dart is not available in the path. Add "$HOME/.pub-cache/bin" to your path.' + exit 1 +fi # # ensure rsync is installed # if command -v rsync &> /dev/null; then @@ -35,7 +51,3 @@ fi # echo 'sed is not available in the path' # exit 1 # fi - -# run setup for veilid -$VEILIDDIR/setup_linux.sh - diff --git a/setup_macos.sh b/setup_macos.sh index 894a112..8b1b862 100755 --- a/setup_macos.sh +++ b/setup_macos.sh @@ -7,13 +7,27 @@ if [[ "$(uname)" != "Darwin" ]]; then exit 1 fi -# # ensure unzip is installed -# if command -v unzip &> /dev/null; then -# echo '[X] unzip is available in the path' -# else -# echo 'unzip is not available in the path' -# exit 1 -# fi +# run setup for veilid +$VEILIDDIR/setup_macos.sh +# run setup for veilid_flutter +$VEILIDDIR/veilid-flutter/setup_flutter.sh + +# ensure unzip is installed +if command -v protoc &> /dev/null; then + echo '[X] protoc is available in the path' +else + echo 'protoc is not available in the path' + exit 1 +fi + +# Install protoc-gen-dart +dart pub global activate protoc_plugin +if command -v protoc-gen-dart &> /dev/null; then + echo '[X] protoc-gen-dart is available in the path' +else + echo 'protoc-gen-dart is not available in the path. Add "$HOME/.pub-cache/bin" to your path.' + exit 1 +fi # # ensure rsync is installed # if command -v rsync &> /dev/null; then @@ -30,7 +44,3 @@ fi # echo 'sed is not available in the path' # exit 1 # fi - -# run setup for veilid -$VEILIDDIR/setup_macos.sh -