🎨 Use feature based folder structure

This commit is contained in:
2026-02-06 00:37:02 +08:00
parent 62a3ea26e3
commit 862e3b451b
539 changed files with 8406 additions and 5056 deletions

View File

@@ -0,0 +1,216 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gap/gap.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/creators/creators/stickers/stickers.dart';
import 'package:island/stickers/stickers_models/sticker.dart';
import 'package:island/core/network.dart';
import 'package:island/shared/widgets/alert.dart';
import 'package:island/shared/widgets/app_scaffold.dart';
import 'package:island/drive/drive_widgets/cloud_files.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:styled_widget/styled_widget.dart';
part 'pack_detail.g.dart'; // generated by riverpod_annotation build_runner
/// Marketplace version of sticker pack detail page (no publisher dependency).
/// Shows all stickers in the pack and provides a button to add the sticker.
/// API interactions are intentionally left blank per request.
@riverpod
Future<List<SnSticker>> marketplaceStickerPackContent(
Ref ref, {
required String packId,
}) async {
final apiClient = ref.watch(apiClientProvider);
final resp = await apiClient.get('/sphere/stickers/$packId/content');
return (resp.data as List).map((e) => SnSticker.fromJson(e)).toList();
}
@riverpod
Future<bool> marketplaceStickerPackOwnership(
Ref ref, {
required String packId,
}) async {
final api = ref.watch(apiClientProvider);
try {
await api.get('/sphere/stickers/$packId/own');
// If not 404, consider owned
return true;
} on Object catch (e) {
// Dio error handling agnostic: treat 404 as not-owned, rethrow others
final msg = e.toString();
if (msg.contains('404')) return false;
rethrow;
}
}
class MarketplaceStickerPackDetailScreen extends HookConsumerWidget {
final String id;
const MarketplaceStickerPackDetailScreen({super.key, required this.id});
@override
Widget build(BuildContext context, WidgetRef ref) {
// Pack metadata provider exists globally in creators file; reuse it.
final pack = ref.watch(stickerPackProvider(id));
final packContent = ref.watch(
marketplaceStickerPackContentProvider(packId: id),
);
final owned = ref.watch(
marketplaceStickerPackOwnershipProvider(packId: id),
);
// Add entire pack to user's collection
Future<void> addPackToMyCollection() async {
final apiClient = ref.watch(apiClientProvider);
await apiClient.post('/sphere/stickers/$id/own');
HapticFeedback.selectionClick();
ref.invalidate(marketplaceStickerPackOwnershipProvider(packId: id));
if (!context.mounted) return;
showSnackBar('stickerPackAdded'.tr());
}
// Remove ownership of the pack
Future<void> removePackFromMyCollection() async {
final apiClient = ref.watch(apiClientProvider);
await apiClient.delete('/sphere/stickers/$id/own');
HapticFeedback.selectionClick();
ref.invalidate(marketplaceStickerPackOwnershipProvider(packId: id));
if (!context.mounted) return;
showSnackBar('stickerPackRemoved'.tr());
}
return AppScaffold(
appBar: AppBar(title: Text(pack.value?.name ?? 'loading'.tr())),
body: pack.when(
data: (p) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Pack meta
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(p?.description ?? ''),
Row(
spacing: 4,
children: [
const Icon(Symbols.folder, size: 16),
Text(
'${packContent.value?.length ?? 0}/24',
style: GoogleFonts.robotoMono(),
),
],
).opacity(0.85),
Row(
spacing: 4,
children: [
const Icon(Symbols.sell, size: 16),
Text(p?.prefix ?? '', style: GoogleFonts.robotoMono()),
],
).opacity(0.85),
Row(
spacing: 4,
children: [
const Icon(Symbols.tag, size: 16),
SelectableText(
p?.id ?? id,
style: GoogleFonts.robotoMono(),
),
],
).opacity(0.85),
],
).padding(horizontal: 24, vertical: 24),
const Divider(height: 1),
// Stickers grid
Expanded(
child: packContent.when(
data: (stickers) => RefreshIndicator(
onRefresh: () => ref.refresh(
marketplaceStickerPackContentProvider(packId: id).future,
),
child: GridView.builder(
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 20,
),
gridDelegate:
const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 96,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
),
itemCount: stickers.length,
itemBuilder: (context, index) {
final sticker = stickers[index];
return Tooltip(
message: ':${p?.prefix ?? ''}+${sticker.slug}:',
child: ClipRRect(
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
child: Container(
decoration: BoxDecoration(
color: Theme.of(
context,
).colorScheme.surfaceContainer,
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
),
child: AspectRatio(
aspectRatio: 1,
child: CloudImageWidget(
file: sticker.image,
fit: BoxFit.contain,
),
),
),
),
);
},
),
),
error: (err, _) => Text(
'Error: $err',
).textAlignment(TextAlign.center).center(),
loading: () => const CircularProgressIndicator().center(),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8),
child: owned.when(
data: (isOwned) => FilledButton.icon(
onPressed: isOwned
? removePackFromMyCollection
: addPackToMyCollection,
icon: Icon(
isOwned ? Symbols.remove_circle : Symbols.add_circle,
),
label: Text(isOwned ? 'removePack'.tr() : 'addPack'.tr()),
),
loading: () => const SizedBox(
height: 32,
width: 32,
child: CircularProgressIndicator(strokeWidth: 2),
).center(),
error: (_, _) => OutlinedButton.icon(
onPressed: addPackToMyCollection,
icon: const Icon(Symbols.add_circle),
label: Text('addPack').tr(),
),
),
),
Gap(MediaQuery.of(context).padding.bottom + 16),
],
);
},
error: (err, _) =>
Text('Error: $err').textAlignment(TextAlign.center).center(),
loading: () => const CircularProgressIndicator().center(),
),
);
}
}

View File

@@ -0,0 +1,178 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'pack_detail.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
/// Marketplace version of sticker pack detail page (no publisher dependency).
/// Shows all stickers in the pack and provides a button to add the sticker.
/// API interactions are intentionally left blank per request.
@ProviderFor(marketplaceStickerPackContent)
final marketplaceStickerPackContentProvider =
MarketplaceStickerPackContentFamily._();
/// Marketplace version of sticker pack detail page (no publisher dependency).
/// Shows all stickers in the pack and provides a button to add the sticker.
/// API interactions are intentionally left blank per request.
final class MarketplaceStickerPackContentProvider
extends
$FunctionalProvider<
AsyncValue<List<SnSticker>>,
List<SnSticker>,
FutureOr<List<SnSticker>>
>
with $FutureModifier<List<SnSticker>>, $FutureProvider<List<SnSticker>> {
/// Marketplace version of sticker pack detail page (no publisher dependency).
/// Shows all stickers in the pack and provides a button to add the sticker.
/// API interactions are intentionally left blank per request.
MarketplaceStickerPackContentProvider._({
required MarketplaceStickerPackContentFamily super.from,
required String super.argument,
}) : super(
retry: null,
name: r'marketplaceStickerPackContentProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$marketplaceStickerPackContentHash();
@override
String toString() {
return r'marketplaceStickerPackContentProvider'
''
'($argument)';
}
@$internal
@override
$FutureProviderElement<List<SnSticker>> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<List<SnSticker>> create(Ref ref) {
final argument = this.argument as String;
return marketplaceStickerPackContent(ref, packId: argument);
}
@override
bool operator ==(Object other) {
return other is MarketplaceStickerPackContentProvider &&
other.argument == argument;
}
@override
int get hashCode {
return argument.hashCode;
}
}
String _$marketplaceStickerPackContentHash() =>
r'886f8305c978dbea6e5d990a7d555048ac704a5d';
/// Marketplace version of sticker pack detail page (no publisher dependency).
/// Shows all stickers in the pack and provides a button to add the sticker.
/// API interactions are intentionally left blank per request.
final class MarketplaceStickerPackContentFamily extends $Family
with $FunctionalFamilyOverride<FutureOr<List<SnSticker>>, String> {
MarketplaceStickerPackContentFamily._()
: super(
retry: null,
name: r'marketplaceStickerPackContentProvider',
dependencies: null,
$allTransitiveDependencies: null,
isAutoDispose: true,
);
/// Marketplace version of sticker pack detail page (no publisher dependency).
/// Shows all stickers in the pack and provides a button to add the sticker.
/// API interactions are intentionally left blank per request.
MarketplaceStickerPackContentProvider call({required String packId}) =>
MarketplaceStickerPackContentProvider._(argument: packId, from: this);
@override
String toString() => r'marketplaceStickerPackContentProvider';
}
@ProviderFor(marketplaceStickerPackOwnership)
final marketplaceStickerPackOwnershipProvider =
MarketplaceStickerPackOwnershipFamily._();
final class MarketplaceStickerPackOwnershipProvider
extends $FunctionalProvider<AsyncValue<bool>, bool, FutureOr<bool>>
with $FutureModifier<bool>, $FutureProvider<bool> {
MarketplaceStickerPackOwnershipProvider._({
required MarketplaceStickerPackOwnershipFamily super.from,
required String super.argument,
}) : super(
retry: null,
name: r'marketplaceStickerPackOwnershipProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$marketplaceStickerPackOwnershipHash();
@override
String toString() {
return r'marketplaceStickerPackOwnershipProvider'
''
'($argument)';
}
@$internal
@override
$FutureProviderElement<bool> $createElement($ProviderPointer pointer) =>
$FutureProviderElement(pointer);
@override
FutureOr<bool> create(Ref ref) {
final argument = this.argument as String;
return marketplaceStickerPackOwnership(ref, packId: argument);
}
@override
bool operator ==(Object other) {
return other is MarketplaceStickerPackOwnershipProvider &&
other.argument == argument;
}
@override
int get hashCode {
return argument.hashCode;
}
}
String _$marketplaceStickerPackOwnershipHash() =>
r'e5dd301c309fac958729d13d984ce7a77edbe7e6';
final class MarketplaceStickerPackOwnershipFamily extends $Family
with $FunctionalFamilyOverride<FutureOr<bool>, String> {
MarketplaceStickerPackOwnershipFamily._()
: super(
retry: null,
name: r'marketplaceStickerPackOwnershipProvider',
dependencies: null,
$allTransitiveDependencies: null,
isAutoDispose: true,
);
MarketplaceStickerPackOwnershipProvider call({required String packId}) =>
MarketplaceStickerPackOwnershipProvider._(argument: packId, from: this);
@override
String toString() => r'marketplaceStickerPackOwnershipProvider';
}

View File

@@ -0,0 +1,288 @@
import 'dart:math' as math;
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:go_router/go_router.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pagination/pagination.dart';
import 'package:island/stickers/stickers_models/sticker.dart';
import 'package:island/core/network.dart';
import 'package:island/shared/widgets/app_scaffold.dart';
import 'package:island/drive/drive_widgets/cloud_files.dart';
import 'package:island/shared/widgets/pagination_list.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'dart:async';
import 'package:styled_widget/styled_widget.dart';
part 'sticker_marketplace.freezed.dart';
@freezed
sealed class MarketplaceStickerQuery with _$MarketplaceStickerQuery {
const factory MarketplaceStickerQuery({
required bool byUsage,
required String? query,
}) = _MarketplaceStickerQuery;
}
final marketplaceStickerPacksNotifierProvider =
AsyncNotifierProvider.autoDispose(MarketplaceStickerPacksNotifier.new);
class MarketplaceStickerPacksNotifier
extends AsyncNotifier<PaginationState<SnStickerPack>>
with
AsyncPaginationController<SnStickerPack>,
AsyncPaginationFilter<MarketplaceStickerQuery, SnStickerPack> {
static const int pageSize = 20;
@override
MarketplaceStickerQuery currentFilter = MarketplaceStickerQuery(
byUsage: true,
query: null,
);
@override
Future<List<SnStickerPack>> fetch() async {
final client = ref.read(apiClientProvider);
final response = await client.get(
'/sphere/stickers',
queryParameters: {
'offset': fetchedCount.toString(),
'take': pageSize,
'order': currentFilter.byUsage ? 'usage' : 'date',
if (currentFilter.query != null && currentFilter.query!.isNotEmpty)
'query': currentFilter.query,
},
);
totalCount = int.parse(response.headers.value('X-Total') ?? '0');
final stickers = response.data
.map((e) => SnStickerPack.fromJson(e))
.cast<SnStickerPack>()
.toList();
return stickers;
}
}
/// User-facing marketplace screen for browsing sticker packs.
/// This version does NOT rely on publisher name (no pubName).
class MarketplaceStickersScreen extends HookConsumerWidget {
const MarketplaceStickersScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final query = useState<MarketplaceStickerQuery>(
MarketplaceStickerQuery(byUsage: true, query: null),
);
final searchController = useTextEditingController();
final focusNode = useFocusNode();
final debounceTimer = useState<Timer?>(null);
final notifier = ref.watch(
marketplaceStickerPacksNotifierProvider.notifier,
);
// Clear search when query is cleared
useEffect(() {
if (query.value.query == null || query.value.query!.isEmpty) {
searchController.clear();
}
return null;
}, [query]);
// Clean up timer on dispose
useEffect(() {
return () {
debounceTimer.value?.cancel();
};
}, []);
return AppScaffold(
appBar: AppBar(
title: const Text('stickers').tr(),
actions: [
IconButton(
onPressed: () {
query.value = query.value.copyWith(byUsage: !query.value.byUsage);
notifier.applyFilter(query.value);
},
icon: query.value.byUsage
? const Icon(Symbols.local_fire_department)
: const Icon(Symbols.access_time),
tooltip: query.value.byUsage
? 'orderByPopularity'.tr()
: 'orderByReleaseDate'.tr(),
),
const Gap(8),
],
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
child: SearchBar(
elevation: WidgetStateProperty.all(4),
controller: searchController,
focusNode: focusNode,
hintText: 'search'.tr(),
leading: const Icon(Symbols.search),
padding: WidgetStateProperty.all(
const EdgeInsets.symmetric(horizontal: 24),
),
onTapOutside: (_) =>
FocusManager.instance.primaryFocus?.unfocus(),
trailing: [
if (query.value.query != null && query.value.query!.isNotEmpty)
IconButton(
icon: const Icon(Symbols.close),
onPressed: () {
query.value = query.value.copyWith(query: null);
notifier.applyFilter(query.value);
searchController.clear();
focusNode.unfocus();
},
),
],
onChanged: (value) {
// Debounce search to avoid excessive API calls
debounceTimer.value?.cancel();
debounceTimer.value = Timer(
const Duration(milliseconds: 500),
() {
query.value = query.value.copyWith(query: value);
notifier.applyFilter(query.value);
},
);
},
onSubmitted: (value) {
query.value = query.value.copyWith(query: value);
notifier.applyFilter(query.value);
focusNode.unfocus();
},
),
),
Expanded(
child: PaginationList(
padding: EdgeInsets.only(top: 8),
provider: marketplaceStickerPacksNotifierProvider,
notifier: marketplaceStickerPacksNotifierProvider.notifier,
itemBuilder: (context, idx, pack) => Card(
margin: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
child: Column(
children: [
if (pack.stickers.isNotEmpty)
Container(
color: Theme.of(context).colorScheme.secondaryContainer,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 20,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
math.min(pack.stickers.length, 4),
(index) => Padding(
padding: EdgeInsets.only(
right: index < 3 ? 8 : 0,
),
child: Container(
constraints: const BoxConstraints(
maxWidth: 80,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Theme.of(
context,
).colorScheme.tertiaryContainer,
),
child: CloudImageWidget(
file: pack.stickers[index].image,
),
).clipRRect(all: 8),
),
),
),
if (pack.stickers.length > 4)
const SizedBox(height: 8),
if (pack.stickers.length > 4)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
math.min(pack.stickers.length - 4, 4),
(index) => Padding(
padding: EdgeInsets.only(
right: index < 3 ? 8 : 0,
),
child: Container(
constraints: const BoxConstraints(
maxWidth: 80,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
8,
),
color: Theme.of(
context,
).colorScheme.tertiaryContainer,
),
child: CloudImageWidget(
file: pack.stickers[index + 4].image,
),
).clipRRect(all: 8),
),
),
),
],
),
),
).clipRRect(topLeft: 8, topRight: 8),
ListTile(
leading: Container(
decoration: BoxDecoration(
color: Theme.of(
context,
).colorScheme.tertiaryContainer,
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
),
child: CloudImageWidget(
file: pack.icon ?? pack.stickers.firstOrNull?.image,
),
).width(40).height(40).clipRRect(all: 8),
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
),
title: Text(pack.name),
subtitle: Text(pack.description),
trailing: const Icon(Symbols.chevron_right),
onTap: () {
// Navigate to user-facing sticker pack detail page.
// Adjust the route name/parameters if your app uses different ones.
context.pushNamed(
'stickerPackDetail',
pathParameters: {'packId': pack.id},
);
},
),
],
),
),
),
),
],
),
);
}
}

View File

@@ -0,0 +1,268 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'sticker_marketplace.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$MarketplaceStickerQuery {
bool get byUsage; String? get query;
/// Create a copy of MarketplaceStickerQuery
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$MarketplaceStickerQueryCopyWith<MarketplaceStickerQuery> get copyWith => _$MarketplaceStickerQueryCopyWithImpl<MarketplaceStickerQuery>(this as MarketplaceStickerQuery, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is MarketplaceStickerQuery&&(identical(other.byUsage, byUsage) || other.byUsage == byUsage)&&(identical(other.query, query) || other.query == query));
}
@override
int get hashCode => Object.hash(runtimeType,byUsage,query);
@override
String toString() {
return 'MarketplaceStickerQuery(byUsage: $byUsage, query: $query)';
}
}
/// @nodoc
abstract mixin class $MarketplaceStickerQueryCopyWith<$Res> {
factory $MarketplaceStickerQueryCopyWith(MarketplaceStickerQuery value, $Res Function(MarketplaceStickerQuery) _then) = _$MarketplaceStickerQueryCopyWithImpl;
@useResult
$Res call({
bool byUsage, String? query
});
}
/// @nodoc
class _$MarketplaceStickerQueryCopyWithImpl<$Res>
implements $MarketplaceStickerQueryCopyWith<$Res> {
_$MarketplaceStickerQueryCopyWithImpl(this._self, this._then);
final MarketplaceStickerQuery _self;
final $Res Function(MarketplaceStickerQuery) _then;
/// Create a copy of MarketplaceStickerQuery
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? byUsage = null,Object? query = freezed,}) {
return _then(_self.copyWith(
byUsage: null == byUsage ? _self.byUsage : byUsage // ignore: cast_nullable_to_non_nullable
as bool,query: freezed == query ? _self.query : query // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// Adds pattern-matching-related methods to [MarketplaceStickerQuery].
extension MarketplaceStickerQueryPatterns on MarketplaceStickerQuery {
/// 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( _MarketplaceStickerQuery value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _MarketplaceStickerQuery() 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( _MarketplaceStickerQuery value) $default,){
final _that = this;
switch (_that) {
case _MarketplaceStickerQuery():
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( _MarketplaceStickerQuery value)? $default,){
final _that = this;
switch (_that) {
case _MarketplaceStickerQuery() 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( bool byUsage, String? query)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _MarketplaceStickerQuery() when $default != null:
return $default(_that.byUsage,_that.query);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( bool byUsage, String? query) $default,) {final _that = this;
switch (_that) {
case _MarketplaceStickerQuery():
return $default(_that.byUsage,_that.query);}
}
/// 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( bool byUsage, String? query)? $default,) {final _that = this;
switch (_that) {
case _MarketplaceStickerQuery() when $default != null:
return $default(_that.byUsage,_that.query);case _:
return null;
}
}
}
/// @nodoc
class _MarketplaceStickerQuery implements MarketplaceStickerQuery {
const _MarketplaceStickerQuery({required this.byUsage, required this.query});
@override final bool byUsage;
@override final String? query;
/// Create a copy of MarketplaceStickerQuery
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$MarketplaceStickerQueryCopyWith<_MarketplaceStickerQuery> get copyWith => __$MarketplaceStickerQueryCopyWithImpl<_MarketplaceStickerQuery>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _MarketplaceStickerQuery&&(identical(other.byUsage, byUsage) || other.byUsage == byUsage)&&(identical(other.query, query) || other.query == query));
}
@override
int get hashCode => Object.hash(runtimeType,byUsage,query);
@override
String toString() {
return 'MarketplaceStickerQuery(byUsage: $byUsage, query: $query)';
}
}
/// @nodoc
abstract mixin class _$MarketplaceStickerQueryCopyWith<$Res> implements $MarketplaceStickerQueryCopyWith<$Res> {
factory _$MarketplaceStickerQueryCopyWith(_MarketplaceStickerQuery value, $Res Function(_MarketplaceStickerQuery) _then) = __$MarketplaceStickerQueryCopyWithImpl;
@override @useResult
$Res call({
bool byUsage, String? query
});
}
/// @nodoc
class __$MarketplaceStickerQueryCopyWithImpl<$Res>
implements _$MarketplaceStickerQueryCopyWith<$Res> {
__$MarketplaceStickerQueryCopyWithImpl(this._self, this._then);
final _MarketplaceStickerQuery _self;
final $Res Function(_MarketplaceStickerQuery) _then;
/// Create a copy of MarketplaceStickerQuery
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? byUsage = null,Object? query = freezed,}) {
return _then(_MarketplaceStickerQuery(
byUsage: null == byUsage ? _self.byUsage : byUsage // ignore: cast_nullable_to_non_nullable
as bool,query: freezed == query ? _self.query : query // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
// dart format on

View File

@@ -0,0 +1,43 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:island/drive/drive_models/file.dart';
import 'package:island/posts/posts_models/publisher.dart';
part 'sticker.freezed.dart';
part 'sticker.g.dart';
@freezed
sealed class SnSticker with _$SnSticker {
const factory SnSticker({
required String id,
required String slug,
required SnCloudFile image,
required String packId,
required SnStickerPack? pack,
required DateTime createdAt,
required DateTime updatedAt,
required DateTime? deletedAt,
}) = _SnSticker;
factory SnSticker.fromJson(Map<String, dynamic> json) =>
_$SnStickerFromJson(json);
}
@freezed
sealed class SnStickerPack with _$SnStickerPack {
const factory SnStickerPack({
required String id,
required String name,
required String description,
required String prefix,
required String publisherId,
required SnCloudFile? icon,
required SnPublisher? publisher,
required DateTime createdAt,
required DateTime updatedAt,
required DateTime? deletedAt,
@Default([]) List<SnSticker> stickers,
}) = _SnStickerPack;
factory SnStickerPack.fromJson(Map<String, dynamic> json) =>
_$SnStickerPackFromJson(json);
}

View File

@@ -0,0 +1,675 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'sticker.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$SnSticker {
String get id; String get slug; SnCloudFile get image; String get packId; SnStickerPack? get pack; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
/// Create a copy of SnSticker
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$SnStickerCopyWith<SnSticker> get copyWith => _$SnStickerCopyWithImpl<SnSticker>(this as SnSticker, _$identity);
/// Serializes this SnSticker to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnSticker&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.image, image) || other.image == image)&&(identical(other.packId, packId) || other.packId == packId)&&(identical(other.pack, pack) || other.pack == pack)&&(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,slug,image,packId,pack,createdAt,updatedAt,deletedAt);
@override
String toString() {
return 'SnSticker(id: $id, slug: $slug, image: $image, packId: $packId, pack: $pack, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
abstract mixin class $SnStickerCopyWith<$Res> {
factory $SnStickerCopyWith(SnSticker value, $Res Function(SnSticker) _then) = _$SnStickerCopyWithImpl;
@useResult
$Res call({
String id, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnCloudFileCopyWith<$Res> get image;$SnStickerPackCopyWith<$Res>? get pack;
}
/// @nodoc
class _$SnStickerCopyWithImpl<$Res>
implements $SnStickerCopyWith<$Res> {
_$SnStickerCopyWithImpl(this._self, this._then);
final SnSticker _self;
final $Res Function(SnSticker) _then;
/// Create a copy of SnSticker
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? image = null,Object? packId = null,Object? pack = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
as String,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable
as SnCloudFile,packId: null == packId ? _self.packId : packId // ignore: cast_nullable_to_non_nullable
as String,pack: freezed == pack ? _self.pack : pack // ignore: cast_nullable_to_non_nullable
as SnStickerPack?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
/// Create a copy of SnSticker
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnCloudFileCopyWith<$Res> get image {
return $SnCloudFileCopyWith<$Res>(_self.image, (value) {
return _then(_self.copyWith(image: value));
});
}/// Create a copy of SnSticker
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnStickerPackCopyWith<$Res>? get pack {
if (_self.pack == null) {
return null;
}
return $SnStickerPackCopyWith<$Res>(_self.pack!, (value) {
return _then(_self.copyWith(pack: value));
});
}
}
/// Adds pattern-matching-related methods to [SnSticker].
extension SnStickerPatterns on SnSticker {
/// 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( _SnSticker value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _SnSticker() 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( _SnSticker value) $default,){
final _that = this;
switch (_that) {
case _SnSticker():
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( _SnSticker value)? $default,){
final _that = this;
switch (_that) {
case _SnSticker() 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, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _SnSticker() when $default != null:
return $default(_that.id,_that.slug,_that.image,_that.packId,_that.pack,_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, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
switch (_that) {
case _SnSticker():
return $default(_that.id,_that.slug,_that.image,_that.packId,_that.pack,_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, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
switch (_that) {
case _SnSticker() when $default != null:
return $default(_that.id,_that.slug,_that.image,_that.packId,_that.pack,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _SnSticker implements SnSticker {
const _SnSticker({required this.id, required this.slug, required this.image, required this.packId, required this.pack, required this.createdAt, required this.updatedAt, required this.deletedAt});
factory _SnSticker.fromJson(Map<String, dynamic> json) => _$SnStickerFromJson(json);
@override final String id;
@override final String slug;
@override final SnCloudFile image;
@override final String packId;
@override final SnStickerPack? pack;
@override final DateTime createdAt;
@override final DateTime updatedAt;
@override final DateTime? deletedAt;
/// Create a copy of SnSticker
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$SnStickerCopyWith<_SnSticker> get copyWith => __$SnStickerCopyWithImpl<_SnSticker>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$SnStickerToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnSticker&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.image, image) || other.image == image)&&(identical(other.packId, packId) || other.packId == packId)&&(identical(other.pack, pack) || other.pack == pack)&&(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,slug,image,packId,pack,createdAt,updatedAt,deletedAt);
@override
String toString() {
return 'SnSticker(id: $id, slug: $slug, image: $image, packId: $packId, pack: $pack, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
abstract mixin class _$SnStickerCopyWith<$Res> implements $SnStickerCopyWith<$Res> {
factory _$SnStickerCopyWith(_SnSticker value, $Res Function(_SnSticker) _then) = __$SnStickerCopyWithImpl;
@override @useResult
$Res call({
String id, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnCloudFileCopyWith<$Res> get image;@override $SnStickerPackCopyWith<$Res>? get pack;
}
/// @nodoc
class __$SnStickerCopyWithImpl<$Res>
implements _$SnStickerCopyWith<$Res> {
__$SnStickerCopyWithImpl(this._self, this._then);
final _SnSticker _self;
final $Res Function(_SnSticker) _then;
/// Create a copy of SnSticker
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? image = null,Object? packId = null,Object? pack = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
return _then(_SnSticker(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
as String,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable
as SnCloudFile,packId: null == packId ? _self.packId : packId // ignore: cast_nullable_to_non_nullable
as String,pack: freezed == pack ? _self.pack : pack // ignore: cast_nullable_to_non_nullable
as SnStickerPack?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
/// Create a copy of SnSticker
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnCloudFileCopyWith<$Res> get image {
return $SnCloudFileCopyWith<$Res>(_self.image, (value) {
return _then(_self.copyWith(image: value));
});
}/// Create a copy of SnSticker
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnStickerPackCopyWith<$Res>? get pack {
if (_self.pack == null) {
return null;
}
return $SnStickerPackCopyWith<$Res>(_self.pack!, (value) {
return _then(_self.copyWith(pack: value));
});
}
}
/// @nodoc
mixin _$SnStickerPack {
String get id; String get name; String get description; String get prefix; String get publisherId; SnCloudFile? get icon; SnPublisher? get publisher; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; List<SnSticker> get stickers;
/// Create a copy of SnStickerPack
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$SnStickerPackCopyWith<SnStickerPack> get copyWith => _$SnStickerPackCopyWithImpl<SnStickerPack>(this as SnStickerPack, _$identity);
/// Serializes this SnStickerPack to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnStickerPack&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.prefix, prefix) || other.prefix == prefix)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.icon, icon) || other.icon == icon)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other.stickers, stickers));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,description,prefix,publisherId,icon,publisher,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(stickers));
@override
String toString() {
return 'SnStickerPack(id: $id, name: $name, description: $description, prefix: $prefix, publisherId: $publisherId, icon: $icon, publisher: $publisher, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stickers: $stickers)';
}
}
/// @nodoc
abstract mixin class $SnStickerPackCopyWith<$Res> {
factory $SnStickerPackCopyWith(SnStickerPack value, $Res Function(SnStickerPack) _then) = _$SnStickerPackCopyWithImpl;
@useResult
$Res call({
String id, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnSticker> stickers
});
$SnCloudFileCopyWith<$Res>? get icon;$SnPublisherCopyWith<$Res>? get publisher;
}
/// @nodoc
class _$SnStickerPackCopyWithImpl<$Res>
implements $SnStickerPackCopyWith<$Res> {
_$SnStickerPackCopyWithImpl(this._self, this._then);
final SnStickerPack _self;
final $Res Function(SnStickerPack) _then;
/// Create a copy of SnStickerPack
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? description = null,Object? prefix = null,Object? publisherId = null,Object? icon = freezed,Object? publisher = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? stickers = null,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String,prefix: null == prefix ? _self.prefix : prefix // ignore: cast_nullable_to_non_nullable
as String,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable
as String,icon: freezed == icon ? _self.icon : icon // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,publisher: freezed == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
as SnPublisher?,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?,stickers: null == stickers ? _self.stickers : stickers // ignore: cast_nullable_to_non_nullable
as List<SnSticker>,
));
}
/// Create a copy of SnStickerPack
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnCloudFileCopyWith<$Res>? get icon {
if (_self.icon == null) {
return null;
}
return $SnCloudFileCopyWith<$Res>(_self.icon!, (value) {
return _then(_self.copyWith(icon: value));
});
}/// Create a copy of SnStickerPack
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnPublisherCopyWith<$Res>? get publisher {
if (_self.publisher == null) {
return null;
}
return $SnPublisherCopyWith<$Res>(_self.publisher!, (value) {
return _then(_self.copyWith(publisher: value));
});
}
}
/// Adds pattern-matching-related methods to [SnStickerPack].
extension SnStickerPackPatterns on SnStickerPack {
/// 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( _SnStickerPack value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _SnStickerPack() 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( _SnStickerPack value) $default,){
final _that = this;
switch (_that) {
case _SnStickerPack():
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( _SnStickerPack value)? $default,){
final _that = this;
switch (_that) {
case _SnStickerPack() 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, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnSticker> stickers)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _SnStickerPack() when $default != null:
return $default(_that.id,_that.name,_that.description,_that.prefix,_that.publisherId,_that.icon,_that.publisher,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.stickers);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, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnSticker> stickers) $default,) {final _that = this;
switch (_that) {
case _SnStickerPack():
return $default(_that.id,_that.name,_that.description,_that.prefix,_that.publisherId,_that.icon,_that.publisher,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.stickers);}
}
/// 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, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnSticker> stickers)? $default,) {final _that = this;
switch (_that) {
case _SnStickerPack() when $default != null:
return $default(_that.id,_that.name,_that.description,_that.prefix,_that.publisherId,_that.icon,_that.publisher,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.stickers);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _SnStickerPack implements SnStickerPack {
const _SnStickerPack({required this.id, required this.name, required this.description, required this.prefix, required this.publisherId, required this.icon, required this.publisher, required this.createdAt, required this.updatedAt, required this.deletedAt, final List<SnSticker> stickers = const []}): _stickers = stickers;
factory _SnStickerPack.fromJson(Map<String, dynamic> json) => _$SnStickerPackFromJson(json);
@override final String id;
@override final String name;
@override final String description;
@override final String prefix;
@override final String publisherId;
@override final SnCloudFile? icon;
@override final SnPublisher? publisher;
@override final DateTime createdAt;
@override final DateTime updatedAt;
@override final DateTime? deletedAt;
final List<SnSticker> _stickers;
@override@JsonKey() List<SnSticker> get stickers {
if (_stickers is EqualUnmodifiableListView) return _stickers;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_stickers);
}
/// Create a copy of SnStickerPack
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$SnStickerPackCopyWith<_SnStickerPack> get copyWith => __$SnStickerPackCopyWithImpl<_SnStickerPack>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$SnStickerPackToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnStickerPack&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.prefix, prefix) || other.prefix == prefix)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.icon, icon) || other.icon == icon)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other._stickers, _stickers));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,description,prefix,publisherId,icon,publisher,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(_stickers));
@override
String toString() {
return 'SnStickerPack(id: $id, name: $name, description: $description, prefix: $prefix, publisherId: $publisherId, icon: $icon, publisher: $publisher, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stickers: $stickers)';
}
}
/// @nodoc
abstract mixin class _$SnStickerPackCopyWith<$Res> implements $SnStickerPackCopyWith<$Res> {
factory _$SnStickerPackCopyWith(_SnStickerPack value, $Res Function(_SnStickerPack) _then) = __$SnStickerPackCopyWithImpl;
@override @useResult
$Res call({
String id, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnSticker> stickers
});
@override $SnCloudFileCopyWith<$Res>? get icon;@override $SnPublisherCopyWith<$Res>? get publisher;
}
/// @nodoc
class __$SnStickerPackCopyWithImpl<$Res>
implements _$SnStickerPackCopyWith<$Res> {
__$SnStickerPackCopyWithImpl(this._self, this._then);
final _SnStickerPack _self;
final $Res Function(_SnStickerPack) _then;
/// Create a copy of SnStickerPack
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? description = null,Object? prefix = null,Object? publisherId = null,Object? icon = freezed,Object? publisher = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? stickers = null,}) {
return _then(_SnStickerPack(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String,prefix: null == prefix ? _self.prefix : prefix // ignore: cast_nullable_to_non_nullable
as String,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable
as String,icon: freezed == icon ? _self.icon : icon // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,publisher: freezed == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
as SnPublisher?,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?,stickers: null == stickers ? _self._stickers : stickers // ignore: cast_nullable_to_non_nullable
as List<SnSticker>,
));
}
/// Create a copy of SnStickerPack
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnCloudFileCopyWith<$Res>? get icon {
if (_self.icon == null) {
return null;
}
return $SnCloudFileCopyWith<$Res>(_self.icon!, (value) {
return _then(_self.copyWith(icon: value));
});
}/// Create a copy of SnStickerPack
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnPublisherCopyWith<$Res>? get publisher {
if (_self.publisher == null) {
return null;
}
return $SnPublisherCopyWith<$Res>(_self.publisher!, (value) {
return _then(_self.copyWith(publisher: value));
});
}
}
// dart format on

View File

@@ -0,0 +1,74 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'sticker.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_SnSticker _$SnStickerFromJson(Map<String, dynamic> json) => _SnSticker(
id: json['id'] as String,
slug: json['slug'] as String,
image: SnCloudFile.fromJson(json['image'] as Map<String, dynamic>),
packId: json['pack_id'] as String,
pack: json['pack'] == null
? null
: SnStickerPack.fromJson(json['pack'] as Map<String, dynamic>),
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<String, dynamic> _$SnStickerToJson(_SnSticker instance) =>
<String, dynamic>{
'id': instance.id,
'slug': instance.slug,
'image': instance.image.toJson(),
'pack_id': instance.packId,
'pack': instance.pack?.toJson(),
'created_at': instance.createdAt.toIso8601String(),
'updated_at': instance.updatedAt.toIso8601String(),
'deleted_at': instance.deletedAt?.toIso8601String(),
};
_SnStickerPack _$SnStickerPackFromJson(Map<String, dynamic> json) =>
_SnStickerPack(
id: json['id'] as String,
name: json['name'] as String,
description: json['description'] as String,
prefix: json['prefix'] as String,
publisherId: json['publisher_id'] as String,
icon: json['icon'] == null
? null
: SnCloudFile.fromJson(json['icon'] as Map<String, dynamic>),
publisher: json['publisher'] == null
? null
: SnPublisher.fromJson(json['publisher'] as Map<String, dynamic>),
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),
stickers:
(json['stickers'] as List<dynamic>?)
?.map((e) => SnSticker.fromJson(e as Map<String, dynamic>))
.toList() ??
const [],
);
Map<String, dynamic> _$SnStickerPackToJson(_SnStickerPack instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'description': instance.description,
'prefix': instance.prefix,
'publisher_id': instance.publisherId,
'icon': instance.icon?.toJson(),
'publisher': instance.publisher?.toJson(),
'created_at': instance.createdAt.toIso8601String(),
'updated_at': instance.updatedAt.toIso8601String(),
'deleted_at': instance.deletedAt?.toIso8601String(),
'stickers': instance.stickers.map((e) => e.toJson()).toList(),
};

View File

@@ -0,0 +1,468 @@
import 'dart:math' as math;
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/stickers/stickers_models/sticker.dart';
import 'package:island/core/network.dart';
import 'package:island/drive/drive_widgets/cloud_files.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:flutter_popup_card/flutter_popup_card.dart';
import 'package:island/shared/widgets/extended_refresh_indicator.dart';
part 'sticker_picker.g.dart';
/// Fetch user-added sticker packs (with stickers) from API:
/// GET /sphere/stickers/me
@riverpod
Future<List<SnStickerPack>> myStickerPacks(Ref ref) async {
final api = ref.watch(apiClientProvider);
final resp = await api.get('/sphere/stickers/me');
final data = resp.data;
if (data is List) {
return data
.map((e) => SnStickerPack.fromJson(e as Map<String, dynamic>))
.toList();
}
return const <SnStickerPack>[];
}
/// Sticker Picker popover dialog
/// - Displays user-owned sticker packs as tabs (chips)
/// - Shows grid of stickers in selected pack
/// - On tap, returns placeholder string :{prefix}+{slug}: via onPick callback
class StickerPicker extends HookConsumerWidget {
final void Function(String placeholder) onPick;
const StickerPicker({super.key, required this.onPick});
@override
Widget build(BuildContext context, WidgetRef ref) {
final packsAsync = ref.watch(myStickerPacksProvider);
return PopupCard(
elevation: 8,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 520, maxHeight: 520),
child: packsAsync.when(
data: (packs) {
if (packs.isEmpty) {
return _EmptyState(
onRefresh: () async {
ref.invalidate(myStickerPacksProvider);
},
);
}
// Maintain selected index locally with a ValueNotifier to avoid hooks dependency
return _PackSwitcher(
packs: packs,
onPick: (pack, sticker) {
final placeholder = ':${pack.prefix}+${sticker.slug}:';
HapticFeedback.selectionClick();
onPick(placeholder);
if (Navigator.of(context).canPop()) {
Navigator.of(context).pop();
}
},
onRefresh: () async {
ref.invalidate(myStickerPacksProvider);
},
);
},
loading: () => const SizedBox(
width: 320,
height: 320,
child: Center(child: CircularProgressIndicator()),
),
error: (err, _) => SizedBox(
width: 360,
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Symbols.error, size: 28),
const Gap(8),
Text('Error: $err', textAlign: TextAlign.center),
const Gap(12),
FilledButton.icon(
onPressed: () => ref.invalidate(myStickerPacksProvider),
icon: const Icon(Symbols.refresh),
label: Text('retry').tr(),
),
],
).padding(all: 16),
),
),
),
);
}
}
class _EmptyState extends StatelessWidget {
final Future<void> Function() onRefresh;
const _EmptyState({required this.onRefresh});
@override
Widget build(BuildContext context) {
return SizedBox(
width: 360,
height: 220,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Symbols.emoji_symbols, size: 28),
const Gap(8),
Text('noStickerPacks'.tr(), textAlign: TextAlign.center),
const Gap(12),
OutlinedButton.icon(
onPressed: onRefresh,
icon: const Icon(Symbols.refresh),
label: Text('refresh').tr(),
),
],
).padding(all: 16),
);
}
}
class _PackSwitcher extends StatefulWidget {
final List<SnStickerPack> packs;
final void Function(SnStickerPack pack, SnSticker sticker) onPick;
final Future<void> Function() onRefresh;
const _PackSwitcher({
required this.packs,
required this.onPick,
required this.onRefresh,
});
@override
State<_PackSwitcher> createState() => _PackSwitcherState();
}
class _PackSwitcherState extends State<_PackSwitcher> {
int _index = 0;
@override
Widget build(BuildContext context) {
final packs = widget.packs;
_index = _index.clamp(0, packs.length - 1);
final selectedPack = packs[_index];
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Header
Row(
children: [
const Icon(Symbols.sticky_note_2, size: 20),
const Gap(8),
Text(
'stickers'.tr(),
style: Theme.of(context).textTheme.titleMedium,
),
const Spacer(),
IconButton(
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
tooltip: 'close'.tr(),
onPressed: () => Navigator.of(context).maybePop(),
icon: const Icon(Symbols.close),
),
],
).padding(horizontal: 12, top: 8),
// Vertical, scrollable packs rail like common emoji pickers
SizedBox(
height: 48,
child: ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: 8),
scrollDirection: Axis.horizontal,
itemCount: packs.length,
separatorBuilder: (_, _) => const Gap(4),
itemBuilder: (context, i) {
final selected = _index == i;
return Tooltip(
message: packs[i].name,
child: FilterChip(
label: Text(packs[i].name, overflow: TextOverflow.ellipsis),
selected: selected,
onSelected: (_) {
setState(() => _index = i);
HapticFeedback.selectionClick();
},
),
);
},
),
).padding(bottom: 8),
const Divider(height: 1),
// Content
Expanded(
child: ExtendedRefreshIndicator(
onRefresh: widget.onRefresh,
child: _StickersGrid(
pack: selectedPack,
onPick: (sticker) => widget.onPick(selectedPack, sticker),
),
),
),
],
);
}
}
class _StickersGrid extends StatelessWidget {
final SnStickerPack pack;
final void Function(SnSticker sticker) onPick;
const _StickersGrid({required this.pack, required this.onPick});
@override
Widget build(BuildContext context) {
final stickers = pack.stickers;
if (stickers.isEmpty) {
return Center(child: Text('noStickersInPack'.tr()));
}
return GridView.builder(
physics: const AlwaysScrollableScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 56,
mainAxisSpacing: 8,
crossAxisSpacing: 8,
),
itemCount: stickers.length,
itemBuilder: (context, index) {
final sticker = stickers[index];
final placeholder = ':${pack.prefix}+${sticker.slug}:';
return Tooltip(
message: placeholder,
child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(8)),
onTap: () => onPick(sticker),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: DecoratedBox(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
borderRadius: const BorderRadius.all(Radius.circular(8)),
),
child: AspectRatio(
aspectRatio: 1,
child: CloudImageWidget(
file: sticker.image,
fit: BoxFit.contain,
),
),
),
),
),
);
},
);
}
}
/// Embedded Sticker Picker variant
/// No background card, no title header, suitable for embedding in other UI
class StickerPickerEmbedded extends HookConsumerWidget {
final double? height;
final void Function(String placeholder) onPick;
const StickerPickerEmbedded({super.key, required this.onPick, this.height});
@override
Widget build(BuildContext context, WidgetRef ref) {
final packsAsync = ref.watch(myStickerPacksProvider);
return packsAsync.when(
data: (packs) {
if (packs.isEmpty) {
return _EmptyState(
onRefresh: () async {
ref.invalidate(myStickerPacksProvider);
},
);
}
return _EmbeddedPackSwitcher(
packs: packs,
onPick: (pack, sticker) {
final placeholder = ':${pack.prefix}+${sticker.slug}:';
HapticFeedback.selectionClick();
onPick(placeholder);
},
onRefresh: () async {
ref.invalidate(myStickerPacksProvider);
},
);
},
loading: () => SizedBox(
width: 320,
height: height ?? 320,
child: const Center(child: CircularProgressIndicator()),
),
error: (err, _) => SizedBox(
width: 360,
height: height ?? 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Symbols.error, size: 28),
const Gap(8),
Text('Error: $err', textAlign: TextAlign.center),
const Gap(12),
FilledButton.icon(
onPressed: () => ref.invalidate(myStickerPacksProvider),
icon: const Icon(Symbols.refresh),
label: Text('retry').tr(),
),
],
).padding(all: 16),
),
);
}
}
class _EmbeddedPackSwitcher extends StatefulWidget {
final List<SnStickerPack> packs;
final void Function(SnStickerPack pack, SnSticker sticker) onPick;
final Future<void> Function() onRefresh;
const _EmbeddedPackSwitcher({
required this.packs,
required this.onPick,
required this.onRefresh,
});
@override
State<_EmbeddedPackSwitcher> createState() => _EmbeddedPackSwitcherState();
}
class _EmbeddedPackSwitcherState extends State<_EmbeddedPackSwitcher> {
int _index = 0;
@override
Widget build(BuildContext context) {
final packs = widget.packs;
_index = _index.clamp(0, packs.length - 1);
final selectedPack = packs[_index];
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Gap(12),
// Vertical, scrollable packs rail like common emoji pickers
Card(
margin: EdgeInsets.zero,
child: SizedBox(
height: 36,
child: ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: 12),
scrollDirection: Axis.horizontal,
itemCount: packs.length,
separatorBuilder: (_, _) => const Gap(4),
itemBuilder: (context, i) {
final selected = _index == i;
return Tooltip(
message: packs[i].name,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
decoration: BoxDecoration(
color: selected
? Theme.of(context).colorScheme.primaryContainer
: Theme.of(context).colorScheme.surfaceContainer,
borderRadius: const BorderRadius.all(Radius.circular(8)),
border: selected
? Border.all(
color: Theme.of(context).colorScheme.primary,
width: 4,
)
: null,
),
margin: const EdgeInsets.only(right: 8),
child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(8)),
onTap: () {
setState(() => _index = i);
HapticFeedback.selectionClick();
},
child: TweenAnimationBuilder<double>(
tween: Tween<double>(end: selected ? 4 : 8),
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
builder: (context, value, _) {
return packs[i].icon != null
? CloudImageWidget(
file: packs[i].icon!,
).clipRRect(all: value)
: CloudImageWidget(
file: packs[i].stickers.firstOrNull?.image,
).clipRRect(all: value);
},
),
),
),
);
},
),
).padding(vertical: 4),
).padding(horizontal: 12),
// Content
Expanded(
child: ExtendedRefreshIndicator(
onRefresh: widget.onRefresh,
child: _StickersGrid(
pack: selectedPack,
onPick: (sticker) => widget.onPick(selectedPack, sticker),
).padding(horizontal: 2),
),
),
],
);
}
}
/// Helper to show sticker picker as an anchored popover near the trigger.
/// Provide the button's BuildContext (typically from the onPressed closure).
/// Fallbacks to dialog if overlay cannot be found (e.g., during tests).
Future<void> showStickerPickerPopover(
BuildContext context,
Offset offset, {
Alignment? alignment,
required void Function(String placeholder) onPick,
}) async {
// Use flutter_popup_card to present the anchored popup near trigger.
await showPopupCard<void>(
context: context,
offset: offset,
alignment: alignment ?? Alignment.topLeft,
dimBackground: true,
builder: (ctx) => SizedBox(
width: math.min(480, MediaQuery.of(context).size.width * 0.9),
height: 480,
child: ProviderScope(
child: StickerPicker(
onPick: (ph) {
onPick(ph);
Navigator.of(ctx).maybePop();
},
),
),
),
);
}

View File

@@ -0,0 +1,58 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'sticker_picker.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
/// Fetch user-added sticker packs (with stickers) from API:
/// GET /sphere/stickers/me
@ProviderFor(myStickerPacks)
final myStickerPacksProvider = MyStickerPacksProvider._();
/// Fetch user-added sticker packs (with stickers) from API:
/// GET /sphere/stickers/me
final class MyStickerPacksProvider
extends
$FunctionalProvider<
AsyncValue<List<SnStickerPack>>,
List<SnStickerPack>,
FutureOr<List<SnStickerPack>>
>
with
$FutureModifier<List<SnStickerPack>>,
$FutureProvider<List<SnStickerPack>> {
/// Fetch user-added sticker packs (with stickers) from API:
/// GET /sphere/stickers/me
MyStickerPacksProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'myStickerPacksProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$myStickerPacksHash();
@$internal
@override
$FutureProviderElement<List<SnStickerPack>> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<List<SnStickerPack>> create(Ref ref) {
return myStickerPacks(ref);
}
}
String _$myStickerPacksHash() => r'1e19832e8ab1cb139ad18aebfa5aebdf4fdea499';