From d320879ad06c0cc4c2a6f0bd23065cea5caebb80 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Thu, 7 Aug 2025 02:01:15 +0800 Subject: [PATCH] :sparkles: Poll feedback --- lib/models/poll.dart | 16 ++ lib/models/poll.freezed.dart | 281 +++++++++++++++++++++++ lib/models/poll.g.dart | 25 ++ lib/screens/chat/room.dart | 22 +- lib/screens/creators/poll/poll_list.dart | 12 +- lib/widgets/poll/poll_feedback.dart | 235 +++++++++++++++++++ lib/widgets/poll/poll_feedback.g.dart | 180 +++++++++++++++ lib/widgets/post/post_list.g.dart | 2 +- 8 files changed, 759 insertions(+), 14 deletions(-) create mode 100644 lib/widgets/poll/poll_feedback.dart create mode 100644 lib/widgets/poll/poll_feedback.g.dart diff --git a/lib/models/poll.dart b/lib/models/poll.dart index 996f145..20e8a3e 100644 --- a/lib/models/poll.dart +++ b/lib/models/poll.dart @@ -90,3 +90,19 @@ enum SnPollQuestionType { @JsonValue(4) freeText, } + +@freezed +sealed class SnPollAnswer with _$SnPollAnswer { + const factory SnPollAnswer({ + required String id, + required Map answer, + required String accountId, + required String pollId, + required DateTime createdAt, + required DateTime updatedAt, + required DateTime? deletedAt, + }) = _SnPollAnswer; + + factory SnPollAnswer.fromJson(Map json) => + _$SnPollAnswerFromJson(json); +} diff --git a/lib/models/poll.freezed.dart b/lib/models/poll.freezed.dart index 7ba4909..fd3f301 100644 --- a/lib/models/poll.freezed.dart +++ b/lib/models/poll.freezed.dart @@ -1181,6 +1181,287 @@ as int, } +} + + +/// @nodoc +mixin _$SnPollAnswer { + + String get id; Map get answer; String get accountId; String get pollId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; +/// Create a copy of SnPollAnswer +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$SnPollAnswerCopyWith get copyWith => _$SnPollAnswerCopyWithImpl(this as SnPollAnswer, _$identity); + + /// Serializes this SnPollAnswer to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other.answer, answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(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,const DeepCollectionEquality().hash(answer),accountId,pollId,createdAt,updatedAt,deletedAt); + +@override +String toString() { + return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; +} + + +} + +/// @nodoc +abstract mixin class $SnPollAnswerCopyWith<$Res> { + factory $SnPollAnswerCopyWith(SnPollAnswer value, $Res Function(SnPollAnswer) _then) = _$SnPollAnswerCopyWithImpl; +@useResult +$Res call({ + String id, Map answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt +}); + + + + +} +/// @nodoc +class _$SnPollAnswerCopyWithImpl<$Res> + implements $SnPollAnswerCopyWith<$Res> { + _$SnPollAnswerCopyWithImpl(this._self, this._then); + + final SnPollAnswer _self; + final $Res Function(SnPollAnswer) _then; + +/// Create a copy of SnPollAnswer +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,answer: null == answer ? _self.answer : answer // ignore: cast_nullable_to_non_nullable +as Map,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable +as String,pollId: null == pollId ? _self.pollId : pollId // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable +as DateTime?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [SnPollAnswer]. +extension SnPollAnswerPatterns on SnPollAnswer { +/// 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 Function( _SnPollAnswer value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _SnPollAnswer() 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 Function( _SnPollAnswer value) $default,){ +final _that = this; +switch (_that) { +case _SnPollAnswer(): +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? Function( _SnPollAnswer value)? $default,){ +final _that = this; +switch (_that) { +case _SnPollAnswer() 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 Function( String id, Map answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _SnPollAnswer() when $default != null: +return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_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 Function( String id, Map answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this; +switch (_that) { +case _SnPollAnswer(): +return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_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? Function( String id, Map answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this; +switch (_that) { +case _SnPollAnswer() when $default != null: +return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _SnPollAnswer implements SnPollAnswer { + const _SnPollAnswer({required this.id, required final Map answer, required this.accountId, required this.pollId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _answer = answer; + factory _SnPollAnswer.fromJson(Map json) => _$SnPollAnswerFromJson(json); + +@override final String id; + final Map _answer; +@override Map get answer { + if (_answer is EqualUnmodifiableMapView) return _answer; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_answer); +} + +@override final String accountId; +@override final String pollId; +@override final DateTime createdAt; +@override final DateTime updatedAt; +@override final DateTime? deletedAt; + +/// Create a copy of SnPollAnswer +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$SnPollAnswerCopyWith<_SnPollAnswer> get copyWith => __$SnPollAnswerCopyWithImpl<_SnPollAnswer>(this, _$identity); + +@override +Map toJson() { + return _$SnPollAnswerToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other._answer, _answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(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,const DeepCollectionEquality().hash(_answer),accountId,pollId,createdAt,updatedAt,deletedAt); + +@override +String toString() { + return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$SnPollAnswerCopyWith<$Res> implements $SnPollAnswerCopyWith<$Res> { + factory _$SnPollAnswerCopyWith(_SnPollAnswer value, $Res Function(_SnPollAnswer) _then) = __$SnPollAnswerCopyWithImpl; +@override @useResult +$Res call({ + String id, Map answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt +}); + + + + +} +/// @nodoc +class __$SnPollAnswerCopyWithImpl<$Res> + implements _$SnPollAnswerCopyWith<$Res> { + __$SnPollAnswerCopyWithImpl(this._self, this._then); + + final _SnPollAnswer _self; + final $Res Function(_SnPollAnswer) _then; + +/// Create a copy of SnPollAnswer +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { + return _then(_SnPollAnswer( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,answer: null == answer ? _self._answer : answer // ignore: cast_nullable_to_non_nullable +as Map,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable +as String,pollId: null == pollId ? _self.pollId : pollId // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable +as DateTime?, + )); +} + + } // dart format on diff --git a/lib/models/poll.g.dart b/lib/models/poll.g.dart index 9a07fde..bed6484 100644 --- a/lib/models/poll.g.dart +++ b/lib/models/poll.g.dart @@ -131,3 +131,28 @@ Map _$SnPollOptionToJson(_SnPollOption instance) => 'description': instance.description, 'order': instance.order, }; + +_SnPollAnswer _$SnPollAnswerFromJson(Map json) => + _SnPollAnswer( + id: json['id'] as String, + answer: json['answer'] as Map, + accountId: json['account_id'] as String, + pollId: json['poll_id'] as String, + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + deletedAt: + json['deleted_at'] == null + ? null + : DateTime.parse(json['deleted_at'] as String), + ); + +Map _$SnPollAnswerToJson(_SnPollAnswer instance) => + { + 'id': instance.id, + 'answer': instance.answer, + 'account_id': instance.accountId, + 'poll_id': instance.pollId, + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt?.toIso8601String(), + }; diff --git a/lib/screens/chat/room.dart b/lib/screens/chat/room.dart index 2b693f1..f231027 100644 --- a/lib/screens/chat/room.dart +++ b/lib/screens/chat/room.dart @@ -1066,15 +1066,19 @@ class _ChatInput extends HookConsumerWidget { scrollDirection: Axis.horizontal, itemCount: attachments.length, itemBuilder: (context, idx) { - return AttachmentPreview( - item: attachments[idx], - onRequestUpload: () => onUploadAttachment(idx), - onDelete: () => onDeleteAttachment(idx), - onUpdate: (value) { - attachments[idx] = value; - onAttachmentsChanged(attachments); - }, - onMove: (delta) => onMoveAttachment(idx, delta), + return SizedBox( + height: 280, + width: 280, + child: AttachmentPreview( + item: attachments[idx], + onRequestUpload: () => onUploadAttachment(idx), + onDelete: () => onDeleteAttachment(idx), + onUpdate: (value) { + attachments[idx] = value; + onAttachmentsChanged(attachments); + }, + onMove: (delta) => onMoveAttachment(idx, delta), + ), ); }, separatorBuilder: (_, _) => const Gap(8), diff --git a/lib/screens/creators/poll/poll_list.dart b/lib/screens/creators/poll/poll_list.dart index d58c7f3..3ca736f 100644 --- a/lib/screens/creators/poll/poll_list.dart +++ b/lib/screens/creators/poll/poll_list.dart @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/poll.dart'; import 'package:island/pods/network.dart'; +import 'package:island/widgets/poll/poll_feedback.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; @@ -164,10 +165,13 @@ class _CreatorPollItem extends StatelessWidget { ], ), onTap: () { - // Open editor for edit - // Navigator push by path to keep consistency with rest of app: - // Note: pub name string may be required in route; when absent, route may need query or pick later. - // For safety, just do nothing if no publisher in list item. + showModalBottomSheet( + context: context, + useRootNavigator: true, + isScrollControlled: true, + builder: + (context) => PollFeedbackSheet(pollId: poll.id, poll: poll), + ); }, ), ); diff --git a/lib/widgets/poll/poll_feedback.dart b/lib/widgets/poll/poll_feedback.dart new file mode 100644 index 0000000..36abddc --- /dev/null +++ b/lib/widgets/poll/poll_feedback.dart @@ -0,0 +1,235 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:island/models/poll.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'; +import 'package:styled_widget/styled_widget.dart'; + +part 'poll_feedback.g.dart'; + +@riverpod +class PollFeedbackNotifier extends _$PollFeedbackNotifier + with CursorPagingNotifierMixin { + static const int _pageSize = 20; + + @override + Future> build(String id) { + // immediately load first page + return fetch(cursor: null); + } + + @override + Future> fetch({ + required String? cursor, + }) async { + final client = ref.read(apiClientProvider); + final offset = cursor == null ? 0 : int.parse(cursor); + + final queryParams = {'offset': offset, 'take': _pageSize}; + + final response = await client.get( + '/sphere/polls/$id/feedback', + queryParameters: queryParams, + ); + final total = int.parse(response.headers.value('X-Total') ?? '0'); + final List data = response.data; + final items = data.map((json) => SnPollAnswer.fromJson(json)).toList(); + + final hasMore = offset + items.length < total; + final nextCursor = hasMore ? (offset + items.length).toString() : null; + + return CursorPagingData( + items: items, + hasMore: hasMore, + nextCursor: nextCursor, + ); + } +} + +class PollFeedbackSheet extends HookConsumerWidget { + final String pollId; + final String? title; + final SnPoll poll; + final Map? stats; // stats object similar to PollSubmit + const PollFeedbackSheet({ + super.key, + required this.pollId, + required this.poll, + this.title, + this.stats, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return SheetScaffold( + titleText: title ?? 'Poll feedback', + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _PollHeader(poll: poll, stats: stats), + const Divider(height: 1), + Expanded( + child: PagingHelperView( + provider: pollFeedbackNotifierProvider(pollId), + futureRefreshable: pollFeedbackNotifierProvider(pollId).future, + notifierRefreshable: + pollFeedbackNotifierProvider(pollId).notifier, + contentBuilder: + (data, widgetCount, endItemView) => ListView.separated( + padding: const EdgeInsets.symmetric(vertical: 4), + itemCount: widgetCount, + itemBuilder: (context, index) { + if (index == widgetCount - 1) { + // Provided by PagingHelperView to indicate end/loading + return endItemView; + } + final answer = data.items[index]; + return _PollAnswerTile(answer: answer, poll: poll); + }, + separatorBuilder: + (context, index) => + const Divider(height: 1).padding(vertical: 4), + ), + ), + ), + ], + ), + ); + } +} + +class _PollHeader extends StatelessWidget { + const _PollHeader({required this.poll, this.stats}); + final SnPoll poll; + final Map? stats; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (poll.title != null) + Text(poll.title!, style: theme.textTheme.titleLarge), + if (poll.description != null) + Padding( + padding: const EdgeInsets.only(top: 2), + child: Text( + poll.description!, + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.textTheme.bodyMedium?.color?.withOpacity(0.7), + ), + ), + ), + ], + ).padding(horizontal: 20, vertical: 16); + } +} + +class _PollAnswerTile extends StatelessWidget { + final SnPollAnswer answer; + final SnPoll poll; + const _PollAnswerTile({required this.answer, required this.poll}); + + String _formatPerQuestionAnswer( + SnPollQuestion q, + Map ansMap, + ) { + switch (q.type) { + case SnPollQuestionType.singleChoice: + final val = ansMap[q.id]; + if (val is String) { + final opt = q.options?.firstWhere( + (o) => o.id == val, + orElse: () => SnPollOption(id: val, label: '#$val', order: 0), + ); + return opt?.label ?? '#$val'; + } + return '—'; + case SnPollQuestionType.multipleChoice: + final val = ansMap[q.id]; + if (val is List) { + final ids = val.whereType().toList(); + if (ids.isEmpty) return '—'; + final labels = + ids.map((id) { + final opt = q.options?.firstWhere( + (o) => o.id == id, + orElse: () => SnPollOption(id: id, label: '#$id', order: 0), + ); + return opt?.label ?? '#$id'; + }).toList(); + return labels.join(', '); + } + return '—'; + case SnPollQuestionType.yesNo: + final val = ansMap[q.id]; + if (val is bool) { + return val ? 'Yes' : 'No'; + } + return '—'; + case SnPollQuestionType.rating: + final val = ansMap[q.id]; + if (val is int) return val.toString(); + if (val is num) return val.toString(); + return '—'; + case SnPollQuestionType.freeText: + final val = ansMap[q.id]; + if (val is String && val.trim().isNotEmpty) return val; + return '—'; + } + } + + @override + Widget build(BuildContext context) { + // Submit date/time (title) + final submitText = answer.createdAt.toLocal().toString(); + + // Compose content from poll questions if provided, otherwise fallback to joined key-values + String content; + if (poll.questions.isNotEmpty) { + final questions = [...poll.questions] + ..sort((a, b) => a.order.compareTo(b.order)); + final buffer = StringBuffer(); + for (final q in questions) { + final formatted = _formatPerQuestionAnswer(q, answer.answer); + buffer.writeln('${q.title}: $formatted'); + } + content = buffer.toString().trimRight(); + } else { + // Fallback formatting without poll context. We still want to show the question title + // instead of the raw question id key if we can derive it from the answer map itself. + // Since we don't have poll metadata here, we cannot resolve the title; therefore we + // will show only values line-by-line without exposing the raw id. + if (answer.answer.isEmpty) { + content = '—'; + } else { + final parts = []; + answer.answer.forEach((key, value) { + var question = poll.questions.firstWhere((q) => q.id == key); + if (value is List) { + parts.add('${question.title}: ${value.join(', ')}'); + } else { + parts.add('${question.title}: $value'); + } + }); + content = parts.join('\n'); + } + } + + return ListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 20), + isThreeLine: true, + leading: const CircleAvatar( + radius: 16, + child: Icon(Icons.how_to_vote, size: 16), + ), + title: Text(submitText), + subtitle: Text(content), + trailing: null, + ); + } +} diff --git a/lib/widgets/poll/poll_feedback.g.dart b/lib/widgets/poll/poll_feedback.g.dart new file mode 100644 index 0000000..855ea5a --- /dev/null +++ b/lib/widgets/poll/poll_feedback.g.dart @@ -0,0 +1,180 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'poll_feedback.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$pollFeedbackNotifierHash() => + r'1bf3925b5b751cfd1a9abafb75274f1e95e7f27e'; + +/// 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 _$PollFeedbackNotifier + extends BuildlessAutoDisposeAsyncNotifier> { + late final String id; + + FutureOr> build(String id); +} + +/// See also [PollFeedbackNotifier]. +@ProviderFor(PollFeedbackNotifier) +const pollFeedbackNotifierProvider = PollFeedbackNotifierFamily(); + +/// See also [PollFeedbackNotifier]. +class PollFeedbackNotifierFamily + extends Family>> { + /// See also [PollFeedbackNotifier]. + const PollFeedbackNotifierFamily(); + + /// See also [PollFeedbackNotifier]. + PollFeedbackNotifierProvider call(String id) { + return PollFeedbackNotifierProvider(id); + } + + @override + PollFeedbackNotifierProvider getProviderOverride( + covariant PollFeedbackNotifierProvider provider, + ) { + return call(provider.id); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'pollFeedbackNotifierProvider'; +} + +/// See also [PollFeedbackNotifier]. +class PollFeedbackNotifierProvider + extends + AutoDisposeAsyncNotifierProviderImpl< + PollFeedbackNotifier, + CursorPagingData + > { + /// See also [PollFeedbackNotifier]. + PollFeedbackNotifierProvider(String id) + : this._internal( + () => PollFeedbackNotifier()..id = id, + from: pollFeedbackNotifierProvider, + name: r'pollFeedbackNotifierProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$pollFeedbackNotifierHash, + dependencies: PollFeedbackNotifierFamily._dependencies, + allTransitiveDependencies: + PollFeedbackNotifierFamily._allTransitiveDependencies, + id: id, + ); + + PollFeedbackNotifierProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.id, + }) : super.internal(); + + final String id; + + @override + FutureOr> runNotifierBuild( + covariant PollFeedbackNotifier notifier, + ) { + return notifier.build(id); + } + + @override + Override overrideWith(PollFeedbackNotifier Function() create) { + return ProviderOverride( + origin: this, + override: PollFeedbackNotifierProvider._internal( + () => create()..id = id, + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + id: id, + ), + ); + } + + @override + AutoDisposeAsyncNotifierProviderElement< + PollFeedbackNotifier, + CursorPagingData + > + createElement() { + return _PollFeedbackNotifierProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is PollFeedbackNotifierProvider && other.id == id; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, id.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin PollFeedbackNotifierRef + on AutoDisposeAsyncNotifierProviderRef> { + /// The parameter `id` of this provider. + String get id; +} + +class _PollFeedbackNotifierProviderElement + extends + AutoDisposeAsyncNotifierProviderElement< + PollFeedbackNotifier, + CursorPagingData + > + with PollFeedbackNotifierRef { + _PollFeedbackNotifierProviderElement(super.provider); + + @override + String get id => (origin as PollFeedbackNotifierProvider).id; +} + +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/widgets/post/post_list.g.dart b/lib/widgets/post/post_list.g.dart index 8acf2ac..58dc750 100644 --- a/lib/widgets/post/post_list.g.dart +++ b/lib/widgets/post/post_list.g.dart @@ -6,7 +6,7 @@ part of 'post_list.dart'; // RiverpodGenerator // ************************************************************************** -String _$postListNotifierHash() => r'c7c82c8cedf6649ac0806bbbfea148dfa1422fc0'; +String _$postListNotifierHash() => r'78222d62957f85713d17aecd95af0305b764e86c'; /// Copied from Dart SDK class _SystemHash {