mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-07 13:38:13 -08:00
234 lines
7.7 KiB
Dart
234 lines
7.7 KiB
Dart
import 'dart:convert';
|
|
import 'package:chopper/chopper.dart';
|
|
import 'package:fladder/models/item_base_model.dart';
|
|
import 'package:fladder/models/item_editing_model.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
|
import 'package:fladder/providers/api_provider.dart';
|
|
|
|
final editItemProvider =
|
|
StateNotifierProvider.autoDispose<EditItemNotifier, ItemEditingModel>((ref) => EditItemNotifier(ref));
|
|
|
|
class EditItemNotifier extends StateNotifier<ItemEditingModel> {
|
|
EditItemNotifier(this.ref) : super(ItemEditingModel());
|
|
|
|
final Ref ref;
|
|
|
|
late final api = ref.read(jellyApiProvider);
|
|
|
|
Map<String, dynamic>? get getFields => state.editAbleFields();
|
|
Map<String, dynamic>? get advancedFields => state.editAdvancedAbleFields(ref);
|
|
|
|
Future<void> fetchInformation(String id) async {
|
|
state = ItemEditingModel();
|
|
final itemResponse = await api.usersUserIdItemsItemIdGet(
|
|
itemId: id,
|
|
);
|
|
final itemModel = itemResponse.body;
|
|
if (itemModel == null) return;
|
|
final images = await api.itemsItemIdImagesGet(itemId: itemModel.id);
|
|
|
|
state = state.copyWith(
|
|
item: () => itemModel,
|
|
json: () => jsonDecode(itemResponse.bodyString),
|
|
editedJson: () => jsonDecode(itemResponse.bodyString),
|
|
primary: state.primary.copyWith(
|
|
serverImages: images.body
|
|
?.where((element) => element.imageType == ImageType.primary)
|
|
.map((e) => EditingImageModel.fromImage(e, itemModel.id, ref))
|
|
.toList(),
|
|
),
|
|
logo: state.logo.copyWith(
|
|
serverImages: images.body
|
|
?.where((element) => element.imageType == ImageType.logo)
|
|
.map((e) => EditingImageModel.fromImage(e, itemModel.id, ref))
|
|
.toList(),
|
|
),
|
|
backdrop: state.backdrop.copyWith(
|
|
serverImages: images.body
|
|
?.where((element) => element.imageType == ImageType.backdrop)
|
|
.map((e) => EditingImageModel.fromImage(e, itemModel.id, ref))
|
|
.toList(),
|
|
),
|
|
);
|
|
final response = await api.itemsItemIdMetadataEditorGet(itemId: id);
|
|
state = state.copyWith(
|
|
editorInfo: () => response.bodyOrThrow,
|
|
);
|
|
}
|
|
|
|
Future<Response<dynamic>?> fetchRemoteImages({ImageType type = ImageType.primary}) async {
|
|
final currentItem = state.item;
|
|
if (currentItem == null) return null;
|
|
final response = await api.itemsItemIdRemoteImagesGet(
|
|
itemId: currentItem.id,
|
|
type: type,
|
|
includeAllLanguages: state.includeAllImages,
|
|
);
|
|
final newImages = (response.body?.images ?? []).map((e) => EditingImageModel.fromDto(e)).toList();
|
|
switch (type) {
|
|
case ImageType.backdrop:
|
|
state = state.copyWith(backdrop: state.backdrop.copyWith(images: newImages));
|
|
case ImageType.logo:
|
|
state = state.copyWith(logo: state.logo.copyWith(images: newImages));
|
|
case ImageType.primary:
|
|
default:
|
|
state = state.copyWith(primary: state.primary.copyWith(images: newImages));
|
|
}
|
|
return response;
|
|
}
|
|
|
|
Future<void> updateField(MapEntry<String, dynamic> field) async {
|
|
final editedJson = state.editedJson;
|
|
editedJson?.update(
|
|
field.key,
|
|
(value) => field.value,
|
|
ifAbsent: () => editedJson.addEntries({field}),
|
|
);
|
|
|
|
state = state.copyWith(
|
|
editedJson: () => editedJson,
|
|
);
|
|
}
|
|
|
|
Future<void> resetChanged() async {
|
|
state = state.copyWith(
|
|
editedJson: () => state.json,
|
|
);
|
|
}
|
|
|
|
Future<Response<ItemBaseModel>?> saveInformation() async {
|
|
final currentItem = state.item;
|
|
if (currentItem == null) return null;
|
|
final jsonBody = state.editedJson;
|
|
if (jsonBody == null) return null;
|
|
state = state.copyWith(saving: true);
|
|
final response = await api.itemsItemIdPost(
|
|
itemId: currentItem.id,
|
|
body: BaseItemDto.fromJson(jsonBody),
|
|
);
|
|
await state.primary.setImage(
|
|
ImageType.primary,
|
|
uploadData: uploadImage,
|
|
uploadUrl: _setImage,
|
|
);
|
|
await state.logo.setImage(
|
|
ImageType.logo,
|
|
uploadData: uploadImage,
|
|
uploadUrl: _setImage,
|
|
);
|
|
|
|
await state.backdrop.setImage(
|
|
ImageType.backdrop,
|
|
uploadData: uploadImage,
|
|
uploadUrl: _setImage,
|
|
);
|
|
|
|
final newItem = await api.usersUserIdItemsItemIdGet(itemId: currentItem.id);
|
|
|
|
state = state.copyWith(saving: false);
|
|
return response.copyWith(body: newItem.body);
|
|
}
|
|
|
|
Future<Response<dynamic>?> uploadImage(EditingImageModel? imageModel) async {
|
|
final currentItem = state.item;
|
|
if (currentItem == null || imageModel == null) return null;
|
|
final response = await api.itemIdImagesImageTypePost(
|
|
imageModel.type,
|
|
currentItem.id,
|
|
imageModel.imageData!,
|
|
);
|
|
return response;
|
|
}
|
|
|
|
Future<Response<dynamic>?> _setImage(EditingImageModel? imageModel) async {
|
|
final currentItem = state.item;
|
|
if (currentItem == null) return null;
|
|
if (imageModel == null) return null;
|
|
return await api.itemsItemIdRemoteImagesDownloadPost(
|
|
itemId: state.item?.id,
|
|
type: imageModel.type,
|
|
imageUrl: imageModel.url,
|
|
);
|
|
}
|
|
|
|
void selectImage(ImageType type, EditingImageModel? image) {
|
|
switch (type) {
|
|
case ImageType.primary:
|
|
state = state.copyWith(
|
|
primary: state.primary.copyWith(selected: () => state.primary.selected == image ? null : image));
|
|
case ImageType.logo:
|
|
state = state.copyWith(logo: state.logo.copyWith(selected: () => state.logo.selected == image ? null : image));
|
|
default:
|
|
if (image == null) return;
|
|
state = state.copyWith(
|
|
backdrop: state.backdrop.copyWith(
|
|
selection: state.backdrop.selection.contains(image)
|
|
? (List.of(state.backdrop.selection)..remove(image))
|
|
: [...state.backdrop.selection, image],
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void setIncludeImages(bool value) => state = state.copyWith(includeAllImages: value);
|
|
|
|
void addCustomImages(ImageType type, Iterable<EditingImageModel> list) {
|
|
switch (type) {
|
|
case ImageType.primary:
|
|
state = state.copyWith(
|
|
primary: state.primary.copyWith(
|
|
customImages: [...state.primary.customImages, ...list],
|
|
selected: () => list.firstOrNull,
|
|
),
|
|
);
|
|
return;
|
|
case ImageType.logo:
|
|
state = state.copyWith(
|
|
logo: state.logo.copyWith(
|
|
customImages: [...state.logo.customImages, ...list],
|
|
selected: () => list.firstOrNull,
|
|
),
|
|
);
|
|
return;
|
|
case ImageType.backdrop:
|
|
state = state.copyWith(
|
|
backdrop: state.backdrop.copyWith(
|
|
customImages: [...state.backdrop.customImages, ...list],
|
|
selection: [...state.backdrop.selection, ...list]),
|
|
);
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
Future<Response<dynamic>?> deleteImage(ImageType type, EditingImageModel image) async {
|
|
final currentItem = state.item;
|
|
if (currentItem == null) return null;
|
|
final response = await api.itemsItemIdImagesImageTypeDelete(
|
|
itemId: state.item?.id,
|
|
imageType: type,
|
|
imageIndex: image.index,
|
|
);
|
|
switch (type) {
|
|
case ImageType.primary:
|
|
state = state.copyWith(
|
|
primary: state.primary
|
|
.copyWith(serverImages: state.primary.serverImages..removeWhere((element) => element == image)),
|
|
);
|
|
case ImageType.logo:
|
|
state = state.copyWith(
|
|
logo: state.logo.copyWith(serverImages: state.logo.serverImages..removeWhere((element) => element == image)),
|
|
);
|
|
case ImageType.backdrop:
|
|
state = state.copyWith(
|
|
backdrop: state.backdrop
|
|
.copyWith(serverImages: state.backdrop.serverImages..removeWhere((element) => element == image)),
|
|
);
|
|
default:
|
|
}
|
|
return response;
|
|
}
|
|
}
|