diff --git a/lib/models/thought.dart b/lib/models/thought.dart index 73e823cc..e0e8eb1f 100644 --- a/lib/models/thought.dart +++ b/lib/models/thought.dart @@ -44,6 +44,9 @@ sealed class SnThinkingSequence with _$SnThinkingSequence { required String id, String? topic, required String accountId, + required DateTime createdAt, + required DateTime updatedAt, + DateTime? deletedAt, }) = _SnThinkingSequence; factory SnThinkingSequence.fromJson(Map json) => @@ -59,6 +62,9 @@ sealed class SnThinkingThought with _$SnThinkingThought { @ThinkingThoughtRoleConverter() required ThinkingThoughtRole role, required String sequenceId, SnThinkingSequence? sequence, + required DateTime createdAt, + required DateTime updatedAt, + DateTime? deletedAt, }) = _SnThinkingThought; factory SnThinkingThought.fromJson(Map json) => diff --git a/lib/models/thought.freezed.dart b/lib/models/thought.freezed.dart index ec273c2e..ad809447 100644 --- a/lib/models/thought.freezed.dart +++ b/lib/models/thought.freezed.dart @@ -275,7 +275,7 @@ as String?, /// @nodoc mixin _$SnThinkingSequence { - String get id; String? get topic; String get accountId; + String get id; String? get topic; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; /// Create a copy of SnThinkingSequence /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -288,16 +288,16 @@ $SnThinkingSequenceCopyWith get copyWith => _$SnThinkingSequ @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is SnThinkingSequence&&(identical(other.id, id) || other.id == id)&&(identical(other.topic, topic) || other.topic == topic)&&(identical(other.accountId, accountId) || other.accountId == accountId)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnThinkingSequence&&(identical(other.id, id) || other.id == id)&&(identical(other.topic, topic) || other.topic == topic)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,topic,accountId); +int get hashCode => Object.hash(runtimeType,id,topic,accountId,createdAt,updatedAt,deletedAt); @override String toString() { - return 'SnThinkingSequence(id: $id, topic: $topic, accountId: $accountId)'; + return 'SnThinkingSequence(id: $id, topic: $topic, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; } @@ -308,7 +308,7 @@ abstract mixin class $SnThinkingSequenceCopyWith<$Res> { factory $SnThinkingSequenceCopyWith(SnThinkingSequence value, $Res Function(SnThinkingSequence) _then) = _$SnThinkingSequenceCopyWithImpl; @useResult $Res call({ - String id, String? topic, String accountId + String id, String? topic, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt }); @@ -325,12 +325,15 @@ class _$SnThinkingSequenceCopyWithImpl<$Res> /// Create a copy of SnThinkingSequence /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? topic = freezed,Object? accountId = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? topic = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { return _then(_self.copyWith( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,topic: freezed == topic ? _self.topic : topic // ignore: cast_nullable_to_non_nullable as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable -as String, +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable +as DateTime?, )); } @@ -412,10 +415,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? topic, String accountId)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? topic, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _SnThinkingSequence() when $default != null: -return $default(_that.id,_that.topic,_that.accountId);case _: +return $default(_that.id,_that.topic,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return orElse(); } @@ -433,10 +436,10 @@ return $default(_that.id,_that.topic,_that.accountId);case _: /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id, String? topic, String accountId) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String id, String? topic, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this; switch (_that) { case _SnThinkingSequence(): -return $default(_that.id,_that.topic,_that.accountId);} +return $default(_that.id,_that.topic,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);} } /// A variant of `when` that fallback to returning `null` /// @@ -450,10 +453,10 @@ return $default(_that.id,_that.topic,_that.accountId);} /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? topic, String accountId)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? topic, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this; switch (_that) { case _SnThinkingSequence() when $default != null: -return $default(_that.id,_that.topic,_that.accountId);case _: +return $default(_that.id,_that.topic,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return null; } @@ -465,12 +468,15 @@ return $default(_that.id,_that.topic,_that.accountId);case _: @JsonSerializable() class _SnThinkingSequence implements SnThinkingSequence { - const _SnThinkingSequence({required this.id, this.topic, required this.accountId}); + const _SnThinkingSequence({required this.id, this.topic, required this.accountId, required this.createdAt, required this.updatedAt, this.deletedAt}); factory _SnThinkingSequence.fromJson(Map json) => _$SnThinkingSequenceFromJson(json); @override final String id; @override final String? topic; @override final String accountId; +@override final DateTime createdAt; +@override final DateTime updatedAt; +@override final DateTime? deletedAt; /// Create a copy of SnThinkingSequence /// with the given fields replaced by the non-null parameter values. @@ -485,16 +491,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnThinkingSequence&&(identical(other.id, id) || other.id == id)&&(identical(other.topic, topic) || other.topic == topic)&&(identical(other.accountId, accountId) || other.accountId == accountId)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnThinkingSequence&&(identical(other.id, id) || other.id == id)&&(identical(other.topic, topic) || other.topic == topic)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,topic,accountId); +int get hashCode => Object.hash(runtimeType,id,topic,accountId,createdAt,updatedAt,deletedAt); @override String toString() { - return 'SnThinkingSequence(id: $id, topic: $topic, accountId: $accountId)'; + return 'SnThinkingSequence(id: $id, topic: $topic, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; } @@ -505,7 +511,7 @@ abstract mixin class _$SnThinkingSequenceCopyWith<$Res> implements $SnThinkingSe factory _$SnThinkingSequenceCopyWith(_SnThinkingSequence value, $Res Function(_SnThinkingSequence) _then) = __$SnThinkingSequenceCopyWithImpl; @override @useResult $Res call({ - String id, String? topic, String accountId + String id, String? topic, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt }); @@ -522,12 +528,15 @@ class __$SnThinkingSequenceCopyWithImpl<$Res> /// Create a copy of SnThinkingSequence /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? topic = freezed,Object? accountId = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? topic = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { return _then(_SnThinkingSequence( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,topic: freezed == topic ? _self.topic : topic // ignore: cast_nullable_to_non_nullable as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable -as String, +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable +as DateTime?, )); } @@ -538,7 +547,7 @@ as String, /// @nodoc mixin _$SnThinkingThought { - String get id; String? get content; List get files;@ThinkingThoughtRoleConverter() ThinkingThoughtRole get role; String get sequenceId; SnThinkingSequence? get sequence; + String get id; String? get content; List get files;@ThinkingThoughtRoleConverter() ThinkingThoughtRole get role; String get sequenceId; SnThinkingSequence? get sequence; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; /// Create a copy of SnThinkingThought /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -551,16 +560,16 @@ $SnThinkingThoughtCopyWith get copyWith => _$SnThinkingThough @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is SnThinkingThought&&(identical(other.id, id) || other.id == id)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other.files, files)&&(identical(other.role, role) || other.role == role)&&(identical(other.sequenceId, sequenceId) || other.sequenceId == sequenceId)&&(identical(other.sequence, sequence) || other.sequence == sequence)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnThinkingThought&&(identical(other.id, id) || other.id == id)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other.files, files)&&(identical(other.role, role) || other.role == role)&&(identical(other.sequenceId, sequenceId) || other.sequenceId == sequenceId)&&(identical(other.sequence, sequence) || other.sequence == sequence)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,content,const DeepCollectionEquality().hash(files),role,sequenceId,sequence); +int get hashCode => Object.hash(runtimeType,id,content,const DeepCollectionEquality().hash(files),role,sequenceId,sequence,createdAt,updatedAt,deletedAt); @override String toString() { - return 'SnThinkingThought(id: $id, content: $content, files: $files, role: $role, sequenceId: $sequenceId, sequence: $sequence)'; + return 'SnThinkingThought(id: $id, content: $content, files: $files, role: $role, sequenceId: $sequenceId, sequence: $sequence, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; } @@ -571,7 +580,7 @@ abstract mixin class $SnThinkingThoughtCopyWith<$Res> { factory $SnThinkingThoughtCopyWith(SnThinkingThought value, $Res Function(SnThinkingThought) _then) = _$SnThinkingThoughtCopyWithImpl; @useResult $Res call({ - String id, String? content, List files,@ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence + String id, String? content, List files,@ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt }); @@ -588,7 +597,7 @@ class _$SnThinkingThoughtCopyWithImpl<$Res> /// Create a copy of SnThinkingThought /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? content = freezed,Object? files = null,Object? role = null,Object? sequenceId = null,Object? sequence = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? content = freezed,Object? files = null,Object? role = null,Object? sequenceId = null,Object? sequence = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { return _then(_self.copyWith( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable @@ -596,7 +605,10 @@ as String?,files: null == files ? _self.files : files // ignore: cast_nullable_t as List,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable as ThinkingThoughtRole,sequenceId: null == sequenceId ? _self.sequenceId : sequenceId // ignore: cast_nullable_to_non_nullable as String,sequence: freezed == sequence ? _self.sequence : sequence // ignore: cast_nullable_to_non_nullable -as SnThinkingSequence?, +as SnThinkingSequence?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable +as DateTime?, )); } /// Create a copy of SnThinkingThought @@ -690,10 +702,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? content, List files, @ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? content, List files, @ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _SnThinkingThought() when $default != null: -return $default(_that.id,_that.content,_that.files,_that.role,_that.sequenceId,_that.sequence);case _: +return $default(_that.id,_that.content,_that.files,_that.role,_that.sequenceId,_that.sequence,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return orElse(); } @@ -711,10 +723,10 @@ return $default(_that.id,_that.content,_that.files,_that.role,_that.sequenceId,_ /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id, String? content, List files, @ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String id, String? content, List files, @ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this; switch (_that) { case _SnThinkingThought(): -return $default(_that.id,_that.content,_that.files,_that.role,_that.sequenceId,_that.sequence);} +return $default(_that.id,_that.content,_that.files,_that.role,_that.sequenceId,_that.sequence,_that.createdAt,_that.updatedAt,_that.deletedAt);} } /// A variant of `when` that fallback to returning `null` /// @@ -728,10 +740,10 @@ return $default(_that.id,_that.content,_that.files,_that.role,_that.sequenceId,_ /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? content, List files, @ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? content, List files, @ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this; switch (_that) { case _SnThinkingThought() when $default != null: -return $default(_that.id,_that.content,_that.files,_that.role,_that.sequenceId,_that.sequence);case _: +return $default(_that.id,_that.content,_that.files,_that.role,_that.sequenceId,_that.sequence,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return null; } @@ -743,7 +755,7 @@ return $default(_that.id,_that.content,_that.files,_that.role,_that.sequenceId,_ @JsonSerializable() class _SnThinkingThought implements SnThinkingThought { - const _SnThinkingThought({required this.id, this.content, final List files = const [], @ThinkingThoughtRoleConverter() required this.role, required this.sequenceId, this.sequence}): _files = files; + const _SnThinkingThought({required this.id, this.content, final List files = const [], @ThinkingThoughtRoleConverter() required this.role, required this.sequenceId, this.sequence, required this.createdAt, required this.updatedAt, this.deletedAt}): _files = files; factory _SnThinkingThought.fromJson(Map json) => _$SnThinkingThoughtFromJson(json); @override final String id; @@ -758,6 +770,9 @@ class _SnThinkingThought implements SnThinkingThought { @override@ThinkingThoughtRoleConverter() final ThinkingThoughtRole role; @override final String sequenceId; @override final SnThinkingSequence? sequence; +@override final DateTime createdAt; +@override final DateTime updatedAt; +@override final DateTime? deletedAt; /// Create a copy of SnThinkingThought /// with the given fields replaced by the non-null parameter values. @@ -772,16 +787,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnThinkingThought&&(identical(other.id, id) || other.id == id)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other._files, _files)&&(identical(other.role, role) || other.role == role)&&(identical(other.sequenceId, sequenceId) || other.sequenceId == sequenceId)&&(identical(other.sequence, sequence) || other.sequence == sequence)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnThinkingThought&&(identical(other.id, id) || other.id == id)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other._files, _files)&&(identical(other.role, role) || other.role == role)&&(identical(other.sequenceId, sequenceId) || other.sequenceId == sequenceId)&&(identical(other.sequence, sequence) || other.sequence == sequence)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,content,const DeepCollectionEquality().hash(_files),role,sequenceId,sequence); +int get hashCode => Object.hash(runtimeType,id,content,const DeepCollectionEquality().hash(_files),role,sequenceId,sequence,createdAt,updatedAt,deletedAt); @override String toString() { - return 'SnThinkingThought(id: $id, content: $content, files: $files, role: $role, sequenceId: $sequenceId, sequence: $sequence)'; + return 'SnThinkingThought(id: $id, content: $content, files: $files, role: $role, sequenceId: $sequenceId, sequence: $sequence, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; } @@ -792,7 +807,7 @@ abstract mixin class _$SnThinkingThoughtCopyWith<$Res> implements $SnThinkingTho factory _$SnThinkingThoughtCopyWith(_SnThinkingThought value, $Res Function(_SnThinkingThought) _then) = __$SnThinkingThoughtCopyWithImpl; @override @useResult $Res call({ - String id, String? content, List files,@ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence + String id, String? content, List files,@ThinkingThoughtRoleConverter() ThinkingThoughtRole role, String sequenceId, SnThinkingSequence? sequence, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt }); @@ -809,7 +824,7 @@ class __$SnThinkingThoughtCopyWithImpl<$Res> /// Create a copy of SnThinkingThought /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? content = freezed,Object? files = null,Object? role = null,Object? sequenceId = null,Object? sequence = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? content = freezed,Object? files = null,Object? role = null,Object? sequenceId = null,Object? sequence = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { return _then(_SnThinkingThought( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable @@ -817,7 +832,10 @@ as String?,files: null == files ? _self._files : files // ignore: cast_nullable_ as List,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable as ThinkingThoughtRole,sequenceId: null == sequenceId ? _self.sequenceId : sequenceId // ignore: cast_nullable_to_non_nullable as String,sequence: freezed == sequence ? _self.sequence : sequence // ignore: cast_nullable_to_non_nullable -as SnThinkingSequence?, +as SnThinkingSequence?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable +as DateTime?, )); } diff --git a/lib/models/thought.g.dart b/lib/models/thought.g.dart index a86ea58b..a8aaa945 100644 --- a/lib/models/thought.g.dart +++ b/lib/models/thought.g.dart @@ -25,6 +25,12 @@ _SnThinkingSequence _$SnThinkingSequenceFromJson(Map json) => id: json['id'] as String, topic: json['topic'] as String?, accountId: json['account_id'] as String, + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + deletedAt: + json['deleted_at'] == null + ? null + : DateTime.parse(json['deleted_at'] as String), ); Map _$SnThinkingSequenceToJson(_SnThinkingSequence instance) => @@ -32,6 +38,9 @@ Map _$SnThinkingSequenceToJson(_SnThinkingSequence instance) => 'id': instance.id, 'topic': instance.topic, 'account_id': instance.accountId, + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt?.toIso8601String(), }; _SnThinkingThought _$SnThinkingThoughtFromJson(Map json) => @@ -53,6 +62,12 @@ _SnThinkingThought _$SnThinkingThoughtFromJson(Map json) => : SnThinkingSequence.fromJson( json['sequence'] as Map, ), + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + deletedAt: + json['deleted_at'] == null + ? null + : DateTime.parse(json['deleted_at'] as String), ); Map _$SnThinkingThoughtToJson(_SnThinkingThought instance) => @@ -63,4 +78,7 @@ Map _$SnThinkingThoughtToJson(_SnThinkingThought instance) => 'role': const ThinkingThoughtRoleConverter().toJson(instance.role), 'sequence_id': instance.sequenceId, 'sequence': instance.sequence?.toJson(), + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt?.toIso8601String(), }; diff --git a/lib/screens/tabs.dart b/lib/screens/tabs.dart index a4da277a..02104d4d 100644 --- a/lib/screens/tabs.dart +++ b/lib/screens/tabs.dart @@ -173,7 +173,7 @@ class TabsScreen extends HookConsumerWidget { horizontal: 24, ), leading: const Icon(Symbols.bubble_chart), - title: Text('让我寻思寻思'), + title: Text('让 SN 酱寻思寻思'), onTap: () async { Navigator.of(context).pop(); context.pushNamed('thought'); diff --git a/lib/screens/thought/think.dart b/lib/screens/thought/think.dart index fdcf61d7..9c1c9b4a 100644 --- a/lib/screens/thought/think.dart +++ b/lib/screens/thought/think.dart @@ -7,24 +7,15 @@ import "package:gap/gap.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:island/models/thought.dart"; import "package:island/pods/network.dart"; +import "package:island/pods/userinfo.dart"; import "package:island/widgets/alert.dart"; import "package:island/widgets/app_scaffold.dart"; import "package:island/widgets/content/markdown.dart"; import "package:island/widgets/response.dart"; +import "package:island/widgets/thought/thought_sequence_list.dart"; import "package:material_symbols_icons/material_symbols_icons.dart"; import "package:super_sliver_list/super_sliver_list.dart"; -// State management providers -final thoughtSequencesProvider = FutureProvider>(( - ref, -) async { - final apiClient = ref.watch(apiClientProvider); - final response = await apiClient.get('/insight/thought/sequences'); - return (response.data as List) - .map((e) => SnThinkingSequence.fromJson(e)) - .toList(); -}); - final thoughtSequenceProvider = FutureProvider.family, String>(( ref, @@ -44,7 +35,6 @@ class ThoughtScreen extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final sequences = ref.watch(thoughtSequencesProvider); final selectedSequenceId = useState(null); final thoughts = selectedSequenceId.value != null @@ -95,20 +85,31 @@ class ThoughtScreen extends HookConsumerWidget { final userMessage = messageController.text.trim(); // Add user message to local thoughts + final userInfo = ref.read(userInfoProvider); + final now = DateTime.now(); final userThought = SnThinkingThought( - id: 'temp-user-${DateTime.now().millisecondsSinceEpoch}', + id: 'user-${DateTime.now().millisecondsSinceEpoch}', content: userMessage, files: [], role: ThinkingThoughtRole.user, sequenceId: selectedSequenceId.value ?? '', + createdAt: now, + updatedAt: now, sequence: selectedSequenceId.value != null ? thoughts.value?.firstOrNull?.sequence ?? SnThinkingSequence( id: selectedSequenceId.value!, accountId: '', + createdAt: now, + updatedAt: now, ) - : SnThinkingSequence(id: '', accountId: ''), + : SnThinkingSequence( + id: '', + accountId: userInfo.value!.id, + createdAt: now, + updatedAt: now, + ), ); localThoughts.value = [userThought, ...localThoughts.value]; @@ -330,32 +331,10 @@ class ThoughtScreen extends HookConsumerWidget { showModalBottomSheet( context: context, builder: - (context) => sequences.when( - data: - (seqs) => ListView.builder( - itemCount: seqs.length, - itemBuilder: (context, index) { - final seq = seqs[index]; - return ListTile( - title: Text( - seq.topic ?? 'Untitled Conversation', - ), - onTap: () { - selectedSequenceId.value = seq.id; - Navigator.of(context).pop(); - }, - ); - }, - ), - loading: - () => - const Center(child: CircularProgressIndicator()), - error: - (error, _) => ResponseErrorWidget( - error: error, - onRetry: - () => ref.invalidate(thoughtSequencesProvider), - ), + (context) => ThoughtSequenceSelector( + onSequenceSelected: (sequenceId) { + selectedSequenceId.value = sequenceId; + }, ), ); }, @@ -424,7 +403,7 @@ class ThoughtScreen extends HookConsumerWidget { decoration: InputDecoration( hintText: isStreaming.value - ? 'AI is thinking...' + ? 'Sn-chan is thinking...' : 'Ask me anything...', border: InputBorder.none, isDense: true, diff --git a/lib/widgets/app_scaffold.dart b/lib/widgets/app_scaffold.dart index 79e32d07..d028a9b5 100644 --- a/lib/widgets/app_scaffold.dart +++ b/lib/widgets/app_scaffold.dart @@ -12,7 +12,6 @@ import 'package:island/pods/config.dart'; import 'package:island/route.dart'; import 'package:island/pods/userinfo.dart'; import 'package:island/pods/websocket.dart'; -import 'package:island/screens/tabs.dart'; import 'package:island/services/responsive.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart'; import 'package:path_provider/path_provider.dart'; diff --git a/lib/widgets/thought/thought_sequence_list.dart b/lib/widgets/thought/thought_sequence_list.dart new file mode 100644 index 00000000..f70074e3 --- /dev/null +++ b/lib/widgets/thought/thought_sequence_list.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:island/models/thought.dart'; +import 'package:island/pods/network.dart'; +import 'package:island/services/time.dart'; +import 'package:island/widgets/content/sheet.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; + +part 'thought_sequence_list.g.dart'; + +@riverpod +class ThoughtSequenceListNotifier extends _$ThoughtSequenceListNotifier + with CursorPagingNotifierMixin { + static const int _pageSize = 20; + + @override + Future> build() { + return fetch(cursor: null); + } + + @override + Future> fetch({ + required String? cursor, + }) async { + final client = ref.read(apiClientProvider); + final offset = cursor == null ? 0 : int.parse(cursor); + + final queryParams = {'offset': offset, 'take': _pageSize}; + + final response = await client.get( + '/insight/thought/sequences', + queryParameters: queryParams, + ); + final total = int.parse(response.headers.value('X-Total') ?? '0'); + final List data = response.data; + final sequences = + data.map((json) => SnThinkingSequence.fromJson(json)).toList(); + + final hasMore = offset + sequences.length < total; + final nextCursor = hasMore ? (offset + sequences.length).toString() : null; + + return CursorPagingData( + items: sequences, + hasMore: hasMore, + nextCursor: nextCursor, + ); + } +} + +class ThoughtSequenceSelector extends HookConsumerWidget { + final Function(String) onSequenceSelected; + + const ThoughtSequenceSelector({super.key, required this.onSequenceSelected}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final provider = thoughtSequenceListNotifierProvider; + return SheetScaffold( + titleText: 'Select Conversation', + child: PagingHelperView( + provider: provider, + futureRefreshable: provider.future, + notifierRefreshable: provider.notifier, + contentBuilder: + (data, widgetCount, endItemView) => ListView.builder( + itemCount: widgetCount, + itemBuilder: (context, index) { + if (index == widgetCount - 1) { + return endItemView; + } + + final sequence = data.items[index]; + return ListTile( + title: Text(sequence.topic ?? 'Untitled Conversation'), + subtitle: Text(sequence.createdAt.formatSystem()), + onTap: () { + onSequenceSelected(sequence.id); + Navigator.of(context).pop(); + }, + ); + }, + ), + ), + ); + } +} diff --git a/lib/widgets/thought/thought_sequence_list.g.dart b/lib/widgets/thought/thought_sequence_list.g.dart new file mode 100644 index 00000000..ccc78e4b --- /dev/null +++ b/lib/widgets/thought/thought_sequence_list.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'thought_sequence_list.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$thoughtSequenceListNotifierHash() => + r'fc619402d8691d523d19d3c7633adfada4956db4'; + +/// See also [ThoughtSequenceListNotifier]. +@ProviderFor(ThoughtSequenceListNotifier) +final thoughtSequenceListNotifierProvider = AutoDisposeAsyncNotifierProvider< + ThoughtSequenceListNotifier, + CursorPagingData +>.internal( + ThoughtSequenceListNotifier.new, + name: r'thoughtSequenceListNotifierProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$thoughtSequenceListNotifierHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$ThoughtSequenceListNotifier = + AutoDisposeAsyncNotifier>; +// 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