diff --git a/assets/i18n/zh-CN.json b/assets/i18n/zh-CN.json index 0e821eb..154fd9f 100644 --- a/assets/i18n/zh-CN.json +++ b/assets/i18n/zh-CN.json @@ -120,6 +120,7 @@ "other": "{}个附件" }, "edited": "已编辑", + "editedAt": "编辑于 {}", "addVideo": "添加视频", "addPhoto": "添加照片", "addFile": "添加文件", diff --git a/lib/main.dart b/lib/main.dart index e09043e..bf0a038 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -54,10 +54,16 @@ void main() async { try { await langdetect.initLangDetect(); await EasyLocalization.ensureInitialized(); - await Firebase.initializeApp( - options: DefaultFirebaseOptions.currentPlatform, - ); - FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); + + if (kIsWeb || !Platform.isLinux) { + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + FirebaseMessaging.onBackgroundMessage( + _firebaseMessagingBackgroundHandler, + ); + } + log("[SplashScreen] Firebase is ready!"); } catch (err) { showErrorAlert(err); diff --git a/lib/models/post.dart b/lib/models/post.dart index edb1aec..03a60c4 100644 --- a/lib/models/post.dart +++ b/lib/models/post.dart @@ -36,8 +36,8 @@ sealed class SnPost with _$SnPost { @Default({}) Map reactionsCount, @Default({}) Map reactionsMade, @Default([]) List reactions, - @Default([]) List tags, - @Default([]) List categories, + @Default([]) List tags, + @Default([]) List categories, @Default([]) List collections, @Default(null) DateTime? createdAt, @Default(null) DateTime? updatedAt, diff --git a/lib/models/post.freezed.dart b/lib/models/post.freezed.dart index 64f76df..460035d 100644 --- a/lib/models/post.freezed.dart +++ b/lib/models/post.freezed.dart @@ -15,7 +15,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$SnPost { - String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; int get type; Map? get meta; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; List get attachments; SnPublisher get publisher; Map get reactionsCount; Map get reactionsMade; List get reactions; List get tags; List get categories; List get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated; + String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; int get type; Map? get meta; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; List get attachments; SnPublisher get publisher; Map get reactionsCount; Map get reactionsMade; List get reactions; List get tags; List get categories; List get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated; /// Create a copy of SnPost /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -48,7 +48,7 @@ abstract mixin class $SnPostCopyWith<$Res> { factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl; @useResult $Res call({ - String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated + String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated }); @@ -94,8 +94,8 @@ as SnPublisher,reactionsCount: null == reactionsCount ? _self.reactionsCount : r as Map,reactionsMade: null == reactionsMade ? _self.reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable as Map,reactions: null == reactions ? _self.reactions : reactions // ignore: cast_nullable_to_non_nullable as List,tags: null == tags ? _self.tags : tags // ignore: cast_nullable_to_non_nullable -as List,categories: null == categories ? _self.categories : categories // ignore: cast_nullable_to_non_nullable -as List,collections: null == collections ? _self.collections : collections // ignore: cast_nullable_to_non_nullable +as List,categories: null == categories ? _self.categories : categories // ignore: cast_nullable_to_non_nullable +as List,collections: null == collections ? _self.collections : collections // ignore: cast_nullable_to_non_nullable as List,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable @@ -227,7 +227,7 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _SnPost() when $default != null: return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _: @@ -248,7 +248,7 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this; switch (_that) { case _SnPost(): return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);} @@ -265,7 +265,7 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this; switch (_that) { case _SnPost() when $default != null: return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _: @@ -280,7 +280,7 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit @JsonSerializable() class _SnPost implements SnPost { - const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.type = 0, final Map? meta, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, final List attachments = const [], required this.publisher, final Map reactionsCount = const {}, final Map reactionsMade = const {}, final List reactions = const [], final List tags = const [], final List categories = const [], final List collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections; + const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.type = 0, final Map? meta, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, final List attachments = const [], required this.publisher, final Map reactionsCount = const {}, final Map reactionsMade = const {}, final List reactions = const [], final List tags = const [], final List categories = const [], final List collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections; factory _SnPost.fromJson(Map json) => _$SnPostFromJson(json); @override final String id; @@ -341,15 +341,15 @@ class _SnPost implements SnPost { return EqualUnmodifiableListView(_reactions); } - final List _tags; -@override@JsonKey() List get tags { + final List _tags; +@override@JsonKey() List get tags { if (_tags is EqualUnmodifiableListView) return _tags; // ignore: implicit_dynamic_type return EqualUnmodifiableListView(_tags); } - final List _categories; -@override@JsonKey() List get categories { + final List _categories; +@override@JsonKey() List get categories { if (_categories is EqualUnmodifiableListView) return _categories; // ignore: implicit_dynamic_type return EqualUnmodifiableListView(_categories); @@ -400,7 +400,7 @@ abstract mixin class _$SnPostCopyWith<$Res> implements $SnPostCopyWith<$Res> { factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl; @override @useResult $Res call({ - String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated + String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated }); @@ -446,8 +446,8 @@ as SnPublisher,reactionsCount: null == reactionsCount ? _self._reactionsCount : as Map,reactionsMade: null == reactionsMade ? _self._reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable as Map,reactions: null == reactions ? _self._reactions : reactions // ignore: cast_nullable_to_non_nullable as List,tags: null == tags ? _self._tags : tags // ignore: cast_nullable_to_non_nullable -as List,categories: null == categories ? _self._categories : categories // ignore: cast_nullable_to_non_nullable -as List,collections: null == collections ? _self._collections : collections // ignore: cast_nullable_to_non_nullable +as List,categories: null == categories ? _self._categories : categories // ignore: cast_nullable_to_non_nullable +as List,collections: null == collections ? _self._collections : collections // ignore: cast_nullable_to_non_nullable as List,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable diff --git a/lib/models/post.g.dart b/lib/models/post.g.dart index a4c91a7..eb71db6 100644 --- a/lib/models/post.g.dart +++ b/lib/models/post.g.dart @@ -62,12 +62,12 @@ _SnPost _$SnPostFromJson(Map json) => _SnPost( reactions: json['reactions'] as List? ?? const [], tags: (json['tags'] as List?) - ?.map((e) => PostTag.fromJson(e as Map)) + ?.map((e) => SnPostTag.fromJson(e as Map)) .toList() ?? const [], categories: (json['categories'] as List?) - ?.map((e) => PostCategory.fromJson(e as Map)) + ?.map((e) => SnPostCategory.fromJson(e as Map)) .toList() ?? const [], collections: json['collections'] as List? ?? const [], diff --git a/lib/models/post_category.dart b/lib/models/post_category.dart index aa14793..0232ca6 100644 --- a/lib/models/post_category.dart +++ b/lib/models/post_category.dart @@ -1,19 +1,30 @@ - +import 'package:easy_localization/easy_localization.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:island/models/post.dart'; +import 'package:island/services/text.dart'; part 'post_category.freezed.dart'; part 'post_category.g.dart'; @freezed -sealed class PostCategory with _$PostCategory { - const factory PostCategory({ +sealed class SnPostCategory with _$SnPostCategory { + const SnPostCategory._(); + + const factory SnPostCategory({ required String id, required String slug, String? name, @Default([]) List posts, - }) = _PostCategory; + }) = _SnPostCategory; - factory PostCategory.fromJson(Map json) => - _$PostCategoryFromJson(json); + factory SnPostCategory.fromJson(Map json) => + _$SnPostCategoryFromJson(json); + + String get categoryDisplayTitle { + final capitalizedSlug = slug.capitalizeEachWord(); + if ('postCategory$capitalizedSlug'.trExists()) { + return 'postCategory$capitalizedSlug'.tr(); + } + return name ?? slug; + } } diff --git a/lib/models/post_category.freezed.dart b/lib/models/post_category.freezed.dart index 88f80b4..6e6d827 100644 --- a/lib/models/post_category.freezed.dart +++ b/lib/models/post_category.freezed.dart @@ -13,22 +13,22 @@ part of 'post_category.dart'; T _$identity(T value) => value; /// @nodoc -mixin _$PostCategory { +mixin _$SnPostCategory { String get id; String get slug; String? get name; List get posts; -/// Create a copy of PostCategory +/// Create a copy of SnPostCategory /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') -$PostCategoryCopyWith get copyWith => _$PostCategoryCopyWithImpl(this as PostCategory, _$identity); +$SnPostCategoryCopyWith get copyWith => _$SnPostCategoryCopyWithImpl(this as SnPostCategory, _$identity); - /// Serializes this PostCategory to a JSON map. + /// Serializes this SnPostCategory to a JSON map. Map toJson(); @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is PostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -37,15 +37,15 @@ int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEqu @override String toString() { - return 'PostCategory(id: $id, slug: $slug, name: $name, posts: $posts)'; + return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts)'; } } /// @nodoc -abstract mixin class $PostCategoryCopyWith<$Res> { - factory $PostCategoryCopyWith(PostCategory value, $Res Function(PostCategory) _then) = _$PostCategoryCopyWithImpl; +abstract mixin class $SnPostCategoryCopyWith<$Res> { + factory $SnPostCategoryCopyWith(SnPostCategory value, $Res Function(SnPostCategory) _then) = _$SnPostCategoryCopyWithImpl; @useResult $Res call({ String id, String slug, String? name, List posts @@ -56,14 +56,14 @@ $Res call({ } /// @nodoc -class _$PostCategoryCopyWithImpl<$Res> - implements $PostCategoryCopyWith<$Res> { - _$PostCategoryCopyWithImpl(this._self, this._then); +class _$SnPostCategoryCopyWithImpl<$Res> + implements $SnPostCategoryCopyWith<$Res> { + _$SnPostCategoryCopyWithImpl(this._self, this._then); - final PostCategory _self; - final $Res Function(PostCategory) _then; + final SnPostCategory _self; + final $Res Function(SnPostCategory) _then; -/// Create a copy of PostCategory +/// 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? slug = null,Object? name = freezed,Object? posts = null,}) { return _then(_self.copyWith( @@ -78,8 +78,8 @@ as List, } -/// Adds pattern-matching-related methods to [PostCategory]. -extension PostCategoryPatterns on PostCategory { +/// Adds pattern-matching-related methods to [SnPostCategory]. +extension SnPostCategoryPatterns on SnPostCategory { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -92,10 +92,10 @@ extension PostCategoryPatterns on PostCategory { /// } /// ``` -@optionalTypeArgs TResult maybeMap(TResult Function( _PostCategory value)? $default,{required TResult orElse(),}){ +@optionalTypeArgs TResult maybeMap(TResult Function( _SnPostCategory value)? $default,{required TResult orElse(),}){ final _that = this; switch (_that) { -case _PostCategory() when $default != null: +case _SnPostCategory() when $default != null: return $default(_that);case _: return orElse(); @@ -114,10 +114,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult map(TResult Function( _PostCategory value) $default,){ +@optionalTypeArgs TResult map(TResult Function( _SnPostCategory value) $default,){ final _that = this; switch (_that) { -case _PostCategory(): +case _SnPostCategory(): return $default(_that);} } /// A variant of `map` that fallback to returning `null`. @@ -132,10 +132,10 @@ return $default(_that);} /// } /// ``` -@optionalTypeArgs TResult? mapOrNull(TResult? Function( _PostCategory value)? $default,){ +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _SnPostCategory value)? $default,){ final _that = this; switch (_that) { -case _PostCategory() when $default != null: +case _SnPostCategory() when $default != null: return $default(_that);case _: return null; @@ -155,7 +155,7 @@ return $default(_that);case _: @optionalTypeArgs TResult maybeWhen(TResult Function( String id, String slug, String? name, List posts)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { -case _PostCategory() when $default != null: +case _SnPostCategory() when $default != null: return $default(_that.id,_that.slug,_that.name,_that.posts);case _: return orElse(); @@ -176,7 +176,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _: @optionalTypeArgs TResult when(TResult Function( String id, String slug, String? name, List posts) $default,) {final _that = this; switch (_that) { -case _PostCategory(): +case _SnPostCategory(): return $default(_that.id,_that.slug,_that.name,_that.posts);} } /// A variant of `when` that fallback to returning `null` @@ -193,7 +193,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);} @optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String slug, String? name, List posts)? $default,) {final _that = this; switch (_that) { -case _PostCategory() when $default != null: +case _SnPostCategory() when $default != null: return $default(_that.id,_that.slug,_that.name,_that.posts);case _: return null; @@ -205,9 +205,9 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _: /// @nodoc @JsonSerializable() -class _PostCategory implements PostCategory { - const _PostCategory({required this.id, required this.slug, this.name, final List posts = const []}): _posts = posts; - factory _PostCategory.fromJson(Map json) => _$PostCategoryFromJson(json); +class _SnPostCategory extends SnPostCategory { + const _SnPostCategory({required this.id, required this.slug, this.name, final List posts = const []}): _posts = posts,super._(); + factory _SnPostCategory.fromJson(Map json) => _$SnPostCategoryFromJson(json); @override final String id; @override final String slug; @@ -220,20 +220,20 @@ class _PostCategory implements PostCategory { } -/// Create a copy of PostCategory +/// Create a copy of SnPostCategory /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') -_$PostCategoryCopyWith<_PostCategory> get copyWith => __$PostCategoryCopyWithImpl<_PostCategory>(this, _$identity); +_$SnPostCategoryCopyWith<_SnPostCategory> get copyWith => __$SnPostCategoryCopyWithImpl<_SnPostCategory>(this, _$identity); @override Map toJson() { - return _$PostCategoryToJson(this, ); + return _$SnPostCategoryToJson(this, ); } @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -242,15 +242,15 @@ int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEqu @override String toString() { - return 'PostCategory(id: $id, slug: $slug, name: $name, posts: $posts)'; + return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts)'; } } /// @nodoc -abstract mixin class _$PostCategoryCopyWith<$Res> implements $PostCategoryCopyWith<$Res> { - factory _$PostCategoryCopyWith(_PostCategory value, $Res Function(_PostCategory) _then) = __$PostCategoryCopyWithImpl; +abstract mixin class _$SnPostCategoryCopyWith<$Res> implements $SnPostCategoryCopyWith<$Res> { + factory _$SnPostCategoryCopyWith(_SnPostCategory value, $Res Function(_SnPostCategory) _then) = __$SnPostCategoryCopyWithImpl; @override @useResult $Res call({ String id, String slug, String? name, List posts @@ -261,17 +261,17 @@ $Res call({ } /// @nodoc -class __$PostCategoryCopyWithImpl<$Res> - implements _$PostCategoryCopyWith<$Res> { - __$PostCategoryCopyWithImpl(this._self, this._then); +class __$SnPostCategoryCopyWithImpl<$Res> + implements _$SnPostCategoryCopyWith<$Res> { + __$SnPostCategoryCopyWithImpl(this._self, this._then); - final _PostCategory _self; - final $Res Function(_PostCategory) _then; + final _SnPostCategory _self; + final $Res Function(_SnPostCategory) _then; -/// Create a copy of PostCategory +/// Create a copy of SnPostCategory /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) { - return _then(_PostCategory( + return _then(_SnPostCategory( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable diff --git a/lib/models/post_category.g.dart b/lib/models/post_category.g.dart index 59ec591..ced2399 100644 --- a/lib/models/post_category.g.dart +++ b/lib/models/post_category.g.dart @@ -6,8 +6,8 @@ part of 'post_category.dart'; // JsonSerializableGenerator // ************************************************************************** -_PostCategory _$PostCategoryFromJson(Map json) => - _PostCategory( +_SnPostCategory _$SnPostCategoryFromJson(Map json) => + _SnPostCategory( id: json['id'] as String, slug: json['slug'] as String, name: json['name'] as String?, @@ -18,7 +18,7 @@ _PostCategory _$PostCategoryFromJson(Map json) => const [], ); -Map _$PostCategoryToJson(_PostCategory instance) => +Map _$SnPostCategoryToJson(_SnPostCategory instance) => { 'id': instance.id, 'slug': instance.slug, diff --git a/lib/models/post_tag.dart b/lib/models/post_tag.dart index d667d1e..5dae786 100644 --- a/lib/models/post_tag.dart +++ b/lib/models/post_tag.dart @@ -1,4 +1,3 @@ - import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:island/models/post.dart'; @@ -6,14 +5,14 @@ part 'post_tag.freezed.dart'; part 'post_tag.g.dart'; @freezed -sealed class PostTag with _$PostTag { - const factory PostTag({ +sealed class SnPostTag with _$SnPostTag { + const factory SnPostTag({ required String id, required String slug, String? name, @Default([]) List posts, - }) = _PostTag; + }) = _SnPostTag; - factory PostTag.fromJson(Map json) => - _$PostTagFromJson(json); + factory SnPostTag.fromJson(Map json) => + _$SnPostTagFromJson(json); } diff --git a/lib/models/post_tag.freezed.dart b/lib/models/post_tag.freezed.dart index f8e28a3..5436b8c 100644 --- a/lib/models/post_tag.freezed.dart +++ b/lib/models/post_tag.freezed.dart @@ -13,22 +13,22 @@ part of 'post_tag.dart'; T _$identity(T value) => value; /// @nodoc -mixin _$PostTag { +mixin _$SnPostTag { String get id; String get slug; String? get name; List get posts; -/// Create a copy of PostTag +/// Create a copy of SnPostTag /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') -$PostTagCopyWith get copyWith => _$PostTagCopyWithImpl(this as PostTag, _$identity); +$SnPostTagCopyWith get copyWith => _$SnPostTagCopyWithImpl(this as SnPostTag, _$identity); - /// Serializes this PostTag to a JSON map. + /// Serializes this SnPostTag to a JSON map. Map toJson(); @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is PostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -37,15 +37,15 @@ int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEqu @override String toString() { - return 'PostTag(id: $id, slug: $slug, name: $name, posts: $posts)'; + return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts)'; } } /// @nodoc -abstract mixin class $PostTagCopyWith<$Res> { - factory $PostTagCopyWith(PostTag value, $Res Function(PostTag) _then) = _$PostTagCopyWithImpl; +abstract mixin class $SnPostTagCopyWith<$Res> { + factory $SnPostTagCopyWith(SnPostTag value, $Res Function(SnPostTag) _then) = _$SnPostTagCopyWithImpl; @useResult $Res call({ String id, String slug, String? name, List posts @@ -56,14 +56,14 @@ $Res call({ } /// @nodoc -class _$PostTagCopyWithImpl<$Res> - implements $PostTagCopyWith<$Res> { - _$PostTagCopyWithImpl(this._self, this._then); +class _$SnPostTagCopyWithImpl<$Res> + implements $SnPostTagCopyWith<$Res> { + _$SnPostTagCopyWithImpl(this._self, this._then); - final PostTag _self; - final $Res Function(PostTag) _then; + final SnPostTag _self; + final $Res Function(SnPostTag) _then; -/// Create a copy of PostTag +/// Create a copy of SnPostTag /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) { return _then(_self.copyWith( @@ -78,8 +78,8 @@ as List, } -/// Adds pattern-matching-related methods to [PostTag]. -extension PostTagPatterns on PostTag { +/// Adds pattern-matching-related methods to [SnPostTag]. +extension SnPostTagPatterns on SnPostTag { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -92,10 +92,10 @@ extension PostTagPatterns on PostTag { /// } /// ``` -@optionalTypeArgs TResult maybeMap(TResult Function( _PostTag value)? $default,{required TResult orElse(),}){ +@optionalTypeArgs TResult maybeMap(TResult Function( _SnPostTag value)? $default,{required TResult orElse(),}){ final _that = this; switch (_that) { -case _PostTag() when $default != null: +case _SnPostTag() when $default != null: return $default(_that);case _: return orElse(); @@ -114,10 +114,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult map(TResult Function( _PostTag value) $default,){ +@optionalTypeArgs TResult map(TResult Function( _SnPostTag value) $default,){ final _that = this; switch (_that) { -case _PostTag(): +case _SnPostTag(): return $default(_that);} } /// A variant of `map` that fallback to returning `null`. @@ -132,10 +132,10 @@ return $default(_that);} /// } /// ``` -@optionalTypeArgs TResult? mapOrNull(TResult? Function( _PostTag value)? $default,){ +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _SnPostTag value)? $default,){ final _that = this; switch (_that) { -case _PostTag() when $default != null: +case _SnPostTag() when $default != null: return $default(_that);case _: return null; @@ -155,7 +155,7 @@ return $default(_that);case _: @optionalTypeArgs TResult maybeWhen(TResult Function( String id, String slug, String? name, List posts)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { -case _PostTag() when $default != null: +case _SnPostTag() when $default != null: return $default(_that.id,_that.slug,_that.name,_that.posts);case _: return orElse(); @@ -176,7 +176,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _: @optionalTypeArgs TResult when(TResult Function( String id, String slug, String? name, List posts) $default,) {final _that = this; switch (_that) { -case _PostTag(): +case _SnPostTag(): return $default(_that.id,_that.slug,_that.name,_that.posts);} } /// A variant of `when` that fallback to returning `null` @@ -193,7 +193,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);} @optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String slug, String? name, List posts)? $default,) {final _that = this; switch (_that) { -case _PostTag() when $default != null: +case _SnPostTag() when $default != null: return $default(_that.id,_that.slug,_that.name,_that.posts);case _: return null; @@ -205,9 +205,9 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _: /// @nodoc @JsonSerializable() -class _PostTag implements PostTag { - const _PostTag({required this.id, required this.slug, this.name, final List posts = const []}): _posts = posts; - factory _PostTag.fromJson(Map json) => _$PostTagFromJson(json); +class _SnPostTag implements SnPostTag { + const _SnPostTag({required this.id, required this.slug, this.name, final List posts = const []}): _posts = posts; + factory _SnPostTag.fromJson(Map json) => _$SnPostTagFromJson(json); @override final String id; @override final String slug; @@ -220,20 +220,20 @@ class _PostTag implements PostTag { } -/// Create a copy of PostTag +/// Create a copy of SnPostTag /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') -_$PostTagCopyWith<_PostTag> get copyWith => __$PostTagCopyWithImpl<_PostTag>(this, _$identity); +_$SnPostTagCopyWith<_SnPostTag> get copyWith => __$SnPostTagCopyWithImpl<_SnPostTag>(this, _$identity); @override Map toJson() { - return _$PostTagToJson(this, ); + return _$SnPostTagToJson(this, ); } @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -242,15 +242,15 @@ int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEqu @override String toString() { - return 'PostTag(id: $id, slug: $slug, name: $name, posts: $posts)'; + return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts)'; } } /// @nodoc -abstract mixin class _$PostTagCopyWith<$Res> implements $PostTagCopyWith<$Res> { - factory _$PostTagCopyWith(_PostTag value, $Res Function(_PostTag) _then) = __$PostTagCopyWithImpl; +abstract mixin class _$SnPostTagCopyWith<$Res> implements $SnPostTagCopyWith<$Res> { + factory _$SnPostTagCopyWith(_SnPostTag value, $Res Function(_SnPostTag) _then) = __$SnPostTagCopyWithImpl; @override @useResult $Res call({ String id, String slug, String? name, List posts @@ -261,17 +261,17 @@ $Res call({ } /// @nodoc -class __$PostTagCopyWithImpl<$Res> - implements _$PostTagCopyWith<$Res> { - __$PostTagCopyWithImpl(this._self, this._then); +class __$SnPostTagCopyWithImpl<$Res> + implements _$SnPostTagCopyWith<$Res> { + __$SnPostTagCopyWithImpl(this._self, this._then); - final _PostTag _self; - final $Res Function(_PostTag) _then; + final _SnPostTag _self; + final $Res Function(_SnPostTag) _then; -/// Create a copy of PostTag +/// Create a copy of SnPostTag /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) { - return _then(_PostTag( + return _then(_SnPostTag( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable diff --git a/lib/models/post_tag.g.dart b/lib/models/post_tag.g.dart index 95a02f9..43b43b4 100644 --- a/lib/models/post_tag.g.dart +++ b/lib/models/post_tag.g.dart @@ -6,7 +6,7 @@ part of 'post_tag.dart'; // JsonSerializableGenerator // ************************************************************************** -_PostTag _$PostTagFromJson(Map json) => _PostTag( +_SnPostTag _$SnPostTagFromJson(Map json) => _SnPostTag( id: json['id'] as String, slug: json['slug'] as String, name: json['name'] as String?, @@ -17,9 +17,10 @@ _PostTag _$PostTagFromJson(Map json) => _PostTag( const [], ); -Map _$PostTagToJson(_PostTag instance) => { - 'id': instance.id, - 'slug': instance.slug, - 'name': instance.name, - 'posts': instance.posts.map((e) => e.toJson()).toList(), -}; +Map _$SnPostTagToJson(_SnPostTag instance) => + { + 'id': instance.id, + 'slug': instance.slug, + 'name': instance.name, + 'posts': instance.posts.map((e) => e.toJson()).toList(), + }; diff --git a/lib/widgets/post/compose_settings_sheet.dart b/lib/widgets/post/compose_settings_sheet.dart index 5bb8edf..192ce6a 100644 --- a/lib/widgets/post/compose_settings_sheet.dart +++ b/lib/widgets/post/compose_settings_sheet.dart @@ -6,7 +6,6 @@ import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/post_category.dart'; import 'package:island/pods/network.dart'; -import 'package:island/services/text.dart'; import 'package:island/widgets/content/sheet.dart'; import 'package:island/widgets/post/compose_shared.dart'; import 'package:material_symbols_icons/symbols.dart'; @@ -16,12 +15,12 @@ import 'package:textfield_tags/textfield_tags.dart'; part 'compose_settings_sheet.g.dart'; @riverpod -Future> postCategories(Ref ref) async { +Future> postCategories(Ref ref) async { final apiClient = ref.watch(apiClientProvider); final resp = await apiClient.get('/sphere/posts/categories'); return resp.data - .map((e) => PostCategory.fromJson(e)) - .cast() + .map((e) => SnPostCategory.fromJson(e)) + .cast() .toList(); } @@ -215,14 +214,6 @@ class ComposeSettingsSheet extends HookConsumerWidget { ); } - String getCategoryDisplayTitle(PostCategory category) { - final capitalizedSlug = category.slug.capitalizeEachWord(); - if ('postCategory$capitalizedSlug'.trExists()) { - return 'postCategory$capitalizedSlug'.tr(); - } - return category.name ?? category.slug; - } - return SheetScaffold( titleText: 'postSettings'.tr(), child: SingleChildScrollView( @@ -253,7 +244,7 @@ class ComposeSettingsSheet extends HookConsumerWidget { // Categories field // FIXME: Sometimes the entire dropdown crashes: 'package:flutter/src/rendering/stack.dart': Failed assertion: line 799 pos 12: 'firstChild == null || child != null': is not true. - DropdownButtonFormField2( + DropdownButtonFormField2( isExpanded: true, decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric(vertical: 9), @@ -263,7 +254,7 @@ class ComposeSettingsSheet extends HookConsumerWidget { ), hint: Text('categories'.tr(), style: TextStyle(fontSize: 15)), items: - (postCategories.value ?? []).map((item) { + (postCategories.value ?? []).map((item) { return DropdownMenuItem( value: item, enabled: false, @@ -299,7 +290,7 @@ class ComposeSettingsSheet extends HookConsumerWidget { const SizedBox(width: 16), Expanded( child: Text( - getCategoryDisplayTitle(item), + item.categoryDisplayTitle, style: const TextStyle(fontSize: 14), ), ), @@ -331,7 +322,7 @@ class ComposeSettingsSheet extends HookConsumerWidget { ), margin: const EdgeInsets.only(right: 4), child: Text( - getCategoryDisplayTitle(category), + category.categoryDisplayTitle, style: TextStyle( color: Theme.of(context).colorScheme.onPrimary, fontSize: 13, diff --git a/lib/widgets/post/compose_settings_sheet.g.dart b/lib/widgets/post/compose_settings_sheet.g.dart index 4ae7e40..7816a5d 100644 --- a/lib/widgets/post/compose_settings_sheet.g.dart +++ b/lib/widgets/post/compose_settings_sheet.g.dart @@ -6,12 +6,12 @@ part of 'compose_settings_sheet.dart'; // RiverpodGenerator // ************************************************************************** -String _$postCategoriesHash() => r'503ce6f0fdd728a8cb991665006c3b4bffbb94d4'; +String _$postCategoriesHash() => r'24337fe806d088b6468a350f62d5a5d40232a73c'; /// See also [postCategories]. @ProviderFor(postCategories) final postCategoriesProvider = - AutoDisposeFutureProvider>.internal( + AutoDisposeFutureProvider>.internal( postCategories, name: r'postCategoriesProvider', debugGetCreateSourceHash: @@ -24,6 +24,6 @@ final postCategoriesProvider = @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element -typedef PostCategoriesRef = AutoDisposeFutureProviderRef>; +typedef PostCategoriesRef = AutoDisposeFutureProviderRef>; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/widgets/post/compose_shared.dart b/lib/widgets/post/compose_shared.dart index 478edf4..0bfbbd3 100644 --- a/lib/widgets/post/compose_shared.dart +++ b/lib/widgets/post/compose_shared.dart @@ -31,7 +31,7 @@ class ComposeState { final ValueNotifier> attachmentProgress; final ValueNotifier currentPublisher; final ValueNotifier submitting; - final ValueNotifier> categories; + final ValueNotifier> categories; StringTagController tagsController; final String draftId; int postType; @@ -109,7 +109,7 @@ class ComposeLogic { attachmentProgress: ValueNotifier>({}), currentPublisher: ValueNotifier(originalPost?.publisher), tagsController: tagsController, - categories: ValueNotifier>( + categories: ValueNotifier>( originalPost?.categories ?? [], ), draftId: id, @@ -140,7 +140,7 @@ class ComposeLogic { attachmentProgress: ValueNotifier>({}), currentPublisher: ValueNotifier(null), tagsController: tagsController, - categories: ValueNotifier>([]), + categories: ValueNotifier>([]), draftId: draft.id, postType: postType, pollId: null, diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart index 4fde4d4..3a0997b 100644 --- a/lib/widgets/post/post_item.dart +++ b/lib/widgets/post/post_item.dart @@ -315,7 +315,7 @@ class PostItem extends HookConsumerWidget { } } - String _parseVisibility(int visibility) { + String parseVisibility(int visibility) { switch (visibility) { case 1: return 'postVisibilityFriends'; @@ -377,12 +377,10 @@ class PostItem extends HookConsumerWidget { if (item.editedAt != null) Text( 'editedAt'.tr(args: [item.editedAt!.formatSystem()]), - style: TextStyle(height: 1.2), ).fontSize(10), if (item.visibility != 0) Text( - _parseVisibility(item.visibility).tr(), - style: TextStyle(height: 1.45), + parseVisibility(item.visibility).tr(), ).fontSize(10), ], ), @@ -573,6 +571,35 @@ class PostItem extends HookConsumerWidget { vertical: 4, ), ), + if (item.tags.isNotEmpty) + Wrap( + spacing: 8, + children: [ + for (final tag in item.tags) + InkWell( + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 4, + children: [ + const Icon(Symbols.label, size: 16), + Text(tag.name ?? tag.slug), + ], + ), + onTap: () {}, + ), + for (final category in item.categories) + InkWell( + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 4, + children: [ + const Icon(Symbols.category, size: 16), + Text(category.categoryDisplayTitle), + ], + ), + ), + ], + ).padding(horizontal: renderingPadding.horizontal + 4, top: 4), if (item.meta?['embeds'] != null) ...((item.meta!['embeds'] as List) .map((embedData) => convertMapKeysToSnakeCase(embedData))