diff --git a/lib/models/livetv_channel.dart b/lib/models/livetv_channel.dart index 420e2904..6706cb70 100644 --- a/lib/models/livetv_channel.dart +++ b/lib/models/livetv_channel.dart @@ -1,23 +1,57 @@ +import 'package:json_annotation/json_annotation.dart'; + import '../utils/json_utils.dart'; import 'mixins/multi_server_fields.dart'; +part 'livetv_channel.g.dart'; + +Object? _readChannelKey(Map json, String _) => + json['key'] as String? ?? + json['ratingKey'] as String? ?? + json['identifier'] as String? ?? + json['id'] as String? ?? + json['channelIdentifier'] as String? ?? + ''; + +Object? _readChannelIdentifier(Map json, String _) => + json['identifier'] as String? ?? json['id'] as String? ?? json['channelIdentifier'] as String?; + +Object? _readChannelTitle(Map json, String _) => json['title'] as String? ?? json['callSign'] as String?; + +Object? _readChannelNumber(Map json, String _) => + json['number'] as String? ?? + json['channelNumber'] as String? ?? + json['channelVcn']?.toString() ?? + json['vcn']?.toString(); + +Object? _readFavoriteChannelId(Map json, String _) => json['id'] as String? ?? json['key'] as String? ?? ''; + /// Represents a Live TV channel from the EPG +@JsonSerializable(createToJson: false) class LiveTvChannel with MultiServerFields { + @JsonKey(readValue: _readChannelKey) final String key; + @JsonKey(readValue: _readChannelIdentifier) final String? identifier; final String? callSign; + @JsonKey(readValue: _readChannelTitle) final String? title; final String? thumb; final String? art; + @JsonKey(readValue: _readChannelNumber) final String? number; + @JsonKey(fromJson: flexibleBool) final bool hd; final String? lineup; final String? slug; + @JsonKey(fromJson: flexibleBool) final bool? drm; @override + @JsonKey(includeFromJson: false, includeToJson: false) final String? serverId; @override + @JsonKey(includeFromJson: false, includeToJson: false) final String? serverName; LiveTvChannel({ @@ -36,31 +70,7 @@ class LiveTvChannel with MultiServerFields { this.serverName, }); - factory LiveTvChannel.fromJson(Map json) { - return LiveTvChannel( - key: - json['key'] as String? ?? - json['ratingKey'] as String? ?? - json['identifier'] as String? ?? - json['id'] as String? ?? - json['channelIdentifier'] as String? ?? - '', - identifier: json['identifier'] as String? ?? json['id'] as String? ?? json['channelIdentifier'] as String?, - callSign: json['callSign'] as String?, - title: json['title'] as String? ?? json['callSign'] as String?, - thumb: json['thumb'] as String?, - art: json['art'] as String?, - number: - json['number'] as String? ?? - json['channelNumber'] as String? ?? - json['channelVcn']?.toString() ?? - json['vcn']?.toString(), - hd: flexibleBool(json['hd']), - lineup: json['lineup'] as String?, - slug: json['slug'] as String?, - drm: flexibleBool(json['drm']), - ); - } + factory LiveTvChannel.fromJson(Map json) => _$LiveTvChannelFromJson(json); LiveTvChannel copyWith({String? serverId, String? serverName}) { return LiveTvChannel( @@ -86,8 +96,11 @@ class LiveTvChannel with MultiServerFields { /// A channel entry in the Plex cloud favorites list. /// Stored at `https://epg.provider.plex.tv/settings/favoriteChannels`. +@JsonSerializable(createToJson: false) class FavoriteChannel { + @JsonKey(defaultValue: '') final String source; + @JsonKey(readValue: _readFavoriteChannelId) final String id; final String? title; final String? thumb; @@ -95,15 +108,7 @@ class FavoriteChannel { FavoriteChannel({required this.source, required this.id, this.title, this.thumb, this.vcn}); - factory FavoriteChannel.fromJson(Map json) { - return FavoriteChannel( - source: json['source'] as String? ?? '', - id: json['id'] as String? ?? json['key'] as String? ?? '', - title: json['title'] as String?, - thumb: json['thumb'] as String?, - vcn: json['vcn'] as String?, - ); - } + factory FavoriteChannel.fromJson(Map json) => _$FavoriteChannelFromJson(json); Map toJson() => { 'source': source, diff --git a/lib/models/livetv_channel.g.dart b/lib/models/livetv_channel.g.dart new file mode 100644 index 00000000..69c9a811 --- /dev/null +++ b/lib/models/livetv_channel.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'livetv_channel.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LiveTvChannel _$LiveTvChannelFromJson(Map json) => + LiveTvChannel( + key: _readChannelKey(json, 'key') as String, + identifier: _readChannelIdentifier(json, 'identifier') as String?, + callSign: json['callSign'] as String?, + title: _readChannelTitle(json, 'title') as String?, + thumb: json['thumb'] as String?, + art: json['art'] as String?, + number: _readChannelNumber(json, 'number') as String?, + hd: json['hd'] == null ? false : flexibleBool(json['hd']), + lineup: json['lineup'] as String?, + slug: json['slug'] as String?, + drm: flexibleBool(json['drm']), + ); + +FavoriteChannel _$FavoriteChannelFromJson(Map json) => + FavoriteChannel( + source: json['source'] as String? ?? '', + id: _readFavoriteChannelId(json, 'id') as String, + title: json['title'] as String?, + thumb: json['thumb'] as String?, + vcn: json['vcn'] as String?, + ); diff --git a/lib/models/livetv_dvr.dart b/lib/models/livetv_dvr.dart index 6a57ffe0..5f00cdf8 100644 --- a/lib/models/livetv_dvr.dart +++ b/lib/models/livetv_dvr.dart @@ -1,8 +1,27 @@ +import 'package:json_annotation/json_annotation.dart'; + import '../utils/json_utils.dart'; +part 'livetv_dvr.g.dart'; + +List _parseChannelMappings(Object? raw) { + final result = []; + if (raw is List) { + for (final item in raw) { + try { + result.add(ChannelMapping.fromJson(item as Map)); + } catch (_) {} + } + } + return result; +} + /// Represents a Plex Live TV DVR device (e.g., HDHomeRun tuner, IPTV provider) +@JsonSerializable(createToJson: false) class LiveTvDvr { + @JsonKey(defaultValue: '') final String key; + @JsonKey(defaultValue: '') final String uuid; final String? make; final String? model; @@ -15,6 +34,7 @@ class LiveTvDvr { final String? country; final String? language; final String? status; + @JsonKey(name: 'ChannelMapping', fromJson: _parseChannelMappings) final List channelMappings; LiveTvDvr({ @@ -34,50 +54,19 @@ class LiveTvDvr { this.channelMappings = const [], }); - factory LiveTvDvr.fromJson(Map json) { - final mappings = []; - if (json['ChannelMapping'] != null) { - for (final item in json['ChannelMapping'] as List) { - try { - mappings.add(ChannelMapping.fromJson(item as Map)); - } catch (_) {} - } - } - - return LiveTvDvr( - key: json['key'] as String? ?? '', - uuid: json['uuid'] as String? ?? '', - make: json['make'] as String?, - model: json['model'] as String?, - modelNumber: json['modelNumber'] as String?, - firmware: json['firmware'] as String?, - tuners: (json['tuners'] as num?)?.toInt(), - lineup: json['lineup'] as String?, - lineupTitle: json['lineupTitle'] as String?, - lineupURL: json['lineupURL'] as String?, - country: json['country'] as String?, - language: json['language'] as String?, - status: json['status'] as String?, - channelMappings: mappings, - ); - } + factory LiveTvDvr.fromJson(Map json) => _$LiveTvDvrFromJson(json); } /// Represents a channel mapping within a DVR device +@JsonSerializable(createToJson: false) class ChannelMapping { final String? channelKey; final String? deviceIdentifier; + @JsonKey(fromJson: flexibleBool) final bool? enabled; final String? lineupIdentifier; ChannelMapping({this.channelKey, this.deviceIdentifier, this.enabled, this.lineupIdentifier}); - factory ChannelMapping.fromJson(Map json) { - return ChannelMapping( - channelKey: json['channelKey'] as String?, - deviceIdentifier: json['deviceIdentifier'] as String?, - enabled: flexibleBool(json['enabled']), - lineupIdentifier: json['lineupIdentifier'] as String?, - ); - } + factory ChannelMapping.fromJson(Map json) => _$ChannelMappingFromJson(json); } diff --git a/lib/models/livetv_dvr.g.dart b/lib/models/livetv_dvr.g.dart new file mode 100644 index 00000000..ff53c06f --- /dev/null +++ b/lib/models/livetv_dvr.g.dart @@ -0,0 +1,34 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'livetv_dvr.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LiveTvDvr _$LiveTvDvrFromJson(Map json) => LiveTvDvr( + key: json['key'] as String? ?? '', + uuid: json['uuid'] as String? ?? '', + make: json['make'] as String?, + model: json['model'] as String?, + modelNumber: json['modelNumber'] as String?, + firmware: json['firmware'] as String?, + tuners: (json['tuners'] as num?)?.toInt(), + lineup: json['lineup'] as String?, + lineupTitle: json['lineupTitle'] as String?, + lineupURL: json['lineupURL'] as String?, + country: json['country'] as String?, + language: json['language'] as String?, + status: json['status'] as String?, + channelMappings: json['ChannelMapping'] == null + ? const [] + : _parseChannelMappings(json['ChannelMapping']), +); + +ChannelMapping _$ChannelMappingFromJson(Map json) => + ChannelMapping( + channelKey: json['channelKey'] as String?, + deviceIdentifier: json['deviceIdentifier'] as String?, + enabled: flexibleBool(json['enabled']), + lineupIdentifier: json['lineupIdentifier'] as String?, + ); diff --git a/lib/models/play_queue_response.g.dart b/lib/models/play_queue_response.g.dart index 70e8cd5a..576098f0 100644 --- a/lib/models/play_queue_response.g.dart +++ b/lib/models/play_queue_response.g.dart @@ -6,15 +6,21 @@ part of 'play_queue_response.dart'; // JsonSerializableGenerator // ************************************************************************** -PlayQueueResponse _$PlayQueueResponseFromJson(Map json) => PlayQueueResponse( - playQueueID: (json['playQueueID'] as num).toInt(), - playQueueSelectedItemID: (json['playQueueSelectedItemID'] as num?)?.toInt(), - playQueueSelectedItemOffset: (json['playQueueSelectedItemOffset'] as num?)?.toInt(), - playQueueSelectedMetadataItemID: json['playQueueSelectedMetadataItemID'] as String?, - playQueueShuffled: flexibleBool(json['playQueueShuffled']), - playQueueSourceURI: json['playQueueSourceURI'] as String?, - playQueueTotalCount: (json['playQueueTotalCount'] as num?)?.toInt(), - playQueueVersion: (json['playQueueVersion'] as num).toInt(), - size: (json['size'] as num?)?.toInt(), - items: (json['Metadata'] as List?)?.map((e) => PlexMetadata.fromJson(e as Map)).toList(), -); +PlayQueueResponse _$PlayQueueResponseFromJson(Map json) => + PlayQueueResponse( + playQueueID: (json['playQueueID'] as num).toInt(), + playQueueSelectedItemID: (json['playQueueSelectedItemID'] as num?) + ?.toInt(), + playQueueSelectedItemOffset: (json['playQueueSelectedItemOffset'] as num?) + ?.toInt(), + playQueueSelectedMetadataItemID: + json['playQueueSelectedMetadataItemID'] as String?, + playQueueShuffled: flexibleBool(json['playQueueShuffled']), + playQueueSourceURI: json['playQueueSourceURI'] as String?, + playQueueTotalCount: (json['playQueueTotalCount'] as num?)?.toInt(), + playQueueVersion: (json['playQueueVersion'] as num).toInt(), + size: (json['size'] as num?)?.toInt(), + items: (json['Metadata'] as List?) + ?.map((e) => PlexMetadata.fromJson(e as Map)) + .toList(), + ); diff --git a/lib/models/plex_activity.dart b/lib/models/plex_activity.dart index 9eb8f757..e560ab1a 100644 --- a/lib/models/plex_activity.dart +++ b/lib/models/plex_activity.dart @@ -1,10 +1,20 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'plex_activity.g.dart'; + /// Represents a running background task on a Plex Media Server (from /activities endpoint). +@JsonSerializable(createToJson: false) class PlexActivity { + @JsonKey(defaultValue: '') final String uuid; + @JsonKey(defaultValue: '') final String type; + @JsonKey(defaultValue: '') final String title; final String? subtitle; + @JsonKey(defaultValue: 0) final int progress; // 0–100 + @JsonKey(defaultValue: false) final bool cancellable; const PlexActivity({ @@ -16,14 +26,5 @@ class PlexActivity { required this.cancellable, }); - factory PlexActivity.fromJson(Map json) { - return PlexActivity( - uuid: json['uuid'] as String? ?? '', - type: json['type'] as String? ?? '', - title: json['title'] as String? ?? '', - subtitle: json['subtitle'] as String?, - progress: (json['progress'] as num?)?.toInt() ?? 0, - cancellable: json['cancellable'] as bool? ?? false, - ); - } + factory PlexActivity.fromJson(Map json) => _$PlexActivityFromJson(json); } diff --git a/lib/models/plex_activity.g.dart b/lib/models/plex_activity.g.dart new file mode 100644 index 00000000..1c6f5555 --- /dev/null +++ b/lib/models/plex_activity.g.dart @@ -0,0 +1,16 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'plex_activity.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PlexActivity _$PlexActivityFromJson(Map json) => PlexActivity( + uuid: json['uuid'] as String? ?? '', + type: json['type'] as String? ?? '', + title: json['title'] as String? ?? '', + subtitle: json['subtitle'] as String?, + progress: (json['progress'] as num?)?.toInt() ?? 0, + cancellable: json['cancellable'] as bool? ?? false, +); diff --git a/lib/models/plex_first_character.dart b/lib/models/plex_first_character.dart index 2a23e287..f5f1ad21 100644 --- a/lib/models/plex_first_character.dart +++ b/lib/models/plex_first_character.dart @@ -1,11 +1,19 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'plex_first_character.g.dart'; + +@JsonSerializable() class PlexFirstCharacter { + @JsonKey(defaultValue: '') final String key; + @JsonKey(defaultValue: '') final String title; + @JsonKey(defaultValue: 0) final int size; PlexFirstCharacter({required this.key, required this.title, required this.size}); - factory PlexFirstCharacter.fromJson(Map json) { - return PlexFirstCharacter(key: json['key'] ?? '', title: json['title'] ?? '', size: json['size'] ?? 0); - } + factory PlexFirstCharacter.fromJson(Map json) => _$PlexFirstCharacterFromJson(json); + + Map toJson() => _$PlexFirstCharacterToJson(this); } diff --git a/lib/models/plex_first_character.g.dart b/lib/models/plex_first_character.g.dart new file mode 100644 index 00000000..b618e8a1 --- /dev/null +++ b/lib/models/plex_first_character.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'plex_first_character.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PlexFirstCharacter _$PlexFirstCharacterFromJson(Map json) => + PlexFirstCharacter( + key: json['key'] as String? ?? '', + title: json['title'] as String? ?? '', + size: (json['size'] as num?)?.toInt() ?? 0, + ); + +Map _$PlexFirstCharacterToJson(PlexFirstCharacter instance) => + { + 'key': instance.key, + 'title': instance.title, + 'size': instance.size, + }; diff --git a/lib/models/plex_library.g.dart b/lib/models/plex_library.g.dart index 37a7f43e..c527e046 100644 --- a/lib/models/plex_library.g.dart +++ b/lib/models/plex_library.g.dart @@ -19,15 +19,16 @@ PlexLibrary _$PlexLibraryFromJson(Map json) => PlexLibrary( hidden: (json['hidden'] as num?)?.toInt(), ); -Map _$PlexLibraryToJson(PlexLibrary instance) => { - 'key': instance.key, - 'title': instance.title, - 'type': instance.type, - 'agent': instance.agent, - 'scanner': instance.scanner, - 'language': instance.language, - 'uuid': instance.uuid, - 'updatedAt': instance.updatedAt, - 'createdAt': instance.createdAt, - 'hidden': instance.hidden, -}; +Map _$PlexLibraryToJson(PlexLibrary instance) => + { + 'key': instance.key, + 'title': instance.title, + 'type': instance.type, + 'agent': instance.agent, + 'scanner': instance.scanner, + 'language': instance.language, + 'uuid': instance.uuid, + 'updatedAt': instance.updatedAt, + 'createdAt': instance.createdAt, + 'hidden': instance.hidden, + }; diff --git a/lib/models/plex_match_result.dart b/lib/models/plex_match_result.dart index d819683d..10d1bbb0 100644 --- a/lib/models/plex_match_result.dart +++ b/lib/models/plex_match_result.dart @@ -1,13 +1,26 @@ +import 'package:json_annotation/json_annotation.dart'; + import '../utils/json_utils.dart'; +part 'plex_match_result.g.dart'; + +@JsonSerializable() class PlexMatchResult { + @JsonKey(readValue: readStringField, defaultValue: '') final String guid; + @JsonKey(readValue: readStringField, defaultValue: '') final String name; + @JsonKey(fromJson: flexibleInt) final int? year; + @JsonKey(fromJson: flexibleInt) final int? score; + @JsonKey(readValue: readStringField) final String? thumb; + @JsonKey(readValue: readStringField) final String? summary; + @JsonKey(readValue: readStringField) final String? type; + @JsonKey(fromJson: flexibleBool) final bool matched; PlexMatchResult({ @@ -21,16 +34,7 @@ class PlexMatchResult { this.matched = false, }); - factory PlexMatchResult.fromJson(Map json) { - return PlexMatchResult( - guid: json['guid']?.toString() ?? '', - name: json['name']?.toString() ?? '', - year: flexibleInt(json['year']), - score: flexibleInt(json['score']), - thumb: json['thumb']?.toString(), - summary: json['summary']?.toString(), - type: json['type']?.toString(), - matched: flexibleBool(json['matched']), - ); - } + factory PlexMatchResult.fromJson(Map json) => _$PlexMatchResultFromJson(json); + + Map toJson() => _$PlexMatchResultToJson(this); } diff --git a/lib/models/plex_match_result.g.dart b/lib/models/plex_match_result.g.dart new file mode 100644 index 00000000..37514316 --- /dev/null +++ b/lib/models/plex_match_result.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'plex_match_result.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PlexMatchResult _$PlexMatchResultFromJson(Map json) => + PlexMatchResult( + guid: readStringField(json, 'guid') as String? ?? '', + name: readStringField(json, 'name') as String? ?? '', + year: flexibleInt(json['year']), + score: flexibleInt(json['score']), + thumb: readStringField(json, 'thumb') as String?, + summary: readStringField(json, 'summary') as String?, + type: readStringField(json, 'type') as String?, + matched: json['matched'] == null ? false : flexibleBool(json['matched']), + ); + +Map _$PlexMatchResultToJson(PlexMatchResult instance) => + { + 'guid': instance.guid, + 'name': instance.name, + 'year': instance.year, + 'score': instance.score, + 'thumb': instance.thumb, + 'summary': instance.summary, + 'type': instance.type, + 'matched': instance.matched, + }; diff --git a/lib/models/plex_media_version.dart b/lib/models/plex_media_version.dart index 0e65f4da..7da08349 100644 --- a/lib/models/plex_media_version.dart +++ b/lib/models/plex_media_version.dart @@ -1,15 +1,35 @@ +import 'package:json_annotation/json_annotation.dart'; + import '../utils/formatters.dart'; import '../utils/codec_utils.dart'; import '../utils/json_utils.dart'; +part 'plex_media_version.g.dart'; + +int _flexibleIntOrZero(Object? v) => flexibleInt(v) ?? 0; + +Object? _readPartKey(Map json, String key) { + final parts = flexibleList(json['Part']); + return parts != null && parts.isNotEmpty ? parts.first['key']?.toString() ?? '' : ''; +} + +@JsonSerializable(createToJson: false) class PlexMediaVersion { + @JsonKey(fromJson: _flexibleIntOrZero) final int id; + @JsonKey(readValue: readStringField) final String? videoResolution; + @JsonKey(readValue: readStringField) final String? videoCodec; + @JsonKey(fromJson: flexibleInt) final int? bitrate; + @JsonKey(fromJson: flexibleInt) final int? width; + @JsonKey(fromJson: flexibleInt) final int? height; + @JsonKey(readValue: readStringField) final String? container; + @JsonKey(readValue: _readPartKey) final String partKey; PlexMediaVersion({ @@ -25,22 +45,7 @@ class PlexMediaVersion { /// Creates a PlexMediaVersion from Plex API Media object. /// Values may be String or int depending on the response format (XML vs JSON). - factory PlexMediaVersion.fromJson(Map json) { - // Get the first Part key for playback - final parts = flexibleList(json['Part']); - final partKey = parts != null && parts.isNotEmpty ? parts.first['key']?.toString() ?? '' : ''; - - return PlexMediaVersion( - id: flexibleInt(json['id']) ?? 0, - videoResolution: json['videoResolution']?.toString(), - videoCodec: json['videoCodec']?.toString(), - bitrate: flexibleInt(json['bitrate']), - width: flexibleInt(json['width']), - height: flexibleInt(json['height']), - container: json['container']?.toString(), - partKey: partKey, - ); - } + factory PlexMediaVersion.fromJson(Map json) => _$PlexMediaVersionFromJson(json); /// Display label with detailed information: "1080p H.264 MKV (8.5 Mbps)" String get displayLabel { diff --git a/lib/models/plex_media_version.g.dart b/lib/models/plex_media_version.g.dart new file mode 100644 index 00000000..7d1e7105 --- /dev/null +++ b/lib/models/plex_media_version.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'plex_media_version.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PlexMediaVersion _$PlexMediaVersionFromJson(Map json) => + PlexMediaVersion( + id: _flexibleIntOrZero(json['id']), + videoResolution: readStringField(json, 'videoResolution') as String?, + videoCodec: readStringField(json, 'videoCodec') as String?, + bitrate: flexibleInt(json['bitrate']), + width: flexibleInt(json['width']), + height: flexibleInt(json['height']), + container: readStringField(json, 'container') as String?, + partKey: _readPartKey(json, 'partKey') as String, + ); diff --git a/lib/models/plex_metadata.g.dart b/lib/models/plex_metadata.g.dart index cd168233..43d0be10 100644 --- a/lib/models/plex_metadata.g.dart +++ b/lib/models/plex_metadata.g.dart @@ -42,7 +42,9 @@ PlexMetadata _$PlexMetadataFromJson(Map json) => PlexMetadata( leafCount: (json['leafCount'] as num?)?.toInt(), viewedLeafCount: (json['viewedLeafCount'] as num?)?.toInt(), childCount: flexibleInt(json['childCount']), - role: (json['Role'] as List?)?.map((e) => PlexRole.fromJson(e as Map)).toList(), + role: (json['Role'] as List?) + ?.map((e) => PlexRole.fromJson(e as Map)) + .toList(), mediaVersions: (json['Media'] as List?) ?.map((e) => PlexMediaVersion.fromJson(e as Map)) .toList(), @@ -74,58 +76,59 @@ PlexMetadata _$PlexMetadataFromJson(Map json) => PlexMetadata( backgroundSquare: json['backgroundSquare'] as String?, ); -Map _$PlexMetadataToJson(PlexMetadata instance) => { - 'ratingKey': instance.ratingKey, - 'key': instance.key, - 'guid': instance.guid, - 'studio': instance.studio, - 'type': instance.type, - 'title': instance.title, - 'titleSort': instance.titleSort, - 'contentRating': instance.contentRating, - 'summary': instance.summary, - 'rating': instance.rating, - 'audienceRating': instance.audienceRating, - 'userRating': instance.userRating, - 'year': instance.year, - 'originallyAvailableAt': instance.originallyAvailableAt, - 'thumb': instance.thumb, - 'art': instance.art, - 'duration': instance.duration, - 'addedAt': instance.addedAt, - 'updatedAt': instance.updatedAt, - 'lastViewedAt': instance.lastViewedAt, - 'grandparentTitle': instance.grandparentTitle, - 'grandparentThumb': instance.grandparentThumb, - 'grandparentArt': instance.grandparentArt, - 'grandparentRatingKey': instance.grandparentRatingKey, - 'parentTitle': instance.parentTitle, - 'parentThumb': instance.parentThumb, - 'parentRatingKey': instance.parentRatingKey, - 'parentIndex': instance.parentIndex, - 'index': instance.index, - 'grandparentTheme': instance.grandparentTheme, - 'viewOffset': instance.viewOffset, - 'viewCount': instance.viewCount, - 'leafCount': instance.leafCount, - 'viewedLeafCount': instance.viewedLeafCount, - 'childCount': instance.childCount, - 'Role': instance.role, - 'audioLanguage': instance.audioLanguage, - 'subtitleLanguage': instance.subtitleLanguage, - 'subtitleMode': instance.subtitleMode, - 'playlistItemID': instance.playlistItemID, - 'playQueueItemID': instance.playQueueItemID, - 'librarySectionID': instance.librarySectionID, - 'librarySectionTitle': instance.librarySectionTitle, - 'ratingImage': instance.ratingImage, - 'audienceRatingImage': instance.audienceRatingImage, - 'tagline': instance.tagline, - 'originalTitle': instance.originalTitle, - 'editionTitle': instance.editionTitle, - 'subtype': instance.subtype, - 'extraType': instance.extraType, - 'primaryExtraKey': instance.primaryExtraKey, - 'clearLogo': instance.clearLogo, - 'backgroundSquare': instance.backgroundSquare, -}; +Map _$PlexMetadataToJson(PlexMetadata instance) => + { + 'ratingKey': instance.ratingKey, + 'key': instance.key, + 'guid': instance.guid, + 'studio': instance.studio, + 'type': instance.type, + 'title': instance.title, + 'titleSort': instance.titleSort, + 'contentRating': instance.contentRating, + 'summary': instance.summary, + 'rating': instance.rating, + 'audienceRating': instance.audienceRating, + 'userRating': instance.userRating, + 'year': instance.year, + 'originallyAvailableAt': instance.originallyAvailableAt, + 'thumb': instance.thumb, + 'art': instance.art, + 'duration': instance.duration, + 'addedAt': instance.addedAt, + 'updatedAt': instance.updatedAt, + 'lastViewedAt': instance.lastViewedAt, + 'grandparentTitle': instance.grandparentTitle, + 'grandparentThumb': instance.grandparentThumb, + 'grandparentArt': instance.grandparentArt, + 'grandparentRatingKey': instance.grandparentRatingKey, + 'parentTitle': instance.parentTitle, + 'parentThumb': instance.parentThumb, + 'parentRatingKey': instance.parentRatingKey, + 'parentIndex': instance.parentIndex, + 'index': instance.index, + 'grandparentTheme': instance.grandparentTheme, + 'viewOffset': instance.viewOffset, + 'viewCount': instance.viewCount, + 'leafCount': instance.leafCount, + 'viewedLeafCount': instance.viewedLeafCount, + 'childCount': instance.childCount, + 'Role': instance.role, + 'audioLanguage': instance.audioLanguage, + 'subtitleLanguage': instance.subtitleLanguage, + 'subtitleMode': instance.subtitleMode, + 'playlistItemID': instance.playlistItemID, + 'playQueueItemID': instance.playQueueItemID, + 'librarySectionID': instance.librarySectionID, + 'librarySectionTitle': instance.librarySectionTitle, + 'ratingImage': instance.ratingImage, + 'audienceRatingImage': instance.audienceRatingImage, + 'tagline': instance.tagline, + 'originalTitle': instance.originalTitle, + 'editionTitle': instance.editionTitle, + 'subtype': instance.subtype, + 'extraType': instance.extraType, + 'primaryExtraKey': instance.primaryExtraKey, + 'clearLogo': instance.clearLogo, + 'backgroundSquare': instance.backgroundSquare, + }; diff --git a/lib/models/plex_playlist.g.dart b/lib/models/plex_playlist.g.dart index 90dc322f..63d5512b 100644 --- a/lib/models/plex_playlist.g.dart +++ b/lib/models/plex_playlist.g.dart @@ -26,22 +26,23 @@ PlexPlaylist _$PlexPlaylistFromJson(Map json) => PlexPlaylist( thumb: json['thumb'] as String?, ); -Map _$PlexPlaylistToJson(PlexPlaylist instance) => { - 'ratingKey': instance.ratingKey, - 'key': instance.key, - 'type': instance.type, - 'title': instance.title, - 'summary': instance.summary, - 'smart': instance.smart, - 'playlistType': instance.playlistType, - 'duration': instance.duration, - 'leafCount': instance.leafCount, - 'composite': instance.composite, - 'addedAt': instance.addedAt, - 'updatedAt': instance.updatedAt, - 'lastViewedAt': instance.lastViewedAt, - 'viewCount': instance.viewCount, - 'content': instance.content, - 'guid': instance.guid, - 'thumb': instance.thumb, -}; +Map _$PlexPlaylistToJson(PlexPlaylist instance) => + { + 'ratingKey': instance.ratingKey, + 'key': instance.key, + 'type': instance.type, + 'title': instance.title, + 'summary': instance.summary, + 'smart': instance.smart, + 'playlistType': instance.playlistType, + 'duration': instance.duration, + 'leafCount': instance.leafCount, + 'composite': instance.composite, + 'addedAt': instance.addedAt, + 'updatedAt': instance.updatedAt, + 'lastViewedAt': instance.lastViewedAt, + 'viewCount': instance.viewCount, + 'content': instance.content, + 'guid': instance.guid, + 'thumb': instance.thumb, + }; diff --git a/lib/models/plex_sort.dart b/lib/models/plex_sort.dart index b34169e0..6884d743 100644 --- a/lib/models/plex_sort.dart +++ b/lib/models/plex_sort.dart @@ -1,3 +1,8 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'plex_sort.g.dart'; + +@JsonSerializable() class PlexSort { final String key; final String? descKey; @@ -6,14 +11,9 @@ class PlexSort { PlexSort({required this.key, this.descKey, required this.title, this.defaultDirection}); - factory PlexSort.fromJson(Map json) { - return PlexSort( - key: json['key'] as String, - descKey: json['descKey'] as String?, - title: json['title'] as String, - defaultDirection: json['defaultDirection'] as String?, - ); - } + factory PlexSort.fromJson(Map json) => _$PlexSortFromJson(json); + + Map toJson() => _$PlexSortToJson(this); /// Gets the full sort key with direction /// If [descending] is true, returns the descKey or key:desc diff --git a/lib/models/plex_sort.g.dart b/lib/models/plex_sort.g.dart new file mode 100644 index 00000000..4ebe5f3c --- /dev/null +++ b/lib/models/plex_sort.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'plex_sort.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PlexSort _$PlexSortFromJson(Map json) => PlexSort( + key: json['key'] as String, + descKey: json['descKey'] as String?, + title: json['title'] as String, + defaultDirection: json['defaultDirection'] as String?, +); + +Map _$PlexSortToJson(PlexSort instance) => { + 'key': instance.key, + 'descKey': instance.descKey, + 'title': instance.title, + 'defaultDirection': instance.defaultDirection, +}; diff --git a/lib/models/plex_subtitle_search_result.dart b/lib/models/plex_subtitle_search_result.dart index 453b9172..f4a9c1a2 100644 --- a/lib/models/plex_subtitle_search_result.dart +++ b/lib/models/plex_subtitle_search_result.dart @@ -1,18 +1,38 @@ +import 'package:json_annotation/json_annotation.dart'; + import '../utils/json_utils.dart'; +part 'plex_subtitle_search_result.g.dart'; + +int _flexibleIntOrZero(Object? v) => flexibleInt(v) ?? 0; + +@JsonSerializable() class PlexSubtitleSearchResult { + @JsonKey(fromJson: _flexibleIntOrZero) final int id; + @JsonKey(readValue: readStringField, defaultValue: '') final String key; + @JsonKey(readValue: readStringField) final String? codec; + @JsonKey(readValue: readStringField) final String? language; + @JsonKey(readValue: readStringField) final String? languageCode; + @JsonKey(fromJson: flexibleDouble) final double? score; + @JsonKey(readValue: readStringField) final String? providerTitle; + @JsonKey(readValue: readStringField) final String? title; + @JsonKey(readValue: readStringField) final String? displayTitle; + @JsonKey(fromJson: flexibleBool) final bool hearingImpaired; + @JsonKey(fromJson: flexibleBool) final bool perfectMatch; + @JsonKey(fromJson: flexibleBool) final bool downloaded; + @JsonKey(fromJson: flexibleBool) final bool forced; PlexSubtitleSearchResult({ @@ -31,21 +51,7 @@ class PlexSubtitleSearchResult { this.forced = false, }); - factory PlexSubtitleSearchResult.fromJson(Map json) { - return PlexSubtitleSearchResult( - id: flexibleInt(json['id']) ?? 0, - key: json['key']?.toString() ?? '', - codec: json['codec']?.toString(), - language: json['language']?.toString(), - languageCode: json['languageCode']?.toString(), - score: flexibleDouble(json['score']), - providerTitle: json['providerTitle']?.toString(), - title: json['title']?.toString(), - displayTitle: json['displayTitle']?.toString(), - hearingImpaired: flexibleBool(json['hearingImpaired']), - perfectMatch: flexibleBool(json['perfectMatch']), - downloaded: flexibleBool(json['downloaded']), - forced: flexibleBool(json['forced']), - ); - } + factory PlexSubtitleSearchResult.fromJson(Map json) => _$PlexSubtitleSearchResultFromJson(json); + + Map toJson() => _$PlexSubtitleSearchResultToJson(this); } diff --git a/lib/models/plex_subtitle_search_result.g.dart b/lib/models/plex_subtitle_search_result.g.dart new file mode 100644 index 00000000..20fd2b45 --- /dev/null +++ b/lib/models/plex_subtitle_search_result.g.dart @@ -0,0 +1,49 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'plex_subtitle_search_result.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PlexSubtitleSearchResult _$PlexSubtitleSearchResultFromJson( + Map json, +) => PlexSubtitleSearchResult( + id: _flexibleIntOrZero(json['id']), + key: readStringField(json, 'key') as String? ?? '', + codec: readStringField(json, 'codec') as String?, + language: readStringField(json, 'language') as String?, + languageCode: readStringField(json, 'languageCode') as String?, + score: flexibleDouble(json['score']), + providerTitle: readStringField(json, 'providerTitle') as String?, + title: readStringField(json, 'title') as String?, + displayTitle: readStringField(json, 'displayTitle') as String?, + hearingImpaired: json['hearingImpaired'] == null + ? false + : flexibleBool(json['hearingImpaired']), + perfectMatch: json['perfectMatch'] == null + ? false + : flexibleBool(json['perfectMatch']), + downloaded: json['downloaded'] == null + ? false + : flexibleBool(json['downloaded']), + forced: json['forced'] == null ? false : flexibleBool(json['forced']), +); + +Map _$PlexSubtitleSearchResultToJson( + PlexSubtitleSearchResult instance, +) => { + 'id': instance.id, + 'key': instance.key, + 'codec': instance.codec, + 'language': instance.language, + 'languageCode': instance.languageCode, + 'score': instance.score, + 'providerTitle': instance.providerTitle, + 'title': instance.title, + 'displayTitle': instance.displayTitle, + 'hearingImpaired': instance.hearingImpaired, + 'perfectMatch': instance.perfectMatch, + 'downloaded': instance.downloaded, + 'forced': instance.forced, +}; diff --git a/lib/models/plex_user_profile.dart b/lib/models/plex_user_profile.dart index 30970add..ea30376b 100644 --- a/lib/models/plex_user_profile.dart +++ b/lib/models/plex_user_profile.dart @@ -1,16 +1,28 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'plex_user_profile.g.dart'; + /// Represents a Plex user's profile preferences /// Fetched from https://clients.plex.tv/api/v2/user +@JsonSerializable() class PlexUserProfile { + @JsonKey(defaultValue: true) final bool autoSelectAudio; + @JsonKey(defaultValue: 0) final int defaultAudioAccessibility; final String? defaultAudioLanguage; final List? defaultAudioLanguages; final String? defaultSubtitleLanguage; final List? defaultSubtitleLanguages; + @JsonKey(defaultValue: 0) final int autoSelectSubtitle; + @JsonKey(defaultValue: 0) final int defaultSubtitleAccessibility; + @JsonKey(defaultValue: 1) final int defaultSubtitleForced; + @JsonKey(defaultValue: 1) final int watchedIndicator; + @JsonKey(defaultValue: 0) final int mediaReviewsVisibility; final List? mediaReviewsLanguages; @@ -31,45 +43,8 @@ class PlexUserProfile { factory PlexUserProfile.fromJson(Map json) { final profile = json['profile'] as Map? ?? json; - - return PlexUserProfile( - autoSelectAudio: profile['autoSelectAudio'] as bool? ?? true, - defaultAudioAccessibility: profile['defaultAudioAccessibility'] as int? ?? 0, - defaultAudioLanguage: profile['defaultAudioLanguage'] as String?, - defaultAudioLanguages: profile['defaultAudioLanguages'] != null - ? List.from(profile['defaultAudioLanguages'] as List) - : null, - defaultSubtitleLanguage: profile['defaultSubtitleLanguage'] as String?, - defaultSubtitleLanguages: profile['defaultSubtitleLanguages'] != null - ? List.from(profile['defaultSubtitleLanguages'] as List) - : null, - autoSelectSubtitle: profile['autoSelectSubtitle'] as int? ?? 0, - defaultSubtitleAccessibility: profile['defaultSubtitleAccessibility'] as int? ?? 0, - defaultSubtitleForced: profile['defaultSubtitleForced'] as int? ?? 1, - watchedIndicator: profile['watchedIndicator'] as int? ?? 1, - mediaReviewsVisibility: profile['mediaReviewsVisibility'] as int? ?? 0, - mediaReviewsLanguages: profile['mediaReviewsLanguages'] != null - ? List.from(profile['mediaReviewsLanguages'] as List) - : null, - ); + return _$PlexUserProfileFromJson(profile); } - Map toJson() { - return { - 'profile': { - 'autoSelectAudio': autoSelectAudio, - 'defaultAudioAccessibility': defaultAudioAccessibility, - 'defaultAudioLanguage': defaultAudioLanguage, - 'defaultAudioLanguages': defaultAudioLanguages, - 'defaultSubtitleLanguage': defaultSubtitleLanguage, - 'defaultSubtitleLanguages': defaultSubtitleLanguages, - 'autoSelectSubtitle': autoSelectSubtitle, - 'defaultSubtitleAccessibility': defaultSubtitleAccessibility, - 'defaultSubtitleForced': defaultSubtitleForced, - 'watchedIndicator': watchedIndicator, - 'mediaReviewsVisibility': mediaReviewsVisibility, - 'mediaReviewsLanguages': mediaReviewsLanguages, - }, - }; - } + Map toJson() => {'profile': _$PlexUserProfileToJson(this)}; } diff --git a/lib/models/plex_user_profile.g.dart b/lib/models/plex_user_profile.g.dart new file mode 100644 index 00000000..bdba7d4a --- /dev/null +++ b/lib/models/plex_user_profile.g.dart @@ -0,0 +1,49 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'plex_user_profile.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PlexUserProfile _$PlexUserProfileFromJson( + Map json, +) => PlexUserProfile( + autoSelectAudio: json['autoSelectAudio'] as bool? ?? true, + defaultAudioAccessibility: + (json['defaultAudioAccessibility'] as num?)?.toInt() ?? 0, + defaultAudioLanguage: json['defaultAudioLanguage'] as String?, + defaultAudioLanguages: (json['defaultAudioLanguages'] as List?) + ?.map((e) => e as String) + .toList(), + defaultSubtitleLanguage: json['defaultSubtitleLanguage'] as String?, + defaultSubtitleLanguages: (json['defaultSubtitleLanguages'] as List?) + ?.map((e) => e as String) + .toList(), + autoSelectSubtitle: (json['autoSelectSubtitle'] as num?)?.toInt() ?? 0, + defaultSubtitleAccessibility: + (json['defaultSubtitleAccessibility'] as num?)?.toInt() ?? 0, + defaultSubtitleForced: (json['defaultSubtitleForced'] as num?)?.toInt() ?? 1, + watchedIndicator: (json['watchedIndicator'] as num?)?.toInt() ?? 1, + mediaReviewsVisibility: + (json['mediaReviewsVisibility'] as num?)?.toInt() ?? 0, + mediaReviewsLanguages: (json['mediaReviewsLanguages'] as List?) + ?.map((e) => e as String) + .toList(), +); + +Map _$PlexUserProfileToJson(PlexUserProfile instance) => + { + 'autoSelectAudio': instance.autoSelectAudio, + 'defaultAudioAccessibility': instance.defaultAudioAccessibility, + 'defaultAudioLanguage': instance.defaultAudioLanguage, + 'defaultAudioLanguages': instance.defaultAudioLanguages, + 'defaultSubtitleLanguage': instance.defaultSubtitleLanguage, + 'defaultSubtitleLanguages': instance.defaultSubtitleLanguages, + 'autoSelectSubtitle': instance.autoSelectSubtitle, + 'defaultSubtitleAccessibility': instance.defaultSubtitleAccessibility, + 'defaultSubtitleForced': instance.defaultSubtitleForced, + 'watchedIndicator': instance.watchedIndicator, + 'mediaReviewsVisibility': instance.mediaReviewsVisibility, + 'mediaReviewsLanguages': instance.mediaReviewsLanguages, + };