diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 24f0b9f3..aab172fd 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -517,6 +517,10 @@ "contactMethodSetPrimary": "Set as Primary", "contactMethodSetPrimaryHint": "Set this contact method as your primary contact method for account recovery and notifications", "contactMethodDeleteHint": "Are you sure to delete this contact method? This action cannot be undone.", + "contactMethodMakePublic": "Make Public", + "contactMethodMakePrivate": "Make Private", + "contactMethodPublic": "Public", + "contactMethodPrivate": "Private", "chatNotifyLevel": "Notify Level", "chatNotifyLevelDescription": "Decide how many notifications you will receive.", "chatNotifyLevelAll": "All", diff --git a/lib/models/account.dart b/lib/models/account.dart index 1f68b7ce..dc12d9be 100644 --- a/lib/models/account.dart +++ b/lib/models/account.dart @@ -19,6 +19,7 @@ sealed class SnAccount with _$SnAccount { required SnAccountProfile profile, required SnWalletSubscriptionRef? perkSubscription, @Default([]) List badges, + @Default([]) List contacts, required DateTime createdAt, required DateTime updatedAt, required DateTime? deletedAt, @@ -135,6 +136,7 @@ sealed class SnContactMethod with _$SnContactMethod { required int type, required DateTime? verifiedAt, required bool isPrimary, + required bool isPublic, required String content, required String accountId, required DateTime createdAt, diff --git a/lib/models/account.freezed.dart b/lib/models/account.freezed.dart index b644f1a3..cc4a035c 100644 --- a/lib/models/account.freezed.dart +++ b/lib/models/account.freezed.dart @@ -15,7 +15,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$SnAccount { - String get id; String get name; String get nick; String get language; String get region; bool get isSuperuser; String? get automatedId; SnAccountProfile get profile; SnWalletSubscriptionRef? get perkSubscription; List get badges; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; + String get id; String get name; String get nick; String get language; String get region; bool get isSuperuser; String? get automatedId; SnAccountProfile get profile; SnWalletSubscriptionRef? get perkSubscription; List get badges; List get contacts; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; /// Create a copy of SnAccount /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -28,16 +28,16 @@ $SnAccountCopyWith get copyWith => _$SnAccountCopyWithImpl @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.region, region) || other.region == region)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.automatedId, automatedId) || other.automatedId == automatedId)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other.badges, badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.region, region) || other.region == region)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.automatedId, automatedId) || other.automatedId == automatedId)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other.badges, badges)&&const DeepCollectionEquality().equals(other.contacts, contacts)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,name,nick,language,region,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(badges),createdAt,updatedAt,deletedAt); +int get hashCode => Object.hash(runtimeType,id,name,nick,language,region,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(badges),const DeepCollectionEquality().hash(contacts),createdAt,updatedAt,deletedAt); @override String toString() { - return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, region: $region, isSuperuser: $isSuperuser, automatedId: $automatedId, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; + return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, region: $region, isSuperuser: $isSuperuser, automatedId: $automatedId, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, contacts: $contacts, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; } @@ -48,7 +48,7 @@ abstract mixin class $SnAccountCopyWith<$Res> { factory $SnAccountCopyWith(SnAccount value, $Res Function(SnAccount) _then) = _$SnAccountCopyWithImpl; @useResult $Res call({ - String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt + String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, List contacts, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt }); @@ -65,7 +65,7 @@ class _$SnAccountCopyWithImpl<$Res> /// Create a copy of SnAccount /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? region = null,Object? isSuperuser = null,Object? automatedId = freezed,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? region = null,Object? isSuperuser = null,Object? automatedId = freezed,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? contacts = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { return _then(_self.copyWith( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable @@ -77,7 +77,8 @@ as bool,automatedId: freezed == automatedId ? _self.automatedId : automatedId // as String?,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable as SnAccountProfile,perkSubscription: freezed == perkSubscription ? _self.perkSubscription : perkSubscription // ignore: cast_nullable_to_non_nullable as SnWalletSubscriptionRef?,badges: null == badges ? _self.badges : badges // ignore: cast_nullable_to_non_nullable -as List,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as List,contacts: null == contacts ? _self.contacts : contacts // ignore: cast_nullable_to_non_nullable +as List,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable as DateTime?, @@ -183,10 +184,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, List contacts, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _SnAccount() when $default != null: -return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: +return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.contacts,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return orElse(); } @@ -204,10 +205,10 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, List contacts, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this; switch (_that) { case _SnAccount(): -return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);} +return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.contacts,_that.createdAt,_that.updatedAt,_that.deletedAt);} } /// A variant of `when` that fallback to returning `null` /// @@ -221,10 +222,10 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, List contacts, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this; switch (_that) { case _SnAccount() when $default != null: -return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: +return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.contacts,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return null; } @@ -236,7 +237,7 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that @JsonSerializable() class _SnAccount implements SnAccount { - const _SnAccount({required this.id, required this.name, required this.nick, required this.language, this.region = "", required this.isSuperuser, required this.automatedId, required this.profile, required this.perkSubscription, final List badges = const [], required this.createdAt, required this.updatedAt, required this.deletedAt}): _badges = badges; + const _SnAccount({required this.id, required this.name, required this.nick, required this.language, this.region = "", required this.isSuperuser, required this.automatedId, required this.profile, required this.perkSubscription, final List badges = const [], final List contacts = const [], required this.createdAt, required this.updatedAt, required this.deletedAt}): _badges = badges,_contacts = contacts; factory _SnAccount.fromJson(Map json) => _$SnAccountFromJson(json); @override final String id; @@ -255,6 +256,13 @@ class _SnAccount implements SnAccount { return EqualUnmodifiableListView(_badges); } + final List _contacts; +@override@JsonKey() List get contacts { + if (_contacts is EqualUnmodifiableListView) return _contacts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_contacts); +} + @override final DateTime createdAt; @override final DateTime updatedAt; @override final DateTime? deletedAt; @@ -272,16 +280,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.region, region) || other.region == region)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.automatedId, automatedId) || other.automatedId == automatedId)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other._badges, _badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.region, region) || other.region == region)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.automatedId, automatedId) || other.automatedId == automatedId)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other._badges, _badges)&&const DeepCollectionEquality().equals(other._contacts, _contacts)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,name,nick,language,region,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(_badges),createdAt,updatedAt,deletedAt); +int get hashCode => Object.hash(runtimeType,id,name,nick,language,region,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(_badges),const DeepCollectionEquality().hash(_contacts),createdAt,updatedAt,deletedAt); @override String toString() { - return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, region: $region, isSuperuser: $isSuperuser, automatedId: $automatedId, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; + return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, region: $region, isSuperuser: $isSuperuser, automatedId: $automatedId, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, contacts: $contacts, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; } @@ -292,7 +300,7 @@ abstract mixin class _$SnAccountCopyWith<$Res> implements $SnAccountCopyWith<$Re factory _$SnAccountCopyWith(_SnAccount value, $Res Function(_SnAccount) _then) = __$SnAccountCopyWithImpl; @override @useResult $Res call({ - String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt + String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List badges, List contacts, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt }); @@ -309,7 +317,7 @@ class __$SnAccountCopyWithImpl<$Res> /// Create a copy of SnAccount /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? region = null,Object? isSuperuser = null,Object? automatedId = freezed,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? region = null,Object? isSuperuser = null,Object? automatedId = freezed,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? contacts = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { return _then(_SnAccount( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable @@ -321,7 +329,8 @@ as bool,automatedId: freezed == automatedId ? _self.automatedId : automatedId // as String?,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable as SnAccountProfile,perkSubscription: freezed == perkSubscription ? _self.perkSubscription : perkSubscription // ignore: cast_nullable_to_non_nullable as SnWalletSubscriptionRef?,badges: null == badges ? _self._badges : badges // ignore: cast_nullable_to_non_nullable -as List,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as List,contacts: null == contacts ? _self._contacts : contacts // ignore: cast_nullable_to_non_nullable +as List,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable as DateTime?, @@ -1627,7 +1636,7 @@ as DateTime?, /// @nodoc mixin _$SnContactMethod { - String get id; int get type; DateTime? get verifiedAt; bool get isPrimary; String get content; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; + String get id; int get type; DateTime? get verifiedAt; bool get isPrimary; bool get isPublic; String get content; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; /// Create a copy of SnContactMethod /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -1640,16 +1649,16 @@ $SnContactMethodCopyWith get copyWith => _$SnContactMethodCopyW @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is SnContactMethod&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isPrimary, isPrimary) || other.isPrimary == isPrimary)&&(identical(other.content, content) || other.content == content)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnContactMethod&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isPrimary, isPrimary) || other.isPrimary == isPrimary)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.content, content) || other.content == content)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,type,verifiedAt,isPrimary,content,accountId,createdAt,updatedAt,deletedAt); +int get hashCode => Object.hash(runtimeType,id,type,verifiedAt,isPrimary,isPublic,content,accountId,createdAt,updatedAt,deletedAt); @override String toString() { - return 'SnContactMethod(id: $id, type: $type, verifiedAt: $verifiedAt, isPrimary: $isPrimary, content: $content, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; + return 'SnContactMethod(id: $id, type: $type, verifiedAt: $verifiedAt, isPrimary: $isPrimary, isPublic: $isPublic, content: $content, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; } @@ -1660,7 +1669,7 @@ abstract mixin class $SnContactMethodCopyWith<$Res> { factory $SnContactMethodCopyWith(SnContactMethod value, $Res Function(SnContactMethod) _then) = _$SnContactMethodCopyWithImpl; @useResult $Res call({ - String id, int type, DateTime? verifiedAt, bool isPrimary, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt + String id, int type, DateTime? verifiedAt, bool isPrimary, bool isPublic, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt }); @@ -1677,12 +1686,13 @@ class _$SnContactMethodCopyWithImpl<$Res> /// Create a copy of SnContactMethod /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? verifiedAt = freezed,Object? isPrimary = null,Object? content = null,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? verifiedAt = freezed,Object? isPrimary = null,Object? isPublic = null,Object? content = null,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { return _then(_self.copyWith( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable as int,verifiedAt: freezed == verifiedAt ? _self.verifiedAt : verifiedAt // ignore: cast_nullable_to_non_nullable as DateTime?,isPrimary: null == isPrimary ? _self.isPrimary : isPrimary // ignore: cast_nullable_to_non_nullable +as bool,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable as bool,content: null == content ? _self.content : content // ignore: cast_nullable_to_non_nullable as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable @@ -1770,10 +1780,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, int type, DateTime? verifiedAt, bool isPrimary, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, int type, DateTime? verifiedAt, bool isPrimary, bool isPublic, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _SnContactMethod() when $default != null: -return $default(_that.id,_that.type,_that.verifiedAt,_that.isPrimary,_that.content,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: +return $default(_that.id,_that.type,_that.verifiedAt,_that.isPrimary,_that.isPublic,_that.content,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return orElse(); } @@ -1791,10 +1801,10 @@ return $default(_that.id,_that.type,_that.verifiedAt,_that.isPrimary,_that.conte /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id, int type, DateTime? verifiedAt, bool isPrimary, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String id, int type, DateTime? verifiedAt, bool isPrimary, bool isPublic, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this; switch (_that) { case _SnContactMethod(): -return $default(_that.id,_that.type,_that.verifiedAt,_that.isPrimary,_that.content,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);} +return $default(_that.id,_that.type,_that.verifiedAt,_that.isPrimary,_that.isPublic,_that.content,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);} } /// A variant of `when` that fallback to returning `null` /// @@ -1808,10 +1818,10 @@ return $default(_that.id,_that.type,_that.verifiedAt,_that.isPrimary,_that.conte /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, int type, DateTime? verifiedAt, bool isPrimary, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, int type, DateTime? verifiedAt, bool isPrimary, bool isPublic, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this; switch (_that) { case _SnContactMethod() when $default != null: -return $default(_that.id,_that.type,_that.verifiedAt,_that.isPrimary,_that.content,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: +return $default(_that.id,_that.type,_that.verifiedAt,_that.isPrimary,_that.isPublic,_that.content,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return null; } @@ -1823,13 +1833,14 @@ return $default(_that.id,_that.type,_that.verifiedAt,_that.isPrimary,_that.conte @JsonSerializable() class _SnContactMethod implements SnContactMethod { - const _SnContactMethod({required this.id, required this.type, required this.verifiedAt, required this.isPrimary, required this.content, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}); + const _SnContactMethod({required this.id, required this.type, required this.verifiedAt, required this.isPrimary, required this.isPublic, required this.content, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}); factory _SnContactMethod.fromJson(Map json) => _$SnContactMethodFromJson(json); @override final String id; @override final int type; @override final DateTime? verifiedAt; @override final bool isPrimary; +@override final bool isPublic; @override final String content; @override final String accountId; @override final DateTime createdAt; @@ -1849,16 +1860,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnContactMethod&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isPrimary, isPrimary) || other.isPrimary == isPrimary)&&(identical(other.content, content) || other.content == content)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnContactMethod&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isPrimary, isPrimary) || other.isPrimary == isPrimary)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.content, content) || other.content == content)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,type,verifiedAt,isPrimary,content,accountId,createdAt,updatedAt,deletedAt); +int get hashCode => Object.hash(runtimeType,id,type,verifiedAt,isPrimary,isPublic,content,accountId,createdAt,updatedAt,deletedAt); @override String toString() { - return 'SnContactMethod(id: $id, type: $type, verifiedAt: $verifiedAt, isPrimary: $isPrimary, content: $content, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; + return 'SnContactMethod(id: $id, type: $type, verifiedAt: $verifiedAt, isPrimary: $isPrimary, isPublic: $isPublic, content: $content, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; } @@ -1869,7 +1880,7 @@ abstract mixin class _$SnContactMethodCopyWith<$Res> implements $SnContactMethod factory _$SnContactMethodCopyWith(_SnContactMethod value, $Res Function(_SnContactMethod) _then) = __$SnContactMethodCopyWithImpl; @override @useResult $Res call({ - String id, int type, DateTime? verifiedAt, bool isPrimary, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt + String id, int type, DateTime? verifiedAt, bool isPrimary, bool isPublic, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt }); @@ -1886,12 +1897,13 @@ class __$SnContactMethodCopyWithImpl<$Res> /// Create a copy of SnContactMethod /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? verifiedAt = freezed,Object? isPrimary = null,Object? content = null,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? verifiedAt = freezed,Object? isPrimary = null,Object? isPublic = null,Object? content = null,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { return _then(_SnContactMethod( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable as int,verifiedAt: freezed == verifiedAt ? _self.verifiedAt : verifiedAt // ignore: cast_nullable_to_non_nullable as DateTime?,isPrimary: null == isPrimary ? _self.isPrimary : isPrimary // ignore: cast_nullable_to_non_nullable +as bool,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable as bool,content: null == content ? _self.content : content // ignore: cast_nullable_to_non_nullable as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable diff --git a/lib/models/account.g.dart b/lib/models/account.g.dart index 3991fbe3..0bf4f96b 100644 --- a/lib/models/account.g.dart +++ b/lib/models/account.g.dart @@ -26,6 +26,11 @@ _SnAccount _$SnAccountFromJson(Map json) => _SnAccount( ?.map((e) => SnAccountBadge.fromJson(e as Map)) .toList() ?? const [], + contacts: + (json['contacts'] as List?) + ?.map((e) => SnContactMethod.fromJson(e as Map)) + .toList() ?? + const [], createdAt: DateTime.parse(json['created_at'] as String), updatedAt: DateTime.parse(json['updated_at'] as String), deletedAt: @@ -46,6 +51,7 @@ Map _$SnAccountToJson(_SnAccount instance) => 'profile': instance.profile.toJson(), 'perk_subscription': instance.perkSubscription?.toJson(), 'badges': instance.badges.map((e) => e.toJson()).toList(), + 'contacts': instance.contacts.map((e) => e.toJson()).toList(), 'created_at': instance.createdAt.toIso8601String(), 'updated_at': instance.updatedAt.toIso8601String(), 'deleted_at': instance.deletedAt?.toIso8601String(), @@ -229,6 +235,7 @@ _SnContactMethod _$SnContactMethodFromJson(Map json) => ? null : DateTime.parse(json['verified_at'] as String), isPrimary: json['is_primary'] as bool, + isPublic: json['is_public'] as bool, content: json['content'] as String, accountId: json['account_id'] as String, createdAt: DateTime.parse(json['created_at'] as String), @@ -245,6 +252,7 @@ Map _$SnContactMethodToJson(_SnContactMethod instance) => 'type': instance.type, 'verified_at': instance.verifiedAt?.toIso8601String(), 'is_primary': instance.isPrimary, + 'is_public': instance.isPublic, 'content': instance.content, 'account_id': instance.accountId, 'created_at': instance.createdAt.toIso8601String(), diff --git a/lib/screens/account/me/account_settings.dart b/lib/screens/account/me/account_settings.dart index c736188a..651bc3a2 100644 --- a/lib/screens/account/me/account_settings.dart +++ b/lib/screens/account/me/account_settings.dart @@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/auth.dart'; import 'package:island/models/account.dart'; @@ -479,6 +480,7 @@ class AccountSettingsScreen extends HookConsumerWidget { ); }, ), + const Gap(8), ] : null, ), diff --git a/lib/screens/account/me/settings_contacts.dart b/lib/screens/account/me/settings_contacts.dart index c1c1f33a..88a4e5b7 100644 --- a/lib/screens/account/me/settings_contacts.dart +++ b/lib/screens/account/me/settings_contacts.dart @@ -62,6 +62,32 @@ class ContactMethodSheet extends HookConsumerWidget { } } + Future makeContactMethodPublic() async { + try { + showLoadingModal(context); + final client = ref.read(apiClientProvider); + await client.post('/id/accounts/me/contacts/${contact.id}/public'); + if (context.mounted) Navigator.pop(context, true); + } catch (err) { + showErrorAlert(err); + } finally { + if (context.mounted) hideLoadingModal(context); + } + } + + Future makeContactMethodPrivate() async { + try { + showLoadingModal(context); + final client = ref.read(apiClientProvider); + await client.delete('/id/accounts/me/contacts/${contact.id}/public'); + if (context.mounted) Navigator.pop(context, true); + } catch (err) { + showErrorAlert(err); + } finally { + if (context.mounted) hideLoadingModal(context); + } + } + return SheetScaffold( titleText: 'contactMethod'.tr(), child: Column( @@ -111,6 +137,27 @@ class ContactMethodSheet extends HookConsumerWidget { backgroundColor: Theme.of(context).colorScheme.tertiary, ), ), + if (contact.isPublic) + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Badge( + label: Text('contactMethodPublic'.tr()), + textColor: Theme.of(context).colorScheme.onPrimary, + backgroundColor: Theme.of(context).colorScheme.primary, + ), + ), + if (!contact.isPublic) + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Badge( + label: Text('contactMethodPrivate'.tr()), + textColor: Theme.of(context).colorScheme.onSurface, + backgroundColor: + Theme.of( + context, + ).colorScheme.surfaceContainerHighest, + ), + ), ], ), ], @@ -130,6 +177,20 @@ class ContactMethodSheet extends HookConsumerWidget { onTap: setContactMethodAsPrimary, contentPadding: EdgeInsets.symmetric(horizontal: 20), ), + if (contact.verifiedAt != null && !contact.isPublic) + ListTile( + leading: const Icon(Symbols.public), + title: Text('contactMethodMakePublic').tr(), + onTap: makeContactMethodPublic, + contentPadding: EdgeInsets.symmetric(horizontal: 20), + ), + if (contact.verifiedAt != null && contact.isPublic) + ListTile( + leading: const Icon(Symbols.visibility_off), + title: Text('contactMethodMakePrivate').tr(), + onTap: makeContactMethodPrivate, + contentPadding: EdgeInsets.symmetric(horizontal: 20), + ), ListTile( leading: const Icon(Symbols.delete), title: Text('contactMethodDelete').tr(), diff --git a/lib/screens/account/profile.dart b/lib/screens/account/profile.dart index 4b110df1..7cc61977 100644 --- a/lib/screens/account/profile.dart +++ b/lib/screens/account/profile.dart @@ -321,6 +321,59 @@ class _AccountProfileLinks extends StatelessWidget { } } +class _AccountProfileContacts extends StatelessWidget { + final SnAccount data; + + const _AccountProfileContacts({required this.data}); + + @override + Widget build(BuildContext context) { + final publicContacts = data.contacts.where((c) => c.isPublic).toList(); + if (publicContacts.isEmpty) return const SizedBox.shrink(); + + return Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'contactMethod', + ).tr().bold().padding(horizontal: 24, top: 12, bottom: 4), + for (final contact in publicContacts) + ListTile( + title: Text(contact.content), + subtitle: Text(switch (contact.type) { + 0 => 'contactMethodTypeEmail'.tr(), + 1 => 'contactMethodTypePhone'.tr(), + _ => 'contactMethodTypeAddress'.tr(), + }), + leading: Icon(switch (contact.type) { + 0 => Symbols.mail, + 1 => Symbols.phone, + _ => Symbols.home, + }), + contentPadding: EdgeInsets.symmetric(horizontal: 24), + trailing: const Icon(Symbols.chevron_right), + shape: RoundedRectangleBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + ), + onTap: () { + switch (contact.type) { + case 0: + launchUrlString('mailto:${contact.content}'); + case 1: + launchUrlString('tel:${contact.content}'); + default: + // For address, maybe copy to clipboard or do nothing + Clipboard.setData(ClipboardData(text: contact.content)); + } + }, + ), + ], + ), + ); + } +} + class _AccountPublisherList extends StatelessWidget { final List publishers; @@ -792,6 +845,10 @@ class AccountProfileScreen extends HookConsumerWidget { SliverToBoxAdapter( child: _AccountProfileLinks(data: data), ), + if (data.contacts.any((c) => c.isPublic)) + SliverToBoxAdapter( + child: _AccountProfileContacts(data: data), + ), SliverToBoxAdapter( child: _AccountProfileDetail(data: data), ), @@ -916,6 +973,12 @@ class AccountProfileScreen extends HookConsumerWidget { data: data, ).padding(horizontal: 4), ), + if (data.contacts.any((c) => c.isPublic)) + SliverToBoxAdapter( + child: _AccountProfileContacts( + data: data, + ).padding(horizontal: 4), + ), SliverToBoxAdapter( child: _AccountPublisherList( publishers: accountPublishers.value ?? [], diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart index 19434daf..81c5cdbc 100644 --- a/lib/widgets/post/post_item.dart +++ b/lib/widgets/post/post_item.dart @@ -18,6 +18,7 @@ import 'package:island/screens/posts/compose.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/content/markdown.dart'; import 'package:island/widgets/post/post_item_screenshot.dart'; +import 'package:island/widgets/post/post_award_sheet.dart'; import 'package:island/widgets/post/post_pin_sheet.dart'; import 'package:island/widgets/post/post_shared.dart'; import 'package:island/widgets/safety/abuse_report_helper.dart'; @@ -245,6 +246,18 @@ class PostActionableItem extends HookConsumerWidget { ); }, ), + MenuAction( + title: 'award'.tr(), + image: MenuImage.icon(Symbols.star), + callback: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + useRootNavigator: true, + builder: (context) => PostAwardSheet(post: item), + ); + }, + ), MenuSeparator(), MenuAction( title: 'share'.tr(),