Display more details in player view

This commit is contained in:
Arkadiusz Fal
2021-08-22 21:13:33 +02:00
parent ea634390a6
commit f80b61f9c7
22 changed files with 716 additions and 36 deletions

25
Model/PlaybackState.swift Normal file
View File

@@ -0,0 +1,25 @@
import CoreMedia
import Foundation
final class PlaybackState: ObservableObject {
@Published var stream: Stream?
@Published var time: CMTime?
var aspectRatio: CGFloat? {
let tracks = stream?.videoAsset.tracks(withMediaType: .video)
guard tracks != nil else {
return nil
}
let size: CGSize! = tracks!.first.flatMap {
tracks!.isEmpty ? nil : $0.naturalSize.applying($0.preferredTransform)
}
guard size != nil else {
return nil
}
return size.width / size.height
}
}

View File

@@ -14,19 +14,21 @@ final class PlayerState: ObservableObject {
private var compositions = [Stream: AVMutableComposition]()
private(set) var currentTime: CMTime?
private(set) var savedTime: CMTime?
private(set) var currentRate: Float = 0.0
static let availableRates: [Double] = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]
let maxResolution: Stream.Resolution?
var playbackState: PlaybackState?
var timeObserver: Any?
let maxResolution: Stream.Resolution?
var playingOutsideViewController = false
init(_ video: Video? = nil, maxResolution: Stream.Resolution? = nil) {
init(_ video: Video? = nil, playbackState: PlaybackState? = nil, maxResolution: Stream.Resolution? = nil) {
self.video = video
self.playbackState = playbackState
self.maxResolution = maxResolution
}
@@ -101,6 +103,10 @@ final class PlayerState: ObservableObject {
DispatchQueue.main.async {
self.saveTime()
self.player?.replaceCurrentItem(with: self.playerItemWithMetadata(for: stream))
self.playbackState?.stream = stream
if self.timeObserver == nil {
self.addTimeObserver()
}
self.player?.playImmediately(atRate: 1.0)
self.seekToSavedTime()
}
@@ -245,9 +251,15 @@ final class PlayerState: ObservableObject {
let interval = CMTime(value: 1, timescale: 1)
timeObserver = player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { _ in
guard self.player != nil else {
return
}
if self.player.rate != self.currentRate, self.player.rate != 0, self.currentRate != 0 {
self.player.rate = self.currentRate
}
self.playbackState?.time = self.player.currentTime()
}
}

View File

@@ -24,6 +24,11 @@ struct Video: Identifiable, Equatable {
var streams = [Stream]()
var hlsUrl: URL?
var publishedAt: Date?
var likes: Int?
var dislikes: Int?
var keywords = [String]()
init(
id: String,
title: String,
@@ -37,7 +42,11 @@ struct Video: Identifiable, Equatable {
thumbnails: [Thumbnail] = [],
indexID: String? = nil,
live: Bool = false,
upcoming: Bool = false
upcoming: Bool = false,
publishedAt: Date? = nil,
likes: Int? = nil,
dislikes: Int? = nil,
keywords: [String] = []
) {
self.id = id
self.title = title
@@ -52,6 +61,10 @@ struct Video: Identifiable, Equatable {
self.indexID = indexID
self.live = live
self.upcoming = upcoming
self.publishedAt = publishedAt
self.likes = likes
self.dislikes = dislikes
self.keywords = keywords
}
init(_ json: JSON) {
@@ -79,6 +92,15 @@ struct Video: Identifiable, Equatable {
live = json["liveNow"].boolValue
upcoming = json["isUpcoming"].boolValue
likes = json["likeCount"].int
dislikes = json["dislikeCount"].int
keywords = json["keywords"].arrayValue.map { $0.stringValue }
if let publishedInterval = json["published"].double {
publishedAt = Date(timeIntervalSince1970: publishedInterval)
}
streams = Video.extractFormatStreams(from: json["formatStreams"].arrayValue)
streams.append(contentsOf: Video.extractAdaptiveFormats(from: json["adaptiveFormats"].arrayValue))
@@ -103,7 +125,23 @@ struct Video: Identifiable, Equatable {
(published.isEmpty || published == "0 seconds ago") ? nil : published
}
var viewsCount: String {
var viewsCount: String? {
views != 0 ? formattedCount(views) : nil
}
var likesCount: String? {
formattedCount(likes)
}
var dislikesCount: String? {
formattedCount(dislikes)
}
func formattedCount(_ count: Int!) -> String? {
guard count != nil else {
return nil
}
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 1
@@ -111,11 +149,13 @@ struct Video: Identifiable, Equatable {
var number: NSNumber
var unit: String
if views < 1_000_000 {
number = NSNumber(value: Double(views) / 1000.0)
if count < 1000 {
return "\(count!)"
} else if count < 1_000_000 {
number = NSNumber(value: Double(count) / 1000.0)
unit = "K"
} else {
number = NSNumber(value: Double(views) / 1_000_000.0)
number = NSNumber(value: Double(count) / 1_000_000.0)
unit = "M"
}