From 273c66f5d513382227d27f641ac8b14712f52922 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Tue, 3 Dec 2024 00:02:30 +0800 Subject: [PATCH] :sparkles: Basic account page --- assets/translations/en.json | 9 +- assets/translations/zh.json | 7 +- lib/router.dart | 10 + lib/screens/account/pfp.dart | 274 ++++++++++++++++++++ lib/screens/post/post_publisher.dart | 9 +- lib/types/account.dart | 17 ++ lib/types/account.freezed.dart | 364 +++++++++++++++++++++++++-- lib/types/account.g.dart | 28 +++ 8 files changed, 693 insertions(+), 25 deletions(-) create mode 100644 lib/screens/account/pfp.dart diff --git a/assets/translations/en.json b/assets/translations/en.json index 5648b0b..a3af96b 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -102,7 +102,7 @@ "publisherTotalUpvote": "Upvote", "publisherTotalDownvote": "Downvote", "publisherSocialPoint": "Social Point", - "publisherJoinedAt": "Joined At {}", + "publisherJoinedAt": "Joined at {}", "publisherSocialPointTotal": { "zero": "No social point", "one": "{} social point", @@ -353,5 +353,10 @@ "subscribe": "Subscribe", "unsubscribe": "Unsubscribe", "attachmentUploadBy": "Upload by", - "attachmentShotOn": "Shot on {}" + "attachmentShotOn": "Shot on {}", + "accountJoinedAt": "Joined at {}", + "accountBirthday": "Born on {}", + "accountBadge": "Badge", + "badgeCompanyStaff": "Solsynth LLC Staff", + "badgeSiteMigration": "Solar Network Native" } diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 2fdc0c4..4c6410f 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -353,5 +353,10 @@ "subscribe": "订阅", "unsubscribe": "取消订阅", "attachmentUploadBy": "上传者", - "attachmentShotOn": "由 {} 拍摄" + "attachmentShotOn": "由 {} 拍摄", + "accountJoinedAt": "加入于 {}", + "accountBirthday": "出生于 {}", + "accountBadge": "徽章", + "badgeCompanyStaff": "索尔辛茨士大夫 · Staff", + "badgeSiteMigration": "Solar Network 原住民" } diff --git a/lib/router.dart b/lib/router.dart index bd944e2..1cc6e02 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -2,6 +2,7 @@ import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:surface/screens/account.dart'; +import 'package:surface/screens/account/pfp.dart'; import 'package:surface/screens/account/profile_edit.dart'; import 'package:surface/screens/account/publishers/publisher_edit.dart'; import 'package:surface/screens/account/publishers/publisher_new.dart'; @@ -103,6 +104,15 @@ final _appRoutes = [ pageBuilder: (context, state) => NoTransitionPage( child: const AccountScreen(), ), + routes: [ + GoRoute( + path: '/:name', + name: 'accountProfilePage', + pageBuilder: (context, state) => NoTransitionPage( + child: UserScreen(name: state.pathParameters['name']!), + ), + ), + ], ), GoRoute( path: '/chat', diff --git a/lib/screens/account/pfp.dart b/lib/screens/account/pfp.dart new file mode 100644 index 0000000..df79f4f --- /dev/null +++ b/lib/screens/account/pfp.dart @@ -0,0 +1,274 @@ +import 'dart:ui'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:material_symbols_icons/symbols.dart'; +import 'package:provider/provider.dart'; +import 'package:styled_widget/styled_widget.dart'; +import 'package:surface/providers/sn_network.dart'; +import 'package:surface/types/account.dart'; +import 'package:surface/widgets/account/account_image.dart'; +import 'package:surface/widgets/dialog.dart'; +import 'package:surface/widgets/universal_image.dart'; + +const Map kBadgesMeta = { + 'company.staff': ( + 'badgeCompanyStaff', + Symbols.tools_wrench, + ), + 'site.migration': ( + 'badgeSiteMigration', + Symbols.flag, + ), +}; + +class UserScreen extends StatefulWidget { + final String name; + const UserScreen({super.key, required this.name}); + + @override + State createState() => _UserScreenState(); +} + +class _UserScreenState extends State + with SingleTickerProviderStateMixin { + late final ScrollController _scrollController = ScrollController(); + + SnAccount? _account; + + Future _fetchAccount() async { + try { + final sn = context.read(); + final resp = await sn.client.get('/cgi/id/users/${widget.name}'); + if (!mounted) return; + _account = SnAccount.fromJson(resp.data); + } catch (err) { + if (!mounted) return; + context.showErrorDialog(err).then((_) { + if (mounted) Navigator.pop(context); + }); + } finally { + setState(() {}); + } + } + + double _appBarBlur = 0.0; + + late final _appBarWidth = MediaQuery.of(context).size.width; + late final _appBarHeight = + (_appBarWidth * kBannerAspectRatio).roundToDouble(); + + void _updateAppBarBlur() { + if (_scrollController.offset > _appBarHeight) return; + setState(() { + _appBarBlur = + (_scrollController.offset / _appBarHeight * 10).clamp(0.0, 10.0); + }); + } + + @override + void initState() { + super.initState(); + _fetchAccount().then((_) {}); + _scrollController.addListener(_updateAppBarBlur); + } + + @override + void dispose() { + _scrollController.removeListener(_updateAppBarBlur); + _scrollController.dispose(); + super.dispose(); + } + + static const kBannerAspectRatio = 7 / 16; + + @override + Widget build(BuildContext context) { + final imageHeight = _appBarHeight + kToolbarHeight + 8; + + const labelShadows = [ + Shadow( + offset: Offset(1, 1), + blurRadius: 5.0, + color: Color.fromARGB(255, 0, 0, 0), + ), + ]; + + final sn = context.read(); + + return Scaffold( + body: NestedScrollView( + controller: _scrollController, + headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { + return [ + SliverAppBar( + expandedHeight: _appBarHeight, + title: _account == null + ? Text('loading').tr() + : RichText( + textAlign: TextAlign.center, + text: TextSpan(children: [ + TextSpan( + text: _account!.nick, + style: + Theme.of(context).textTheme.titleLarge!.copyWith( + color: Colors.white, + shadows: labelShadows, + ), + ), + const TextSpan(text: '\n'), + TextSpan( + text: '@${_account!.name}', + style: + Theme.of(context).textTheme.bodySmall!.copyWith( + color: Colors.white, + shadows: labelShadows, + ), + ), + ]), + ), + pinned: true, + flexibleSpace: _account != null + ? Stack( + fit: StackFit.expand, + children: [ + UniversalImage( + sn.getAttachmentUrl(_account!.banner), + fit: BoxFit.cover, + height: imageHeight, + width: _appBarWidth, + cacheHeight: imageHeight, + cacheWidth: _appBarWidth, + ), + Positioned( + top: 0, + left: 0, + right: 0, + height: 56 + MediaQuery.of(context).padding.top, + child: ClipRect( + child: BackdropFilter( + filter: ImageFilter.blur( + sigmaX: _appBarBlur, + sigmaY: _appBarBlur, + ), + child: Container( + color: Colors.black.withOpacity( + clampDouble(_appBarBlur * 0.1, 0, 0.5), + ), + ), + ), + ), + ), + ], + ) + : null, + ), + ]; + }, + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + AccountImage( + content: _account!.avatar, + radius: 28, + ), + const Gap(16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _account!.nick, + style: Theme.of(context).textTheme.titleMedium, + ).bold(), + Text('@${_account!.name}').fontSize(13), + ], + ), + ), + ], + ).padding(right: 8), + const Gap(12), + Text(_account!.description).padding(horizontal: 8), + const Gap(12), + Column( + children: [ + Row( + children: [ + const Icon(Symbols.calendar_add_on), + const Gap(8), + Text('publisherJoinedAt').tr(args: [ + DateFormat('y/M/d').format(_account!.createdAt) + ]), + ], + ), + Row( + children: [ + const Icon(Symbols.cake), + const Gap(8), + Text('accountBirthday').tr(args: [ + _account!.profile?.birthday == null + ? 'unknown'.tr() + : DateFormat('M/d') + .format(_account!.profile!.birthday!) + ]), + ], + ), + Row( + children: [ + const Icon(Symbols.identity_platform), + const Gap(8), + Text( + '#${_account!.id.toString().padLeft(8, '0')}', + style: GoogleFonts.robotoMono(), + ).opacity(0.8), + ], + ), + ], + ).padding(horizontal: 8), + ], + ).padding(all: 16), + const Divider(), + const Gap(12), + Text('accountBadge') + .bold() + .fontSize(17) + .tr() + .padding(horizontal: 20, bottom: 4), + SizedBox( + height: 64, + width: double.infinity, + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 8), + scrollDirection: Axis.horizontal, + children: [ + for (final badge in _account?.badges ?? []) + SizedBox( + width: 280, + child: Card( + child: ListTile( + leading: Icon( + kBadgesMeta[badge.type]?.$2 ?? + Symbols.question_mark, + ), + title: Text( + kBadgesMeta[badge.type]?.$1 ?? 'unknown', + ).tr(), + ), + ), + ), + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/post/post_publisher.dart b/lib/screens/post/post_publisher.dart index 82b24a9..01ba92b 100644 --- a/lib/screens/post/post_publisher.dart +++ b/lib/screens/post/post_publisher.dart @@ -359,7 +359,14 @@ class _PostPublisherScreenState extends State child: Text('publisherRunBy').tr(args: [ '@${_account?.name ?? 'unknown'}', ]), - onTap: () {}, + onTap: () { + GoRouter.of(context).pushNamed( + 'accountProfilePage', + pathParameters: { + 'name': _account!.name, + }, + ); + }, ), const Gap(8), AccountImage( diff --git a/lib/types/account.dart b/lib/types/account.dart index afc7c16..4ef0b13 100644 --- a/lib/types/account.dart +++ b/lib/types/account.dart @@ -22,6 +22,7 @@ class SnAccount with _$SnAccount { required String nick, required Map permNodes, required SnAccountProfile? profile, + @Default([]) List badges, required DateTime? suspendedAt, required int? affiliatedId, required int? affiliatedTo, @@ -89,3 +90,19 @@ class SnRelationship with _$SnRelationship { factory SnRelationship.fromJson(Map json) => _$SnRelationshipFromJson(json); } + +@freezed +class SnAccountBadge with _$SnAccountBadge { + const factory SnAccountBadge({ + required int id, + required DateTime createdAt, + required DateTime updatedAt, + required dynamic deletedAt, + required String type, + required int accountId, + @Default({}) Map metadata, + }) = _SnAccountBadge; + + factory SnAccountBadge.fromJson(Map json) => + _$SnAccountBadgeFromJson(json); +} diff --git a/lib/types/account.freezed.dart b/lib/types/account.freezed.dart index bdb1cbd..16d0114 100644 --- a/lib/types/account.freezed.dart +++ b/lib/types/account.freezed.dart @@ -34,6 +34,7 @@ mixin _$SnAccount { String get nick => throw _privateConstructorUsedError; Map get permNodes => throw _privateConstructorUsedError; SnAccountProfile? get profile => throw _privateConstructorUsedError; + List get badges => throw _privateConstructorUsedError; DateTime? get suspendedAt => throw _privateConstructorUsedError; int? get affiliatedId => throw _privateConstructorUsedError; int? get affiliatedTo => throw _privateConstructorUsedError; @@ -69,6 +70,7 @@ abstract class $SnAccountCopyWith<$Res> { String nick, Map permNodes, SnAccountProfile? profile, + List badges, DateTime? suspendedAt, int? affiliatedId, int? affiliatedTo, @@ -106,6 +108,7 @@ class _$SnAccountCopyWithImpl<$Res, $Val extends SnAccount> Object? nick = null, Object? permNodes = null, Object? profile = freezed, + Object? badges = null, Object? suspendedAt = freezed, Object? affiliatedId = freezed, Object? affiliatedTo = freezed, @@ -165,6 +168,10 @@ class _$SnAccountCopyWithImpl<$Res, $Val extends SnAccount> ? _value.profile : profile // ignore: cast_nullable_to_non_nullable as SnAccountProfile?, + badges: null == badges + ? _value.badges + : badges // ignore: cast_nullable_to_non_nullable + as List, suspendedAt: freezed == suspendedAt ? _value.suspendedAt : suspendedAt // ignore: cast_nullable_to_non_nullable @@ -225,6 +232,7 @@ abstract class _$$SnAccountImplCopyWith<$Res> String nick, Map permNodes, SnAccountProfile? profile, + List badges, DateTime? suspendedAt, int? affiliatedId, int? affiliatedTo, @@ -261,6 +269,7 @@ class __$$SnAccountImplCopyWithImpl<$Res> Object? nick = null, Object? permNodes = null, Object? profile = freezed, + Object? badges = null, Object? suspendedAt = freezed, Object? affiliatedId = freezed, Object? affiliatedTo = freezed, @@ -320,6 +329,10 @@ class __$$SnAccountImplCopyWithImpl<$Res> ? _value.profile : profile // ignore: cast_nullable_to_non_nullable as SnAccountProfile?, + badges: null == badges + ? _value._badges + : badges // ignore: cast_nullable_to_non_nullable + as List, suspendedAt: freezed == suspendedAt ? _value.suspendedAt : suspendedAt // ignore: cast_nullable_to_non_nullable @@ -361,6 +374,7 @@ class _$SnAccountImpl extends _SnAccount { required this.nick, required final Map permNodes, required this.profile, + final List badges = const [], required this.suspendedAt, required this.affiliatedId, required this.affiliatedTo, @@ -368,6 +382,7 @@ class _$SnAccountImpl extends _SnAccount { required this.automatedId}) : _contacts = contacts, _permNodes = permNodes, + _badges = badges, super._(); factory _$SnAccountImpl.fromJson(Map json) => @@ -414,6 +429,15 @@ class _$SnAccountImpl extends _SnAccount { @override final SnAccountProfile? profile; + final List _badges; + @override + @JsonKey() + List get badges { + if (_badges is EqualUnmodifiableListView) return _badges; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_badges); + } + @override final DateTime? suspendedAt; @override @@ -427,7 +451,7 @@ class _$SnAccountImpl extends _SnAccount { @override String toString() { - return 'SnAccount(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, confirmedAt: $confirmedAt, contacts: $contacts, avatar: $avatar, banner: $banner, description: $description, name: $name, nick: $nick, permNodes: $permNodes, profile: $profile, suspendedAt: $suspendedAt, affiliatedId: $affiliatedId, affiliatedTo: $affiliatedTo, automatedBy: $automatedBy, automatedId: $automatedId)'; + return 'SnAccount(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, confirmedAt: $confirmedAt, contacts: $contacts, avatar: $avatar, banner: $banner, description: $description, name: $name, nick: $nick, permNodes: $permNodes, profile: $profile, badges: $badges, suspendedAt: $suspendedAt, affiliatedId: $affiliatedId, affiliatedTo: $affiliatedTo, automatedBy: $automatedBy, automatedId: $automatedId)'; } @override @@ -454,6 +478,7 @@ class _$SnAccountImpl extends _SnAccount { const DeepCollectionEquality() .equals(other._permNodes, _permNodes) && (identical(other.profile, profile) || other.profile == profile) && + const DeepCollectionEquality().equals(other._badges, _badges) && (identical(other.suspendedAt, suspendedAt) || other.suspendedAt == suspendedAt) && (identical(other.affiliatedId, affiliatedId) || @@ -468,26 +493,28 @@ class _$SnAccountImpl extends _SnAccount { @JsonKey(includeFromJson: false, includeToJson: false) @override - int get hashCode => Object.hash( - runtimeType, - id, - createdAt, - updatedAt, - deletedAt, - confirmedAt, - const DeepCollectionEquality().hash(_contacts), - avatar, - banner, - description, - name, - nick, - const DeepCollectionEquality().hash(_permNodes), - profile, - suspendedAt, - affiliatedId, - affiliatedTo, - automatedBy, - automatedId); + int get hashCode => Object.hashAll([ + runtimeType, + id, + createdAt, + updatedAt, + deletedAt, + confirmedAt, + const DeepCollectionEquality().hash(_contacts), + avatar, + banner, + description, + name, + nick, + const DeepCollectionEquality().hash(_permNodes), + profile, + const DeepCollectionEquality().hash(_badges), + suspendedAt, + affiliatedId, + affiliatedTo, + automatedBy, + automatedId + ]); /// Create a copy of SnAccount /// with the given fields replaced by the non-null parameter values. @@ -520,6 +547,7 @@ abstract class _SnAccount extends SnAccount { required final String nick, required final Map permNodes, required final SnAccountProfile? profile, + final List badges, required final DateTime? suspendedAt, required final int? affiliatedId, required final int? affiliatedTo, @@ -558,6 +586,8 @@ abstract class _SnAccount extends SnAccount { @override SnAccountProfile? get profile; @override + List get badges; + @override DateTime? get suspendedAt; @override int? get affiliatedId; @@ -1665,3 +1695,295 @@ abstract class _SnRelationship implements SnRelationship { _$$SnRelationshipImplCopyWith<_$SnRelationshipImpl> get copyWith => throw _privateConstructorUsedError; } + +SnAccountBadge _$SnAccountBadgeFromJson(Map json) { + return _SnAccountBadge.fromJson(json); +} + +/// @nodoc +mixin _$SnAccountBadge { + int get id => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + dynamic get deletedAt => throw _privateConstructorUsedError; + String get type => throw _privateConstructorUsedError; + int get accountId => throw _privateConstructorUsedError; + Map get metadata => throw _privateConstructorUsedError; + + /// Serializes this SnAccountBadge to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SnAccountBadge + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SnAccountBadgeCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SnAccountBadgeCopyWith<$Res> { + factory $SnAccountBadgeCopyWith( + SnAccountBadge value, $Res Function(SnAccountBadge) then) = + _$SnAccountBadgeCopyWithImpl<$Res, SnAccountBadge>; + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + dynamic deletedAt, + String type, + int accountId, + Map metadata}); +} + +/// @nodoc +class _$SnAccountBadgeCopyWithImpl<$Res, $Val extends SnAccountBadge> + implements $SnAccountBadgeCopyWith<$Res> { + _$SnAccountBadgeCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _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? createdAt = null, + Object? updatedAt = null, + Object? deletedAt = freezed, + Object? type = null, + Object? accountId = null, + Object? metadata = null, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + deletedAt: freezed == deletedAt + ? _value.deletedAt + : deletedAt // ignore: cast_nullable_to_non_nullable + as dynamic, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String, + accountId: null == accountId + ? _value.accountId + : accountId // ignore: cast_nullable_to_non_nullable + as int, + metadata: null == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$SnAccountBadgeImplCopyWith<$Res> + implements $SnAccountBadgeCopyWith<$Res> { + factory _$$SnAccountBadgeImplCopyWith(_$SnAccountBadgeImpl value, + $Res Function(_$SnAccountBadgeImpl) then) = + __$$SnAccountBadgeImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + dynamic deletedAt, + String type, + int accountId, + Map metadata}); +} + +/// @nodoc +class __$$SnAccountBadgeImplCopyWithImpl<$Res> + extends _$SnAccountBadgeCopyWithImpl<$Res, _$SnAccountBadgeImpl> + implements _$$SnAccountBadgeImplCopyWith<$Res> { + __$$SnAccountBadgeImplCopyWithImpl( + _$SnAccountBadgeImpl _value, $Res Function(_$SnAccountBadgeImpl) _then) + : super(_value, _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? createdAt = null, + Object? updatedAt = null, + Object? deletedAt = freezed, + Object? type = null, + Object? accountId = null, + Object? metadata = null, + }) { + return _then(_$SnAccountBadgeImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + deletedAt: freezed == deletedAt + ? _value.deletedAt + : deletedAt // ignore: cast_nullable_to_non_nullable + as dynamic, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String, + accountId: null == accountId + ? _value.accountId + : accountId // ignore: cast_nullable_to_non_nullable + as int, + metadata: null == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SnAccountBadgeImpl implements _SnAccountBadge { + const _$SnAccountBadgeImpl( + {required this.id, + required this.createdAt, + required this.updatedAt, + required this.deletedAt, + required this.type, + required this.accountId, + final Map metadata = const {}}) + : _metadata = metadata; + + factory _$SnAccountBadgeImpl.fromJson(Map json) => + _$$SnAccountBadgeImplFromJson(json); + + @override + final int id; + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + @override + final dynamic deletedAt; + @override + final String type; + @override + final int accountId; + final Map _metadata; + @override + @JsonKey() + Map get metadata { + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_metadata); + } + + @override + String toString() { + return 'SnAccountBadge(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, type: $type, accountId: $accountId, metadata: $metadata)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SnAccountBadgeImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + const DeepCollectionEquality().equals(other.deletedAt, deletedAt) && + (identical(other.type, type) || other.type == type) && + (identical(other.accountId, accountId) || + other.accountId == accountId) && + const DeepCollectionEquality().equals(other._metadata, _metadata)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + createdAt, + updatedAt, + const DeepCollectionEquality().hash(deletedAt), + type, + accountId, + const DeepCollectionEquality().hash(_metadata)); + + /// Create a copy of SnAccountBadge + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SnAccountBadgeImplCopyWith<_$SnAccountBadgeImpl> get copyWith => + __$$SnAccountBadgeImplCopyWithImpl<_$SnAccountBadgeImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$SnAccountBadgeImplToJson( + this, + ); + } +} + +abstract class _SnAccountBadge implements SnAccountBadge { + const factory _SnAccountBadge( + {required final int id, + required final DateTime createdAt, + required final DateTime updatedAt, + required final dynamic deletedAt, + required final String type, + required final int accountId, + final Map metadata}) = _$SnAccountBadgeImpl; + + factory _SnAccountBadge.fromJson(Map json) = + _$SnAccountBadgeImpl.fromJson; + + @override + int get id; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + @override + dynamic get deletedAt; + @override + String get type; + @override + int get accountId; + @override + Map get metadata; + + /// Create a copy of SnAccountBadge + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SnAccountBadgeImplCopyWith<_$SnAccountBadgeImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/types/account.g.dart b/lib/types/account.g.dart index 90adbe4..60cb271 100644 --- a/lib/types/account.g.dart +++ b/lib/types/account.g.dart @@ -29,6 +29,10 @@ _$SnAccountImpl _$$SnAccountImplFromJson(Map json) => profile: json['profile'] == null ? null : SnAccountProfile.fromJson(json['profile'] as Map), + badges: (json['badges'] as List?) + ?.map((e) => SnAccountBadge.fromJson(e as Map)) + .toList() ?? + const [], suspendedAt: json['suspended_at'] == null ? null : DateTime.parse(json['suspended_at'] as String), @@ -53,6 +57,7 @@ Map _$$SnAccountImplToJson(_$SnAccountImpl instance) => 'nick': instance.nick, 'perm_nodes': instance.permNodes, 'profile': instance.profile?.toJson(), + 'badges': instance.badges.map((e) => e.toJson()).toList(), 'suspended_at': instance.suspendedAt?.toIso8601String(), 'affiliated_id': instance.affiliatedId, 'affiliated_to': instance.affiliatedTo, @@ -164,3 +169,26 @@ Map _$$SnRelationshipImplToJson( 'status': instance.status, 'perm_nodes': instance.permNodes, }; + +_$SnAccountBadgeImpl _$$SnAccountBadgeImplFromJson(Map json) => + _$SnAccountBadgeImpl( + id: (json['id'] as num).toInt(), + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + deletedAt: json['deleted_at'], + type: json['type'] as String, + accountId: (json['account_id'] as num).toInt(), + metadata: json['metadata'] as Map? ?? const {}, + ); + +Map _$$SnAccountBadgeImplToJson( + _$SnAccountBadgeImpl instance) => + { + 'id': instance.id, + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt, + 'type': instance.type, + 'account_id': instance.accountId, + 'metadata': instance.metadata, + };