feat: display movie edition titles across all views
This commit is contained in:
@@ -99,6 +99,7 @@ class PlexMetadata with MultiServerFields {
|
|||||||
final String? audienceRatingImage; // Audience rating source URI
|
final String? audienceRatingImage; // Audience rating source URI
|
||||||
final String? tagline;
|
final String? tagline;
|
||||||
final String? originalTitle;
|
final String? originalTitle;
|
||||||
|
final String? editionTitle; // Edition name for movies (e.g., "Director's Cut", "Extended")
|
||||||
final String? subtype; // Clip subtype: "trailer", "behindTheScenes", "deleted", etc.
|
final String? subtype; // Clip subtype: "trailer", "behindTheScenes", "deleted", etc.
|
||||||
final int? extraType; // Numeric extra type identifier
|
final int? extraType; // Numeric extra type identifier
|
||||||
final String? primaryExtraKey; // Points to main trailer (e.g., "/library/metadata/52601")
|
final String? primaryExtraKey; // Points to main trailer (e.g., "/library/metadata/52601")
|
||||||
@@ -186,6 +187,7 @@ class PlexMetadata with MultiServerFields {
|
|||||||
this.audienceRatingImage,
|
this.audienceRatingImage,
|
||||||
this.tagline,
|
this.tagline,
|
||||||
this.originalTitle,
|
this.originalTitle,
|
||||||
|
this.editionTitle,
|
||||||
this.subtype,
|
this.subtype,
|
||||||
this.extraType,
|
this.extraType,
|
||||||
this.primaryExtraKey,
|
this.primaryExtraKey,
|
||||||
@@ -244,6 +246,7 @@ class PlexMetadata with MultiServerFields {
|
|||||||
String? audienceRatingImage,
|
String? audienceRatingImage,
|
||||||
String? tagline,
|
String? tagline,
|
||||||
String? originalTitle,
|
String? originalTitle,
|
||||||
|
String? editionTitle,
|
||||||
String? subtype,
|
String? subtype,
|
||||||
int? extraType,
|
int? extraType,
|
||||||
String? primaryExtraKey,
|
String? primaryExtraKey,
|
||||||
@@ -300,6 +303,7 @@ class PlexMetadata with MultiServerFields {
|
|||||||
audienceRatingImage: audienceRatingImage ?? this.audienceRatingImage,
|
audienceRatingImage: audienceRatingImage ?? this.audienceRatingImage,
|
||||||
tagline: tagline ?? this.tagline,
|
tagline: tagline ?? this.tagline,
|
||||||
originalTitle: originalTitle ?? this.originalTitle,
|
originalTitle: originalTitle ?? this.originalTitle,
|
||||||
|
editionTitle: editionTitle ?? this.editionTitle,
|
||||||
subtype: subtype ?? this.subtype,
|
subtype: subtype ?? this.subtype,
|
||||||
extraType: extraType ?? this.extraType,
|
extraType: extraType ?? this.extraType,
|
||||||
primaryExtraKey: primaryExtraKey ?? this.primaryExtraKey,
|
primaryExtraKey: primaryExtraKey ?? this.primaryExtraKey,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ PlexMetadata _$PlexMetadataFromJson(Map<String, dynamic> json) => PlexMetadata(
|
|||||||
audienceRatingImage: json['audienceRatingImage'] as String?,
|
audienceRatingImage: json['audienceRatingImage'] as String?,
|
||||||
tagline: json['tagline'] as String?,
|
tagline: json['tagline'] as String?,
|
||||||
originalTitle: json['originalTitle'] as String?,
|
originalTitle: json['originalTitle'] as String?,
|
||||||
|
editionTitle: json['editionTitle'] as String?,
|
||||||
subtype: json['subtype'] as String?,
|
subtype: json['subtype'] as String?,
|
||||||
extraType: (json['extraType'] as num?)?.toInt(),
|
extraType: (json['extraType'] as num?)?.toInt(),
|
||||||
primaryExtraKey: json['primaryExtraKey'] as String?,
|
primaryExtraKey: json['primaryExtraKey'] as String?,
|
||||||
@@ -109,6 +110,7 @@ Map<String, dynamic> _$PlexMetadataToJson(PlexMetadata instance) => <String, dyn
|
|||||||
'audienceRatingImage': instance.audienceRatingImage,
|
'audienceRatingImage': instance.audienceRatingImage,
|
||||||
'tagline': instance.tagline,
|
'tagline': instance.tagline,
|
||||||
'originalTitle': instance.originalTitle,
|
'originalTitle': instance.originalTitle,
|
||||||
|
'editionTitle': instance.editionTitle,
|
||||||
'subtype': instance.subtype,
|
'subtype': instance.subtype,
|
||||||
'extraType': instance.extraType,
|
'extraType': instance.extraType,
|
||||||
'primaryExtraKey': instance.primaryExtraKey,
|
'primaryExtraKey': instance.primaryExtraKey,
|
||||||
|
|||||||
@@ -2041,6 +2041,7 @@ class _MediaDetailScreenState extends State<MediaDetailScreen>
|
|||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
children: [
|
children: [
|
||||||
if (metadata.year != null) _buildMetadataChip('${metadata.year}'),
|
if (metadata.year != null) _buildMetadataChip('${metadata.year}'),
|
||||||
|
if (metadata.editionTitle != null) _buildMetadataChip(metadata.editionTitle!),
|
||||||
if (metadata.contentRating != null)
|
if (metadata.contentRating != null)
|
||||||
_buildMetadataChip(formatContentRating(metadata.contentRating!)),
|
_buildMetadataChip(formatContentRating(metadata.contentRating!)),
|
||||||
if (metadata.duration != null)
|
if (metadata.duration != null)
|
||||||
|
|||||||
@@ -248,8 +248,12 @@ class _PlaylistItemCardState extends State<PlaylistItemCard> {
|
|||||||
}
|
}
|
||||||
return widget.item.displaySubtitle ?? t.discover.tvShow;
|
return widget.item.displaySubtitle ?? t.discover.tvShow;
|
||||||
} else if (itemType == 'movie') {
|
} else if (itemType == 'movie') {
|
||||||
// For movies, show year
|
// For movies, show year and edition
|
||||||
return widget.item.year?.toString() ?? t.discover.movie;
|
final year = widget.item.year?.toString();
|
||||||
|
if (year != null && widget.item.editionTitle != null) {
|
||||||
|
return '$year · ${widget.item.editionTitle}';
|
||||||
|
}
|
||||||
|
return year ?? t.discover.movie;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to type
|
// Default to type
|
||||||
|
|||||||
@@ -455,6 +455,11 @@ class _MediaCardList extends StatelessWidget {
|
|||||||
parts.add('${metadata.year}');
|
parts.add('${metadata.year}');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add edition title
|
||||||
|
if (metadata.editionTitle != null) {
|
||||||
|
parts.add(metadata.editionTitle!);
|
||||||
|
}
|
||||||
|
|
||||||
// Add duration
|
// Add duration
|
||||||
if (metadata.duration != null) {
|
if (metadata.duration != null) {
|
||||||
parts.add(formatDurationTextual(metadata.duration!));
|
parts.add(formatDurationTextual(metadata.duration!));
|
||||||
@@ -749,7 +754,9 @@ class _MediaCardHelpers {
|
|||||||
);
|
);
|
||||||
} else if (metadata.year != null) {
|
} else if (metadata.year != null) {
|
||||||
return Text(
|
return Text(
|
||||||
'${metadata.year}',
|
metadata.editionTitle != null ? '${metadata.year} · ${metadata.editionTitle}' : '${metadata.year}',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
style: Theme.of(
|
style: Theme.of(
|
||||||
context,
|
context,
|
||||||
).textTheme.bodySmall?.copyWith(color: tokens(context).textMuted, fontSize: 11, height: 1.1),
|
).textTheme.bodySmall?.copyWith(color: tokens(context).textMuted, fontSize: 11, height: 1.1),
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class QueueSheet extends StatelessWidget {
|
|||||||
return item.grandparentTitle!;
|
return item.grandparentTitle!;
|
||||||
}
|
}
|
||||||
if (item.year != null) {
|
if (item.year != null) {
|
||||||
return '${item.year}';
|
return item.editionTitle != null ? '${item.year} · ${item.editionTitle}' : '${item.year}';
|
||||||
}
|
}
|
||||||
return item.type;
|
return item.type;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -510,7 +510,7 @@ class ContentStripState extends State<ContentStrip> {
|
|||||||
return '${item.grandparentTitle} \u00b7 S${item.parentIndex}E${item.index}';
|
return '${item.grandparentTitle} \u00b7 S${item.parentIndex}E${item.index}';
|
||||||
}
|
}
|
||||||
if (item.grandparentTitle != null) return item.grandparentTitle!;
|
if (item.grandparentTitle != null) return item.grandparentTitle!;
|
||||||
if (item.year != null) return '${item.year}';
|
if (item.year != null) return item.editionTitle != null ? '${item.year} · ${item.editionTitle}' : '${item.year}';
|
||||||
return item.type;
|
return item.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user