mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-10 07:50:28 -07:00
fix: Improve null handling when parsing image urls (#228)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
06c4af81e7
commit
a34f8fe2f4
3 changed files with 100 additions and 188 deletions
|
|
@ -12,7 +12,6 @@ import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart' as enums;
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
|
||||||
import 'package:fladder/providers/image_provider.dart';
|
import 'package:fladder/providers/image_provider.dart';
|
||||||
import 'package:fladder/util/custom_cache_manager.dart';
|
import 'package:fladder/util/custom_cache_manager.dart';
|
||||||
import 'package:fladder/util/jelly_id.dart';
|
|
||||||
|
|
||||||
class ImagesData {
|
class ImagesData {
|
||||||
final ImageData? primary;
|
final ImageData? primary;
|
||||||
|
|
@ -35,74 +34,80 @@ class ImagesData {
|
||||||
|
|
||||||
ImageData? get randomBackDrop => (backDrop?..shuffle())?.firstOrNull ?? primary;
|
ImageData? get randomBackDrop => (backDrop?..shuffle())?.firstOrNull ?? primary;
|
||||||
|
|
||||||
factory ImagesData.fromBaseItem(
|
static ImagesData? fromBaseItem(
|
||||||
dto.BaseItemDto item,
|
dto.BaseItemDto item,
|
||||||
Ref ref, {
|
Ref ref, {
|
||||||
Size backDrop = const Size(2000, 2000),
|
Size backDrop = const Size(2000, 2000),
|
||||||
Size logo = const Size(1000, 1000),
|
Size logo = const Size(1000, 1000),
|
||||||
Size primary = const Size(600, 600),
|
Size primary = const Size(600, 600),
|
||||||
bool getOriginalSize = false,
|
bool getOriginalSize = false,
|
||||||
int quality = 90,
|
int quality = 95,
|
||||||
}) {
|
}) {
|
||||||
|
final itemid = item.id;
|
||||||
|
if (itemid == null) return null;
|
||||||
|
final imageProvider = ref.read(imageUtilityProvider);
|
||||||
final newImgesData = ImagesData(
|
final newImgesData = ImagesData(
|
||||||
primary: item.imageTags?['Primary'] != null
|
primary: item.imageTags?['Primary'] != null
|
||||||
? ImageData(
|
? ImageData(
|
||||||
path: getOriginalSize
|
path: getOriginalSize
|
||||||
? ref.read(imageUtilityProvider).getItemsOrigImageUrl(
|
? imageProvider.getItemsOrigImageUrl(
|
||||||
item.id!,
|
itemid,
|
||||||
type: enums.ImageType.primary,
|
type: enums.ImageType.primary,
|
||||||
)
|
)
|
||||||
: ref.read(imageUtilityProvider).getItemsImageUrl(
|
: imageProvider.getItemsImageUrl(
|
||||||
(item.id!),
|
itemid,
|
||||||
type: enums.ImageType.primary,
|
type: enums.ImageType.primary,
|
||||||
maxHeight: primary.height.toInt(),
|
maxHeight: primary.height.toInt(),
|
||||||
maxWidth: primary.width.toInt(),
|
maxWidth: primary.width.toInt(),
|
||||||
quality: quality,
|
quality: quality,
|
||||||
),
|
),
|
||||||
key: item.imageTags?['Primary'],
|
key: item.imageTags?['Primary'],
|
||||||
hash: item.imageBlurHashes?.primary?[item.imageTags?['Primary']] as String? ?? "",
|
hash: item.imageBlurHashes?.primary?[item.imageTags?['Primary']] ?? "",
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
logo: item.imageTags?['Logo'] != null
|
logo: item.imageTags?['Logo'] != null
|
||||||
? ImageData(
|
? ImageData(
|
||||||
path: getOriginalSize
|
path: getOriginalSize
|
||||||
? ref.read(imageUtilityProvider).getItemsOrigImageUrl(
|
? imageProvider.getItemsOrigImageUrl(
|
||||||
item.id!,
|
itemid,
|
||||||
type: enums.ImageType.logo,
|
type: enums.ImageType.logo,
|
||||||
)
|
|
||||||
: ref.read(imageUtilityProvider).getItemsImageUrl(
|
|
||||||
(item.id!),
|
|
||||||
type: enums.ImageType.logo,
|
|
||||||
maxHeight: logo.height.toInt(),
|
|
||||||
maxWidth: logo.width.toInt(),
|
|
||||||
quality: quality,
|
|
||||||
),
|
|
||||||
key: item.imageTags?['Logo'],
|
|
||||||
hash: item.imageBlurHashes?.logo?[item.imageTags?['Logo']] as String? ?? "")
|
|
||||||
: null,
|
|
||||||
backDrop: (item.backdropImageTags ?? []).mapIndexed(
|
|
||||||
(index, backdrop) {
|
|
||||||
final image = ImageData(
|
|
||||||
path: getOriginalSize
|
|
||||||
? ref.read(imageUtilityProvider).getBackdropOrigImage(
|
|
||||||
item.id!,
|
|
||||||
index,
|
|
||||||
backdrop,
|
|
||||||
)
|
)
|
||||||
: ref.read(imageUtilityProvider).getBackdropImage(
|
: imageProvider.getItemsImageUrl(
|
||||||
(item.id!),
|
itemid,
|
||||||
index,
|
type: enums.ImageType.logo,
|
||||||
backdrop,
|
maxHeight: logo.height.toInt(),
|
||||||
maxHeight: backDrop.height.toInt(),
|
maxWidth: logo.width.toInt(),
|
||||||
maxWidth: backDrop.width.toInt(),
|
|
||||||
quality: quality,
|
quality: quality,
|
||||||
),
|
),
|
||||||
key: backdrop,
|
key: item.imageTags?['Logo'],
|
||||||
hash: item.imageBlurHashes?.backdrop?[backdrop] ?? jellyId,
|
hash: item.imageBlurHashes?.logo?[item.imageTags?['Logo']] ?? "")
|
||||||
);
|
: null,
|
||||||
return image;
|
backDrop: (item.backdropImageTags ?? [])
|
||||||
},
|
.mapIndexed(
|
||||||
).toList(),
|
(index, backdrop) {
|
||||||
|
final image = ImageData(
|
||||||
|
path: getOriginalSize
|
||||||
|
? imageProvider.getBackdropOrigImage(
|
||||||
|
itemid,
|
||||||
|
index,
|
||||||
|
backdrop,
|
||||||
|
)
|
||||||
|
: imageProvider.getBackdropImage(
|
||||||
|
itemid,
|
||||||
|
index,
|
||||||
|
backdrop,
|
||||||
|
maxHeight: backDrop.height.toInt(),
|
||||||
|
maxWidth: backDrop.width.toInt(),
|
||||||
|
quality: quality,
|
||||||
|
),
|
||||||
|
key: backdrop,
|
||||||
|
hash: item.imageBlurHashes?.backdrop?[backdrop] ?? "",
|
||||||
|
);
|
||||||
|
return image;
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.nonNulls
|
||||||
|
.toList(),
|
||||||
);
|
);
|
||||||
return newImgesData;
|
return newImgesData;
|
||||||
}
|
}
|
||||||
|
|
@ -113,51 +118,59 @@ class ImagesData {
|
||||||
Size backDrop = const Size(2000, 2000),
|
Size backDrop = const Size(2000, 2000),
|
||||||
Size logo = const Size(1000, 1000),
|
Size logo = const Size(1000, 1000),
|
||||||
Size primary = const Size(600, 600),
|
Size primary = const Size(600, 600),
|
||||||
int quality = 90,
|
int quality = 95,
|
||||||
}) {
|
}) {
|
||||||
if (item.seriesId == null && item.parentId == null) return null;
|
if (item.seriesId == null && item.parentId == null) return null;
|
||||||
|
|
||||||
|
final imageProvider = ref.read(imageUtilityProvider);
|
||||||
|
|
||||||
final newImgesData = ImagesData(
|
final newImgesData = ImagesData(
|
||||||
primary: (item.seriesPrimaryImageTag != null)
|
primary: (item.seriesPrimaryImageTag != null)
|
||||||
? ImageData(
|
? ImageData(
|
||||||
path: ref.read(imageUtilityProvider).getItemsImageUrl(
|
path: imageProvider.getItemsImageUrl(
|
||||||
(item.seriesId!),
|
item.seriesId,
|
||||||
type: enums.ImageType.primary,
|
type: enums.ImageType.primary,
|
||||||
maxHeight: primary.height.toInt(),
|
maxHeight: primary.height.toInt(),
|
||||||
maxWidth: primary.width.toInt(),
|
maxWidth: primary.width.toInt(),
|
||||||
quality: quality,
|
quality: quality,
|
||||||
),
|
),
|
||||||
key: item.seriesPrimaryImageTag ?? "",
|
key: item.seriesPrimaryImageTag ?? "",
|
||||||
hash: item.imageBlurHashes?.primary?[item.seriesPrimaryImageTag] as String? ?? "")
|
hash: item.imageBlurHashes?.primary?[item.seriesPrimaryImageTag] ?? "")
|
||||||
: null,
|
: null,
|
||||||
logo: (item.parentLogoImageTag != null)
|
logo: (item.parentLogoImageTag != null)
|
||||||
? ImageData(
|
? ImageData(
|
||||||
path: ref.read(imageUtilityProvider).getItemsImageUrl(
|
path: imageProvider.getItemsImageUrl(
|
||||||
(item.seriesId!),
|
item.seriesId,
|
||||||
type: enums.ImageType.logo,
|
type: enums.ImageType.logo,
|
||||||
maxHeight: logo.height.toInt(),
|
maxHeight: logo.height.toInt(),
|
||||||
maxWidth: logo.width.toInt(),
|
maxWidth: logo.width.toInt(),
|
||||||
quality: quality,
|
quality: quality,
|
||||||
),
|
),
|
||||||
key: item.parentLogoImageTag ?? "",
|
key: item.parentLogoImageTag ?? "",
|
||||||
hash: item.imageBlurHashes?.logo?[item.parentLogoImageTag] as String? ?? "")
|
hash: item.imageBlurHashes?.logo?[item.parentLogoImageTag] ?? "")
|
||||||
: null,
|
: null,
|
||||||
backDrop: (item.backdropImageTags ?? []).mapIndexed(
|
backDrop: (item.backdropImageTags ?? [])
|
||||||
(index, backdrop) {
|
.mapIndexed(
|
||||||
final image = ImageData(
|
(index, backdrop) {
|
||||||
path: ref.read(imageUtilityProvider).getBackdropImage(
|
final itemId = item.seriesId ?? item.parentId;
|
||||||
((item.seriesId ?? item.parentId)!),
|
if (itemId == null) return null;
|
||||||
|
final image = ImageData(
|
||||||
|
path: imageProvider.getBackdropImage(
|
||||||
|
itemId,
|
||||||
index,
|
index,
|
||||||
backdrop,
|
backdrop,
|
||||||
maxHeight: backDrop.height.toInt(),
|
maxHeight: backDrop.height.toInt(),
|
||||||
maxWidth: backDrop.width.toInt(),
|
maxWidth: backDrop.width.toInt(),
|
||||||
quality: quality,
|
quality: quality,
|
||||||
),
|
),
|
||||||
key: backdrop,
|
key: backdrop,
|
||||||
hash: item.imageBlurHashes?.backdrop?[backdrop],
|
hash: item.imageBlurHashes?.backdrop?[backdrop] ?? "",
|
||||||
);
|
);
|
||||||
return image;
|
return image;
|
||||||
},
|
},
|
||||||
).toList(),
|
)
|
||||||
|
.nonNulls
|
||||||
|
.toList(),
|
||||||
);
|
);
|
||||||
return newImgesData;
|
return newImgesData;
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +181,7 @@ class ImagesData {
|
||||||
Size backDrop = const Size(2000, 2000),
|
Size backDrop = const Size(2000, 2000),
|
||||||
Size logo = const Size(1000, 1000),
|
Size logo = const Size(1000, 1000),
|
||||||
Size primary = const Size(2000, 2000),
|
Size primary = const Size(2000, 2000),
|
||||||
int quality = 90,
|
int quality = 95,
|
||||||
}) {
|
}) {
|
||||||
return ImagesData(
|
return ImagesData(
|
||||||
primary: (item.primaryImageTag != null && item.imageBlurHashes != null)
|
primary: (item.primaryImageTag != null && item.imageBlurHashes != null)
|
||||||
|
|
@ -181,7 +194,7 @@ class ImagesData {
|
||||||
quality: quality,
|
quality: quality,
|
||||||
),
|
),
|
||||||
key: item.primaryImageTag ?? "",
|
key: item.primaryImageTag ?? "",
|
||||||
hash: item.imageBlurHashes?.primary?[item.primaryImageTag] as String? ?? jellyId)
|
hash: item.imageBlurHashes?.primary?[item.primaryImageTag] ?? '')
|
||||||
: null,
|
: null,
|
||||||
logo: null,
|
logo: null,
|
||||||
backDrop: null,
|
backDrop: null,
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ class Person {
|
||||||
return Person(
|
return Person(
|
||||||
id: item.id ?? "",
|
id: item.id ?? "",
|
||||||
name: item.name ?? "",
|
name: item.name ?? "",
|
||||||
image: ImagesData.fromBaseItem(item, ref).primary,
|
image: ImagesData.fromBaseItem(item, ref)?.primary,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,107 +274,3 @@ class Studio {
|
||||||
@override
|
@override
|
||||||
int get hashCode => id.hashCode ^ name.hashCode;
|
int get hashCode => id.hashCode ^ name.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// class UserData {
|
|
||||||
// final bool isFavourite;
|
|
||||||
// final int playCount;
|
|
||||||
// final int? unPlayedItemCount;
|
|
||||||
// final int playbackPositionTicks;
|
|
||||||
// final double progress;
|
|
||||||
// final bool played;
|
|
||||||
// UserData({
|
|
||||||
// this.isFavourite = false,
|
|
||||||
// this.playCount = 0,
|
|
||||||
// this.unPlayedItemCount,
|
|
||||||
// this.playbackPositionTicks = 0,
|
|
||||||
// this.progress = 0,
|
|
||||||
// this.played = false,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// factory UserData.fromDto(dto.UserItemDataDto? dto) {
|
|
||||||
// if (dto == null) {
|
|
||||||
// return UserData();
|
|
||||||
// }
|
|
||||||
// return UserData(
|
|
||||||
// isFavourite: dto.isFavorite ?? false,
|
|
||||||
// playCount: dto.playCount ?? 0,
|
|
||||||
// playbackPositionTicks: dto.playbackPositionTicks ?? 0,
|
|
||||||
// played: dto.played ?? false,
|
|
||||||
// unPlayedItemCount: dto.unplayedItemCount ?? 0,
|
|
||||||
// progress: dto.playedPercentage ?? 0,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Duration get playBackPosition => Duration(milliseconds: playbackPositionTicks ~/ 10000);
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// String toString() {
|
|
||||||
// return 'UserData(isFavourite: $isFavourite, playCount: $playCount, unPlayedItemCount: $unPlayedItemCount, playbackPositionTicks: $playbackPositionTicks, progress: $progress, played: $played)';
|
|
||||||
// }
|
|
||||||
|
|
||||||
// UserData copyWith({
|
|
||||||
// bool? isFavourite,
|
|
||||||
// int? playCount,
|
|
||||||
// int? unPlayedItemCount,
|
|
||||||
// int? playbackPositionTicks,
|
|
||||||
// double? progress,
|
|
||||||
// bool? played,
|
|
||||||
// }) {
|
|
||||||
// return UserData(
|
|
||||||
// isFavourite: isFavourite ?? this.isFavourite,
|
|
||||||
// playCount: playCount ?? this.playCount,
|
|
||||||
// unPlayedItemCount: unPlayedItemCount ?? this.unPlayedItemCount,
|
|
||||||
// playbackPositionTicks: playbackPositionTicks ?? this.playbackPositionTicks,
|
|
||||||
// progress: progress ?? this.progress,
|
|
||||||
// played: played ?? this.played,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Map<String, dynamic> toMap() {
|
|
||||||
// return <String, dynamic>{
|
|
||||||
// 'isFavourite': isFavourite,
|
|
||||||
// 'playCount': playCount,
|
|
||||||
// 'unPlayedItemCount': unPlayedItemCount,
|
|
||||||
// 'playbackPositionTicks': playbackPositionTicks,
|
|
||||||
// 'progress': progress,
|
|
||||||
// 'played': played,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// factory UserData.fromMap(Map<String, dynamic> map) {
|
|
||||||
// return UserData(
|
|
||||||
// isFavourite: (map['isFavourite'] ?? false) as bool,
|
|
||||||
// playCount: (map['playCount'] ?? 0) as int,
|
|
||||||
// unPlayedItemCount: (map['unPlayedItemCount'] ?? 0) as int,
|
|
||||||
// playbackPositionTicks: (map['playbackPositionTicks'] ?? 0) as int,
|
|
||||||
// progress: (map['progress'] ?? 0.0) as double,
|
|
||||||
// played: (map['played'] ?? false) as bool,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// String toJson() => json.encode(toMap());
|
|
||||||
|
|
||||||
// factory UserData.fromJson(String source) => UserData.fromMap(json.decode(source) as Map<String, dynamic>);
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// bool operator ==(covariant UserData other) {
|
|
||||||
// if (identical(this, other)) return true;
|
|
||||||
|
|
||||||
// return other.isFavourite == isFavourite &&
|
|
||||||
// other.playCount == playCount &&
|
|
||||||
// other.unPlayedItemCount == unPlayedItemCount &&
|
|
||||||
// other.playbackPositionTicks == playbackPositionTicks &&
|
|
||||||
// other.progress == progress &&
|
|
||||||
// other.played == played;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// int get hashCode {
|
|
||||||
// return isFavourite.hashCode ^
|
|
||||||
// playCount.hashCode ^
|
|
||||||
// unPlayedItemCount.hashCode ^
|
|
||||||
// playbackPositionTicks.hashCode ^
|
|
||||||
// progress.hashCode ^
|
|
||||||
// played.hashCode;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import 'package:fladder/providers/auth_provider.dart';
|
|
||||||
import 'package:fladder/providers/user_provider.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
||||||
|
import 'package:fladder/providers/auth_provider.dart';
|
||||||
|
import 'package:fladder/providers/user_provider.dart';
|
||||||
|
|
||||||
const _defaultHeight = 576;
|
const _defaultHeight = 576;
|
||||||
const _defaultWidth = 384;
|
const _defaultWidth = 384;
|
||||||
|
|
@ -26,12 +26,14 @@ class ImageNotifier {
|
||||||
return Uri.decodeFull("$currentServerUrl/Users/$id/Images/${ImageType.primary.value}");
|
return Uri.decodeFull("$currentServerUrl/Users/$id/Images/${ImageType.primary.value}");
|
||||||
}
|
}
|
||||||
|
|
||||||
String getItemsImageUrl(String itemId,
|
String getItemsImageUrl(String? itemId,
|
||||||
{ImageType type = ImageType.primary,
|
{ImageType type = ImageType.primary,
|
||||||
int maxHeight = _defaultHeight,
|
int maxHeight = _defaultHeight,
|
||||||
int maxWidth = _defaultWidth,
|
int maxWidth = _defaultWidth,
|
||||||
int quality = _defaultQuality}) {
|
int quality = _defaultQuality}) {
|
||||||
try {
|
try {
|
||||||
|
if (itemId == null) return "";
|
||||||
|
|
||||||
return Uri.decodeFull(
|
return Uri.decodeFull(
|
||||||
"$currentServerUrl/Items/$itemId/Images/${type.value}?fillHeight=$maxHeight&fillWidth=$maxWidth&quality=$quality");
|
"$currentServerUrl/Items/$itemId/Images/${type.value}?fillHeight=$maxHeight&fillWidth=$maxWidth&quality=$quality");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -39,8 +41,9 @@ class ImageNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getItemsOrigImageUrl(String itemId, {ImageType type = ImageType.primary}) {
|
String getItemsOrigImageUrl(String? itemId, {ImageType type = ImageType.primary}) {
|
||||||
try {
|
try {
|
||||||
|
if (itemId == null) return "";
|
||||||
return Uri.decodeFull("$currentServerUrl/Items/$itemId/Images/${type.value}");
|
return Uri.decodeFull("$currentServerUrl/Items/$itemId/Images/${type.value}");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue