diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index c02c07c1..9f655c38 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -1300,5 +1300,6 @@ "thoughtParseError": "Failed to parse AI response", "thoughtFunctionCall": "Function Call", "aiThought": "AI Thought", - "aiThoughtTitle": "Let sn-chan think" + "aiThoughtTitle": "Let sn-chan think", + "postReferenceUnavailable": "Referenced post is unavailable" } diff --git a/lib/models/post.dart b/lib/models/post.dart index 58541ca7..f2c5b7d4 100644 --- a/lib/models/post.dart +++ b/lib/models/post.dart @@ -51,6 +51,8 @@ sealed class SnPost with _$SnPost { @Default(null) DateTime? createdAt, @Default(null) DateTime? updatedAt, DateTime? deletedAt, + @Default(false) bool repliedGone, + @Default(false) bool forwardedGone, @Default(false) bool isTruncated, }) = _SnPost; diff --git a/lib/models/post.freezed.dart b/lib/models/post.freezed.dart index a3dee4fa..acdafeb8 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; String? get slug; int get type; Map? get meta; SnPostEmbedView? get embedView; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; int get awardedScore; int? get pinMode; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List get attachments; SnPublisher get publisher; Map get reactionsCount; Map get reactionsMade; List get reactions; List get tags; List get categories; List get collections; List get featuredRecords; 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; String? get slug; int get type; Map? get meta; SnPostEmbedView? get embedView; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; int get awardedScore; int? get pinMode; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List get attachments; SnPublisher get publisher; Map get reactionsCount; Map get reactionsMade; List get reactions; List get tags; List get categories; List get collections; List get featuredRecords; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get repliedGone; bool get forwardedGone; bool get isTruncated; /// Create a copy of SnPost /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -28,16 +28,16 @@ $SnPostCopyWith get copyWith => _$SnPostCopyWithImpl(this as SnP @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&const DeepCollectionEquality().equals(other.featuredRecords, featuredRecords)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&const DeepCollectionEquality().equals(other.featuredRecords, featuredRecords)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.repliedGone, repliedGone) || other.repliedGone == repliedGone)&&(identical(other.forwardedGone, forwardedGone) || other.forwardedGone == forwardedGone)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),const DeepCollectionEquality().hash(featuredRecords),createdAt,updatedAt,deletedAt,isTruncated]); +int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),const DeepCollectionEquality().hash(featuredRecords),createdAt,updatedAt,deletedAt,repliedGone,forwardedGone,isTruncated]); @override String toString() { - return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, featuredRecords: $featuredRecords, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)'; + return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, featuredRecords: $featuredRecords, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, repliedGone: $repliedGone, forwardedGone: $forwardedGone, isTruncated: $isTruncated)'; } @@ -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, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated + String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, bool isTruncated }); @@ -65,7 +65,7 @@ class _$SnPostCopyWithImpl<$Res> /// Create a copy of SnPost /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? featuredRecords = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? featuredRecords = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? repliedGone = null,Object? forwardedGone = null,Object? isTruncated = null,}) { return _then(_self.copyWith( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable @@ -106,7 +106,9 @@ as List,featuredRecords: null == featuredRecords ? _self.featuredRecord 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 -as DateTime?,isTruncated: null == isTruncated ? _self.isTruncated : isTruncated // ignore: cast_nullable_to_non_nullable +as DateTime?,repliedGone: null == repliedGone ? _self.repliedGone : repliedGone // ignore: cast_nullable_to_non_nullable +as bool,forwardedGone: null == forwardedGone ? _self.forwardedGone : forwardedGone // ignore: cast_nullable_to_non_nullable +as bool,isTruncated: null == isTruncated ? _self.isTruncated : isTruncated // ignore: cast_nullable_to_non_nullable as bool, )); } @@ -258,10 +260,10 @@ 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, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, 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, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, 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.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.featuredRecords,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _: +return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.featuredRecords,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.repliedGone,_that.forwardedGone,_that.isTruncated);case _: return orElse(); } @@ -279,10 +281,10 @@ 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, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, 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, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, 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.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.featuredRecords,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);} +return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.featuredRecords,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.repliedGone,_that.forwardedGone,_that.isTruncated);} } /// A variant of `when` that fallback to returning `null` /// @@ -296,10 +298,10 @@ 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, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, 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, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, 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.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.featuredRecords,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _: +return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.featuredRecords,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.repliedGone,_that.forwardedGone,_that.isTruncated);case _: return null; } @@ -311,7 +313,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.slug, this.type = 0, final Map? meta, this.embedView, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.awardedScore = 0, this.pinMode, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, 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 [], final List featuredRecords = 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,_featuredRecords = featuredRecords; + const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.slug, this.type = 0, final Map? meta, this.embedView, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.awardedScore = 0, this.pinMode, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, 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 [], final List featuredRecords = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.repliedGone = false, this.forwardedGone = false, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections,_featuredRecords = featuredRecords; factory _SnPost.fromJson(Map json) => _$SnPostFromJson(json); @override final String id; @@ -409,6 +411,8 @@ class _SnPost implements SnPost { @override@JsonKey() final DateTime? createdAt; @override@JsonKey() final DateTime? updatedAt; @override final DateTime? deletedAt; +@override@JsonKey() final bool repliedGone; +@override@JsonKey() final bool forwardedGone; @override@JsonKey() final bool isTruncated; /// Create a copy of SnPost @@ -424,16 +428,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&const DeepCollectionEquality().equals(other._featuredRecords, _featuredRecords)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&const DeepCollectionEquality().equals(other._featuredRecords, _featuredRecords)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.repliedGone, repliedGone) || other.repliedGone == repliedGone)&&(identical(other.forwardedGone, forwardedGone) || other.forwardedGone == forwardedGone)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),const DeepCollectionEquality().hash(_featuredRecords),createdAt,updatedAt,deletedAt,isTruncated]); +int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),const DeepCollectionEquality().hash(_featuredRecords),createdAt,updatedAt,deletedAt,repliedGone,forwardedGone,isTruncated]); @override String toString() { - return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, featuredRecords: $featuredRecords, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)'; + return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, featuredRecords: $featuredRecords, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, repliedGone: $repliedGone, forwardedGone: $forwardedGone, isTruncated: $isTruncated)'; } @@ -444,7 +448,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, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated + String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List attachments, SnPublisher publisher, Map reactionsCount, Map reactionsMade, List reactions, List tags, List categories, List collections, List featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, bool isTruncated }); @@ -461,7 +465,7 @@ class __$SnPostCopyWithImpl<$Res> /// Create a copy of SnPost /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? featuredRecords = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? featuredRecords = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? repliedGone = null,Object? forwardedGone = null,Object? isTruncated = null,}) { return _then(_SnPost( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable @@ -502,7 +506,9 @@ as List,featuredRecords: null == featuredRecords ? _self._featuredRecor 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 -as DateTime?,isTruncated: null == isTruncated ? _self.isTruncated : isTruncated // ignore: cast_nullable_to_non_nullable +as DateTime?,repliedGone: null == repliedGone ? _self.repliedGone : repliedGone // ignore: cast_nullable_to_non_nullable +as bool,forwardedGone: null == forwardedGone ? _self.forwardedGone : forwardedGone // ignore: cast_nullable_to_non_nullable +as bool,isTruncated: null == isTruncated ? _self.isTruncated : isTruncated // ignore: cast_nullable_to_non_nullable as bool, )); } diff --git a/lib/models/post.g.dart b/lib/models/post.g.dart index ee77b4b7..66751d9d 100644 --- a/lib/models/post.g.dart +++ b/lib/models/post.g.dart @@ -102,6 +102,8 @@ _SnPost _$SnPostFromJson(Map json) => _SnPost( json['deleted_at'] == null ? null : DateTime.parse(json['deleted_at'] as String), + repliedGone: json['replied_gone'] as bool? ?? false, + forwardedGone: json['forwarded_gone'] as bool? ?? false, isTruncated: json['is_truncated'] as bool? ?? false, ); @@ -145,6 +147,8 @@ Map _$SnPostToJson(_SnPost instance) => { 'created_at': instance.createdAt?.toIso8601String(), 'updated_at': instance.updatedAt?.toIso8601String(), 'deleted_at': instance.deletedAt?.toIso8601String(), + 'replied_gone': instance.repliedGone, + 'forwarded_gone': instance.forwardedGone, 'is_truncated': instance.isTruncated, }; diff --git a/lib/widgets/post/post_shared.dart b/lib/widgets/post/post_shared.dart index 1e2b34d0..f7ac1b08 100644 --- a/lib/widgets/post/post_shared.dart +++ b/lib/widgets/post/post_shared.dart @@ -358,9 +358,11 @@ class ReferencedPostWidget extends StatelessWidget { @override Widget build(BuildContext context) { final referencePost = item.repliedPost ?? item.forwardedPost; - if (referencePost == null) return const SizedBox.shrink(); + final isGone = item.repliedGone || item.forwardedGone; - final isReply = item.repliedPost != null; + if (referencePost == null && !isGone) return const SizedBox.shrink(); + + final isReply = item.repliedPost != null || item.repliedGone; final content = Container( padding: EdgeInsets.symmetric( @@ -401,115 +403,136 @@ class ReferencedPostWidget extends StatelessWidget { ], ), const SizedBox(height: 8), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ProfilePictureWidget( - fileId: referencePost.publisher.picture?.id, - radius: 16, - ), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - referencePost.publisher.nick, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - ), - ), - if (referencePost.visibility != 0) - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - PostVisibilityHelpers.getVisibilityIcon( - referencePost.visibility, - ), - size: 12, - color: Theme.of(context).colorScheme.secondary, - ), - const SizedBox(width: 4), - Text( - PostVisibilityHelpers.getVisibilityText( - referencePost.visibility, - ).tr(), - style: TextStyle( - fontSize: 10, - color: Theme.of(context).colorScheme.secondary, - ), - ), - ], - ).padding(top: 2, bottom: 2), - if (referencePost.title?.isNotEmpty ?? false) - Text( - referencePost.title!, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 13, - color: Theme.of(context).colorScheme.onSurface, - ), - ).padding(top: 2, bottom: 2), - if (referencePost.description?.isNotEmpty ?? false) - Text( - referencePost.description!, - style: TextStyle( - fontSize: 12, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ).padding(bottom: 2), - if (referencePost.content?.isNotEmpty ?? false) - MarkdownTextContent( - content: referencePost.content!, - textStyle: const TextStyle(fontSize: 14), - isSelectable: false, - linesMargin: - referencePost.type == 0 - ? const EdgeInsets.only(bottom: 4) - : null, - attachments: item.attachments, - ).padding(bottom: 4), - if (referencePost.isTruncated) - const PostTruncateHint( - isCompact: true, - margin: EdgeInsets.only(top: 4, bottom: 8), - ), - if (referencePost.attachments.isNotEmpty && - referencePost.type != 1) - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Symbols.attach_file, - size: 12, - color: Theme.of(context).colorScheme.secondary, - ), - const SizedBox(width: 4), - Text( - 'postHasAttachments'.plural( - referencePost.attachments.length, - ), - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontSize: 12, - ), - ), - ], - ).padding(vertical: 2), - ], + if (isGone) + Row( + children: [ + Icon( + Symbols.visibility_off, + size: 16, + color: Theme.of(context).colorScheme.secondary, ), - ), - ], - ), + const SizedBox(width: 8), + Text( + 'postReferenceUnavailable'.tr(), + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontSize: 14, + fontStyle: FontStyle.italic, + ), + ), + ], + ) + else + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ProfilePictureWidget( + fileId: referencePost!.publisher.picture?.id, + radius: 16, + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + referencePost.publisher.nick, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ), + if (referencePost.visibility != 0) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + PostVisibilityHelpers.getVisibilityIcon( + referencePost.visibility, + ), + size: 12, + color: Theme.of(context).colorScheme.secondary, + ), + const SizedBox(width: 4), + Text( + PostVisibilityHelpers.getVisibilityText( + referencePost.visibility, + ).tr(), + style: TextStyle( + fontSize: 10, + color: Theme.of(context).colorScheme.secondary, + ), + ), + ], + ).padding(top: 2, bottom: 2), + if (referencePost.title?.isNotEmpty ?? false) + Text( + referencePost.title!, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13, + color: Theme.of(context).colorScheme.onSurface, + ), + ).padding(top: 2, bottom: 2), + if (referencePost.description?.isNotEmpty ?? false) + Text( + referencePost.description!, + style: TextStyle( + fontSize: 12, + color: + Theme.of(context).colorScheme.onSurfaceVariant, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ).padding(bottom: 2), + if (referencePost.content?.isNotEmpty ?? false) + MarkdownTextContent( + content: referencePost.content!, + textStyle: const TextStyle(fontSize: 14), + isSelectable: false, + linesMargin: + referencePost.type == 0 + ? const EdgeInsets.only(bottom: 4) + : null, + attachments: item.attachments, + ).padding(bottom: 4), + if (referencePost.isTruncated) + const PostTruncateHint( + isCompact: true, + margin: EdgeInsets.only(top: 4, bottom: 8), + ), + if (referencePost.attachments.isNotEmpty && + referencePost.type != 1) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Symbols.attach_file, + size: 12, + color: Theme.of(context).colorScheme.secondary, + ), + const SizedBox(width: 4), + Text( + 'postHasAttachments'.plural( + referencePost.attachments.length, + ), + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontSize: 12, + ), + ), + ], + ).padding(vertical: 2), + ], + ), + ), + ], + ), ], ), ); - if (!isInteractive) { + if (!isInteractive || isGone) { return content; } @@ -517,7 +540,7 @@ class ReferencedPostWidget extends StatelessWidget { onTap: () => context.pushNamed( 'postDetail', - pathParameters: {'id': referencePost.id}, + pathParameters: {'id': referencePost!.id}, ), ); } diff --git a/lib/widgets/thought/function_calls_section.dart b/lib/widgets/thought/function_calls_section.dart index f2cf5873..a6a228d8 100644 --- a/lib/widgets/thought/function_calls_section.dart +++ b/lib/widgets/thought/function_calls_section.dart @@ -7,7 +7,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart'; import 'package:island/models/thought.dart'; -class FunctionCallsSection extends StatelessWidget { +class FunctionCallsSection extends StatefulWidget { const FunctionCallsSection({ super.key, required this.isStreaming, @@ -19,12 +19,19 @@ class FunctionCallsSection extends StatelessWidget { final List streamingFunctionCalls; final SnThinkingThought? thought; + @override + State createState() => _FunctionCallsSectionState(); +} + +class _FunctionCallsSectionState extends State { + bool _isExpanded = false; + bool get _hasFunctionCalls { - if (isStreaming) { - return streamingFunctionCalls.isNotEmpty; + if (widget.isStreaming) { + return widget.streamingFunctionCalls.isNotEmpty; } else { - return thought!.chunks.isNotEmpty && - thought!.chunks.any( + return widget.thought!.chunks.isNotEmpty && + widget.thought!.chunks.any( (chunk) => chunk.type == ThinkingChunkType.functionCall, ); } @@ -49,81 +56,103 @@ class FunctionCallsSection extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - Icon( - Symbols.code, - size: 14, - color: Theme.of(context).colorScheme.tertiary, - ), - const Gap(4), - Text( - 'functionCalls'.tr(), - style: Theme.of(context).textTheme.bodySmall!.copyWith( - fontWeight: FontWeight.w600, + InkWell( + onTap: () => setState(() => _isExpanded = !_isExpanded), + child: Row( + children: [ + Icon( + Symbols.code, + size: 14, color: Theme.of(context).colorScheme.tertiary, ), - ), - ], - ), - const Gap(4), - if (isStreaming) ...[ - ...streamingFunctionCalls.map( - (call) => Container( - width: double.infinity, - padding: const EdgeInsets.all(8), - margin: const EdgeInsets.only(bottom: 4), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(4), - border: Border.all( - color: Theme.of( - context, - ).colorScheme.outline.withOpacity(0.3), - width: 1, + const Gap(4), + Expanded( + child: Text( + 'thoughtFunctionCall'.tr(), + style: Theme.of(context).textTheme.bodySmall!.copyWith( + fontWeight: FontWeight.w600, + color: Theme.of(context).colorScheme.tertiary, + ), ), ), - child: SelectableText( - call, - style: GoogleFonts.robotoMono( - fontSize: 11, - color: Theme.of(context).colorScheme.onSurface, - height: 1.3, - ), + Icon( + _isExpanded ? Symbols.expand_more : Symbols.expand_less, + size: 16, + color: Theme.of(context).colorScheme.tertiary, ), - ), + ], ), - ] else ...[ - ...thought!.chunks - .where( - (chunk) => chunk.type == ThinkingChunkType.functionCall, - ) - .map( - (chunk) => Container( - width: double.infinity, - padding: const EdgeInsets.all(8), - margin: const EdgeInsets.only(bottom: 4), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(4), - border: Border.all( - color: Theme.of( - context, - ).colorScheme.outline.withOpacity(0.3), - width: 1, + ), + Visibility(visible: _isExpanded, child: const Gap(4)), + Visibility( + visible: _isExpanded, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.isStreaming) ...[ + ...widget.streamingFunctionCalls.map( + (call) => Container( + width: double.infinity, + padding: const EdgeInsets.all(8), + margin: const EdgeInsets.only(bottom: 4), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(4), + border: Border.all( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.3), + width: 1, + ), ), - ), - child: SelectableText( - JsonEncoder.withIndent(' ').convert(chunk.data), - style: GoogleFonts.robotoMono( - fontSize: 11, - color: Theme.of(context).colorScheme.onSurface, - height: 1.3, + child: SelectableText( + call, + style: GoogleFonts.robotoMono( + fontSize: 11, + color: Theme.of(context).colorScheme.onSurface, + height: 1.3, + ), ), ), ), - ), - ], + ] else ...[ + ...widget.thought!.chunks + .where( + (chunk) => + chunk.type == ThinkingChunkType.functionCall, + ) + .map( + (chunk) => Container( + width: double.infinity, + padding: const EdgeInsets.all(8), + margin: const EdgeInsets.only(bottom: 4), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(4), + border: Border.all( + color: Theme.of( + context, + ).colorScheme.outline.withOpacity(0.3), + width: 1, + ), + ), + child: SelectableText( + JsonEncoder.withIndent( + ' ', + ).convert(chunk.data), + style: GoogleFonts.robotoMono( + fontSize: 11, + color: + Theme.of(context).colorScheme.onSurface, + height: 1.3, + ), + ), + ), + ), + ], + ], + ), + ), ], ), ), diff --git a/lib/widgets/thought/thought_header.dart b/lib/widgets/thought/thought_header.dart index 8c3f7895..8394d815 100644 --- a/lib/widgets/thought/thought_header.dart +++ b/lib/widgets/thought/thought_header.dart @@ -28,7 +28,7 @@ class ThoughtHeader extends StatelessWidget { fill: 1, ), Text( - isUser ? 'thoughtUserName'.tr() : 'aiThought'.tr(), + isUser ? 'thoughtUserName'.tr() : 'thoughtAiName'.tr(), style: Theme.of(context).textTheme.titleSmall!.copyWith( fontWeight: FontWeight.w600, color: @@ -40,12 +40,29 @@ class ThoughtHeader extends StatelessWidget { ], ); } else { - return Text( - 'aiThought'.tr(), - style: Theme.of(context).textTheme.titleSmall!.copyWith( - fontWeight: FontWeight.w600, - color: Theme.of(context).colorScheme.primary, - ), + return Row( + spacing: 6, + children: [ + Icon( + Symbols.smart_toy, + size: 16, + color: + isUser + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.secondary, + fill: 1, + ), + Text( + 'thoughtAiName'.tr(), + style: Theme.of(context).textTheme.titleSmall!.copyWith( + fontWeight: FontWeight.w600, + color: + isUser + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.secondary, + ), + ), + ], ); } } diff --git a/lib/widgets/thought/thought_shared.dart b/lib/widgets/thought/thought_shared.dart index 959aaede..8a54db59 100644 --- a/lib/widgets/thought/thought_shared.dart +++ b/lib/widgets/thought/thought_shared.dart @@ -13,6 +13,7 @@ import 'package:island/widgets/thought/thought_content.dart'; import 'package:island/widgets/thought/thought_header.dart'; import 'package:island/widgets/thought/token_info.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:styled_widget/styled_widget.dart'; List> _extractProposals(String content) { final proposalRegex = RegExp( @@ -81,18 +82,12 @@ class ThoughtInput extends HookWidget { 'attachments-${attachedMessages?.length ?? 0}-${attachedPosts?.length ?? 0}', ), padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), - margin: const EdgeInsets.only( - left: 4, - right: 4, - top: 4, - bottom: 4, + horizontal: 16, + vertical: 8, ), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceContainerHigh, - borderRadius: BorderRadius.circular(16), + borderRadius: BorderRadius.circular(24), border: Border.all( color: Theme.of( context, @@ -100,6 +95,12 @@ class ThoughtInput extends HookWidget { width: 1, ), ), + margin: const EdgeInsets.only( + left: 8, + right: 8, + top: 8, + bottom: 4, + ), child: Row( mainAxisSize: MainAxisSize.max, children: [ @@ -264,6 +265,11 @@ class ThoughtItem extends StatelessWidget { proposals: proposals, onProposalAction: _handleProposalAction, ), + + if (isStreaming && isAI) + LinearProgressIndicator().padding( + top: streamingText.isNotEmpty ? 8 : 0, + ), ], ), ),