mirror of
https://github.com/yattee/yattee.git
synced 2025-08-09 20:24:06 +00:00
Player controls UI changes
WIP on controls Chapters working Add previews variable Add lists ids WIP
This commit is contained in:
@@ -383,6 +383,8 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
||||
id = videoID
|
||||
}
|
||||
|
||||
let description = json["description"].stringValue
|
||||
|
||||
return Video(
|
||||
id: id,
|
||||
videoID: videoID,
|
||||
@@ -391,7 +393,7 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
||||
length: json["lengthSeconds"].doubleValue,
|
||||
published: json["publishedText"].stringValue,
|
||||
views: json["viewCount"].intValue,
|
||||
description: json["description"].stringValue,
|
||||
description: description,
|
||||
genre: json["genre"].stringValue,
|
||||
channel: extractChannel(from: json),
|
||||
thumbnails: extractThumbnails(from: json),
|
||||
@@ -403,7 +405,8 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
||||
dislikes: json["dislikeCount"].int,
|
||||
keywords: json["keywords"].arrayValue.compactMap { $0.string },
|
||||
streams: extractStreams(from: json),
|
||||
related: extractRelated(from: json)
|
||||
related: extractRelated(from: json),
|
||||
chapters: extractChapters(from: description)
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -409,6 +409,13 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
|
||||
|
||||
let live = details["livestream"]?.bool ?? (details["duration"]?.int == -1)
|
||||
|
||||
let description = extractDescription(from: content) ?? ""
|
||||
|
||||
var chapters = extractChapters(from: content)
|
||||
if chapters.isEmpty, !description.isEmpty {
|
||||
chapters = extractChapters(from: description)
|
||||
}
|
||||
|
||||
return Video(
|
||||
videoID: extractID(from: content),
|
||||
title: details["title"]?.string ?? "",
|
||||
@@ -416,14 +423,15 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
|
||||
length: details["duration"]?.double ?? 0,
|
||||
published: published ?? "",
|
||||
views: details["views"]?.int ?? 0,
|
||||
description: extractDescription(from: content),
|
||||
description: description,
|
||||
channel: Channel(id: channelId, name: author, thumbnailURL: authorThumbnailURL, subscriptionsCount: subscriptionsCount),
|
||||
thumbnails: thumbnails,
|
||||
live: live,
|
||||
likes: details["likes"]?.int,
|
||||
dislikes: details["dislikes"]?.int,
|
||||
streams: extractStreams(from: content),
|
||||
related: extractRelated(from: content)
|
||||
related: extractRelated(from: content),
|
||||
chapters: extractChapters(from: content)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -571,4 +579,21 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
|
||||
channel: Channel(id: channelId, name: author)
|
||||
)
|
||||
}
|
||||
|
||||
private func extractChapters(from content: JSON) -> [Chapter] {
|
||||
guard let chapters = content.dictionaryValue["chapters"]?.array else {
|
||||
return .init()
|
||||
}
|
||||
|
||||
return chapters.compactMap { chapter in
|
||||
guard let title = chapter["title"].string,
|
||||
let image = chapter["image"].url,
|
||||
let start = chapter["start"].double
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return Chapter(title: title, image: image, start: start)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -116,4 +116,54 @@ extension VideosAPI {
|
||||
|
||||
return urlComponents.url
|
||||
}
|
||||
|
||||
func extractChapters(from description: String) -> [Chapter] {
|
||||
guard let chaptersRegularExpression = try? NSRegularExpression(
|
||||
pattern: "(?<start>(?:[0-9]+:){1,}(?:[0-9]+))(?:\\s)+(?:- ?)?(?<title>.*)",
|
||||
options: .caseInsensitive
|
||||
) else { return [] }
|
||||
|
||||
let chapterLines = chaptersRegularExpression.matches(
|
||||
in: description,
|
||||
range: NSRange(description.startIndex..., in: description)
|
||||
)
|
||||
|
||||
return chapterLines.compactMap { line in
|
||||
let titleRange = line.range(withName: "title")
|
||||
let startRange = line.range(withName: "start")
|
||||
|
||||
guard let titleSubstringRange = Range(titleRange, in: description),
|
||||
let startSubstringRange = Range(startRange, in: description),
|
||||
let titleCapture = String(description[titleSubstringRange]),
|
||||
let startCapture = String(description[startSubstringRange]) else { return nil }
|
||||
|
||||
let startComponents = startCapture.components(separatedBy: ":")
|
||||
guard startComponents.count <= 3 else { return nil }
|
||||
|
||||
var hours: Double?
|
||||
var minutes: Double?
|
||||
var seconds: Double?
|
||||
|
||||
if startComponents.count == 3 {
|
||||
hours = Double(startComponents[0])
|
||||
minutes = Double(startComponents[1])
|
||||
seconds = Double(startComponents[2])
|
||||
} else if startComponents.count == 2 {
|
||||
minutes = Double(startComponents[0])
|
||||
seconds = Double(startComponents[1])
|
||||
}
|
||||
|
||||
guard var startSeconds = seconds else { return nil }
|
||||
|
||||
if let minutes = minutes {
|
||||
startSeconds += 60 * minutes
|
||||
}
|
||||
|
||||
if let hours = hours {
|
||||
startSeconds += 60 * 60 * hours
|
||||
}
|
||||
|
||||
return .init(title: titleCapture, start: startSeconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user