114 lines
3.2 KiB
Dart
114 lines
3.2 KiB
Dart
class VideoItem {
|
|
const VideoItem({
|
|
required this.id,
|
|
required this.title,
|
|
required this.author,
|
|
required this.thumbnailUrl,
|
|
this.duration,
|
|
this.channelId,
|
|
this.viewCount,
|
|
this.likeCount,
|
|
this.commentCount,
|
|
this.description = '',
|
|
this.uploadDate,
|
|
});
|
|
|
|
final String id;
|
|
final String title;
|
|
final String author;
|
|
final String thumbnailUrl;
|
|
final Duration? duration;
|
|
|
|
/// YouTube channel ID when it is known.
|
|
///
|
|
/// Old history/favorites saved before step 18.3 simply have null here.
|
|
/// The channel screen can resolve it lazily from the video ID.
|
|
final String? channelId;
|
|
|
|
/// Public YouTube view count at the time the metadata was fetched.
|
|
final int? viewCount;
|
|
|
|
/// Public likes for this video when YouTube exposes the statistic.
|
|
final int? likeCount;
|
|
|
|
/// Public comments for this video when YouTube exposes the statistic.
|
|
final int? commentCount;
|
|
|
|
/// Public YouTube video description.
|
|
final String description;
|
|
|
|
/// YouTube upload date when available.
|
|
final DateTime? uploadDate;
|
|
|
|
String get durationLabel {
|
|
final value = duration;
|
|
if (value == null) {
|
|
return '';
|
|
}
|
|
|
|
final hours = value.inHours;
|
|
final minutes = value.inMinutes.remainder(60);
|
|
final seconds = value.inSeconds.remainder(60);
|
|
|
|
if (hours > 0) {
|
|
return '$hours:${minutes.toString().padLeft(2, '0')}:'
|
|
'${seconds.toString().padLeft(2, '0')}';
|
|
}
|
|
|
|
return '$minutes:${seconds.toString().padLeft(2, '0')}';
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
'id': id,
|
|
'title': title,
|
|
'author': author,
|
|
'thumbnailUrl': thumbnailUrl,
|
|
'durationSeconds': duration?.inSeconds,
|
|
if (channelId != null) 'channelId': channelId,
|
|
if (viewCount != null) 'viewCount': viewCount,
|
|
if (likeCount != null) 'likeCount': likeCount,
|
|
if (commentCount != null) 'commentCount': commentCount,
|
|
if (description.isNotEmpty) 'description': description,
|
|
if (uploadDate != null)
|
|
'uploadDate': uploadDate!.toIso8601String(),
|
|
};
|
|
}
|
|
|
|
factory VideoItem.fromJson(Map<String, dynamic> json) {
|
|
final durationSeconds = json['durationSeconds'];
|
|
final rawViewCount = json['viewCount'];
|
|
final rawLikeCount = json['likeCount'];
|
|
final rawCommentCount = json['commentCount'];
|
|
final rawUploadDate = json['uploadDate'];
|
|
|
|
return VideoItem(
|
|
id: json['id'] as String,
|
|
title: json['title'] as String,
|
|
author: json['author'] as String,
|
|
thumbnailUrl: json['thumbnailUrl'] as String,
|
|
duration: durationSeconds is num
|
|
? Duration(seconds: durationSeconds.toInt())
|
|
: null,
|
|
channelId: json['channelId'] is String
|
|
? json['channelId'] as String
|
|
: null,
|
|
viewCount: rawViewCount is num
|
|
? rawViewCount.toInt()
|
|
: null,
|
|
likeCount: rawLikeCount is num
|
|
? rawLikeCount.toInt()
|
|
: null,
|
|
commentCount: rawCommentCount is num
|
|
? rawCommentCount.toInt()
|
|
: null,
|
|
description: json['description'] is String
|
|
? json['description'] as String
|
|
: '',
|
|
uploadDate: rawUploadDate is String
|
|
? DateTime.tryParse(rawUploadDate)
|
|
: null,
|
|
);
|
|
}
|
|
}
|