✨ Badges
This commit is contained in:
parent
ee8d502fc6
commit
610b924daf
@ -182,5 +182,29 @@
|
||||
"uploadAll": "Upload All",
|
||||
"stickerCopyPlaceholder": "Copy Placeholder",
|
||||
"realmSelection": "Select a Realm",
|
||||
"publisherIndividual": "Individual Publishers"
|
||||
"publisherIndividual": "Individual Publishers",
|
||||
"firstPostBadgeName": "First Post",
|
||||
"firstPostBadgeDescription": "Created your first post on Solar Network",
|
||||
"popularPostBadgeName": "Popular Post",
|
||||
"popularPostBadgeDescription": "Your post received significant engagement from the community",
|
||||
"viralPostBadgeName": "Viral Post",
|
||||
"viralPostBadgeDescription": "Your post went viral and reached a wide audience",
|
||||
"helpfulCommentBadgeName": "Helpful Comment",
|
||||
"helpfulCommentBadgeDescription": "Your comment was marked as helpful by others",
|
||||
"newcomerBadgeName": "Newcomer",
|
||||
"newcomerBadgeDescription": "Welcome to Solar Network! Start exploring and connecting",
|
||||
"contributorBadgeName": "Contributor",
|
||||
"contributorBadgeDescription": "Actively contributing to the Solar Network community",
|
||||
"expertBadgeName": "Expert",
|
||||
"expertBadgeDescription": "Recognized for your expertise and valuable contributions",
|
||||
"founderBadgeName": "Founder",
|
||||
"founderBadgeDescription": "One of the earliest members of Solar Network",
|
||||
"betaTesterBadgeName": "Beta Tester",
|
||||
"betaTesterBadgeDescription": "Helped test and improve Solar Network during beta",
|
||||
"moderatorBadgeName": "Moderator",
|
||||
"moderatorBadgeDescription": "Helping maintain and moderate the community",
|
||||
"developerBadgeName": "Developer",
|
||||
"developerBadgeDescription": "Contributing to Solar Network's development",
|
||||
"translatorBadgeName": "Translator",
|
||||
"translatorBadgeDescription": "Helping translate Solar Network into different languages"
|
||||
}
|
||||
|
104
lib/models/badge.dart
Normal file
104
lib/models/badge.dart
Normal file
@ -0,0 +1,104 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BadgeInfo {
|
||||
final String type;
|
||||
final String name;
|
||||
final String description;
|
||||
final IconData icon;
|
||||
final Color color;
|
||||
|
||||
const BadgeInfo({
|
||||
required this.type,
|
||||
required this.name,
|
||||
required this.description,
|
||||
this.icon = Icons.star,
|
||||
this.color = Colors.blue,
|
||||
});
|
||||
}
|
||||
|
||||
const Map<String, BadgeInfo> kBadgeTemplates = {
|
||||
'achievements.post.first': BadgeInfo(
|
||||
type: 'achievements.post.first',
|
||||
name: 'firstPostBadgeName',
|
||||
description: 'firstPostBadgeDescription',
|
||||
icon: Icons.create,
|
||||
color: Colors.green,
|
||||
),
|
||||
'achievements.post.popular': BadgeInfo(
|
||||
type: 'achievements.post.popular',
|
||||
name: 'popularPostBadgeName',
|
||||
description: 'popularPostBadgeDescription',
|
||||
icon: Icons.trending_up,
|
||||
color: Colors.orange,
|
||||
),
|
||||
'achievements.post.viral': BadgeInfo(
|
||||
type: 'achievements.post.viral',
|
||||
name: 'viralPostBadgeName',
|
||||
description: 'viralPostBadgeDescription',
|
||||
icon: Icons.whatshot,
|
||||
color: Colors.red,
|
||||
),
|
||||
'achievements.comment.helpful': BadgeInfo(
|
||||
type: 'achievements.comment.helpful',
|
||||
name: 'helpfulCommentBadgeName',
|
||||
description: 'helpfulCommentBadgeDescription',
|
||||
icon: Icons.thumb_up,
|
||||
color: Colors.lightBlue,
|
||||
),
|
||||
'ranks.newcomer': BadgeInfo(
|
||||
type: 'ranks.newcomer',
|
||||
name: 'newcomerBadgeName',
|
||||
description: 'newcomerBadgeDescription',
|
||||
icon: Icons.person_outline,
|
||||
color: Colors.blue,
|
||||
),
|
||||
'ranks.contributor': BadgeInfo(
|
||||
type: 'ranks.contributor',
|
||||
name: 'contributorBadgeName',
|
||||
description: 'contributorBadgeDescription',
|
||||
icon: Icons.stars,
|
||||
color: Colors.purple,
|
||||
),
|
||||
'ranks.expert': BadgeInfo(
|
||||
type: 'ranks.expert',
|
||||
name: 'expertBadgeName',
|
||||
description: 'expertBadgeDescription',
|
||||
icon: Icons.workspace_premium,
|
||||
color: Colors.amber,
|
||||
),
|
||||
'event.founder': BadgeInfo(
|
||||
type: 'event.founder',
|
||||
name: 'founderBadgeName',
|
||||
description: 'founderBadgeDescription',
|
||||
icon: Icons.foundation,
|
||||
color: Colors.deepPurple,
|
||||
),
|
||||
'event.beta.tester': BadgeInfo(
|
||||
type: 'event.beta.tester',
|
||||
name: 'betaTesterBadgeName',
|
||||
description: 'betaTesterBadgeDescription',
|
||||
icon: Icons.bug_report,
|
||||
color: Colors.teal,
|
||||
),
|
||||
'special.moderator': BadgeInfo(
|
||||
type: 'special.moderator',
|
||||
name: 'moderatorBadgeName',
|
||||
description: 'moderatorBadgeDescription',
|
||||
icon: Icons.construction,
|
||||
color: Colors.indigo,
|
||||
),
|
||||
'special.developer': BadgeInfo(
|
||||
type: 'special.developer',
|
||||
name: 'developerBadgeName',
|
||||
description: 'developerBadgeDescription',
|
||||
icon: Icons.code,
|
||||
color: Colors.indigo,
|
||||
),
|
||||
'special.translator': BadgeInfo(
|
||||
type: 'special.translator',
|
||||
name: 'translatorBadgeName',
|
||||
description: 'translatorBadgeDescription',
|
||||
icon: Icons.code,
|
||||
color: Colors.grey,
|
||||
),
|
||||
};
|
@ -13,6 +13,7 @@ abstract class SnAccount with _$SnAccount {
|
||||
required String language,
|
||||
required bool isSuperuser,
|
||||
required SnAccountProfile profile,
|
||||
@Default([]) List<SnAccountBadge> badges,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
@ -63,3 +64,22 @@ abstract class SnAccountStatus with _$SnAccountStatus {
|
||||
factory SnAccountStatus.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnAccountStatusFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class SnAccountBadge with _$SnAccountBadge {
|
||||
const factory SnAccountBadge({
|
||||
required String id,
|
||||
required String type,
|
||||
required String? label,
|
||||
required String? caption,
|
||||
required Map<String, dynamic> meta,
|
||||
required DateTime? expiredAt,
|
||||
required int accountId,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
}) = _SnAccountBadge;
|
||||
|
||||
factory SnAccountBadge.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnAccountBadgeFromJson(json);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$SnAccount {
|
||||
|
||||
int get id; String get name; String get nick; String get language; bool get isSuperuser; SnAccountProfile get profile; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
int get id; String get name; String get nick; String get language; bool get isSuperuser; SnAccountProfile get profile; List<SnAccountBadge> get badges; 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)
|
||||
@ -29,16 +29,16 @@ $SnAccountCopyWith<SnAccount> get copyWith => _$SnAccountCopyWithImpl<SnAccount>
|
||||
|
||||
@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.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.profile, profile) || other.profile == profile)&&(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.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.profile, profile) || other.profile == profile)&&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));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,profile,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,profile,const DeepCollectionEquality().hash(badges),createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ abstract mixin class $SnAccountCopyWith<$Res> {
|
||||
factory $SnAccountCopyWith(SnAccount value, $Res Function(SnAccount) _then) = _$SnAccountCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
int id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
int id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@ -66,7 +66,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? isSuperuser = null,Object? profile = 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? isSuperuser = null,Object? profile = null,Object? badges = 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 int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
@ -74,7 +74,8 @@ as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non
|
||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
||||
as bool,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountProfile,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountProfile,badges: null == badges ? _self.badges : badges // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnAccountBadge>,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?,
|
||||
@ -97,7 +98,7 @@ $SnAccountProfileCopyWith<$Res> get profile {
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnAccount implements SnAccount {
|
||||
const _SnAccount({required this.id, required this.name, required this.nick, required this.language, required this.isSuperuser, required this.profile, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||
const _SnAccount({required this.id, required this.name, required this.nick, required this.language, required this.isSuperuser, required this.profile, final List<SnAccountBadge> badges = const [], required this.createdAt, required this.updatedAt, required this.deletedAt}): _badges = badges;
|
||||
factory _SnAccount.fromJson(Map<String, dynamic> json) => _$SnAccountFromJson(json);
|
||||
|
||||
@override final int id;
|
||||
@ -106,6 +107,13 @@ class _SnAccount implements SnAccount {
|
||||
@override final String language;
|
||||
@override final bool isSuperuser;
|
||||
@override final SnAccountProfile profile;
|
||||
final List<SnAccountBadge> _badges;
|
||||
@override@JsonKey() List<SnAccountBadge> get badges {
|
||||
if (_badges is EqualUnmodifiableListView) return _badges;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_badges);
|
||||
}
|
||||
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
@ -123,16 +131,16 @@ Map<String, dynamic> 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.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.profile, profile) || other.profile == profile)&&(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.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.profile, profile) || other.profile == profile)&&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));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,profile,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,profile,const DeepCollectionEquality().hash(_badges),createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@ -143,7 +151,7 @@ abstract mixin class _$SnAccountCopyWith<$Res> implements $SnAccountCopyWith<$Re
|
||||
factory _$SnAccountCopyWith(_SnAccount value, $Res Function(_SnAccount) _then) = __$SnAccountCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
int id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
int id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@ -160,7 +168,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? isSuperuser = null,Object? profile = 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? isSuperuser = null,Object? profile = null,Object? badges = 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 int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
@ -168,7 +176,8 @@ as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non
|
||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
||||
as bool,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountProfile,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountProfile,badges: null == badges ? _self._badges : badges // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnAccountBadge>,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?,
|
||||
@ -565,6 +574,172 @@ as DateTime?,
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnAccountBadge {
|
||||
|
||||
String get id; String get type; String? get label; String? get caption; Map<String, dynamic> get meta; DateTime? get expiredAt; int get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnAccountBadge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountBadgeCopyWith<SnAccountBadge> get copyWith => _$SnAccountBadgeCopyWithImpl<SnAccountBadge>(this as SnAccountBadge, _$identity);
|
||||
|
||||
/// Serializes this SnAccountBadge to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountBadge&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.label, label) || other.label == label)&&(identical(other.caption, caption) || other.caption == caption)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(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,label,caption,const DeepCollectionEquality().hash(meta),expiredAt,accountId,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountBadge(id: $id, type: $type, label: $label, caption: $caption, meta: $meta, expiredAt: $expiredAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnAccountBadgeCopyWith<$Res> {
|
||||
factory $SnAccountBadgeCopyWith(SnAccountBadge value, $Res Function(SnAccountBadge) _then) = _$SnAccountBadgeCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String type, String? label, String? caption, Map<String, dynamic> meta, DateTime? expiredAt, int accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnAccountBadgeCopyWithImpl<$Res>
|
||||
implements $SnAccountBadgeCopyWith<$Res> {
|
||||
_$SnAccountBadgeCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnAccountBadge _self;
|
||||
final $Res Function(SnAccountBadge) _then;
|
||||
|
||||
/// Create a copy of SnAccountBadge
|
||||
/// 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? label = freezed,Object? caption = freezed,Object? meta = null,Object? expiredAt = freezed,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 String,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,caption: freezed == caption ? _self.caption : caption // ignore: cast_nullable_to_non_nullable
|
||||
as String?,meta: null == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as int,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?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnAccountBadge implements SnAccountBadge {
|
||||
const _SnAccountBadge({required this.id, required this.type, required this.label, required this.caption, required final Map<String, dynamic> meta, required this.expiredAt, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _meta = meta;
|
||||
factory _SnAccountBadge.fromJson(Map<String, dynamic> json) => _$SnAccountBadgeFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final String type;
|
||||
@override final String? label;
|
||||
@override final String? caption;
|
||||
final Map<String, dynamic> _meta;
|
||||
@override Map<String, dynamic> get meta {
|
||||
if (_meta is EqualUnmodifiableMapView) return _meta;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_meta);
|
||||
}
|
||||
|
||||
@override final DateTime? expiredAt;
|
||||
@override final int accountId;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
|
||||
/// Create a copy of SnAccountBadge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnAccountBadgeCopyWith<_SnAccountBadge> get copyWith => __$SnAccountBadgeCopyWithImpl<_SnAccountBadge>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnAccountBadgeToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountBadge&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.label, label) || other.label == label)&&(identical(other.caption, caption) || other.caption == caption)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(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,label,caption,const DeepCollectionEquality().hash(_meta),expiredAt,accountId,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountBadge(id: $id, type: $type, label: $label, caption: $caption, meta: $meta, expiredAt: $expiredAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnAccountBadgeCopyWith<$Res> implements $SnAccountBadgeCopyWith<$Res> {
|
||||
factory _$SnAccountBadgeCopyWith(_SnAccountBadge value, $Res Function(_SnAccountBadge) _then) = __$SnAccountBadgeCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String type, String? label, String? caption, Map<String, dynamic> meta, DateTime? expiredAt, int accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnAccountBadgeCopyWithImpl<$Res>
|
||||
implements _$SnAccountBadgeCopyWith<$Res> {
|
||||
__$SnAccountBadgeCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnAccountBadge _self;
|
||||
final $Res Function(_SnAccountBadge) _then;
|
||||
|
||||
/// Create a copy of SnAccountBadge
|
||||
/// 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? label = freezed,Object? caption = freezed,Object? meta = null,Object? expiredAt = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnAccountBadge(
|
||||
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 String,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,caption: freezed == caption ? _self.caption : caption // ignore: cast_nullable_to_non_nullable
|
||||
as String?,meta: null == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as int,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?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
|
@ -13,6 +13,11 @@ _SnAccount _$SnAccountFromJson(Map<String, dynamic> json) => _SnAccount(
|
||||
language: json['language'] as String,
|
||||
isSuperuser: json['is_superuser'] as bool,
|
||||
profile: SnAccountProfile.fromJson(json['profile'] as Map<String, dynamic>),
|
||||
badges:
|
||||
(json['badges'] as List<dynamic>?)
|
||||
?.map((e) => SnAccountBadge.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
@ -29,6 +34,7 @@ Map<String, dynamic> _$SnAccountToJson(_SnAccount instance) =>
|
||||
'language': instance.language,
|
||||
'is_superuser': instance.isSuperuser,
|
||||
'profile': instance.profile.toJson(),
|
||||
'badges': instance.badges.map((e) => e.toJson()).toList(),
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
@ -114,3 +120,37 @@ Map<String, dynamic> _$SnAccountStatusToJson(_SnAccountStatus instance) =>
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
_SnAccountBadge _$SnAccountBadgeFromJson(Map<String, dynamic> json) =>
|
||||
_SnAccountBadge(
|
||||
id: json['id'] as String,
|
||||
type: json['type'] as String,
|
||||
label: json['label'] as String?,
|
||||
caption: json['caption'] as String?,
|
||||
meta: json['meta'] as Map<String, dynamic>,
|
||||
expiredAt:
|
||||
json['expired_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['expired_at'] as String),
|
||||
accountId: (json['account_id'] as num).toInt(),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnAccountBadgeToJson(_SnAccountBadge instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'type': instance.type,
|
||||
'label': instance.label,
|
||||
'caption': instance.caption,
|
||||
'meta': instance.meta,
|
||||
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||
'account_id': instance.accountId,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
@ -36,7 +36,7 @@ class AccountScreen extends HookConsumerWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (user.value?.profile.background != null)
|
||||
if (user.value?.profile.backgroundId != null)
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(8),
|
||||
@ -44,8 +44,8 @@ class AccountScreen extends HookConsumerWidget {
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 7,
|
||||
child: CloudFileWidget(
|
||||
item: user.value!.profile.background!,
|
||||
child: CloudImageWidget(
|
||||
fileId: user.value!.profile.backgroundId!,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
@ -65,7 +65,8 @@ class AccountScreen extends HookConsumerWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
Column(
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
@ -79,9 +80,12 @@ class AccountScreen extends HookConsumerWidget {
|
||||
),
|
||||
Text(
|
||||
user.value!.profile.bio ?? 'No description yet.',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
).padding(horizontal: 16, top: 16),
|
||||
AccountStatusCreationWidget(uname: user.value!.name),
|
||||
|
@ -143,7 +143,9 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
title: Text('updateYourProfile').tr(),
|
||||
leading: const PageBackButton(),
|
||||
),
|
||||
body: Column(
|
||||
body: SingleChildScrollView(
|
||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
AspectRatio(
|
||||
@ -254,6 +256,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,16 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/widgets/account/badge.dart';
|
||||
import 'package:island/widgets/account/status.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
part 'profile.g.dart';
|
||||
|
||||
@ -28,6 +32,13 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final accountAsync = ref.watch(accountProvider(name));
|
||||
|
||||
final iconShadow = Shadow(
|
||||
color: Colors.black54,
|
||||
blurRadius: 5.0,
|
||||
offset: Offset(1.0, 1.0),
|
||||
);
|
||||
|
||||
return accountAsync.when(
|
||||
data:
|
||||
(data) => AppScaffold(
|
||||
@ -36,6 +47,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
SliverAppBar(
|
||||
expandedHeight: 180,
|
||||
pinned: true,
|
||||
leading: PageBackButton(shadows: [iconShadow]),
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
background:
|
||||
data.profile.backgroundId != null
|
||||
@ -47,33 +59,67 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
Theme.of(context).appBarTheme.backgroundColor,
|
||||
),
|
||||
title: Text(
|
||||
data.name,
|
||||
data.nick,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor,
|
||||
shadows: [
|
||||
Shadow(
|
||||
color: Colors.black54,
|
||||
blurRadius: 5.0,
|
||||
offset: Offset(1.0, 1.0),
|
||||
),
|
||||
],
|
||||
shadows: [iconShadow],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 20,
|
||||
children: [
|
||||
ProfilePictureWidget(
|
||||
fileId: data.profile.pictureId!,
|
||||
radius: 32,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 6,
|
||||
children: [
|
||||
Text(data.nick).fontSize(20),
|
||||
Text(
|
||||
data.profile.bio ?? '',
|
||||
style: const TextStyle(fontSize: 16),
|
||||
'@${data.name}',
|
||||
).fontSize(14).opacity(0.85),
|
||||
],
|
||||
),
|
||||
AccountStatusWidget(
|
||||
uname: name,
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
).padding(horizontal: 24, top: 24, bottom: 8),
|
||||
),
|
||||
if (data.badges.isNotEmpty)
|
||||
SliverToBoxAdapter(
|
||||
child: BadgeList(
|
||||
badges: data.badges,
|
||||
).padding(horizontal: 24, bottom: 24),
|
||||
)
|
||||
else
|
||||
const Gap(16),
|
||||
SliverToBoxAdapter(
|
||||
child: const Divider(height: 1).padding(bottom: 24),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text('bio').tr().bold(),
|
||||
if (data.profile.bio != null &&
|
||||
data.profile.bio!.isNotEmpty)
|
||||
Text(data.profile.bio!),
|
||||
],
|
||||
).padding(horizontal: 24),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
46
lib/widgets/account/badge.dart
Normal file
46
lib/widgets/account/badge.dart
Normal file
@ -0,0 +1,46 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/badge.dart';
|
||||
|
||||
class BadgeList extends StatelessWidget {
|
||||
final List<SnAccountBadge> badges;
|
||||
const BadgeList({super.key, required this.badges});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: badges.map((badge) => BadgeItem(badge: badge)).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BadgeItem extends StatelessWidget {
|
||||
final SnAccountBadge badge;
|
||||
const BadgeItem({super.key, required this.badge});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final template = kBadgeTemplates[badge.type];
|
||||
final name = badge.label ?? template?.name.tr() ?? 'unknown'.tr();
|
||||
final description = badge.caption ?? template?.description.tr() ?? '';
|
||||
|
||||
return Tooltip(
|
||||
message: '$name\n$description',
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: (template?.color ?? Colors.blue).withOpacity(0.1),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
template?.icon ?? Icons.stars,
|
||||
color: template?.color ?? Colors.orange,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -50,7 +50,10 @@ class AccountStatusCreationWidget extends HookConsumerWidget {
|
||||
data:
|
||||
(status) =>
|
||||
(status?.isCustomized ?? false)
|
||||
? AccountStatusWidget(uname: uname)
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(left: 4),
|
||||
child: AccountStatusWidget(uname: uname),
|
||||
)
|
||||
: Padding(
|
||||
padding:
|
||||
padding ??
|
||||
@ -112,15 +115,13 @@ class AccountStatusWidget extends HookConsumerWidget {
|
||||
child: Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
if (!(userStatus.value?.isCustomized ?? false))
|
||||
Icon(Symbols.keyboard_arrow_up)
|
||||
else if (userStatus.value!.isOnline)
|
||||
if (userStatus.value!.isOnline)
|
||||
Icon(
|
||||
Symbols.circle,
|
||||
fill: 1,
|
||||
color: Colors.green,
|
||||
size: 16,
|
||||
).padding(all: 4)
|
||||
).padding(right: 4)
|
||||
else
|
||||
Icon(Symbols.circle, color: Colors.grey, size: 16).padding(all: 4),
|
||||
if (userStatus.value?.isCustomized ?? false)
|
||||
|
Loading…
x
Reference in New Issue
Block a user