✨ Award history
This commit is contained in:
		| @@ -124,3 +124,21 @@ sealed class SnPostEmbedView with _$SnPostEmbedView { | |||||||
|   factory SnPostEmbedView.fromJson(Map<String, dynamic> json) => |   factory SnPostEmbedView.fromJson(Map<String, dynamic> json) => | ||||||
|       _$SnPostEmbedViewFromJson(json); |       _$SnPostEmbedViewFromJson(json); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @freezed | ||||||
|  | sealed class SnPostAward with _$SnPostAward { | ||||||
|  |   const factory SnPostAward({ | ||||||
|  |     required String id, | ||||||
|  |     required double amount, | ||||||
|  |     required int attitude, | ||||||
|  |     String? message, | ||||||
|  |     required String postId, | ||||||
|  |     required String accountId, | ||||||
|  |     @Default(null) DateTime? createdAt, | ||||||
|  |     @Default(null) DateTime? updatedAt, | ||||||
|  |     DateTime? deletedAt, | ||||||
|  |   }) = _SnPostAward; | ||||||
|  |  | ||||||
|  |   factory SnPostAward.fromJson(Map<String, dynamic> json) => | ||||||
|  |       _$SnPostAwardFromJson(json); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1617,6 +1617,287 @@ as PostEmbedViewRenderer, | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /// @nodoc | ||||||
|  | mixin _$SnPostAward { | ||||||
|  |  | ||||||
|  |  String get id; double get amount; int get attitude; String? get message; String get postId; String get accountId; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; | ||||||
|  | /// Create a copy of SnPostAward | ||||||
|  | /// with the given fields replaced by the non-null parameter values. | ||||||
|  | @JsonKey(includeFromJson: false, includeToJson: false) | ||||||
|  | @pragma('vm:prefer-inline') | ||||||
|  | $SnPostAwardCopyWith<SnPostAward> get copyWith => _$SnPostAwardCopyWithImpl<SnPostAward>(this as SnPostAward, _$identity); | ||||||
|  |  | ||||||
|  |   /// Serializes this SnPostAward to a JSON map. | ||||||
|  |   Map<String, dynamic> toJson(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @override | ||||||
|  | bool operator ==(Object other) { | ||||||
|  |   return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostAward&&(identical(other.id, id) || other.id == id)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.message, message) || other.message == message)&&(identical(other.postId, postId) || other.postId == postId)&&(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,amount,attitude,message,postId,accountId,createdAt,updatedAt,deletedAt); | ||||||
|  |  | ||||||
|  | @override | ||||||
|  | String toString() { | ||||||
|  |   return 'SnPostAward(id: $id, amount: $amount, attitude: $attitude, message: $message, postId: $postId, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// @nodoc | ||||||
|  | abstract mixin class $SnPostAwardCopyWith<$Res>  { | ||||||
|  |   factory $SnPostAwardCopyWith(SnPostAward value, $Res Function(SnPostAward) _then) = _$SnPostAwardCopyWithImpl; | ||||||
|  | @useResult | ||||||
|  | $Res call({ | ||||||
|  |  String id, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt | ||||||
|  | }); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  | /// @nodoc | ||||||
|  | class _$SnPostAwardCopyWithImpl<$Res> | ||||||
|  |     implements $SnPostAwardCopyWith<$Res> { | ||||||
|  |   _$SnPostAwardCopyWithImpl(this._self, this._then); | ||||||
|  |  | ||||||
|  |   final SnPostAward _self; | ||||||
|  |   final $Res Function(SnPostAward) _then; | ||||||
|  |  | ||||||
|  | /// Create a copy of SnPostAward | ||||||
|  | /// with the given fields replaced by the non-null parameter values. | ||||||
|  | @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? amount = null,Object? attitude = null,Object? message = freezed,Object? postId = null,Object? accountId = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,}) { | ||||||
|  |   return _then(_self.copyWith( | ||||||
|  | id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||||
|  | as String,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable | ||||||
|  | as double,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable | ||||||
|  | as int,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable | ||||||
|  | as String?,postId: null == postId ? _self.postId : postId // ignore: cast_nullable_to_non_nullable | ||||||
|  | as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable | ||||||
|  | as String,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||||
|  | as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable | ||||||
|  | as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable | ||||||
|  | as DateTime?, | ||||||
|  |   )); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /// Adds pattern-matching-related methods to [SnPostAward]. | ||||||
|  | extension SnPostAwardPatterns on SnPostAward { | ||||||
|  | /// 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( _SnPostAward value)?  $default,{required TResult orElse(),}){ | ||||||
|  | final _that = this; | ||||||
|  | switch (_that) { | ||||||
|  | case _SnPostAward() 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( _SnPostAward value)  $default,){ | ||||||
|  | final _that = this; | ||||||
|  | switch (_that) { | ||||||
|  | case _SnPostAward(): | ||||||
|  | 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( _SnPostAward value)?  $default,){ | ||||||
|  | final _that = this; | ||||||
|  | switch (_that) { | ||||||
|  | case _SnPostAward() 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( String id,  double amount,  int attitude,  String? message,  String postId,  String accountId,  DateTime? createdAt,  DateTime? updatedAt,  DateTime? deletedAt)?  $default,{required TResult orElse(),}) {final _that = this; | ||||||
|  | switch (_that) { | ||||||
|  | case _SnPostAward() when $default != null: | ||||||
|  | return $default(_that.id,_that.amount,_that.attitude,_that.message,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);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( String id,  double amount,  int attitude,  String? message,  String postId,  String accountId,  DateTime? createdAt,  DateTime? updatedAt,  DateTime? deletedAt)  $default,) {final _that = this; | ||||||
|  | switch (_that) { | ||||||
|  | case _SnPostAward(): | ||||||
|  | return $default(_that.id,_that.amount,_that.attitude,_that.message,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);} | ||||||
|  | } | ||||||
|  | /// 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( String id,  double amount,  int attitude,  String? message,  String postId,  String accountId,  DateTime? createdAt,  DateTime? updatedAt,  DateTime? deletedAt)?  $default,) {final _that = this; | ||||||
|  | switch (_that) { | ||||||
|  | case _SnPostAward() when $default != null: | ||||||
|  | return $default(_that.id,_that.amount,_that.attitude,_that.message,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: | ||||||
|  |   return null; | ||||||
|  |  | ||||||
|  | } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// @nodoc | ||||||
|  | @JsonSerializable() | ||||||
|  |  | ||||||
|  | class _SnPostAward implements SnPostAward { | ||||||
|  |   const _SnPostAward({required this.id, required this.amount, required this.attitude, this.message, required this.postId, required this.accountId, this.createdAt = null, this.updatedAt = null, this.deletedAt}); | ||||||
|  |   factory _SnPostAward.fromJson(Map<String, dynamic> json) => _$SnPostAwardFromJson(json); | ||||||
|  |  | ||||||
|  | @override final  String id; | ||||||
|  | @override final  double amount; | ||||||
|  | @override final  int attitude; | ||||||
|  | @override final  String? message; | ||||||
|  | @override final  String postId; | ||||||
|  | @override final  String accountId; | ||||||
|  | @override@JsonKey() final  DateTime? createdAt; | ||||||
|  | @override@JsonKey() final  DateTime? updatedAt; | ||||||
|  | @override final  DateTime? deletedAt; | ||||||
|  |  | ||||||
|  | /// Create a copy of SnPostAward | ||||||
|  | /// with the given fields replaced by the non-null parameter values. | ||||||
|  | @override @JsonKey(includeFromJson: false, includeToJson: false) | ||||||
|  | @pragma('vm:prefer-inline') | ||||||
|  | _$SnPostAwardCopyWith<_SnPostAward> get copyWith => __$SnPostAwardCopyWithImpl<_SnPostAward>(this, _$identity); | ||||||
|  |  | ||||||
|  | @override | ||||||
|  | Map<String, dynamic> toJson() { | ||||||
|  |   return _$SnPostAwardToJson(this, ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @override | ||||||
|  | bool operator ==(Object other) { | ||||||
|  |   return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostAward&&(identical(other.id, id) || other.id == id)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.message, message) || other.message == message)&&(identical(other.postId, postId) || other.postId == postId)&&(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,amount,attitude,message,postId,accountId,createdAt,updatedAt,deletedAt); | ||||||
|  |  | ||||||
|  | @override | ||||||
|  | String toString() { | ||||||
|  |   return 'SnPostAward(id: $id, amount: $amount, attitude: $attitude, message: $message, postId: $postId, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// @nodoc | ||||||
|  | abstract mixin class _$SnPostAwardCopyWith<$Res> implements $SnPostAwardCopyWith<$Res> { | ||||||
|  |   factory _$SnPostAwardCopyWith(_SnPostAward value, $Res Function(_SnPostAward) _then) = __$SnPostAwardCopyWithImpl; | ||||||
|  | @override @useResult | ||||||
|  | $Res call({ | ||||||
|  |  String id, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt | ||||||
|  | }); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  | /// @nodoc | ||||||
|  | class __$SnPostAwardCopyWithImpl<$Res> | ||||||
|  |     implements _$SnPostAwardCopyWith<$Res> { | ||||||
|  |   __$SnPostAwardCopyWithImpl(this._self, this._then); | ||||||
|  |  | ||||||
|  |   final _SnPostAward _self; | ||||||
|  |   final $Res Function(_SnPostAward) _then; | ||||||
|  |  | ||||||
|  | /// Create a copy of SnPostAward | ||||||
|  | /// with the given fields replaced by the non-null parameter values. | ||||||
|  | @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? amount = null,Object? attitude = null,Object? message = freezed,Object? postId = null,Object? accountId = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,}) { | ||||||
|  |   return _then(_SnPostAward( | ||||||
|  | id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||||
|  | as String,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable | ||||||
|  | as double,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable | ||||||
|  | as int,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable | ||||||
|  | as String?,postId: null == postId ? _self.postId : postId // ignore: cast_nullable_to_non_nullable | ||||||
|  | as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable | ||||||
|  | as String,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||||
|  | as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable | ||||||
|  | as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable | ||||||
|  | as DateTime?, | ||||||
|  |   )); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // dart format on | // dart format on | ||||||
|   | |||||||
| @@ -196,3 +196,37 @@ Map<String, dynamic> _$SnPostEmbedViewToJson(_SnPostEmbedView instance) => | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
| const _$PostEmbedViewRendererEnumMap = {PostEmbedViewRenderer.webView: 0}; | const _$PostEmbedViewRendererEnumMap = {PostEmbedViewRenderer.webView: 0}; | ||||||
|  |  | ||||||
|  | _SnPostAward _$SnPostAwardFromJson(Map<String, dynamic> json) => _SnPostAward( | ||||||
|  |   id: json['id'] as String, | ||||||
|  |   amount: (json['amount'] as num).toDouble(), | ||||||
|  |   attitude: (json['attitude'] as num).toInt(), | ||||||
|  |   message: json['message'] as String?, | ||||||
|  |   postId: json['post_id'] as String, | ||||||
|  |   accountId: json['account_id'] as String, | ||||||
|  |   createdAt: | ||||||
|  |       json['created_at'] == null | ||||||
|  |           ? null | ||||||
|  |           : DateTime.parse(json['created_at'] as String), | ||||||
|  |   updatedAt: | ||||||
|  |       json['updated_at'] == null | ||||||
|  |           ? null | ||||||
|  |           : DateTime.parse(json['updated_at'] as String), | ||||||
|  |   deletedAt: | ||||||
|  |       json['deleted_at'] == null | ||||||
|  |           ? null | ||||||
|  |           : DateTime.parse(json['deleted_at'] as String), | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | Map<String, dynamic> _$SnPostAwardToJson(_SnPostAward instance) => | ||||||
|  |     <String, dynamic>{ | ||||||
|  |       'id': instance.id, | ||||||
|  |       'amount': instance.amount, | ||||||
|  |       'attitude': instance.attitude, | ||||||
|  |       'message': instance.message, | ||||||
|  |       'post_id': instance.postId, | ||||||
|  |       'account_id': instance.accountId, | ||||||
|  |       'created_at': instance.createdAt?.toIso8601String(), | ||||||
|  |       'updated_at': instance.updatedAt?.toIso8601String(), | ||||||
|  |       'deleted_at': instance.deletedAt?.toIso8601String(), | ||||||
|  |     }; | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ import 'package:island/widgets/alert.dart'; | |||||||
| import 'package:island/widgets/app_scaffold.dart'; | import 'package:island/widgets/app_scaffold.dart'; | ||||||
| import 'package:island/widgets/extended_refresh_indicator.dart'; | import 'package:island/widgets/extended_refresh_indicator.dart'; | ||||||
| import 'package:island/widgets/post/post_item.dart'; | import 'package:island/widgets/post/post_item.dart'; | ||||||
|  | import 'package:island/widgets/post/post_award_history_sheet.dart'; | ||||||
| import 'package:island/widgets/post/post_pin_sheet.dart'; | import 'package:island/widgets/post/post_pin_sheet.dart'; | ||||||
| import 'package:island/widgets/post/post_quick_reply.dart'; | import 'package:island/widgets/post/post_quick_reply.dart'; | ||||||
| import 'package:island/widgets/post/post_replies.dart'; | import 'package:island/widgets/post/post_replies.dart'; | ||||||
| @@ -273,6 +274,13 @@ class PostActionButtons extends HookConsumerWidget { | |||||||
|     actions.add( |     actions.add( | ||||||
|       FilledButton.tonalIcon( |       FilledButton.tonalIcon( | ||||||
|         onPressed: () {}, |         onPressed: () {}, | ||||||
|  |         onLongPress: () { | ||||||
|  |           showModalBottomSheet( | ||||||
|  |             context: context, | ||||||
|  |             isScrollControlled: true, | ||||||
|  |             builder: (context) => PostAwardHistorySheet(postId: post.id), | ||||||
|  |           ); | ||||||
|  |         }, | ||||||
|         icon: const Icon(Symbols.star), |         icon: const Icon(Symbols.star), | ||||||
|         label: |         label: | ||||||
|             post.awardedScore > 0 |             post.awardedScore > 0 | ||||||
|   | |||||||
							
								
								
									
										164
									
								
								lib/widgets/post/post_award_history_sheet.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								lib/widgets/post/post_award_history_sheet.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||||
|  | import 'package:island/models/post.dart'; | ||||||
|  | import 'package:island/pods/network.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 'post_award_history_sheet.g.dart'; | ||||||
|  |  | ||||||
|  | @riverpod | ||||||
|  | class PostAwardListNotifier extends _$PostAwardListNotifier | ||||||
|  |     with CursorPagingNotifierMixin<SnPostAward> { | ||||||
|  |   static const int _pageSize = 20; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Future<CursorPagingData<SnPostAward>> build({required String postId}) { | ||||||
|  |     return fetch(cursor: null); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Future<CursorPagingData<SnPostAward>> 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( | ||||||
|  |       '/sphere/posts/$postId/awards', | ||||||
|  |       queryParameters: queryParams, | ||||||
|  |     ); | ||||||
|  |     final total = int.parse(response.headers.value('X-Total') ?? '0'); | ||||||
|  |     final List<dynamic> data = response.data; | ||||||
|  |     final awards = data.map((json) => SnPostAward.fromJson(json)).toList(); | ||||||
|  |  | ||||||
|  |     final hasMore = offset + awards.length < total; | ||||||
|  |     final nextCursor = hasMore ? (offset + awards.length).toString() : null; | ||||||
|  |  | ||||||
|  |     return CursorPagingData( | ||||||
|  |       items: awards, | ||||||
|  |       hasMore: hasMore, | ||||||
|  |       nextCursor: nextCursor, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class PostAwardHistorySheet extends HookConsumerWidget { | ||||||
|  |   final String postId; | ||||||
|  |  | ||||||
|  |   const PostAwardHistorySheet({super.key, required this.postId}); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context, WidgetRef ref) { | ||||||
|  |     final provider = postAwardListNotifierProvider(postId: postId); | ||||||
|  |  | ||||||
|  |     return SheetScaffold( | ||||||
|  |       titleText: 'Award History', | ||||||
|  |       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 award = data.items[index]; | ||||||
|  |                 return Column( | ||||||
|  |                   children: [ | ||||||
|  |                     PostAwardItem(award: award), | ||||||
|  |                     const Divider(height: 1), | ||||||
|  |                   ], | ||||||
|  |                 ); | ||||||
|  |               }, | ||||||
|  |             ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class PostAwardItem extends StatelessWidget { | ||||||
|  |   final SnPostAward award; | ||||||
|  |  | ||||||
|  |   const PostAwardItem({super.key, required this.award}); | ||||||
|  |  | ||||||
|  |   String _getAttitudeText(int attitude) { | ||||||
|  |     switch (attitude) { | ||||||
|  |       case 0: | ||||||
|  |         return 'Positive'; | ||||||
|  |       case 2: | ||||||
|  |         return 'Negative'; | ||||||
|  |       default: | ||||||
|  |         return 'Neutral'; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Color _getAttitudeColor(int attitude, BuildContext context) { | ||||||
|  |     switch (attitude) { | ||||||
|  |       case 0: | ||||||
|  |         return Colors.green; | ||||||
|  |       case 2: | ||||||
|  |         return Colors.red; | ||||||
|  |       default: | ||||||
|  |         return Theme.of(context).colorScheme.onSurfaceVariant; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return ListTile( | ||||||
|  |       leading: CircleAvatar( | ||||||
|  |         backgroundColor: _getAttitudeColor( | ||||||
|  |           award.attitude, | ||||||
|  |           context, | ||||||
|  |         ).withOpacity(0.1), | ||||||
|  |         child: Icon( | ||||||
|  |           award.attitude == 0 | ||||||
|  |               ? Icons.thumb_up | ||||||
|  |               : award.attitude == 2 | ||||||
|  |               ? Icons.thumb_down | ||||||
|  |               : Icons.thumbs_up_down, | ||||||
|  |           color: _getAttitudeColor(award.attitude, context), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |       title: Text( | ||||||
|  |         '${award.amount} pts', | ||||||
|  |         style: Theme.of( | ||||||
|  |           context, | ||||||
|  |         ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600), | ||||||
|  |       ), | ||||||
|  |       subtitle: Column( | ||||||
|  |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |         children: [ | ||||||
|  |           Text( | ||||||
|  |             _getAttitudeText(award.attitude), | ||||||
|  |             style: TextStyle( | ||||||
|  |               color: _getAttitudeColor(award.attitude, context), | ||||||
|  |               fontWeight: FontWeight.w500, | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           if (award.message != null && award.message!.isNotEmpty) ...[ | ||||||
|  |             const SizedBox(height: 4), | ||||||
|  |             Text(award.message!, style: Theme.of(context).textTheme.bodyMedium), | ||||||
|  |           ], | ||||||
|  |           const SizedBox(height: 2), | ||||||
|  |           if (award.createdAt != null) ...[ | ||||||
|  |             const SizedBox(height: 2), | ||||||
|  |             Text( | ||||||
|  |               award.createdAt!.toLocal().toString().split('.')[0], | ||||||
|  |               style: Theme.of(context).textTheme.bodySmall?.copyWith( | ||||||
|  |                 color: Theme.of(context).colorScheme.onSurfaceVariant, | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |       isThreeLine: award.message != null && award.message!.isNotEmpty, | ||||||
|  |       contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										180
									
								
								lib/widgets/post/post_award_history_sheet.g.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								lib/widgets/post/post_award_history_sheet.g.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | |||||||
|  | // GENERATED CODE - DO NOT MODIFY BY HAND | ||||||
|  |  | ||||||
|  | part of 'post_award_history_sheet.dart'; | ||||||
|  |  | ||||||
|  | // ************************************************************************** | ||||||
|  | // RiverpodGenerator | ||||||
|  | // ************************************************************************** | ||||||
|  |  | ||||||
|  | String _$postAwardListNotifierHash() => | ||||||
|  |     r'492ae59a5dbbfb5c98f863f036023193b6e08668'; | ||||||
|  |  | ||||||
|  | /// Copied from Dart SDK | ||||||
|  | class _SystemHash { | ||||||
|  |   _SystemHash._(); | ||||||
|  |  | ||||||
|  |   static int combine(int hash, int value) { | ||||||
|  |     // ignore: parameter_assignments | ||||||
|  |     hash = 0x1fffffff & (hash + value); | ||||||
|  |     // ignore: parameter_assignments | ||||||
|  |     hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); | ||||||
|  |     return hash ^ (hash >> 6); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static int finish(int hash) { | ||||||
|  |     // ignore: parameter_assignments | ||||||
|  |     hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); | ||||||
|  |     // ignore: parameter_assignments | ||||||
|  |     hash = hash ^ (hash >> 11); | ||||||
|  |     return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | abstract class _$PostAwardListNotifier | ||||||
|  |     extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPostAward>> { | ||||||
|  |   late final String postId; | ||||||
|  |  | ||||||
|  |   FutureOr<CursorPagingData<SnPostAward>> build({required String postId}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// See also [PostAwardListNotifier]. | ||||||
|  | @ProviderFor(PostAwardListNotifier) | ||||||
|  | const postAwardListNotifierProvider = PostAwardListNotifierFamily(); | ||||||
|  |  | ||||||
|  | /// See also [PostAwardListNotifier]. | ||||||
|  | class PostAwardListNotifierFamily | ||||||
|  |     extends Family<AsyncValue<CursorPagingData<SnPostAward>>> { | ||||||
|  |   /// See also [PostAwardListNotifier]. | ||||||
|  |   const PostAwardListNotifierFamily(); | ||||||
|  |  | ||||||
|  |   /// See also [PostAwardListNotifier]. | ||||||
|  |   PostAwardListNotifierProvider call({required String postId}) { | ||||||
|  |     return PostAwardListNotifierProvider(postId: postId); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   PostAwardListNotifierProvider getProviderOverride( | ||||||
|  |     covariant PostAwardListNotifierProvider provider, | ||||||
|  |   ) { | ||||||
|  |     return call(postId: provider.postId); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static const Iterable<ProviderOrFamily>? _dependencies = null; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Iterable<ProviderOrFamily>? get dependencies => _dependencies; | ||||||
|  |  | ||||||
|  |   static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Iterable<ProviderOrFamily>? get allTransitiveDependencies => | ||||||
|  |       _allTransitiveDependencies; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   String? get name => r'postAwardListNotifierProvider'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// See also [PostAwardListNotifier]. | ||||||
|  | class PostAwardListNotifierProvider | ||||||
|  |     extends | ||||||
|  |         AutoDisposeAsyncNotifierProviderImpl< | ||||||
|  |           PostAwardListNotifier, | ||||||
|  |           CursorPagingData<SnPostAward> | ||||||
|  |         > { | ||||||
|  |   /// See also [PostAwardListNotifier]. | ||||||
|  |   PostAwardListNotifierProvider({required String postId}) | ||||||
|  |     : this._internal( | ||||||
|  |         () => PostAwardListNotifier()..postId = postId, | ||||||
|  |         from: postAwardListNotifierProvider, | ||||||
|  |         name: r'postAwardListNotifierProvider', | ||||||
|  |         debugGetCreateSourceHash: | ||||||
|  |             const bool.fromEnvironment('dart.vm.product') | ||||||
|  |                 ? null | ||||||
|  |                 : _$postAwardListNotifierHash, | ||||||
|  |         dependencies: PostAwardListNotifierFamily._dependencies, | ||||||
|  |         allTransitiveDependencies: | ||||||
|  |             PostAwardListNotifierFamily._allTransitiveDependencies, | ||||||
|  |         postId: postId, | ||||||
|  |       ); | ||||||
|  |  | ||||||
|  |   PostAwardListNotifierProvider._internal( | ||||||
|  |     super._createNotifier, { | ||||||
|  |     required super.name, | ||||||
|  |     required super.dependencies, | ||||||
|  |     required super.allTransitiveDependencies, | ||||||
|  |     required super.debugGetCreateSourceHash, | ||||||
|  |     required super.from, | ||||||
|  |     required this.postId, | ||||||
|  |   }) : super.internal(); | ||||||
|  |  | ||||||
|  |   final String postId; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   FutureOr<CursorPagingData<SnPostAward>> runNotifierBuild( | ||||||
|  |     covariant PostAwardListNotifier notifier, | ||||||
|  |   ) { | ||||||
|  |     return notifier.build(postId: postId); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Override overrideWith(PostAwardListNotifier Function() create) { | ||||||
|  |     return ProviderOverride( | ||||||
|  |       origin: this, | ||||||
|  |       override: PostAwardListNotifierProvider._internal( | ||||||
|  |         () => create()..postId = postId, | ||||||
|  |         from: from, | ||||||
|  |         name: null, | ||||||
|  |         dependencies: null, | ||||||
|  |         allTransitiveDependencies: null, | ||||||
|  |         debugGetCreateSourceHash: null, | ||||||
|  |         postId: postId, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   AutoDisposeAsyncNotifierProviderElement< | ||||||
|  |     PostAwardListNotifier, | ||||||
|  |     CursorPagingData<SnPostAward> | ||||||
|  |   > | ||||||
|  |   createElement() { | ||||||
|  |     return _PostAwardListNotifierProviderElement(this); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   bool operator ==(Object other) { | ||||||
|  |     return other is PostAwardListNotifierProvider && other.postId == postId; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   int get hashCode { | ||||||
|  |     var hash = _SystemHash.combine(0, runtimeType.hashCode); | ||||||
|  |     hash = _SystemHash.combine(hash, postId.hashCode); | ||||||
|  |  | ||||||
|  |     return _SystemHash.finish(hash); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @Deprecated('Will be removed in 3.0. Use Ref instead') | ||||||
|  | // ignore: unused_element | ||||||
|  | mixin PostAwardListNotifierRef | ||||||
|  |     on AutoDisposeAsyncNotifierProviderRef<CursorPagingData<SnPostAward>> { | ||||||
|  |   /// The parameter `postId` of this provider. | ||||||
|  |   String get postId; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class _PostAwardListNotifierProviderElement | ||||||
|  |     extends | ||||||
|  |         AutoDisposeAsyncNotifierProviderElement< | ||||||
|  |           PostAwardListNotifier, | ||||||
|  |           CursorPagingData<SnPostAward> | ||||||
|  |         > | ||||||
|  |     with PostAwardListNotifierRef { | ||||||
|  |   _PostAwardListNotifierProviderElement(super.provider); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   String get postId => (origin as PostAwardListNotifierProvider).postId; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 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 | ||||||
		Reference in New Issue
	
	Block a user