diff --git a/lib/models/sticker.dart b/lib/models/sticker.dart index 0e3d700f..29ab6742 100644 --- a/lib/models/sticker.dart +++ b/lib/models/sticker.dart @@ -30,6 +30,7 @@ sealed class SnStickerPack with _$SnStickerPack { required String description, required String prefix, required String publisherId, + required SnCloudFile? icon, required SnPublisher? publisher, required DateTime createdAt, required DateTime updatedAt, diff --git a/lib/models/sticker.freezed.dart b/lib/models/sticker.freezed.dart index db8c8c2f..a5213366 100644 --- a/lib/models/sticker.freezed.dart +++ b/lib/models/sticker.freezed.dart @@ -335,7 +335,7 @@ $SnStickerPackCopyWith<$Res>? get pack { /// @nodoc mixin _$SnStickerPack { - String get id; String get name; String get description; String get prefix; String get publisherId; SnPublisher? get publisher; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; List get stickers; + 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 get stickers; /// Create a copy of SnStickerPack /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -348,16 +348,16 @@ $SnStickerPackCopyWith get copyWith => _$SnStickerPackCopyWithImp @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.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)); + 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,publisher,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(stickers)); +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, publisher: $publisher, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stickers: $stickers)'; + return 'SnStickerPack(id: $id, name: $name, description: $description, prefix: $prefix, publisherId: $publisherId, icon: $icon, publisher: $publisher, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stickers: $stickers)'; } @@ -368,11 +368,11 @@ 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, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List stickers + String id, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List stickers }); -$SnPublisherCopyWith<$Res>? get publisher; +$SnCloudFileCopyWith<$Res>? get icon;$SnPublisherCopyWith<$Res>? get publisher; } /// @nodoc @@ -385,14 +385,15 @@ class _$SnStickerPackCopyWithImpl<$Res> /// 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? publisher = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? stickers = null,}) { +@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,publisher: freezed == publisher ? _self.publisher : publisher // 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 @@ -404,6 +405,18 @@ as List, /// 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; @@ -491,10 +504,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String name, String description, String prefix, String publisherId, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List stickers)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List 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.publisher,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.stickers);case _: +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(); } @@ -512,10 +525,10 @@ return $default(_that.id,_that.name,_that.description,_that.prefix,_that.publish /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id, String name, String description, String prefix, String publisherId, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List stickers) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String id, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List stickers) $default,) {final _that = this; switch (_that) { case _SnStickerPack(): -return $default(_that.id,_that.name,_that.description,_that.prefix,_that.publisherId,_that.publisher,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.stickers);} +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` /// @@ -529,10 +542,10 @@ return $default(_that.id,_that.name,_that.description,_that.prefix,_that.publish /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String name, String description, String prefix, String publisherId, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List stickers)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List 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.publisher,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.stickers);case _: +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; } @@ -544,7 +557,7 @@ return $default(_that.id,_that.name,_that.description,_that.prefix,_that.publish @JsonSerializable() class _SnStickerPack implements SnStickerPack { - const _SnStickerPack({required this.id, required this.name, required this.description, required this.prefix, required this.publisherId, required this.publisher, required this.createdAt, required this.updatedAt, required this.deletedAt, final List stickers = const []}): _stickers = stickers; + 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 stickers = const []}): _stickers = stickers; factory _SnStickerPack.fromJson(Map json) => _$SnStickerPackFromJson(json); @override final String id; @@ -552,6 +565,7 @@ class _SnStickerPack implements SnStickerPack { @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; @@ -577,16 +591,16 @@ Map 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.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)); + 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,publisher,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(_stickers)); +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, publisher: $publisher, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stickers: $stickers)'; + return 'SnStickerPack(id: $id, name: $name, description: $description, prefix: $prefix, publisherId: $publisherId, icon: $icon, publisher: $publisher, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stickers: $stickers)'; } @@ -597,11 +611,11 @@ abstract mixin class _$SnStickerPackCopyWith<$Res> implements $SnStickerPackCopy factory _$SnStickerPackCopyWith(_SnStickerPack value, $Res Function(_SnStickerPack) _then) = __$SnStickerPackCopyWithImpl; @override @useResult $Res call({ - String id, String name, String description, String prefix, String publisherId, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List stickers + String id, String name, String description, String prefix, String publisherId, SnCloudFile? icon, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List stickers }); -@override $SnPublisherCopyWith<$Res>? get publisher; +@override $SnCloudFileCopyWith<$Res>? get icon;@override $SnPublisherCopyWith<$Res>? get publisher; } /// @nodoc @@ -614,14 +628,15 @@ class __$SnStickerPackCopyWithImpl<$Res> /// 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? publisher = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? stickers = null,}) { +@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,publisher: freezed == publisher ? _self.publisher : publisher // 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 @@ -634,6 +649,18 @@ as List, /// 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; diff --git a/lib/models/sticker.g.dart b/lib/models/sticker.g.dart index a846a8e4..4770f4a0 100644 --- a/lib/models/sticker.g.dart +++ b/lib/models/sticker.g.dart @@ -42,6 +42,10 @@ _SnStickerPack _$SnStickerPackFromJson(Map json) => 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), publisher: json['publisher'] == null ? null @@ -66,6 +70,7 @@ Map _$SnStickerPackToJson(_SnStickerPack instance) => '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(), diff --git a/lib/screens/creators/stickers/pack_detail.dart b/lib/screens/creators/stickers/pack_detail.dart index 85e915e2..2b578199 100644 --- a/lib/screens/creators/stickers/pack_detail.dart +++ b/lib/screens/creators/stickers/pack_detail.dart @@ -320,7 +320,6 @@ class StickerForm extends HookConsumerWidget { final formKey = useMemoized(() => GlobalKey(), []); final image = useState(id == null ? '' : sticker.value?.image.id); - final imageController = useTextEditingController(text: image.value); final slugController = useTextEditingController( text: id == null ? '' : sticker.value?.slug, ); @@ -328,7 +327,6 @@ class StickerForm extends HookConsumerWidget { useEffect(() { if (sticker.value != null) { image.value = sticker.value!.image.id; - imageController.text = sticker.value!.image.id; slugController.text = sticker.value!.slug; } return null; @@ -344,7 +342,7 @@ class StickerForm extends HookConsumerWidget { id == null ? '/sphere/stickers/$packId/content' : '/sphere/stickers/$packId/content/$id', - data: {'slug': slugController.text, 'image_id': imageController.text}, + data: {'slug': slugController.text, 'image_id': image.value}, options: Options(method: id == null ? 'POST' : 'PATCH'), ); if (context.mounted) { @@ -392,7 +390,6 @@ class StickerForm extends HookConsumerWidget { ).then((value) { if (value == null) return; image.value = value[0].id; - imageController.text = image.value!; }); }, icon: const Icon(Symbols.cloud_upload), diff --git a/lib/screens/creators/stickers/stickers.dart b/lib/screens/creators/stickers/stickers.dart index 355968da..47ea955e 100644 --- a/lib/screens/creators/stickers/stickers.dart +++ b/lib/screens/creators/stickers/stickers.dart @@ -4,11 +4,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:island/models/file.dart'; import 'package:island/models/sticker.dart'; import 'package:island/pods/network.dart'; import 'package:island/services/responsive.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; +import 'package:island/widgets/content/cloud_file_picker.dart'; +import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/content/sheet.dart'; import 'package:island/screens/creators/stickers/pack_detail.dart'; import 'package:material_symbols_icons/symbols.dart'; @@ -207,6 +210,9 @@ class StickerPackForm extends HookConsumerWidget { final formKey = useMemoized(() => GlobalKey(), []); final initialPack = ref.watch(stickerPackProvider(packId)); + final icon = useState( + packId == null ? '' : initialPack.value?.icon?.id, + ); final nameController = useTextEditingController(); final descriptionController = useTextEditingController(); final prefixController = useTextEditingController(); @@ -229,11 +235,12 @@ class StickerPackForm extends HookConsumerWidget { submitting.value = true; final apiClient = ref.watch(apiClientProvider); final resp = await apiClient.request( - '/sphere/stickers', + packId == null ? '/sphere/stickers' : '/sphere/stickers/$packId', data: { 'name': nameController.text, 'description': descriptionController.text, 'prefix': prefixController.text, + 'icon_id': icon.value, }, queryParameters: {'pub': pubName}, options: Options(method: packId == null ? 'POST' : 'PATCH'), @@ -255,6 +262,44 @@ class StickerPackForm extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.stretch, spacing: 16, children: [ + Row( + spacing: 8, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SizedBox( + height: 80, + width: 80, + child: ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(8)), + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainer, + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + child: + (icon.value?.isEmpty ?? true) + ? const SizedBox.shrink() + : CloudImageWidget(fileId: icon.value!), + ), + ), + ), + IconButton.filledTonal( + onPressed: () { + showModalBottomSheet( + context: context, + builder: + (context) => CloudFilePicker( + allowedTypes: {UniversalFileType.image}, + ), + ).then((value) { + if (value == null) return; + icon.value = value[0].id; + }); + }, + icon: const Icon(Symbols.cloud_upload), + ), + ], + ), TextFormField( controller: nameController, decoration: InputDecoration(