Compare commits
	
		
			6 Commits
		
	
	
		
			3.1.0+116
			...
			3c4a9767e1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3c4a9767e1 | |||
| 5df2445f3f | |||
| 56543d7b4c | |||
| 4c6fea1242 | |||
| fff43de9e3 | |||
| b31a915544 | 
| @@ -3,25 +3,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; | |||||||
| part 'embed.freezed.dart'; | part 'embed.freezed.dart'; | ||||||
| part 'embed.g.dart'; | part 'embed.g.dart'; | ||||||
|  |  | ||||||
| @freezed |  | ||||||
| sealed class SnEmbedLink with _$SnEmbedLink { |  | ||||||
|   const factory SnEmbedLink({ |  | ||||||
|     @JsonKey(name: 'Type') required String type, |  | ||||||
|     @JsonKey(name: 'Url') required String url, |  | ||||||
|     @JsonKey(name: 'Title') required String title, |  | ||||||
|     @JsonKey(name: 'Description') required String? description, |  | ||||||
|     @JsonKey(name: 'ImageUrl') required String? imageUrl, |  | ||||||
|     @JsonKey(name: 'FaviconUrl') @Default("") String faviconUrl, |  | ||||||
|     @JsonKey(name: 'SiteName') @Default("") String siteName, |  | ||||||
|     @JsonKey(name: 'ContentType') required String? contentType, |  | ||||||
|     @JsonKey(name: 'Author') required String? author, |  | ||||||
|     @JsonKey(name: 'PublishedDate') required DateTime? publishedDate, |  | ||||||
|   }) = _SnEmbedLink; |  | ||||||
|  |  | ||||||
|   factory SnEmbedLink.fromJson(Map<String, dynamic> json) => |  | ||||||
|       _$SnEmbedLinkFromJson(json); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @freezed | @freezed | ||||||
| sealed class SnScrappedLink with _$SnScrappedLink { | sealed class SnScrappedLink with _$SnScrappedLink { | ||||||
|   const factory SnScrappedLink({ |   const factory SnScrappedLink({ | ||||||
|   | |||||||
| @@ -12,290 +12,6 @@ part of 'embed.dart'; | |||||||
| // dart format off | // dart format off | ||||||
| T _$identity<T>(T value) => value; | T _$identity<T>(T value) => value; | ||||||
|  |  | ||||||
| /// @nodoc |  | ||||||
| mixin _$SnEmbedLink { |  | ||||||
|  |  | ||||||
| @JsonKey(name: 'Type') String get type;@JsonKey(name: 'Url') String get url;@JsonKey(name: 'Title') String get title;@JsonKey(name: 'Description') String? get description;@JsonKey(name: 'ImageUrl') String? get imageUrl;@JsonKey(name: 'FaviconUrl') String get faviconUrl;@JsonKey(name: 'SiteName') String get siteName;@JsonKey(name: 'ContentType') String? get contentType;@JsonKey(name: 'Author') String? get author;@JsonKey(name: 'PublishedDate') DateTime? get publishedDate; |  | ||||||
| /// Create a copy of SnEmbedLink |  | ||||||
| /// with the given fields replaced by the non-null parameter values. |  | ||||||
| @JsonKey(includeFromJson: false, includeToJson: false) |  | ||||||
| @pragma('vm:prefer-inline') |  | ||||||
| $SnEmbedLinkCopyWith<SnEmbedLink> get copyWith => _$SnEmbedLinkCopyWithImpl<SnEmbedLink>(this as SnEmbedLink, _$identity); |  | ||||||
|  |  | ||||||
|   /// Serializes this SnEmbedLink to a JSON map. |  | ||||||
|   Map<String, dynamic> toJson(); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @override |  | ||||||
| bool operator ==(Object other) { |  | ||||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is SnEmbedLink&&(identical(other.type, type) || other.type == type)&&(identical(other.url, url) || other.url == url)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.imageUrl, imageUrl) || other.imageUrl == imageUrl)&&(identical(other.faviconUrl, faviconUrl) || other.faviconUrl == faviconUrl)&&(identical(other.siteName, siteName) || other.siteName == siteName)&&(identical(other.contentType, contentType) || other.contentType == contentType)&&(identical(other.author, author) || other.author == author)&&(identical(other.publishedDate, publishedDate) || other.publishedDate == publishedDate)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @JsonKey(includeFromJson: false, includeToJson: false) |  | ||||||
| @override |  | ||||||
| int get hashCode => Object.hash(runtimeType,type,url,title,description,imageUrl,faviconUrl,siteName,contentType,author,publishedDate); |  | ||||||
|  |  | ||||||
| @override |  | ||||||
| String toString() { |  | ||||||
|   return 'SnEmbedLink(type: $type, url: $url, title: $title, description: $description, imageUrl: $imageUrl, faviconUrl: $faviconUrl, siteName: $siteName, contentType: $contentType, author: $author, publishedDate: $publishedDate)'; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// @nodoc |  | ||||||
| abstract mixin class $SnEmbedLinkCopyWith<$Res>  { |  | ||||||
|   factory $SnEmbedLinkCopyWith(SnEmbedLink value, $Res Function(SnEmbedLink) _then) = _$SnEmbedLinkCopyWithImpl; |  | ||||||
| @useResult |  | ||||||
| $Res call({ |  | ||||||
| @JsonKey(name: 'Type') String type,@JsonKey(name: 'Url') String url,@JsonKey(name: 'Title') String title,@JsonKey(name: 'Description') String? description,@JsonKey(name: 'ImageUrl') String? imageUrl,@JsonKey(name: 'FaviconUrl') String faviconUrl,@JsonKey(name: 'SiteName') String siteName,@JsonKey(name: 'ContentType') String? contentType,@JsonKey(name: 'Author') String? author,@JsonKey(name: 'PublishedDate') DateTime? publishedDate |  | ||||||
| }); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } |  | ||||||
| /// @nodoc |  | ||||||
| class _$SnEmbedLinkCopyWithImpl<$Res> |  | ||||||
|     implements $SnEmbedLinkCopyWith<$Res> { |  | ||||||
|   _$SnEmbedLinkCopyWithImpl(this._self, this._then); |  | ||||||
|  |  | ||||||
|   final SnEmbedLink _self; |  | ||||||
|   final $Res Function(SnEmbedLink) _then; |  | ||||||
|  |  | ||||||
| /// Create a copy of SnEmbedLink |  | ||||||
| /// with the given fields replaced by the non-null parameter values. |  | ||||||
| @pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = null,Object? siteName = null,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) { |  | ||||||
|   return _then(_self.copyWith( |  | ||||||
| type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String?,faviconUrl: null == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,siteName: null == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String?,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String?,publishedDate: freezed == publishedDate ? _self.publishedDate : publishedDate // ignore: cast_nullable_to_non_nullable |  | ||||||
| as DateTime?, |  | ||||||
|   )); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Adds pattern-matching-related methods to [SnEmbedLink]. |  | ||||||
| extension SnEmbedLinkPatterns on SnEmbedLink { |  | ||||||
| /// A variant of `map` that fallback to returning `orElse`. |  | ||||||
| /// |  | ||||||
| /// It is equivalent to doing: |  | ||||||
| /// ```dart |  | ||||||
| /// switch (sealedClass) { |  | ||||||
| ///   case final Subclass value: |  | ||||||
| ///     return ...; |  | ||||||
| ///   case _: |  | ||||||
| ///     return orElse(); |  | ||||||
| /// } |  | ||||||
| /// ``` |  | ||||||
|  |  | ||||||
| @optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _SnEmbedLink value)?  $default,{required TResult orElse(),}){ |  | ||||||
| final _that = this; |  | ||||||
| switch (_that) { |  | ||||||
| case _SnEmbedLink() when $default != null: |  | ||||||
| return $default(_that);case _: |  | ||||||
|   return orElse(); |  | ||||||
|  |  | ||||||
| } |  | ||||||
| } |  | ||||||
| /// A `switch`-like method, using callbacks. |  | ||||||
| /// |  | ||||||
| /// Callbacks receives the raw object, upcasted. |  | ||||||
| /// It is equivalent to doing: |  | ||||||
| /// ```dart |  | ||||||
| /// switch (sealedClass) { |  | ||||||
| ///   case final Subclass value: |  | ||||||
| ///     return ...; |  | ||||||
| ///   case final Subclass2 value: |  | ||||||
| ///     return ...; |  | ||||||
| /// } |  | ||||||
| /// ``` |  | ||||||
|  |  | ||||||
| @optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _SnEmbedLink value)  $default,){ |  | ||||||
| final _that = this; |  | ||||||
| switch (_that) { |  | ||||||
| case _SnEmbedLink(): |  | ||||||
| return $default(_that);} |  | ||||||
| } |  | ||||||
| /// A variant of `map` that fallback to returning `null`. |  | ||||||
| /// |  | ||||||
| /// It is equivalent to doing: |  | ||||||
| /// ```dart |  | ||||||
| /// switch (sealedClass) { |  | ||||||
| ///   case final Subclass value: |  | ||||||
| ///     return ...; |  | ||||||
| ///   case _: |  | ||||||
| ///     return null; |  | ||||||
| /// } |  | ||||||
| /// ``` |  | ||||||
|  |  | ||||||
| @optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _SnEmbedLink value)?  $default,){ |  | ||||||
| final _that = this; |  | ||||||
| switch (_that) { |  | ||||||
| case _SnEmbedLink() when $default != null: |  | ||||||
| return $default(_that);case _: |  | ||||||
|   return null; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| } |  | ||||||
| /// A variant of `when` that fallback to an `orElse` callback. |  | ||||||
| /// |  | ||||||
| /// It is equivalent to doing: |  | ||||||
| /// ```dart |  | ||||||
| /// switch (sealedClass) { |  | ||||||
| ///   case Subclass(:final field): |  | ||||||
| ///     return ...; |  | ||||||
| ///   case _: |  | ||||||
| ///     return orElse(); |  | ||||||
| /// } |  | ||||||
| /// ``` |  | ||||||
|  |  | ||||||
| @optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@JsonKey(name: 'Type')  String type, @JsonKey(name: 'Url')  String url, @JsonKey(name: 'Title')  String title, @JsonKey(name: 'Description')  String? description, @JsonKey(name: 'ImageUrl')  String? imageUrl, @JsonKey(name: 'FaviconUrl')  String faviconUrl, @JsonKey(name: 'SiteName')  String siteName, @JsonKey(name: 'ContentType')  String? contentType, @JsonKey(name: 'Author')  String? author, @JsonKey(name: 'PublishedDate')  DateTime? publishedDate)?  $default,{required TResult orElse(),}) {final _that = this; |  | ||||||
| switch (_that) { |  | ||||||
| case _SnEmbedLink() when $default != null: |  | ||||||
| return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);case _: |  | ||||||
|   return orElse(); |  | ||||||
|  |  | ||||||
| } |  | ||||||
| } |  | ||||||
| /// A `switch`-like method, using callbacks. |  | ||||||
| /// |  | ||||||
| /// As opposed to `map`, this offers destructuring. |  | ||||||
| /// It is equivalent to doing: |  | ||||||
| /// ```dart |  | ||||||
| /// switch (sealedClass) { |  | ||||||
| ///   case Subclass(:final field): |  | ||||||
| ///     return ...; |  | ||||||
| ///   case Subclass2(:final field2): |  | ||||||
| ///     return ...; |  | ||||||
| /// } |  | ||||||
| /// ``` |  | ||||||
|  |  | ||||||
| @optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@JsonKey(name: 'Type')  String type, @JsonKey(name: 'Url')  String url, @JsonKey(name: 'Title')  String title, @JsonKey(name: 'Description')  String? description, @JsonKey(name: 'ImageUrl')  String? imageUrl, @JsonKey(name: 'FaviconUrl')  String faviconUrl, @JsonKey(name: 'SiteName')  String siteName, @JsonKey(name: 'ContentType')  String? contentType, @JsonKey(name: 'Author')  String? author, @JsonKey(name: 'PublishedDate')  DateTime? publishedDate)  $default,) {final _that = this; |  | ||||||
| switch (_that) { |  | ||||||
| case _SnEmbedLink(): |  | ||||||
| return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);} |  | ||||||
| } |  | ||||||
| /// A variant of `when` that fallback to returning `null` |  | ||||||
| /// |  | ||||||
| /// It is equivalent to doing: |  | ||||||
| /// ```dart |  | ||||||
| /// switch (sealedClass) { |  | ||||||
| ///   case Subclass(:final field): |  | ||||||
| ///     return ...; |  | ||||||
| ///   case _: |  | ||||||
| ///     return null; |  | ||||||
| /// } |  | ||||||
| /// ``` |  | ||||||
|  |  | ||||||
| @optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@JsonKey(name: 'Type')  String type, @JsonKey(name: 'Url')  String url, @JsonKey(name: 'Title')  String title, @JsonKey(name: 'Description')  String? description, @JsonKey(name: 'ImageUrl')  String? imageUrl, @JsonKey(name: 'FaviconUrl')  String faviconUrl, @JsonKey(name: 'SiteName')  String siteName, @JsonKey(name: 'ContentType')  String? contentType, @JsonKey(name: 'Author')  String? author, @JsonKey(name: 'PublishedDate')  DateTime? publishedDate)?  $default,) {final _that = this; |  | ||||||
| switch (_that) { |  | ||||||
| case _SnEmbedLink() when $default != null: |  | ||||||
| return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);case _: |  | ||||||
|   return null; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// @nodoc |  | ||||||
| @JsonSerializable() |  | ||||||
|  |  | ||||||
| class _SnEmbedLink implements SnEmbedLink { |  | ||||||
|   const _SnEmbedLink({@JsonKey(name: 'Type') required this.type, @JsonKey(name: 'Url') required this.url, @JsonKey(name: 'Title') required this.title, @JsonKey(name: 'Description') required this.description, @JsonKey(name: 'ImageUrl') required this.imageUrl, @JsonKey(name: 'FaviconUrl') this.faviconUrl = "", @JsonKey(name: 'SiteName') this.siteName = "", @JsonKey(name: 'ContentType') required this.contentType, @JsonKey(name: 'Author') required this.author, @JsonKey(name: 'PublishedDate') required this.publishedDate}); |  | ||||||
|   factory _SnEmbedLink.fromJson(Map<String, dynamic> json) => _$SnEmbedLinkFromJson(json); |  | ||||||
|  |  | ||||||
| @override@JsonKey(name: 'Type') final  String type; |  | ||||||
| @override@JsonKey(name: 'Url') final  String url; |  | ||||||
| @override@JsonKey(name: 'Title') final  String title; |  | ||||||
| @override@JsonKey(name: 'Description') final  String? description; |  | ||||||
| @override@JsonKey(name: 'ImageUrl') final  String? imageUrl; |  | ||||||
| @override@JsonKey(name: 'FaviconUrl') final  String faviconUrl; |  | ||||||
| @override@JsonKey(name: 'SiteName') final  String siteName; |  | ||||||
| @override@JsonKey(name: 'ContentType') final  String? contentType; |  | ||||||
| @override@JsonKey(name: 'Author') final  String? author; |  | ||||||
| @override@JsonKey(name: 'PublishedDate') final  DateTime? publishedDate; |  | ||||||
|  |  | ||||||
| /// Create a copy of SnEmbedLink |  | ||||||
| /// with the given fields replaced by the non-null parameter values. |  | ||||||
| @override @JsonKey(includeFromJson: false, includeToJson: false) |  | ||||||
| @pragma('vm:prefer-inline') |  | ||||||
| _$SnEmbedLinkCopyWith<_SnEmbedLink> get copyWith => __$SnEmbedLinkCopyWithImpl<_SnEmbedLink>(this, _$identity); |  | ||||||
|  |  | ||||||
| @override |  | ||||||
| Map<String, dynamic> toJson() { |  | ||||||
|   return _$SnEmbedLinkToJson(this, ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @override |  | ||||||
| bool operator ==(Object other) { |  | ||||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnEmbedLink&&(identical(other.type, type) || other.type == type)&&(identical(other.url, url) || other.url == url)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.imageUrl, imageUrl) || other.imageUrl == imageUrl)&&(identical(other.faviconUrl, faviconUrl) || other.faviconUrl == faviconUrl)&&(identical(other.siteName, siteName) || other.siteName == siteName)&&(identical(other.contentType, contentType) || other.contentType == contentType)&&(identical(other.author, author) || other.author == author)&&(identical(other.publishedDate, publishedDate) || other.publishedDate == publishedDate)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @JsonKey(includeFromJson: false, includeToJson: false) |  | ||||||
| @override |  | ||||||
| int get hashCode => Object.hash(runtimeType,type,url,title,description,imageUrl,faviconUrl,siteName,contentType,author,publishedDate); |  | ||||||
|  |  | ||||||
| @override |  | ||||||
| String toString() { |  | ||||||
|   return 'SnEmbedLink(type: $type, url: $url, title: $title, description: $description, imageUrl: $imageUrl, faviconUrl: $faviconUrl, siteName: $siteName, contentType: $contentType, author: $author, publishedDate: $publishedDate)'; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// @nodoc |  | ||||||
| abstract mixin class _$SnEmbedLinkCopyWith<$Res> implements $SnEmbedLinkCopyWith<$Res> { |  | ||||||
|   factory _$SnEmbedLinkCopyWith(_SnEmbedLink value, $Res Function(_SnEmbedLink) _then) = __$SnEmbedLinkCopyWithImpl; |  | ||||||
| @override @useResult |  | ||||||
| $Res call({ |  | ||||||
| @JsonKey(name: 'Type') String type,@JsonKey(name: 'Url') String url,@JsonKey(name: 'Title') String title,@JsonKey(name: 'Description') String? description,@JsonKey(name: 'ImageUrl') String? imageUrl,@JsonKey(name: 'FaviconUrl') String faviconUrl,@JsonKey(name: 'SiteName') String siteName,@JsonKey(name: 'ContentType') String? contentType,@JsonKey(name: 'Author') String? author,@JsonKey(name: 'PublishedDate') DateTime? publishedDate |  | ||||||
| }); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } |  | ||||||
| /// @nodoc |  | ||||||
| class __$SnEmbedLinkCopyWithImpl<$Res> |  | ||||||
|     implements _$SnEmbedLinkCopyWith<$Res> { |  | ||||||
|   __$SnEmbedLinkCopyWithImpl(this._self, this._then); |  | ||||||
|  |  | ||||||
|   final _SnEmbedLink _self; |  | ||||||
|   final $Res Function(_SnEmbedLink) _then; |  | ||||||
|  |  | ||||||
| /// Create a copy of SnEmbedLink |  | ||||||
| /// with the given fields replaced by the non-null parameter values. |  | ||||||
| @override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = null,Object? siteName = null,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) { |  | ||||||
|   return _then(_SnEmbedLink( |  | ||||||
| type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String?,faviconUrl: null == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,siteName: null == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String?,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable |  | ||||||
| as String?,publishedDate: freezed == publishedDate ? _self.publishedDate : publishedDate // ignore: cast_nullable_to_non_nullable |  | ||||||
| as DateTime?, |  | ||||||
|   )); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /// @nodoc | /// @nodoc | ||||||
| mixin _$SnScrappedLink { | mixin _$SnScrappedLink { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,36 +6,6 @@ part of 'embed.dart'; | |||||||
| // JsonSerializableGenerator | // JsonSerializableGenerator | ||||||
| // ************************************************************************** | // ************************************************************************** | ||||||
|  |  | ||||||
| _SnEmbedLink _$SnEmbedLinkFromJson(Map<String, dynamic> json) => _SnEmbedLink( |  | ||||||
|   type: json['Type'] as String, |  | ||||||
|   url: json['Url'] as String, |  | ||||||
|   title: json['Title'] as String, |  | ||||||
|   description: json['Description'] as String?, |  | ||||||
|   imageUrl: json['ImageUrl'] as String?, |  | ||||||
|   faviconUrl: json['FaviconUrl'] as String? ?? "", |  | ||||||
|   siteName: json['SiteName'] as String? ?? "", |  | ||||||
|   contentType: json['ContentType'] as String?, |  | ||||||
|   author: json['Author'] as String?, |  | ||||||
|   publishedDate: |  | ||||||
|       json['PublishedDate'] == null |  | ||||||
|           ? null |  | ||||||
|           : DateTime.parse(json['PublishedDate'] as String), |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| Map<String, dynamic> _$SnEmbedLinkToJson(_SnEmbedLink instance) => |  | ||||||
|     <String, dynamic>{ |  | ||||||
|       'Type': instance.type, |  | ||||||
|       'Url': instance.url, |  | ||||||
|       'Title': instance.title, |  | ||||||
|       'Description': instance.description, |  | ||||||
|       'ImageUrl': instance.imageUrl, |  | ||||||
|       'FaviconUrl': instance.faviconUrl, |  | ||||||
|       'SiteName': instance.siteName, |  | ||||||
|       'ContentType': instance.contentType, |  | ||||||
|       'Author': instance.author, |  | ||||||
|       'PublishedDate': instance.publishedDate?.toIso8601String(), |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
| _SnScrappedLink _$SnScrappedLinkFromJson(Map<String, dynamic> json) => | _SnScrappedLink _$SnScrappedLinkFromJson(Map<String, dynamic> json) => | ||||||
|     _SnScrappedLink( |     _SnScrappedLink( | ||||||
|       type: json['type'] as String, |       type: json['type'] as String, | ||||||
|   | |||||||
| @@ -205,7 +205,7 @@ class _AboutScreenState extends ConsumerState<AboutScreen> { | |||||||
|                           title: 'aboutScreenTermsOfServiceTitle'.tr(), |                           title: 'aboutScreenTermsOfServiceTitle'.tr(), | ||||||
|                           onTap: |                           onTap: | ||||||
|                               () => _launchURL( |                               () => _launchURL( | ||||||
|                                 'https://solsynth.dev/terms/basic-law', |                                 'https://solsynth.dev/terms/user-agreement', | ||||||
|                               ), |                               ), | ||||||
|                         ), |                         ), | ||||||
|                         _buildListTile( |                         _buildListTile( | ||||||
|   | |||||||
| @@ -218,6 +218,11 @@ class ExploreScreen extends HookConsumerWidget { | |||||||
|                               right: 12, |                               right: 12, | ||||||
|                               top: 16, |                               top: 16, | ||||||
|                             ), |                             ), | ||||||
|  |                             onChecked: () { | ||||||
|  |                               ref.invalidate( | ||||||
|  |                                 eventCalendarProvider(query.value), | ||||||
|  |                               ); | ||||||
|  |                             }, | ||||||
|                           ), |                           ), | ||||||
|                           Card( |                           Card( | ||||||
|                             margin: EdgeInsets.only(left: 8, right: 12, top: 8), |                             margin: EdgeInsets.only(left: 8, right: 12, top: 8), | ||||||
|   | |||||||
| @@ -207,8 +207,6 @@ class PostComposeScreen extends HookConsumerWidget { | |||||||
|         isScrollControlled: true, |         isScrollControlled: true, | ||||||
|         builder: |         builder: | ||||||
|             (context) => ComposeSettingsSheet( |             (context) => ComposeSettingsSheet( | ||||||
|               titleController: state.titleController, |  | ||||||
|               descriptionController: state.descriptionController, |  | ||||||
|               visibility: state.visibility, |               visibility: state.visibility, | ||||||
|               tagsController: state.tagsController, |               tagsController: state.tagsController, | ||||||
|               categoriesController: state.categoriesController, |               categoriesController: state.categoriesController, | ||||||
| @@ -370,14 +368,52 @@ class PostComposeScreen extends HookConsumerWidget { | |||||||
|                     // Post content form |                     // Post content form | ||||||
|                     Expanded( |                     Expanded( | ||||||
|                       child: SingleChildScrollView( |                       child: SingleChildScrollView( | ||||||
|                         padding: const EdgeInsets.symmetric(vertical: 12), |                         padding: const EdgeInsets.symmetric(vertical: 16), | ||||||
|                         child: Column( |                         child: Column( | ||||||
|                           crossAxisAlignment: CrossAxisAlignment.start, |                           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                           children: [ |                           children: [ | ||||||
|  |                             TextField( | ||||||
|  |                               controller: state.titleController, | ||||||
|  |                               decoration: InputDecoration( | ||||||
|  |                                 hintText: 'postTitle'.tr(), | ||||||
|  |                                 border: InputBorder.none, | ||||||
|  |                                 isCollapsed: true, | ||||||
|  |                                 contentPadding: const EdgeInsets.symmetric( | ||||||
|  |                                   vertical: 8, | ||||||
|  |                                   horizontal: 8, | ||||||
|  |                                 ), | ||||||
|  |                               ), | ||||||
|  |                               style: theme.textTheme.titleMedium, | ||||||
|  |                               onTapOutside: | ||||||
|  |                                   (_) => | ||||||
|  |                                       FocusManager.instance.primaryFocus | ||||||
|  |                                           ?.unfocus(), | ||||||
|  |                             ), | ||||||
|  |                             TextField( | ||||||
|  |                               controller: state.descriptionController, | ||||||
|  |                               decoration: InputDecoration( | ||||||
|  |                                 hintText: 'postDescription'.tr(), | ||||||
|  |                                 border: InputBorder.none, | ||||||
|  |                                 isCollapsed: true, | ||||||
|  |                                 contentPadding: const EdgeInsets.fromLTRB( | ||||||
|  |                                   8, | ||||||
|  |                                   4, | ||||||
|  |                                   8, | ||||||
|  |                                   12, | ||||||
|  |                                 ), | ||||||
|  |                               ), | ||||||
|  |                               style: theme.textTheme.bodyMedium, | ||||||
|  |                               minLines: 1, | ||||||
|  |                               maxLines: 3, | ||||||
|  |                               onTapOutside: | ||||||
|  |                                   (_) => | ||||||
|  |                                       FocusManager.instance.primaryFocus | ||||||
|  |                                           ?.unfocus(), | ||||||
|  |                             ), | ||||||
|                             // Content field with borderless design |                             // Content field with borderless design | ||||||
|                             RawKeyboardListener( |                             KeyboardListener( | ||||||
|                               focusNode: FocusNode(), |                               focusNode: FocusNode(), | ||||||
|                               onKey: |                               onKeyEvent: | ||||||
|                                   (event) => ComposeLogic.handleKeyPress( |                                   (event) => ComposeLogic.handleKeyPress( | ||||||
|                                     event, |                                     event, | ||||||
|                                     state, |                                     state, | ||||||
| @@ -393,7 +429,11 @@ class PostComposeScreen extends HookConsumerWidget { | |||||||
|                                 decoration: InputDecoration( |                                 decoration: InputDecoration( | ||||||
|                                   border: InputBorder.none, |                                   border: InputBorder.none, | ||||||
|                                   hintText: 'postContent'.tr(), |                                   hintText: 'postContent'.tr(), | ||||||
|                                   contentPadding: const EdgeInsets.all(8), |                                   isCollapsed: true, | ||||||
|  |                                   contentPadding: const EdgeInsets.symmetric( | ||||||
|  |                                     vertical: 8, | ||||||
|  |                                     horizontal: 8, | ||||||
|  |                                   ), | ||||||
|                                 ), |                                 ), | ||||||
|                                 maxLines: null, |                                 maxLines: null, | ||||||
|                                 onTapOutside: |                                 onTapOutside: | ||||||
|   | |||||||
| @@ -140,8 +140,6 @@ class ArticleComposeScreen extends HookConsumerWidget { | |||||||
|         isScrollControlled: true, |         isScrollControlled: true, | ||||||
|         builder: |         builder: | ||||||
|             (context) => ComposeSettingsSheet( |             (context) => ComposeSettingsSheet( | ||||||
|               titleController: state.titleController, |  | ||||||
|               descriptionController: state.descriptionController, |  | ||||||
|               visibility: state.visibility, |               visibility: state.visibility, | ||||||
|               tagsController: state.tagsController, |               tagsController: state.tagsController, | ||||||
|               categoriesController: state.categoriesController, |               categoriesController: state.categoriesController, | ||||||
| @@ -242,10 +240,39 @@ class ArticleComposeScreen extends HookConsumerWidget { | |||||||
|           child: Column( |           child: Column( | ||||||
|             crossAxisAlignment: CrossAxisAlignment.start, |             crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|             children: [ |             children: [ | ||||||
|  |               TextField( | ||||||
|  |                 controller: state.titleController, | ||||||
|  |                 decoration: InputDecoration( | ||||||
|  |                   hintText: 'postTitle'.tr(), | ||||||
|  |                   border: InputBorder.none, | ||||||
|  |                   isCollapsed: true, | ||||||
|  |                   contentPadding: const EdgeInsets.symmetric( | ||||||
|  |                     vertical: 8, | ||||||
|  |                     horizontal: 8, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |                 style: theme.textTheme.titleMedium, | ||||||
|  |                 onTapOutside: | ||||||
|  |                     (_) => FocusManager.instance.primaryFocus?.unfocus(), | ||||||
|  |               ), | ||||||
|  |               TextField( | ||||||
|  |                 controller: state.descriptionController, | ||||||
|  |                 decoration: InputDecoration( | ||||||
|  |                   hintText: 'postDescription'.tr(), | ||||||
|  |                   border: InputBorder.none, | ||||||
|  |                   isCollapsed: true, | ||||||
|  |                   contentPadding: const EdgeInsets.fromLTRB(8, 4, 8, 12), | ||||||
|  |                 ), | ||||||
|  |                 style: theme.textTheme.bodyMedium, | ||||||
|  |                 minLines: 1, | ||||||
|  |                 maxLines: 3, | ||||||
|  |                 onTapOutside: | ||||||
|  |                     (_) => FocusManager.instance.primaryFocus?.unfocus(), | ||||||
|  |               ), | ||||||
|               Expanded( |               Expanded( | ||||||
|                 child: RawKeyboardListener( |                 child: KeyboardListener( | ||||||
|                   focusNode: FocusNode(), |                   focusNode: FocusNode(), | ||||||
|                   onKey: |                   onKeyEvent: | ||||||
|                       (event) => _handleKeyPress( |                       (event) => _handleKeyPress( | ||||||
|                         event, |                         event, | ||||||
|                         state, |                         state, | ||||||
| @@ -454,7 +481,7 @@ class ArticleComposeScreen extends HookConsumerWidget { | |||||||
|                               flex: showPreview.value ? 1 : 2, |                               flex: showPreview.value ? 1 : 2, | ||||||
|                               child: buildEditorPane(), |                               child: buildEditorPane(), | ||||||
|                             ), |                             ), | ||||||
|                             const VerticalDivider(), |                             if (showPreview.value) const VerticalDivider(), | ||||||
|                             if (showPreview.value) |                             if (showPreview.value) | ||||||
|                               Expanded(child: buildPreviewPane()), |                               Expanded(child: buildPreviewPane()), | ||||||
|                           ], |                           ], | ||||||
| @@ -475,7 +502,7 @@ class ArticleComposeScreen extends HookConsumerWidget { | |||||||
|  |  | ||||||
|   // Helper method to handle keyboard shortcuts |   // Helper method to handle keyboard shortcuts | ||||||
|   void _handleKeyPress( |   void _handleKeyPress( | ||||||
|     RawKeyEvent event, |     KeyEvent event, | ||||||
|     ComposeState state, |     ComposeState state, | ||||||
|     WidgetRef ref, |     WidgetRef ref, | ||||||
|     BuildContext context, { |     BuildContext context, { | ||||||
| @@ -485,7 +512,9 @@ class ArticleComposeScreen extends HookConsumerWidget { | |||||||
|  |  | ||||||
|     final isPaste = event.logicalKey == LogicalKeyboardKey.keyV; |     final isPaste = event.logicalKey == LogicalKeyboardKey.keyV; | ||||||
|     final isSave = event.logicalKey == LogicalKeyboardKey.keyS; |     final isSave = event.logicalKey == LogicalKeyboardKey.keyS; | ||||||
|     final isModifierPressed = event.isMetaPressed || event.isControlPressed; |     final isModifierPressed = | ||||||
|  |         HardwareKeyboard.instance.isMetaPressed || | ||||||
|  |         HardwareKeyboard.instance.isControlPressed; | ||||||
|     final isSubmit = event.logicalKey == LogicalKeyboardKey.enter; |     final isSubmit = event.logicalKey == LogicalKeyboardKey.enter; | ||||||
|  |  | ||||||
|     if (isPaste && isModifierPressed) { |     if (isPaste && isModifierPressed) { | ||||||
|   | |||||||
| @@ -87,6 +87,12 @@ class PublisherProfileScreen extends HookConsumerWidget { | |||||||
|       publisherAppbarForcegroundColorProvider(name), |       publisherAppbarForcegroundColorProvider(name), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  |     final categoryTabController = useTabController(initialLength: 3); | ||||||
|  |     final categoryTab = useState(0); | ||||||
|  |     categoryTabController.addListener(() { | ||||||
|  |       categoryTab.value = categoryTabController.index; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|     final subscribing = useState(false); |     final subscribing = useState(false); | ||||||
|  |  | ||||||
|     Future<void> subscribe() async { |     Future<void> subscribe() async { | ||||||
| @@ -268,6 +274,16 @@ class PublisherProfileScreen extends HookConsumerWidget { | |||||||
|       ).padding(horizontal: 20, vertical: 16), |       ).padding(horizontal: 20, vertical: 16), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  |     Widget publisherCategoryTabWidget() => Card( | ||||||
|  |       margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), | ||||||
|  |       child: TabBar( | ||||||
|  |         controller: categoryTabController, | ||||||
|  |         dividerColor: Colors.transparent, | ||||||
|  |         splashBorderRadius: const BorderRadius.all(Radius.circular(8)), | ||||||
|  |         tabs: [Tab(text: 'All'), Tab(text: 'Posts'), Tab(text: 'Articles')], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|     return publisher.when( |     return publisher.when( | ||||||
|       data: |       data: | ||||||
|           (data) => AppScaffold( |           (data) => AppScaffold( | ||||||
| @@ -398,7 +414,16 @@ class PublisherProfileScreen extends HookConsumerWidget { | |||||||
|                           child: publisherVerificationWidget(data), |                           child: publisherVerificationWidget(data), | ||||||
|                         ), |                         ), | ||||||
|                         SliverToBoxAdapter(child: publisherBioWidget(data)), |                         SliverToBoxAdapter(child: publisherBioWidget(data)), | ||||||
|                         SliverPostList(pubName: name), |                         SliverToBoxAdapter(child: publisherCategoryTabWidget()), | ||||||
|  |                         SliverPostList( | ||||||
|  |                           key: ValueKey(categoryTab.value), | ||||||
|  |                           pubName: name, | ||||||
|  |                           type: switch (categoryTab.value) { | ||||||
|  |                             1 => 0, | ||||||
|  |                             2 => 1, | ||||||
|  |                             _ => null, | ||||||
|  |                           }, | ||||||
|  |                         ), | ||||||
|                         SliverGap(MediaQuery.of(context).padding.bottom + 16), |                         SliverGap(MediaQuery.of(context).padding.bottom + 16), | ||||||
|                       ], |                       ], | ||||||
|                     ), |                     ), | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								lib/utils/mapping.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								lib/utils/mapping.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | String _upperCamelToLowerSnake(String input) { | ||||||
|  |   final regex = RegExp(r'(?<=[a-z0-9])([A-Z])'); | ||||||
|  |   return input | ||||||
|  |       .replaceAllMapped(regex, (match) => '_${match.group(0)}') | ||||||
|  |       .toLowerCase(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Map<String, dynamic> convertMapKeysToSnakeCase(Map<String, dynamic> input) { | ||||||
|  |   final result = <String, dynamic>{}; | ||||||
|  |  | ||||||
|  |   input.forEach((key, value) { | ||||||
|  |     final newKey = _upperCamelToLowerSnake(key); | ||||||
|  |  | ||||||
|  |     if (value is Map<String, dynamic>) { | ||||||
|  |       result[newKey] = convertMapKeysToSnakeCase(value); | ||||||
|  |     } else if (value is List) { | ||||||
|  |       result[newKey] = | ||||||
|  |           value.map((item) { | ||||||
|  |             if (item is Map<String, dynamic>) { | ||||||
|  |               return convertMapKeysToSnakeCase(item); | ||||||
|  |             } | ||||||
|  |             return item; | ||||||
|  |           }).toList(); | ||||||
|  |     } else { | ||||||
|  |       result[newKey] = value; | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   return result; | ||||||
|  | } | ||||||
| @@ -14,6 +14,7 @@ import 'package:island/models/embed.dart'; | |||||||
| import 'package:island/pods/call.dart'; | import 'package:island/pods/call.dart'; | ||||||
| import 'package:island/pods/translate.dart'; | import 'package:island/pods/translate.dart'; | ||||||
| import 'package:island/screens/chat/room.dart'; | import 'package:island/screens/chat/room.dart'; | ||||||
|  | import 'package:island/utils/mapping.dart'; | ||||||
| import 'package:island/widgets/account/account_name.dart'; | import 'package:island/widgets/account/account_name.dart'; | ||||||
| import 'package:island/widgets/account/account_pfc.dart'; | import 'package:island/widgets/account/account_pfc.dart'; | ||||||
| import 'package:island/widgets/app_scaffold.dart'; | import 'package:island/widgets/app_scaffold.dart'; | ||||||
| @@ -292,12 +293,11 @@ class MessageItem extends HookConsumerWidget { | |||||||
|                             ), |                             ), | ||||||
|                           if (remoteMessage.meta['embeds'] != null) |                           if (remoteMessage.meta['embeds'] != null) | ||||||
|                             ...((remoteMessage.meta['embeds'] as List<dynamic>) |                             ...((remoteMessage.meta['embeds'] as List<dynamic>) | ||||||
|                                 .where((embed) => embed['Type'] == 'link') |  | ||||||
|                                 .map( |                                 .map( | ||||||
|                                   (embed) => SnEmbedLink.fromJson( |                                   (embed) => convertMapKeysToSnakeCase(embed), | ||||||
|                                     embed as Map<String, dynamic>, |  | ||||||
|                                   ), |  | ||||||
|                                 ) |                                 ) | ||||||
|  |                                 .where((embed) => embed['type'] == 'link') | ||||||
|  |                                 .map((embed) => SnScrappedLink.fromJson(embed)) | ||||||
|                                 .map( |                                 .map( | ||||||
|                                   (link) => LayoutBuilder( |                                   (link) => LayoutBuilder( | ||||||
|                                     builder: (context, constraints) { |                                     builder: (context, constraints) { | ||||||
|   | |||||||
| @@ -36,7 +36,8 @@ Future<SnCheckInResult?> checkInResultToday(Ref ref) async { | |||||||
|  |  | ||||||
| class CheckInWidget extends HookConsumerWidget { | class CheckInWidget extends HookConsumerWidget { | ||||||
|   final EdgeInsets? margin; |   final EdgeInsets? margin; | ||||||
|   const CheckInWidget({super.key, this.margin}); |   final VoidCallback? onChecked; | ||||||
|  |   const CheckInWidget({super.key, this.margin, this.onChecked}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context, WidgetRef ref) { |   Widget build(BuildContext context, WidgetRef ref) { | ||||||
| @@ -52,6 +53,7 @@ class CheckInWidget extends HookConsumerWidget { | |||||||
|         ref.invalidate(checkInResultTodayProvider); |         ref.invalidate(checkInResultTodayProvider); | ||||||
|         final userNotifier = ref.read(userInfoProvider.notifier); |         final userNotifier = ref.read(userInfoProvider.notifier); | ||||||
|         userNotifier.fetchUser(); |         userNotifier.fetchUser(); | ||||||
|  |         onChecked?.call(); | ||||||
|       } catch (err) { |       } catch (err) { | ||||||
|         if (err is DioException) { |         if (err is DioException) { | ||||||
|           if (err.response?.statusCode == 423 && context.mounted) { |           if (err.response?.statusCode == 423 && context.mounted) { | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| import 'dart:math' as math; | import 'dart:math' as math; | ||||||
| import 'dart:ui'; |  | ||||||
|  |  | ||||||
| import 'package:cached_network_image/cached_network_image.dart'; | import 'package:cached_network_image/cached_network_image.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| @@ -103,6 +102,7 @@ class CloudVideoWidget extends HookConsumerWidget { | |||||||
|                 Symbols.play_arrow, |                 Symbols.play_arrow, | ||||||
|                 fill: 1, |                 fill: 1, | ||||||
|                 size: 32, |                 size: 32, | ||||||
|  |                 color: Colors.white, | ||||||
|                 shadows: [ |                 shadows: [ | ||||||
|                   BoxShadow( |                   BoxShadow( | ||||||
|                     color: Colors.black54, |                     color: Colors.black54, | ||||||
| @@ -114,6 +114,26 @@ class CloudVideoWidget extends HookConsumerWidget { | |||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
|  |           Positioned( | ||||||
|  |             bottom: 0, | ||||||
|  |             left: 0, | ||||||
|  |             right: 0, | ||||||
|  |             child: IgnorePointer( | ||||||
|  |               child: Container( | ||||||
|  |                 height: 100, | ||||||
|  |                 decoration: BoxDecoration( | ||||||
|  |                   gradient: LinearGradient( | ||||||
|  |                     begin: Alignment.bottomCenter, | ||||||
|  |                     end: Alignment.topCenter, | ||||||
|  |                     colors: [ | ||||||
|  |                       Theme.of(context).colorScheme.surface.withOpacity(0.85), | ||||||
|  |                       Colors.transparent, | ||||||
|  |                     ], | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|           Positioned( |           Positioned( | ||||||
|             bottom: 0, |             bottom: 0, | ||||||
|             left: 0, |             left: 0, | ||||||
| @@ -133,6 +153,7 @@ class CloudVideoWidget extends HookConsumerWidget { | |||||||
|                                   .toInt(), |                                   .toInt(), | ||||||
|                         ).formatDuration(), |                         ).formatDuration(), | ||||||
|                         style: TextStyle( |                         style: TextStyle( | ||||||
|  |                           color: Colors.white, | ||||||
|                           shadows: [ |                           shadows: [ | ||||||
|                             BoxShadow( |                             BoxShadow( | ||||||
|                               color: Colors.black54, |                               color: Colors.black54, | ||||||
| @@ -147,6 +168,7 @@ class CloudVideoWidget extends HookConsumerWidget { | |||||||
|                       Text( |                       Text( | ||||||
|                         '${int.parse(item.fileMeta?['bit_rate'] as String) ~/ 1000} Kbps', |                         '${int.parse(item.fileMeta?['bit_rate'] as String) ~/ 1000} Kbps', | ||||||
|                         style: TextStyle( |                         style: TextStyle( | ||||||
|  |                           color: Colors.white, | ||||||
|                           shadows: [ |                           shadows: [ | ||||||
|                             BoxShadow( |                             BoxShadow( | ||||||
|                               color: Colors.black54, |                               color: Colors.black54, | ||||||
| @@ -161,7 +183,10 @@ class CloudVideoWidget extends HookConsumerWidget { | |||||||
|                 ), |                 ), | ||||||
|                 Text( |                 Text( | ||||||
|                   item.name, |                   item.name, | ||||||
|  |                   maxLines: 1, | ||||||
|  |                   overflow: TextOverflow.ellipsis, | ||||||
|                   style: TextStyle( |                   style: TextStyle( | ||||||
|  |                     color: Colors.white, | ||||||
|                     fontWeight: FontWeight.bold, |                     fontWeight: FontWeight.bold, | ||||||
|                     shadows: [ |                     shadows: [ | ||||||
|                       BoxShadow( |                       BoxShadow( | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import 'package:material_symbols_icons/symbols.dart'; | |||||||
| import 'package:url_launcher/url_launcher.dart'; | import 'package:url_launcher/url_launcher.dart'; | ||||||
|  |  | ||||||
| class EmbedLinkWidget extends StatelessWidget { | class EmbedLinkWidget extends StatelessWidget { | ||||||
|   final SnEmbedLink link; |   final SnScrappedLink link; | ||||||
|   final double? maxWidth; |   final double? maxWidth; | ||||||
|   final EdgeInsetsGeometry? margin; |   final EdgeInsetsGeometry? margin; | ||||||
|  |  | ||||||
| @@ -116,7 +116,8 @@ class EmbedLinkWidget extends StatelessWidget { | |||||||
|                     ], |                     ], | ||||||
|  |  | ||||||
|                     // Description |                     // Description | ||||||
|                     if (link.description != null && link.description!.isNotEmpty) ...[ |                     if (link.description != null && | ||||||
|  |                         link.description!.isNotEmpty) ...[ | ||||||
|                       Text( |                       Text( | ||||||
|                         link.description!, |                         link.description!, | ||||||
|                         style: theme.textTheme.bodyMedium?.copyWith( |                         style: theme.textTheme.bodyMedium?.copyWith( | ||||||
|   | |||||||
| @@ -3,21 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; | |||||||
| import 'package:island/models/poll.dart'; | import 'package:island/models/poll.dart'; | ||||||
| import 'package:island/pods/network.dart'; | import 'package:island/pods/network.dart'; | ||||||
|  |  | ||||||
| /// A poll answering widget that shows one question at a time and collects answers. |  | ||||||
| /// |  | ||||||
| /// Usage: |  | ||||||
| /// PollSubmit( |  | ||||||
| ///   poll: poll, |  | ||||||
| ///   onSubmit: (answers) { |  | ||||||
| ///     // answers is Map<String, dynamic>: questionId -> answer |  | ||||||
| ///     // answer types by question: |  | ||||||
| ///     // - singleChoice: String optionId |  | ||||||
| ///     // - multipleChoice: List<String> optionIds |  | ||||||
| ///     // - yesNo: bool |  | ||||||
| ///     // - rating: int (1..5) |  | ||||||
| ///     // - freeText: String |  | ||||||
| ///   }, |  | ||||||
| /// ) |  | ||||||
| class PollSubmit extends ConsumerStatefulWidget { | class PollSubmit extends ConsumerStatefulWidget { | ||||||
|   const PollSubmit({ |   const PollSubmit({ | ||||||
|     super.key, |     super.key, | ||||||
|   | |||||||
| @@ -189,8 +189,8 @@ class ComposePollSheet extends HookConsumerWidget { | |||||||
|   Widget? _buildPollSubtitle(SnPoll poll) { |   Widget? _buildPollSubtitle(SnPoll poll) { | ||||||
|     try { |     try { | ||||||
|       final SnPoll dyn = poll; |       final SnPoll dyn = poll; | ||||||
|       final List<SnPollQuestion>? options = dyn.questions; |       final List<SnPollQuestion> options = dyn.questions; | ||||||
|       if (options == null || options.isEmpty) return null; |       if (options.isEmpty) return null; | ||||||
|       final preview = options.take(3).map((e) => e.title).join(' · '); |       final preview = options.take(3).map((e) => e.title).join(' · '); | ||||||
|       if (preview.trim().isEmpty) return null; |       if (preview.trim().isEmpty) return null; | ||||||
|       return Text(preview); |       return Text(preview); | ||||||
|   | |||||||
| @@ -99,8 +99,6 @@ class ChipTagInputField extends StatelessWidget { | |||||||
| } | } | ||||||
|  |  | ||||||
| class ComposeSettingsSheet extends HookWidget { | class ComposeSettingsSheet extends HookWidget { | ||||||
|   final TextEditingController titleController; |  | ||||||
|   final TextEditingController descriptionController; |  | ||||||
|   final ValueNotifier<int> visibility; |   final ValueNotifier<int> visibility; | ||||||
|   final VoidCallback? onVisibilityChanged; |   final VoidCallback? onVisibilityChanged; | ||||||
|   final StringTagController tagsController; |   final StringTagController tagsController; | ||||||
| @@ -108,8 +106,6 @@ class ComposeSettingsSheet extends HookWidget { | |||||||
|  |  | ||||||
|   const ComposeSettingsSheet({ |   const ComposeSettingsSheet({ | ||||||
|     super.key, |     super.key, | ||||||
|     required this.titleController, |  | ||||||
|     required this.descriptionController, |  | ||||||
|     required this.visibility, |     required this.visibility, | ||||||
|     this.onVisibilityChanged, |     this.onVisibilityChanged, | ||||||
|     required this.tagsController, |     required this.tagsController, | ||||||
| @@ -216,39 +212,6 @@ class ComposeSettingsSheet extends HookWidget { | |||||||
|           crossAxisAlignment: CrossAxisAlignment.start, |           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|           spacing: 16, |           spacing: 16, | ||||||
|           children: [ |           children: [ | ||||||
|             // Title field |  | ||||||
|             TextField( |  | ||||||
|               controller: titleController, |  | ||||||
|               decoration: InputDecoration( |  | ||||||
|                 labelText: 'postTitle'.tr(), |  | ||||||
|                 hintText: 'postTitle'.tr(), |  | ||||||
|                 border: OutlineInputBorder( |  | ||||||
|                   borderRadius: BorderRadius.circular(12), |  | ||||||
|                 ), |  | ||||||
|                 contentPadding: const EdgeInsets.all(16), |  | ||||||
|               ), |  | ||||||
|               style: theme.textTheme.titleMedium, |  | ||||||
|               onTapOutside: |  | ||||||
|                   (_) => FocusManager.instance.primaryFocus?.unfocus(), |  | ||||||
|             ), |  | ||||||
|  |  | ||||||
|             // Description field |  | ||||||
|             TextField( |  | ||||||
|               controller: descriptionController, |  | ||||||
|               decoration: InputDecoration( |  | ||||||
|                 labelText: 'postDescription'.tr(), |  | ||||||
|                 hintText: 'postDescription'.tr(), |  | ||||||
|                 border: OutlineInputBorder( |  | ||||||
|                   borderRadius: BorderRadius.circular(12), |  | ||||||
|                 ), |  | ||||||
|                 contentPadding: const EdgeInsets.all(16), |  | ||||||
|               ), |  | ||||||
|               style: theme.textTheme.bodyMedium, |  | ||||||
|               maxLines: 3, |  | ||||||
|               onTapOutside: |  | ||||||
|                   (_) => FocusManager.instance.primaryFocus?.unfocus(), |  | ||||||
|             ), |  | ||||||
|  |  | ||||||
|             // Tags field |             // Tags field | ||||||
|             TextFieldTags( |             TextFieldTags( | ||||||
|               textfieldTagsController: tagsController, |               textfieldTagsController: tagsController, | ||||||
|   | |||||||
| @@ -689,7 +689,7 @@ class ComposeLogic { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   static void handleKeyPress( |   static void handleKeyPress( | ||||||
|     RawKeyEvent event, |     KeyEvent event, | ||||||
|     ComposeState state, |     ComposeState state, | ||||||
|     WidgetRef ref, |     WidgetRef ref, | ||||||
|     BuildContext context, { |     BuildContext context, { | ||||||
| @@ -701,7 +701,9 @@ class ComposeLogic { | |||||||
|  |  | ||||||
|     final isPaste = event.logicalKey == LogicalKeyboardKey.keyV; |     final isPaste = event.logicalKey == LogicalKeyboardKey.keyV; | ||||||
|     final isSave = event.logicalKey == LogicalKeyboardKey.keyS; |     final isSave = event.logicalKey == LogicalKeyboardKey.keyS; | ||||||
|     final isModifierPressed = event.isMetaPressed || event.isControlPressed; |     final isModifierPressed = | ||||||
|  |         HardwareKeyboard.instance.isMetaPressed || | ||||||
|  |         HardwareKeyboard.instance.isControlPressed; | ||||||
|     final isSubmit = event.logicalKey == LogicalKeyboardKey.enter; |     final isSubmit = event.logicalKey == LogicalKeyboardKey.enter; | ||||||
|  |  | ||||||
|     if (isPaste && isModifierPressed) { |     if (isPaste && isModifierPressed) { | ||||||
|   | |||||||
| @@ -63,6 +63,7 @@ class ComposeToolbar extends HookConsumerWidget { | |||||||
|  |  | ||||||
|     return Material( |     return Material( | ||||||
|       elevation: 4, |       elevation: 4, | ||||||
|  |       color: Theme.of(context).colorScheme.surfaceContainerLow, | ||||||
|       child: Center( |       child: Center( | ||||||
|         child: ConstrainedBox( |         child: ConstrainedBox( | ||||||
|           constraints: const BoxConstraints(maxWidth: 560), |           constraints: const BoxConstraints(maxWidth: 560), | ||||||
|   | |||||||
| @@ -547,7 +547,9 @@ class PostItem extends HookConsumerWidget { | |||||||
|           ...((item.meta!['embeds'] as List<dynamic>).map( |           ...((item.meta!['embeds'] as List<dynamic>).map( | ||||||
|             (embedData) => switch (embedData['type']) { |             (embedData) => switch (embedData['type']) { | ||||||
|               'link' => EmbedLinkWidget( |               'link' => EmbedLinkWidget( | ||||||
|                 link: SnEmbedLink.fromJson(embedData as Map<String, dynamic>), |                 link: SnScrappedLink.fromJson( | ||||||
|  |                   embedData as Map<String, dynamic>, | ||||||
|  |                 ), | ||||||
|                 maxWidth: math.min( |                 maxWidth: math.min( | ||||||
|                   MediaQuery.of(context).size.width, |                   MediaQuery.of(context).size.width, | ||||||
|                   kWideScreenWidth, |                   kWideScreenWidth, | ||||||
| @@ -770,7 +772,7 @@ class PostReplyPreview extends HookConsumerWidget { | |||||||
|     final posts = useState<List<SnPost>>([]); |     final posts = useState<List<SnPost>>([]); | ||||||
|     final loading = useState(false); |     final loading = useState(false); | ||||||
|  |  | ||||||
|     Future<void> fetchMoreReplies({int pageSize = 1}) async { |     Future<void> fetchMoreReplies({int pageSize = 3}) async { | ||||||
|       final client = ref.read(apiClientProvider); |       final client = ref.read(apiClientProvider); | ||||||
|       loading.value = true; |       loading.value = true; | ||||||
|  |  | ||||||
| @@ -877,38 +879,40 @@ class PostReplyPreview extends HookConsumerWidget { | |||||||
|                   ), |                   ), | ||||||
|               ], |               ], | ||||||
|             ) |             ) | ||||||
|             : featuredReply!.when( |             : (featuredReply!).map( | ||||||
|               data: |               data: | ||||||
|                   (value) => Row( |                   (data) => Row( | ||||||
|                     crossAxisAlignment: CrossAxisAlignment.center, |                     crossAxisAlignment: CrossAxisAlignment.center, | ||||||
|                     spacing: 8, |                     spacing: 8, | ||||||
|                     children: [ |                     children: [ | ||||||
|                       ProfilePictureWidget( |                       ProfilePictureWidget( | ||||||
|                         file: value?.publisher.picture, |                         file: data.value?.publisher.picture, | ||||||
|                         radius: 12, |                         radius: 12, | ||||||
|                       ).padding(top: 4), |                       ).padding(top: 4), | ||||||
|                       if (value?.content?.isNotEmpty ?? false) |                       if (data.value?.content?.isNotEmpty ?? false) | ||||||
|                         Expanded( |                         Expanded( | ||||||
|                           child: MarkdownTextContent(content: value!.content!), |                           child: MarkdownTextContent( | ||||||
|  |                             content: data.value!.content!, | ||||||
|  |                           ), | ||||||
|                         ) |                         ) | ||||||
|                       else |                       else | ||||||
|                         Expanded( |                         Expanded( | ||||||
|                           child: Text( |                           child: Text( | ||||||
|                             'postHasAttachments', |                             'postHasAttachments', | ||||||
|                           ).plural(value?.attachments.length ?? 0), |                           ).plural(data.value?.attachments.length ?? 0), | ||||||
|                         ), |                         ), | ||||||
|                     ], |                     ], | ||||||
|                   ), |                   ), | ||||||
|               error: |               error: | ||||||
|                   (error, _) => Row( |                   (e) => Row( | ||||||
|                     spacing: 8, |                     spacing: 8, | ||||||
|                     children: [ |                     children: [ | ||||||
|                       const Icon(Symbols.close, size: 18), |                       const Icon(Symbols.close, size: 18), | ||||||
|                       Text(error.toString()), |                       Text(e.error.toString()), | ||||||
|                     ], |                     ], | ||||||
|                   ), |                   ), | ||||||
|               loading: |               loading: | ||||||
|                   () => Row( |                   (_) => Row( | ||||||
|                     spacing: 8, |                     spacing: 8, | ||||||
|                     children: [ |                     children: [ | ||||||
|                       SizedBox( |                       SizedBox( | ||||||
| @@ -939,7 +943,6 @@ class PostReplyPreview extends HookConsumerWidget { | |||||||
|                 children: [ |                 children: [ | ||||||
|                   Text('repliesCount') |                   Text('repliesCount') | ||||||
|                       .plural(parent.repliesCount) |                       .plural(parent.repliesCount) | ||||||
|                       .tr() |  | ||||||
|                       .fontSize(15) |                       .fontSize(15) | ||||||
|                       .bold() |                       .bold() | ||||||
|                       .padding(horizontal: 5), |                       .padding(horizontal: 5), | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ class PostListNotifier extends _$PostListNotifier | |||||||
|   static const int _pageSize = 20; |   static const int _pageSize = 20; | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Future<CursorPagingData<SnPost>> build(String? pubName) { |   Future<CursorPagingData<SnPost>> build(String? pubName, int? type) { | ||||||
|     return fetch(cursor: null); |     return fetch(cursor: null); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -28,6 +28,7 @@ class PostListNotifier extends _$PostListNotifier | |||||||
|       'offset': offset, |       'offset': offset, | ||||||
|       'take': _pageSize, |       'take': _pageSize, | ||||||
|       if (pubName != null) 'pub': pubName, |       if (pubName != null) 'pub': pubName, | ||||||
|  |       if (type != null) 'type': type, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     final response = await client.get( |     final response = await client.get( | ||||||
| @@ -60,6 +61,7 @@ enum PostItemType { | |||||||
|  |  | ||||||
| class SliverPostList extends HookConsumerWidget { | class SliverPostList extends HookConsumerWidget { | ||||||
|   final String? pubName; |   final String? pubName; | ||||||
|  |   final int? type; | ||||||
|   final PostItemType itemType; |   final PostItemType itemType; | ||||||
|   final Color? backgroundColor; |   final Color? backgroundColor; | ||||||
|   final EdgeInsets? padding; |   final EdgeInsets? padding; | ||||||
| @@ -70,6 +72,7 @@ class SliverPostList extends HookConsumerWidget { | |||||||
|   const SliverPostList({ |   const SliverPostList({ | ||||||
|     super.key, |     super.key, | ||||||
|     this.pubName, |     this.pubName, | ||||||
|  |     this.type, | ||||||
|     this.itemType = PostItemType.regular, |     this.itemType = PostItemType.regular, | ||||||
|     this.backgroundColor, |     this.backgroundColor, | ||||||
|     this.padding, |     this.padding, | ||||||
| @@ -81,9 +84,9 @@ class SliverPostList extends HookConsumerWidget { | |||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context, WidgetRef ref) { |   Widget build(BuildContext context, WidgetRef ref) { | ||||||
|     return PagingHelperSliverView( |     return PagingHelperSliverView( | ||||||
|       provider: postListNotifierProvider(pubName), |       provider: postListNotifierProvider(pubName, type), | ||||||
|       futureRefreshable: postListNotifierProvider(pubName).future, |       futureRefreshable: postListNotifierProvider(pubName, type).future, | ||||||
|       notifierRefreshable: postListNotifierProvider(pubName).notifier, |       notifierRefreshable: postListNotifierProvider(pubName, type).notifier, | ||||||
|       contentBuilder: |       contentBuilder: | ||||||
|           (data, widgetCount, endItemView) => SliverList.builder( |           (data, widgetCount, endItemView) => SliverList.builder( | ||||||
|             itemCount: widgetCount, |             itemCount: widgetCount, | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ part of 'post_list.dart'; | |||||||
| // RiverpodGenerator | // RiverpodGenerator | ||||||
| // ************************************************************************** | // ************************************************************************** | ||||||
|  |  | ||||||
| String _$postListNotifierHash() => r'2e4fb36123d3f97ac1edf9945043251d4eb519a2'; | String _$postListNotifierHash() => r'c7c82c8cedf6649ac0806bbbfea148dfa1422fc0'; | ||||||
|  |  | ||||||
| /// Copied from Dart SDK | /// Copied from Dart SDK | ||||||
| class _SystemHash { | class _SystemHash { | ||||||
| @@ -32,8 +32,9 @@ class _SystemHash { | |||||||
| abstract class _$PostListNotifier | abstract class _$PostListNotifier | ||||||
|     extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPost>> { |     extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPost>> { | ||||||
|   late final String? pubName; |   late final String? pubName; | ||||||
|  |   late final int? type; | ||||||
|  |  | ||||||
|   FutureOr<CursorPagingData<SnPost>> build(String? pubName); |   FutureOr<CursorPagingData<SnPost>> build(String? pubName, int? type); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// See also [PostListNotifier]. | /// See also [PostListNotifier]. | ||||||
| @@ -47,15 +48,15 @@ class PostListNotifierFamily | |||||||
|   const PostListNotifierFamily(); |   const PostListNotifierFamily(); | ||||||
|  |  | ||||||
|   /// See also [PostListNotifier]. |   /// See also [PostListNotifier]. | ||||||
|   PostListNotifierProvider call(String? pubName) { |   PostListNotifierProvider call(String? pubName, int? type) { | ||||||
|     return PostListNotifierProvider(pubName); |     return PostListNotifierProvider(pubName, type); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   PostListNotifierProvider getProviderOverride( |   PostListNotifierProvider getProviderOverride( | ||||||
|     covariant PostListNotifierProvider provider, |     covariant PostListNotifierProvider provider, | ||||||
|   ) { |   ) { | ||||||
|     return call(provider.pubName); |     return call(provider.pubName, provider.type); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static const Iterable<ProviderOrFamily>? _dependencies = null; |   static const Iterable<ProviderOrFamily>? _dependencies = null; | ||||||
| @@ -81,9 +82,12 @@ class PostListNotifierProvider | |||||||
|           CursorPagingData<SnPost> |           CursorPagingData<SnPost> | ||||||
|         > { |         > { | ||||||
|   /// See also [PostListNotifier]. |   /// See also [PostListNotifier]. | ||||||
|   PostListNotifierProvider(String? pubName) |   PostListNotifierProvider(String? pubName, int? type) | ||||||
|     : this._internal( |     : this._internal( | ||||||
|         () => PostListNotifier()..pubName = pubName, |         () => | ||||||
|  |             PostListNotifier() | ||||||
|  |               ..pubName = pubName | ||||||
|  |               ..type = type, | ||||||
|         from: postListNotifierProvider, |         from: postListNotifierProvider, | ||||||
|         name: r'postListNotifierProvider', |         name: r'postListNotifierProvider', | ||||||
|         debugGetCreateSourceHash: |         debugGetCreateSourceHash: | ||||||
| @@ -94,6 +98,7 @@ class PostListNotifierProvider | |||||||
|         allTransitiveDependencies: |         allTransitiveDependencies: | ||||||
|             PostListNotifierFamily._allTransitiveDependencies, |             PostListNotifierFamily._allTransitiveDependencies, | ||||||
|         pubName: pubName, |         pubName: pubName, | ||||||
|  |         type: type, | ||||||
|       ); |       ); | ||||||
|  |  | ||||||
|   PostListNotifierProvider._internal( |   PostListNotifierProvider._internal( | ||||||
| @@ -104,15 +109,17 @@ class PostListNotifierProvider | |||||||
|     required super.debugGetCreateSourceHash, |     required super.debugGetCreateSourceHash, | ||||||
|     required super.from, |     required super.from, | ||||||
|     required this.pubName, |     required this.pubName, | ||||||
|  |     required this.type, | ||||||
|   }) : super.internal(); |   }) : super.internal(); | ||||||
|  |  | ||||||
|   final String? pubName; |   final String? pubName; | ||||||
|  |   final int? type; | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   FutureOr<CursorPagingData<SnPost>> runNotifierBuild( |   FutureOr<CursorPagingData<SnPost>> runNotifierBuild( | ||||||
|     covariant PostListNotifier notifier, |     covariant PostListNotifier notifier, | ||||||
|   ) { |   ) { | ||||||
|     return notifier.build(pubName); |     return notifier.build(pubName, type); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -120,13 +127,17 @@ class PostListNotifierProvider | |||||||
|     return ProviderOverride( |     return ProviderOverride( | ||||||
|       origin: this, |       origin: this, | ||||||
|       override: PostListNotifierProvider._internal( |       override: PostListNotifierProvider._internal( | ||||||
|         () => create()..pubName = pubName, |         () => | ||||||
|  |             create() | ||||||
|  |               ..pubName = pubName | ||||||
|  |               ..type = type, | ||||||
|         from: from, |         from: from, | ||||||
|         name: null, |         name: null, | ||||||
|         dependencies: null, |         dependencies: null, | ||||||
|         allTransitiveDependencies: null, |         allTransitiveDependencies: null, | ||||||
|         debugGetCreateSourceHash: null, |         debugGetCreateSourceHash: null, | ||||||
|         pubName: pubName, |         pubName: pubName, | ||||||
|  |         type: type, | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| @@ -142,13 +153,16 @@ class PostListNotifierProvider | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   bool operator ==(Object other) { |   bool operator ==(Object other) { | ||||||
|     return other is PostListNotifierProvider && other.pubName == pubName; |     return other is PostListNotifierProvider && | ||||||
|  |         other.pubName == pubName && | ||||||
|  |         other.type == type; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   int get hashCode { |   int get hashCode { | ||||||
|     var hash = _SystemHash.combine(0, runtimeType.hashCode); |     var hash = _SystemHash.combine(0, runtimeType.hashCode); | ||||||
|     hash = _SystemHash.combine(hash, pubName.hashCode); |     hash = _SystemHash.combine(hash, pubName.hashCode); | ||||||
|  |     hash = _SystemHash.combine(hash, type.hashCode); | ||||||
|  |  | ||||||
|     return _SystemHash.finish(hash); |     return _SystemHash.finish(hash); | ||||||
|   } |   } | ||||||
| @@ -160,6 +174,9 @@ mixin PostListNotifierRef | |||||||
|     on AutoDisposeAsyncNotifierProviderRef<CursorPagingData<SnPost>> { |     on AutoDisposeAsyncNotifierProviderRef<CursorPagingData<SnPost>> { | ||||||
|   /// The parameter `pubName` of this provider. |   /// The parameter `pubName` of this provider. | ||||||
|   String? get pubName; |   String? get pubName; | ||||||
|  |  | ||||||
|  |   /// The parameter `type` of this provider. | ||||||
|  |   int? get type; | ||||||
| } | } | ||||||
|  |  | ||||||
| class _PostListNotifierProviderElement | class _PostListNotifierProviderElement | ||||||
| @@ -173,6 +190,8 @@ class _PostListNotifierProviderElement | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   String? get pubName => (origin as PostListNotifierProvider).pubName; |   String? get pubName => (origin as PostListNotifierProvider).pubName; | ||||||
|  |   @override | ||||||
|  |   int? get type => (origin as PostListNotifierProvider).type; | ||||||
| } | } | ||||||
|  |  | ||||||
| // ignore_for_file: type=lint | // ignore_for_file: type=lint | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user