diff --git a/lib/types/post.dart b/lib/types/post.dart index 250c74b..66fa8b8 100644 --- a/lib/types/post.dart +++ b/lib/types/post.dart @@ -19,7 +19,7 @@ class SnPost with _$SnPost { required String? alias, required String? aliasPrefix, @Default([]) List tags, - @Default([]) List categories, + @Default([]) List categories, required List? replies, required int? replyId, required int? repostId, @@ -67,6 +67,23 @@ class SnPostTag with _$SnPostTag { _$SnPostTagFromJson(json); } +@freezed +class SnPostCategory with _$SnPostCategory { + const factory SnPostCategory({ + required int id, + required DateTime createdAt, + required DateTime updatedAt, + required dynamic deletedAt, + required String alias, + required String name, + required String description, + required dynamic posts, + }) = _SnPostCategory; + + factory SnPostCategory.fromJson(Map json) => + _$SnPostCategoryFromJson(json); +} + @freezed class SnPostPreload with _$SnPostPreload { const factory SnPostPreload({ diff --git a/lib/types/post.freezed.dart b/lib/types/post.freezed.dart index 6aa7349..8ee6a2a 100644 --- a/lib/types/post.freezed.dart +++ b/lib/types/post.freezed.dart @@ -30,7 +30,7 @@ mixin _$SnPost { String? get alias => throw _privateConstructorUsedError; String? get aliasPrefix => throw _privateConstructorUsedError; List get tags => throw _privateConstructorUsedError; - List get categories => throw _privateConstructorUsedError; + List get categories => throw _privateConstructorUsedError; List? get replies => throw _privateConstructorUsedError; int? get replyId => throw _privateConstructorUsedError; int? get repostId => throw _privateConstructorUsedError; @@ -77,7 +77,7 @@ abstract class $SnPostCopyWith<$Res> { String? alias, String? aliasPrefix, List tags, - List categories, + List categories, List? replies, int? replyId, int? repostId, @@ -197,7 +197,7 @@ class _$SnPostCopyWithImpl<$Res, $Val extends SnPost> categories: null == categories ? _value.categories : categories // ignore: cast_nullable_to_non_nullable - as List, + as List, replies: freezed == replies ? _value.replies : replies // ignore: cast_nullable_to_non_nullable @@ -362,7 +362,7 @@ abstract class _$$SnPostImplCopyWith<$Res> implements $SnPostCopyWith<$Res> { String? alias, String? aliasPrefix, List tags, - List categories, + List categories, List? replies, int? replyId, int? repostId, @@ -485,7 +485,7 @@ class __$$SnPostImplCopyWithImpl<$Res> categories: null == categories ? _value._categories : categories // ignore: cast_nullable_to_non_nullable - as List, + as List, replies: freezed == replies ? _value._replies : replies // ignore: cast_nullable_to_non_nullable @@ -584,7 +584,7 @@ class _$SnPostImpl extends _SnPost { required this.alias, required this.aliasPrefix, final List tags = const [], - final List categories = const [], + final List categories = const [], required final List? replies, required this.replyId, required this.repostId, @@ -649,10 +649,10 @@ class _$SnPostImpl extends _SnPost { return EqualUnmodifiableListView(_tags); } - final List _categories; + final List _categories; @override @JsonKey() - List get categories { + List get categories { if (_categories is EqualUnmodifiableListView) return _categories; // ignore: implicit_dynamic_type return EqualUnmodifiableListView(_categories); @@ -853,7 +853,7 @@ abstract class _SnPost extends SnPost { required final String? alias, required final String? aliasPrefix, final List tags, - final List categories, + final List categories, required final List? replies, required final int? replyId, required final int? repostId, @@ -899,7 +899,7 @@ abstract class _SnPost extends SnPost { @override List get tags; @override - List get categories; + List get categories; @override List? get replies; @override @@ -1253,6 +1253,312 @@ abstract class _SnPostTag implements SnPostTag { throw _privateConstructorUsedError; } +SnPostCategory _$SnPostCategoryFromJson(Map json) { + return _SnPostCategory.fromJson(json); +} + +/// @nodoc +mixin _$SnPostCategory { + int get id => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + dynamic get deletedAt => throw _privateConstructorUsedError; + String get alias => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + String get description => throw _privateConstructorUsedError; + dynamic get posts => throw _privateConstructorUsedError; + + /// Serializes this SnPostCategory to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SnPostCategory + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SnPostCategoryCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SnPostCategoryCopyWith<$Res> { + factory $SnPostCategoryCopyWith( + SnPostCategory value, $Res Function(SnPostCategory) then) = + _$SnPostCategoryCopyWithImpl<$Res, SnPostCategory>; + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + dynamic deletedAt, + String alias, + String name, + String description, + dynamic posts}); +} + +/// @nodoc +class _$SnPostCategoryCopyWithImpl<$Res, $Val extends SnPostCategory> + implements $SnPostCategoryCopyWith<$Res> { + _$SnPostCategoryCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SnPostCategory + /// 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? alias = null, + Object? name = null, + Object? description = null, + Object? posts = freezed, + }) { + 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, + alias: null == alias + ? _value.alias + : alias // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + posts: freezed == posts + ? _value.posts + : posts // ignore: cast_nullable_to_non_nullable + as dynamic, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$SnPostCategoryImplCopyWith<$Res> + implements $SnPostCategoryCopyWith<$Res> { + factory _$$SnPostCategoryImplCopyWith(_$SnPostCategoryImpl value, + $Res Function(_$SnPostCategoryImpl) then) = + __$$SnPostCategoryImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + dynamic deletedAt, + String alias, + String name, + String description, + dynamic posts}); +} + +/// @nodoc +class __$$SnPostCategoryImplCopyWithImpl<$Res> + extends _$SnPostCategoryCopyWithImpl<$Res, _$SnPostCategoryImpl> + implements _$$SnPostCategoryImplCopyWith<$Res> { + __$$SnPostCategoryImplCopyWithImpl( + _$SnPostCategoryImpl _value, $Res Function(_$SnPostCategoryImpl) _then) + : super(_value, _then); + + /// Create a copy of SnPostCategory + /// 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? alias = null, + Object? name = null, + Object? description = null, + Object? posts = freezed, + }) { + return _then(_$SnPostCategoryImpl( + 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, + alias: null == alias + ? _value.alias + : alias // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + posts: freezed == posts + ? _value.posts + : posts // ignore: cast_nullable_to_non_nullable + as dynamic, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SnPostCategoryImpl implements _SnPostCategory { + const _$SnPostCategoryImpl( + {required this.id, + required this.createdAt, + required this.updatedAt, + required this.deletedAt, + required this.alias, + required this.name, + required this.description, + required this.posts}); + + factory _$SnPostCategoryImpl.fromJson(Map json) => + _$$SnPostCategoryImplFromJson(json); + + @override + final int id; + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + @override + final dynamic deletedAt; + @override + final String alias; + @override + final String name; + @override + final String description; + @override + final dynamic posts; + + @override + String toString() { + return 'SnPostCategory(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, alias: $alias, name: $name, description: $description, posts: $posts)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SnPostCategoryImpl && + (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.alias, alias) || other.alias == alias) && + (identical(other.name, name) || other.name == name) && + (identical(other.description, description) || + other.description == description) && + const DeepCollectionEquality().equals(other.posts, posts)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + createdAt, + updatedAt, + const DeepCollectionEquality().hash(deletedAt), + alias, + name, + description, + const DeepCollectionEquality().hash(posts)); + + /// Create a copy of SnPostCategory + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SnPostCategoryImplCopyWith<_$SnPostCategoryImpl> get copyWith => + __$$SnPostCategoryImplCopyWithImpl<_$SnPostCategoryImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$SnPostCategoryImplToJson( + this, + ); + } +} + +abstract class _SnPostCategory implements SnPostCategory { + const factory _SnPostCategory( + {required final int id, + required final DateTime createdAt, + required final DateTime updatedAt, + required final dynamic deletedAt, + required final String alias, + required final String name, + required final String description, + required final dynamic posts}) = _$SnPostCategoryImpl; + + factory _SnPostCategory.fromJson(Map json) = + _$SnPostCategoryImpl.fromJson; + + @override + int get id; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + @override + dynamic get deletedAt; + @override + String get alias; + @override + String get name; + @override + String get description; + @override + dynamic get posts; + + /// Create a copy of SnPostCategory + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SnPostCategoryImplCopyWith<_$SnPostCategoryImpl> get copyWith => + throw _privateConstructorUsedError; +} + SnPostPreload _$SnPostPreloadFromJson(Map json) { return _SnPostPreload.fromJson(json); } diff --git a/lib/types/post.g.dart b/lib/types/post.g.dart index 943e4b2..db63047 100644 --- a/lib/types/post.g.dart +++ b/lib/types/post.g.dart @@ -22,7 +22,10 @@ _$SnPostImpl _$$SnPostImplFromJson(Map json) => _$SnPostImpl( ?.map((e) => SnPostTag.fromJson(e as Map)) .toList() ?? const [], - categories: json['categories'] as List? ?? const [], + categories: (json['categories'] as List?) + ?.map((e) => SnPostCategory.fromJson(e as Map)) + .toList() ?? + const [], replies: (json['replies'] as List?) ?.map((e) => SnPost.fromJson(e as Map)) .toList(), @@ -80,7 +83,7 @@ Map _$$SnPostImplToJson(_$SnPostImpl instance) => 'alias': instance.alias, 'alias_prefix': instance.aliasPrefix, 'tags': instance.tags.map((e) => e.toJson()).toList(), - 'categories': instance.categories, + 'categories': instance.categories.map((e) => e.toJson()).toList(), 'replies': instance.replies?.map((e) => e.toJson()).toList(), 'reply_id': instance.replyId, 'repost_id': instance.repostId, @@ -127,6 +130,31 @@ Map _$$SnPostTagImplToJson(_$SnPostTagImpl instance) => 'posts': instance.posts, }; +_$SnPostCategoryImpl _$$SnPostCategoryImplFromJson(Map json) => + _$SnPostCategoryImpl( + 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'], + alias: json['alias'] as String, + name: json['name'] as String, + description: json['description'] as String, + posts: json['posts'], + ); + +Map _$$SnPostCategoryImplToJson( + _$SnPostCategoryImpl instance) => + { + 'id': instance.id, + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt, + 'alias': instance.alias, + 'name': instance.name, + 'description': instance.description, + 'posts': instance.posts, + }; + _$SnPostPreloadImpl _$$SnPostPreloadImplFromJson(Map json) => _$SnPostPreloadImpl( thumbnail: json['thumbnail'] == null diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart index 9c00da0..9d44a6e 100644 --- a/lib/widgets/post/post_item.dart +++ b/lib/widgets/post/post_item.dart @@ -179,6 +179,7 @@ class PostItem extends StatelessWidget { children: [ if (data.visibility > 0) _PostVisibilityHint(data: data), _PostTruncatedHint(data: data), + if (data.tags.isNotEmpty) _PostTagsList(data: data), ], ).padding(horizontal: 12), const Gap(8), @@ -186,7 +187,6 @@ class PostItem extends StatelessWidget { ), ), Text('postArticle').tr().fontSize(13).opacity(0.75).padding(horizontal: 24, bottom: 8), - if (data.tags.isNotEmpty) _PostTagsList(data: data).padding(horizontal: 16, bottom: 6), _PostBottomAction( data: data, showComments: showComments, @@ -966,23 +966,50 @@ class _PostTagsList extends StatelessWidget { @override Widget build(BuildContext context) { - return Wrap( - spacing: 4, - runSpacing: 4, - children: data.tags - .map( - (ele) => InkWell( - child: Text( - '#${ele.alias}', - style: TextStyle( - decoration: TextDecoration.underline, + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + spacing: 4, + runSpacing: 4, + children: data.categories + .map( + (ele) => InkWell( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Symbols.category, size: 20), + const Gap(4), + Text(ele.alias, style: GoogleFonts.robotoMono()), + ], + ), + onTap: () {}, ), - ).fontSize(13), - onTap: () {}, - ), - ) - .toList(), - ).opacity(0.8); + ) + .toList(), + ).opacity(0.8), + Wrap( + spacing: 4, + runSpacing: 4, + children: data.tags + .map( + (ele) => InkWell( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Symbols.label, size: 20), + const Gap(4), + Text(ele.alias, style: GoogleFonts.robotoMono()), + ], + ), + onTap: () {}, + ), + ) + .toList(), + ).opacity(0.8), + ], + ); } } @@ -1023,6 +1050,7 @@ class _PostTruncatedHint extends StatelessWidget { return SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( + spacing: 8, children: [ if (data.body['content_length'] != null) Row( @@ -1035,7 +1063,7 @@ class _PostTruncatedHint extends StatelessWidget { ).inSeconds}s', ]), ], - ).padding(right: 8), + ), if (data.body['content_length'] != null) Row( children: [