feat: jellyfin
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import '../../media/media_item.dart';
|
||||
|
||||
/// Response from Plex play queue API.
|
||||
/// Contains queue metadata and a window of items in neutral [MediaItem] form.
|
||||
class PlayQueueResponse {
|
||||
final int playQueueID;
|
||||
final int? playQueueSelectedItemID;
|
||||
final int? playQueueSelectedItemOffset;
|
||||
final String? playQueueSelectedMetadataItemID;
|
||||
final bool playQueueShuffled;
|
||||
final String? playQueueSourceURI;
|
||||
final int? playQueueTotalCount;
|
||||
final int playQueueVersion;
|
||||
final int? size; // Number of items in this response window
|
||||
final List<MediaItem>? items;
|
||||
|
||||
PlayQueueResponse({
|
||||
required this.playQueueID,
|
||||
this.playQueueSelectedItemID,
|
||||
this.playQueueSelectedItemOffset,
|
||||
this.playQueueSelectedMetadataItemID,
|
||||
required this.playQueueShuffled,
|
||||
this.playQueueSourceURI,
|
||||
required this.playQueueTotalCount,
|
||||
required this.playQueueVersion,
|
||||
this.size,
|
||||
this.items,
|
||||
});
|
||||
|
||||
/// Get the current selected item from the queue. Items in a Plex
|
||||
/// `PlayQueueResponse` are always [PlexMediaItem]; the cast is safe.
|
||||
MediaItem? get selectedItem {
|
||||
if (items == null || playQueueSelectedItemID == null) return null;
|
||||
try {
|
||||
return items!.firstWhere((item) => item is PlexMediaItem && item.playQueueItemId == playQueueSelectedItemID);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the index of the selected item in the current window
|
||||
int? get selectedItemIndex {
|
||||
if (items == null || playQueueSelectedItemID == null) return null;
|
||||
return items!.indexWhere((item) => item is PlexMediaItem && item.playQueueItemId == playQueueSelectedItemID);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
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({
|
||||
required this.uuid,
|
||||
required this.type,
|
||||
required this.title,
|
||||
this.subtitle,
|
||||
required this.progress,
|
||||
required this.cancellable,
|
||||
});
|
||||
|
||||
factory PlexActivity.fromJson(Map<String, dynamic> json) => _$PlexActivityFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'plex_activity.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
PlexActivity _$PlexActivityFromJson(Map<String, dynamic> 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,
|
||||
);
|
||||
@@ -0,0 +1,92 @@
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
class PlexConfig {
|
||||
final String baseUrl;
|
||||
final String? token;
|
||||
final String clientIdentifier;
|
||||
final String product;
|
||||
final String version;
|
||||
final String platform;
|
||||
final String? device;
|
||||
final bool acceptJson;
|
||||
final String? machineIdentifier;
|
||||
|
||||
PlexConfig({
|
||||
required this.baseUrl,
|
||||
this.token,
|
||||
required this.clientIdentifier,
|
||||
required this.product,
|
||||
required this.version,
|
||||
this.platform = 'Flutter',
|
||||
this.device,
|
||||
this.acceptJson = true,
|
||||
this.machineIdentifier,
|
||||
});
|
||||
|
||||
static Future<PlexConfig> create({
|
||||
required String baseUrl,
|
||||
String? token,
|
||||
required String clientIdentifier,
|
||||
String? product,
|
||||
String? platform,
|
||||
String? device,
|
||||
bool acceptJson = true,
|
||||
String? machineIdentifier,
|
||||
}) async {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
return PlexConfig(
|
||||
baseUrl: baseUrl,
|
||||
token: token,
|
||||
clientIdentifier: clientIdentifier,
|
||||
product: product ?? 'Plezy',
|
||||
version: packageInfo.version,
|
||||
platform: platform ?? 'Flutter',
|
||||
device: device,
|
||||
acceptJson: acceptJson,
|
||||
machineIdentifier: machineIdentifier,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, String> get headers {
|
||||
final headers = {
|
||||
'X-Plex-Client-Identifier': clientIdentifier,
|
||||
'X-Plex-Product': product,
|
||||
'X-Plex-Version': version,
|
||||
'X-Plex-Platform': platform,
|
||||
'X-Plex-Client-Profile-Name': 'Generic',
|
||||
'X-Plex-Device': ?device,
|
||||
if (acceptJson) 'Accept': 'application/json',
|
||||
'Accept-Charset': 'utf-8',
|
||||
};
|
||||
|
||||
if (token != null) {
|
||||
headers['X-Plex-Token'] = token!;
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
PlexConfig copyWith({
|
||||
String? baseUrl,
|
||||
String? token,
|
||||
String? clientIdentifier,
|
||||
String? product,
|
||||
String? version,
|
||||
String? platform,
|
||||
String? device,
|
||||
bool? acceptJson,
|
||||
String? machineIdentifier,
|
||||
}) {
|
||||
return PlexConfig(
|
||||
baseUrl: baseUrl ?? this.baseUrl,
|
||||
token: token ?? this.token,
|
||||
clientIdentifier: clientIdentifier ?? this.clientIdentifier,
|
||||
product: product ?? this.product,
|
||||
version: version ?? this.version,
|
||||
platform: platform ?? this.platform,
|
||||
device: device ?? this.device,
|
||||
acceptJson: acceptJson ?? this.acceptJson,
|
||||
machineIdentifier: machineIdentifier ?? this.machineIdentifier,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
import 'plex_home_user.dart';
|
||||
|
||||
part 'plex_home.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class PlexHome {
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int id;
|
||||
@JsonKey(defaultValue: '')
|
||||
final String name;
|
||||
final int? guestUserID;
|
||||
@JsonKey(defaultValue: '')
|
||||
final String guestUserUUID;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool guestEnabled;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool subscription;
|
||||
@JsonKey(defaultValue: <PlexHomeUser>[])
|
||||
final List<PlexHomeUser> users;
|
||||
|
||||
PlexHome({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.guestUserID,
|
||||
required this.guestUserUUID,
|
||||
required this.guestEnabled,
|
||||
required this.subscription,
|
||||
required this.users,
|
||||
});
|
||||
|
||||
factory PlexHome.fromJson(Map<String, dynamic> json) => _$PlexHomeFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$PlexHomeToJson(this);
|
||||
|
||||
PlexHomeUser? get adminUser => users.where((user) => user.admin).firstOrNull;
|
||||
|
||||
List<PlexHomeUser> get managedUsers => users.where((user) => !user.admin).toList();
|
||||
|
||||
List<PlexHomeUser> get restrictedUsers => users.where((user) => user.restricted).toList();
|
||||
|
||||
PlexHomeUser? getUserByUUID(String uuid) {
|
||||
try {
|
||||
return users.firstWhere((user) => user.uuid == uuid);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
bool get hasMultipleUsers => users.length > 1;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'plex_home.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
PlexHome _$PlexHomeFromJson(Map<String, dynamic> json) => PlexHome(
|
||||
id: (json['id'] as num?)?.toInt() ?? 0,
|
||||
name: json['name'] as String? ?? '',
|
||||
guestUserID: (json['guestUserID'] as num?)?.toInt(),
|
||||
guestUserUUID: json['guestUserUUID'] as String? ?? '',
|
||||
guestEnabled: json['guestEnabled'] as bool? ?? false,
|
||||
subscription: json['subscription'] as bool? ?? false,
|
||||
users: (json['users'] as List<dynamic>?)?.map((e) => PlexHomeUser.fromJson(e as Map<String, dynamic>)).toList() ?? [],
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PlexHomeToJson(PlexHome instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'name': instance.name,
|
||||
'guestUserID': instance.guestUserID,
|
||||
'guestUserUUID': instance.guestUserUUID,
|
||||
'guestEnabled': instance.guestEnabled,
|
||||
'subscription': instance.subscription,
|
||||
'users': instance.users,
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'plex_home_user.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class PlexHomeUser {
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int id;
|
||||
@JsonKey(defaultValue: '')
|
||||
final String uuid;
|
||||
@JsonKey(defaultValue: 'Unknown')
|
||||
final String title;
|
||||
final String? username;
|
||||
final String? email;
|
||||
final String? friendlyName;
|
||||
@JsonKey(defaultValue: '')
|
||||
final String thumb;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool hasPassword;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool restricted;
|
||||
final int? updatedAt;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool admin;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool guest;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool protected;
|
||||
|
||||
PlexHomeUser({
|
||||
required this.id,
|
||||
required this.uuid,
|
||||
required this.title,
|
||||
this.username,
|
||||
this.email,
|
||||
this.friendlyName,
|
||||
required this.thumb,
|
||||
required this.hasPassword,
|
||||
required this.restricted,
|
||||
required this.updatedAt,
|
||||
required this.admin,
|
||||
required this.guest,
|
||||
required this.protected,
|
||||
});
|
||||
|
||||
factory PlexHomeUser.fromJson(Map<String, dynamic> json) => _$PlexHomeUserFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$PlexHomeUserToJson(this);
|
||||
|
||||
String get displayName => friendlyName ?? title;
|
||||
|
||||
bool get isAdminUser => admin;
|
||||
bool get isRestrictedUser => restricted;
|
||||
bool get isGuestUser => guest;
|
||||
bool get requiresPassword => protected;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'plex_home_user.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
PlexHomeUser _$PlexHomeUserFromJson(Map<String, dynamic> json) => PlexHomeUser(
|
||||
id: (json['id'] as num?)?.toInt() ?? 0,
|
||||
uuid: json['uuid'] as String? ?? '',
|
||||
title: json['title'] as String? ?? 'Unknown',
|
||||
username: json['username'] as String?,
|
||||
email: json['email'] as String?,
|
||||
friendlyName: json['friendlyName'] as String?,
|
||||
thumb: json['thumb'] as String? ?? '',
|
||||
hasPassword: json['hasPassword'] as bool? ?? false,
|
||||
restricted: json['restricted'] as bool? ?? false,
|
||||
updatedAt: (json['updatedAt'] as num?)?.toInt(),
|
||||
admin: json['admin'] as bool? ?? false,
|
||||
guest: json['guest'] as bool? ?? false,
|
||||
protected: json['protected'] as bool? ?? false,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PlexHomeUserToJson(PlexHomeUser instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'uuid': instance.uuid,
|
||||
'title': instance.title,
|
||||
'username': instance.username,
|
||||
'email': instance.email,
|
||||
'friendlyName': instance.friendlyName,
|
||||
'thumb': instance.thumb,
|
||||
'hasPassword': instance.hasPassword,
|
||||
'restricted': instance.restricted,
|
||||
'updatedAt': instance.updatedAt,
|
||||
'admin': instance.admin,
|
||||
'guest': instance.guest,
|
||||
'protected': instance.protected,
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
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({
|
||||
required this.guid,
|
||||
required this.name,
|
||||
this.year,
|
||||
this.score,
|
||||
this.thumb,
|
||||
this.summary,
|
||||
this.type,
|
||||
this.matched = false,
|
||||
});
|
||||
|
||||
factory PlexMatchResult.fromJson(Map<String, dynamic> json) => _$PlexMatchResultFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$PlexMatchResultToJson(this);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'plex_match_result.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
PlexMatchResult _$PlexMatchResultFromJson(Map<String, dynamic> 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<String, dynamic> _$PlexMatchResultToJson(PlexMatchResult instance) => <String, dynamic>{
|
||||
'guid': instance.guid,
|
||||
'name': instance.name,
|
||||
'year': instance.year,
|
||||
'score': instance.score,
|
||||
'thumb': instance.thumb,
|
||||
'summary': instance.summary,
|
||||
'type': instance.type,
|
||||
'matched': instance.matched,
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
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({
|
||||
required this.id,
|
||||
required this.key,
|
||||
this.codec,
|
||||
this.language,
|
||||
this.languageCode,
|
||||
this.score,
|
||||
this.providerTitle,
|
||||
this.title,
|
||||
this.displayTitle,
|
||||
this.hearingImpaired = false,
|
||||
this.perfectMatch = false,
|
||||
this.downloaded = false,
|
||||
this.forced = false,
|
||||
});
|
||||
|
||||
factory PlexSubtitleSearchResult.fromJson(Map<String, dynamic> json) => _$PlexSubtitleSearchResultFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$PlexSubtitleSearchResultToJson(this);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'plex_subtitle_search_result.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
PlexSubtitleSearchResult _$PlexSubtitleSearchResultFromJson(Map<String, dynamic> 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<String, dynamic> _$PlexSubtitleSearchResultToJson(PlexSubtitleSearchResult instance) => <String, dynamic>{
|
||||
'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,
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
import '../../media/media_server_user_profile.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 implements MediaServerUserProfile {
|
||||
@JsonKey(defaultValue: true)
|
||||
@override
|
||||
final bool autoSelectAudio;
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int defaultAudioAccessibility;
|
||||
@override
|
||||
final String? defaultAudioLanguage;
|
||||
@override
|
||||
final List<String>? defaultAudioLanguages;
|
||||
@override
|
||||
final String? defaultSubtitleLanguage;
|
||||
@override
|
||||
final List<String>? 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<String>? mediaReviewsLanguages;
|
||||
|
||||
@override
|
||||
SubtitlePlaybackMode? get subtitleMode => null;
|
||||
|
||||
PlexUserProfile({
|
||||
required this.autoSelectAudio,
|
||||
required this.defaultAudioAccessibility,
|
||||
this.defaultAudioLanguage,
|
||||
this.defaultAudioLanguages,
|
||||
this.defaultSubtitleLanguage,
|
||||
this.defaultSubtitleLanguages,
|
||||
required this.autoSelectSubtitle,
|
||||
required this.defaultSubtitleAccessibility,
|
||||
required this.defaultSubtitleForced,
|
||||
required this.watchedIndicator,
|
||||
required this.mediaReviewsVisibility,
|
||||
this.mediaReviewsLanguages,
|
||||
});
|
||||
|
||||
factory PlexUserProfile.fromJson(Map<String, dynamic> json) {
|
||||
final profile = json['profile'] as Map<String, dynamic>? ?? json;
|
||||
return _$PlexUserProfileFromJson(profile);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'profile': _$PlexUserProfileToJson(this)};
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'plex_user_profile.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
PlexUserProfile _$PlexUserProfileFromJson(Map<String, dynamic> 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<dynamic>?)?.map((e) => e as String).toList(),
|
||||
defaultSubtitleLanguage: json['defaultSubtitleLanguage'] as String?,
|
||||
defaultSubtitleLanguages: (json['defaultSubtitleLanguages'] as List<dynamic>?)?.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<dynamic>?)?.map((e) => e as String).toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PlexUserProfileToJson(PlexUserProfile instance) => <String, dynamic>{
|
||||
'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,
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
import '../../media/media_source_info.dart';
|
||||
import '../../media/media_version.dart';
|
||||
|
||||
/// Consolidated data model containing all information needed for video playback.
|
||||
/// This model combines data from multiple Plex API endpoints to reduce redundant requests.
|
||||
class PlexVideoPlaybackData {
|
||||
/// Direct video URL for playback
|
||||
final String? videoUrl;
|
||||
|
||||
/// Media information including audio/subtitle tracks and chapters
|
||||
final MediaSourceInfo? mediaInfo;
|
||||
|
||||
/// Available media versions/qualities for this content
|
||||
final List<MediaVersion> availableVersions;
|
||||
|
||||
/// Markers for intro/credits skip functionality
|
||||
final List<MediaMarker> markers;
|
||||
|
||||
PlexVideoPlaybackData({
|
||||
required this.videoUrl,
|
||||
required this.mediaInfo,
|
||||
required this.availableVersions,
|
||||
this.markers = const [],
|
||||
});
|
||||
|
||||
/// Returns true if this playback data has a valid video URL
|
||||
bool get hasValidVideoUrl => videoUrl != null && videoUrl!.isNotEmpty;
|
||||
|
||||
/// Returns true if media info is available
|
||||
bool get hasMediaInfo => mediaInfo != null;
|
||||
}
|
||||
Reference in New Issue
Block a user