diff --git a/lib/domain/data/auction.dart b/lib/domain/data/auction.dart index 2f3c299..3078938 100644 --- a/lib/domain/data/auction.dart +++ b/lib/domain/data/auction.dart @@ -1,5 +1,6 @@ import 'package:estatesales_sdk/domain/data/auction_status.dart'; import 'package:estatesales_sdk/domain/data/company.dart'; +import 'package:estatesales_sdk/domain/data/converters/remote_asset_converter.dart'; import 'package:estatesales_sdk/domain/data/location.dart'; import 'package:estatesales_sdk/domain/data/lot.dart'; import 'package:estatesales_sdk/domain/data/remote_asset.dart'; @@ -25,7 +26,7 @@ class Auction with _$Auction, Serializable { @HiveField(8) required String? terms, @HiveField(9) required String? privacyPolicy, @HiveField(10) required Company? company, - @HiveField(11) required RemoteAsset? logo, + @HiveField(11) @remoteAsset required RemoteAsset? logo, @HiveField(12) required Location? location, @HiveField(13) required List? lots, }) = _Auction; diff --git a/lib/domain/data/company.dart b/lib/domain/data/company.dart index 8f8fa34..51e0778 100644 --- a/lib/domain/data/company.dart +++ b/lib/domain/data/company.dart @@ -1,3 +1,4 @@ +import 'package:estatesales_sdk/domain/data/converters/remote_asset_converter.dart'; import 'package:estatesales_sdk/domain/data/rating.dart'; import 'package:estatesales_sdk/domain/data/remote_asset.dart'; import 'package:estatesales_sdk/domain/local/estatesales_hive.dart'; @@ -24,8 +25,8 @@ class Company with _$Company, Serializable { @HiveField(7) @Default(false) bool hideClosedLots, @HiveField(8) @Default(true) bool enabled, @HiveField(9) @Default(Rating.zero) Rating rating, - @HiveField(10) RemoteAsset? photo, - @HiveField(11) RemoteAsset? cover, + @HiveField(10) @remoteAsset RemoteAsset? photo, + @HiveField(11) @remoteAsset RemoteAsset? cover, }) = _Company; factory Company.fromJson(Map json) => diff --git a/lib/domain/data/converters/remote_asset_converter.dart b/lib/domain/data/converters/remote_asset_converter.dart new file mode 100644 index 0000000..1db4548 --- /dev/null +++ b/lib/domain/data/converters/remote_asset_converter.dart @@ -0,0 +1,209 @@ +import 'package:estatesales_sdk/domain/data/converters/uri_converter.dart'; +import 'package:estatesales_sdk/domain/data/remote_asset.dart'; +import 'package:estatesales_sdk/domain/data/remote_asset_visibility.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +const remoteAsset = RemoteAssetConverter(); +const remoteAssetEnhanced = RemoteAssetEnhancedConverter(); + +const remoteAssets = RemoteAssetListConverter(); +const remoteAssetsEnhanced = RemoteAssetEnhancedListConverter(); + +class RemoteAssetConverter extends JsonConverter { + const RemoteAssetConverter(); + + @protected + RemoteAssetEnhanced? enhancedFromJson(Map json) { + final file = json['file']; + if (file is Map) { + final data = file['data']; + if (data is Map) { + if (data['url'] != null) { + return RemoteAssetEnhanced( + id: json['id'] as int, + order: json['order'] as int?, + visibility: _parseVisibility(json['visibility']), + uriOrNull: _parseUri(file), + thumbnailOrNull: _parseUri(file, 'thumbnail'), + smallOrNull: _parseUri(file, 'small'), + mediumOrNull: _parseUri(file, 'medium'), + largeOrNull: _parseUri(file, 'large'), + ); + } + } + } + return null; + } + + @override + RemoteAsset? fromJson(dynamic json) { + if (json is Map) { + if (json.containsKey('file')) return enhancedFromJson(json); + if (json.containsKey('url')) { + return RemoteAsset( + uri: _parseUri(json)!, + thumbnailOrNull: _parseUri(json, 'thumbnail'), + smallOrNull: _parseUri(json, 'small'), + mediumOrNull: _parseUri(json, 'medium'), + largeOrNull: _parseUri(json, 'large'), + ); + } + } + return null; + } + + @override + dynamic toJson(RemoteAsset? object) { + if (object == null) return null; + return object.when( + ( + uri, + thumbnailOrNull, + smallOrNull, + mediumOrNull, + largeOrNull, + ) => + { + 'url': uri.toString(), + 'thumbnail': thumbnailOrNull?.toString(), + 'small': smallOrNull?.toString(), + 'medium': mediumOrNull?.toString(), + 'large': largeOrNull?.toString(), + }, + enhanced: ( + id, + order, + visibility, + uri, + thumbnailOrNull, + smallOrNull, + mediumOrNull, + largeOrNull, + ) => + { + 'id': id, + 'order': order, + 'visibility': visibility?.name, + if (uri != null) + 'file': { + 'url': uri.toString(), + 'thumbnail': thumbnailOrNull?.toString(), + 'small': smallOrNull?.toString(), + 'medium': mediumOrNull?.toString(), + 'large': largeOrNull?.toString(), + }, + }, + ); + } +} + +class RemoteAssetEnhancedConverter + extends JsonConverter { + const RemoteAssetEnhancedConverter(); + + @override + RemoteAssetEnhanced? fromJson(json) { + final asset = remoteAsset.fromJson(json); + if (asset is RemoteAssetEnhanced) return asset; + return null; + } + + @override + dynamic toJson(RemoteAssetEnhanced? object) { + return remoteAsset.toJson(object); + } +} + +class RemoteAssetListConverter + extends JsonConverter?, dynamic> { + const RemoteAssetListConverter(); + + @override + List? fromJson(dynamic json) { + if (json is Iterable) { + return json + .map(remoteAsset.fromJson) + .where((it) => it != null && it.uriOrNull != null) + .toList() + .cast(); + } + if (json is Map) { + return fromJson(json['data']); + } + + return null; + } + + @override + List>? toJson(List? object) { + if (object == null) return null; + + return object + .map((e) => remoteAsset.toJson(e)) + .whereType>() + .toList(); + } +} + +class RemoteAssetEnhancedListConverter + extends JsonConverter?, dynamic> { + const RemoteAssetEnhancedListConverter(); + + @override + List? fromJson(json) { + if (json is Iterable) { + return json + .map(remoteAssetEnhanced.fromJson) + .where((it) => it != null && it.uriOrNull != null) + .toList() + .cast(); + } + if (json is Map) { + return fromJson(json['data']); + } + + return null; + } + + @override + dynamic toJson(List? object) { + if (object == null) return null; + + return object + .map((e) => remoteAssetEnhanced.toJson(e)) + .whereType>() + .toList(); + } +} + +RemoteAssetVisibility? _parseVisibility(dynamic value) { + if (value is String) { + return RemoteAssetVisibility.values + .where((it) => it.name == value) + .firstOrNull; + } + return null; +} + +Uri? _parseUri( + dynamic value, [ + String? format, +]) { + if (value is String) return const UriConverter().fromJson(value); + if (value is Map) { + if (format != null) { + return _parseUri( + value['data'] ?? + value['attributes'] ?? + value['formats'] ?? + value[format] ?? + value['url'], + format, + ); + } + return _parseUri( + value['data'] ?? value['attributes'] ?? value['url'], + ); + } + return null; +} diff --git a/lib/domain/data/converters/remote_asset_enhanced_file_converter.dart b/lib/domain/data/converters/remote_asset_enhanced_file_converter.dart deleted file mode 100644 index 58367b2..0000000 --- a/lib/domain/data/converters/remote_asset_enhanced_file_converter.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'package:estatesales_sdk/domain/data/remote_asset.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; - -class RemoteAssetEnhancedConverter - extends JsonConverter { - const RemoteAssetEnhancedConverter(); - - @override - RemoteAssetEnhanced? fromJson(dynamic json) { - if (json == null) return null; - return RemoteAsset.fromJson(json) as RemoteAssetEnhanced; - } - - @override - dynamic toJson(RemoteAssetEnhanced? object) { - if (object == null) return null; - return object.toJson(); - } -} - -class RemoteAssetEnhancedListConverter - extends JsonConverter?, dynamic> { - const RemoteAssetEnhancedListConverter(); - - @override - List? fromJson(dynamic json) { - if (json is List) { - return json - .map(const RemoteAssetEnhancedConverter().fromJson) - .whereType() - .toList(); - } - if (json is Map) { - return fromJson(json['data']); - } - - return null; - } - - @override - List>? toJson(List? object) { - if (object == null) return null; - - return object - .map((e) => const RemoteAssetEnhancedConverter().toJson(e)) - .whereType>() - .toList(); - } -} diff --git a/lib/domain/data/lot.dart b/lib/domain/data/lot.dart index 35af394..b0eef0e 100644 --- a/lib/domain/data/lot.dart +++ b/lib/domain/data/lot.dart @@ -1,7 +1,7 @@ import 'package:estatesales_sdk/domain/data/auction.dart'; import 'package:estatesales_sdk/domain/data/bid_increment.dart'; import 'package:estatesales_sdk/domain/data/category.dart'; -import 'package:estatesales_sdk/domain/data/converters/remote_asset_enhanced_file_converter.dart'; +import 'package:estatesales_sdk/domain/data/converters/remote_asset_converter.dart'; import 'package:estatesales_sdk/domain/data/location.dart'; import 'package:estatesales_sdk/domain/data/lot_status.dart'; import 'package:estatesales_sdk/domain/data/remote_asset.dart'; @@ -23,7 +23,7 @@ class Lot with _$Lot, Serializable { required LotStatus status, int? lotNumber, // todo: add User? consignor - @RemoteAssetEnhancedListConverter() List? photos, + @remoteAssetsEnhanced List? photos, int? quantity, Auction? auction, Category? category, diff --git a/lib/domain/data/remote_asset.dart b/lib/domain/data/remote_asset.dart index 99ae34b..1cc3b4f 100644 --- a/lib/domain/data/remote_asset.dart +++ b/lib/domain/data/remote_asset.dart @@ -28,29 +28,6 @@ sealed class RemoteAsset with _$RemoteAsset { @UriConverter() Uri? largeOrNull, }) = RemoteAssetEnhanced; - factory RemoteAsset.fromJson(Map json) { - if (json.containsKey('file')) { - final file = _extractFile(json['file']); - return RemoteAsset.enhanced( - id: json['id'] as int, - order: json['order'] as int?, - visibility: _extractVisibility(json['visibility']), - uriOrNull: _extractUri(file), - thumbnailOrNull: _extractUri(file, 'thumbnail'), - smallOrNull: _extractUri(file, 'small'), - mediumOrNull: _extractUri(file, 'medium'), - largeOrNull: _extractUri(file, 'large'), - ); - } - return RemoteAsset( - uri: _extractUri(json)!, - thumbnailOrNull: _extractUri(json, 'thumbnail'), - smallOrNull: _extractUri(json, 'small'), - mediumOrNull: _extractUri(json, 'medium'), - largeOrNull: _extractUri(json, 'large'), - ); - } - Uri? get uriOrNull { return when( (uri, _, __, ___, ____) => uri, @@ -70,48 +47,6 @@ sealed class RemoteAsset with _$RemoteAsset { Uri get medium => mediumOrNull ?? requireUri; Uri get large => largeOrNull ?? requireUri; - - Map toJson() { - return when( - ( - uri, - thumbnailOrNull, - smallOrNull, - mediumOrNull, - largeOrNull, - ) => - { - 'url': uri.toString(), - 'thumbnail': thumbnailOrNull?.toString(), - 'small': smallOrNull?.toString(), - 'medium': mediumOrNull?.toString(), - 'large': largeOrNull?.toString(), - }, - enhanced: ( - id, - order, - visibility, - uri, - thumbnailOrNull, - smallOrNull, - mediumOrNull, - largeOrNull, - ) => - { - 'id': id, - 'order': order, - 'visibility': visibility?.name, - if (uri != null) - 'file': { - 'url': uri.toString(), - 'thumbnail': thumbnailOrNull?.toString(), - 'small': smallOrNull?.toString(), - 'medium': mediumOrNull?.toString(), - 'large': largeOrNull?.toString(), - }, - }, - ); - } } Map? _extractFile(dynamic value) {