mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 05:23:41 +00:00
Fix lint issues
This commit is contained in:
parent
b12933e61d
commit
e827b97cd5
@ -6,15 +6,9 @@ disabled_rules:
|
|||||||
- opening_brace
|
- opening_brace
|
||||||
- number_separator
|
- number_separator
|
||||||
- multiline_arguments
|
- multiline_arguments
|
||||||
opt_in_rules:
|
|
||||||
- implicit_return
|
- implicit_return
|
||||||
excluded:
|
excluded:
|
||||||
- Vendor
|
- Vendor
|
||||||
- Tests Apple TV
|
- Tests Apple TV
|
||||||
- Tests iOS
|
- Tests iOS
|
||||||
- Tests macOS
|
- Tests macOS
|
||||||
|
|
||||||
implicit_return:
|
|
||||||
included:
|
|
||||||
- function
|
|
||||||
- getter
|
|
||||||
|
@ -76,8 +76,7 @@ final class InstancesModel: ObservableObject {
|
|||||||
func standardizedURL(_ url: String) -> String {
|
func standardizedURL(_ url: String) -> String {
|
||||||
if url.count > 7, url.last == "/" {
|
if url.count > 7, url.last == "/" {
|
||||||
return String(url.dropLast())
|
return String(url.dropLast())
|
||||||
} else {
|
|
||||||
return url
|
|
||||||
}
|
}
|
||||||
|
return url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,11 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
|||||||
|
|
||||||
if type == "channel" {
|
if type == "channel" {
|
||||||
return ContentItem(channel: self.extractChannel(from: json))
|
return ContentItem(channel: self.extractChannel(from: json))
|
||||||
} else if type == "playlist" {
|
}
|
||||||
|
if type == "playlist" {
|
||||||
return ContentItem(playlist: self.extractChannelPlaylist(from: json))
|
return ContentItem(playlist: self.extractChannelPlaylist(from: json))
|
||||||
} else if type == "video" {
|
}
|
||||||
|
if type == "video" {
|
||||||
return ContentItem(video: self.extractVideo(from: json))
|
return ContentItem(video: self.extractVideo(from: json))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,9 +726,11 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
|||||||
|
|
||||||
if type == "channel" {
|
if type == "channel" {
|
||||||
return ContentItem(channel: extractChannel(from: json))
|
return ContentItem(channel: extractChannel(from: json))
|
||||||
} else if type == "playlist" {
|
}
|
||||||
|
if type == "playlist" {
|
||||||
return ContentItem(playlist: extractChannelPlaylist(from: json))
|
return ContentItem(playlist: extractChannelPlaylist(from: json))
|
||||||
} else if type == "video" {
|
}
|
||||||
|
if type == "video" {
|
||||||
return ContentItem(video: extractVideo(from: json))
|
return ContentItem(video: extractVideo(from: json))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +392,7 @@ final class PeerTubeAPI: Service, ObservableObject, VideosAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func search(_ query: SearchQuery, page _: String?) -> Resource {
|
func search(_ query: SearchQuery, page _: String?) -> Resource {
|
||||||
var resource = resource(baseURL: account.url, path: basePathAppending("search/videos"))
|
resource(baseURL: account.url, path: basePathAppending("search/videos"))
|
||||||
.withParam("search", query.query)
|
.withParam("search", query.query)
|
||||||
// .withParam("sort_by", query.sortBy.parameter)
|
// .withParam("sort_by", query.sortBy.parameter)
|
||||||
// .withParam("type", "all")
|
// .withParam("type", "all")
|
||||||
@ -409,7 +409,7 @@ final class PeerTubeAPI: Service, ObservableObject, VideosAPI {
|
|||||||
// resource = resource.withParam("page", page)
|
// resource = resource.withParam("page", page)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return resource
|
// return resource
|
||||||
}
|
}
|
||||||
|
|
||||||
func searchSuggestions(query: String) -> Resource {
|
func searchSuggestions(query: String) -> Resource {
|
||||||
|
@ -110,7 +110,7 @@ struct Channel: Identifiable, Hashable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func hasData(for contentType: ContentType) -> Bool {
|
func hasData(for contentType: ContentType) -> Bool {
|
||||||
return tabs.contains { $0.contentType == contentType }
|
tabs.contains { $0.contentType == contentType }
|
||||||
}
|
}
|
||||||
|
|
||||||
var cacheKey: String {
|
var cacheKey: String {
|
||||||
|
@ -15,7 +15,7 @@ struct ContentItem: Identifiable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func < (lhs: ContentType, rhs: ContentType) -> Bool {
|
static func < (lhs: Self, rhs: Self) -> Bool {
|
||||||
lhs.sortOrder < rhs.sortOrder
|
lhs.sortOrder < rhs.sortOrder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,19 +30,19 @@ struct ContentItem: Identifiable {
|
|||||||
|
|
||||||
var id: String = UUID().uuidString
|
var id: String = UUID().uuidString
|
||||||
|
|
||||||
static func array(of videos: [Video]) -> [ContentItem] {
|
static func array(of videos: [Video]) -> [Self] {
|
||||||
videos.map { Self(video: $0) }
|
videos.map { Self(video: $0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
static func array(of playlists: [ChannelPlaylist]) -> [ContentItem] {
|
static func array(of playlists: [ChannelPlaylist]) -> [Self] {
|
||||||
playlists.map { Self(playlist: $0) }
|
playlists.map { Self(playlist: $0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
static func array(of channels: [Channel]) -> [ContentItem] {
|
static func array(of channels: [Channel]) -> [Self] {
|
||||||
channels.map { Self(channel: $0) }
|
channels.map { Self(channel: $0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
static func < (lhs: ContentItem, rhs: ContentItem) -> Bool {
|
static func < (lhs: Self, rhs: Self) -> Bool {
|
||||||
lhs.contentType < rhs.contentType
|
lhs.contentType < rhs.contentType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ struct FavoriteItem: Codable, Equatable, Identifiable, Defaults.Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func == (lhs: FavoriteItem, rhs: FavoriteItem) -> Bool {
|
static func == (lhs: Self, rhs: Self) -> Bool {
|
||||||
lhs.section == rhs.section
|
lhs.section == rhs.section
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,11 @@ struct FavoritesModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func toggle(_ item: FavoriteItem) {
|
func toggle(_ item: FavoriteItem) {
|
||||||
contains(item) ? remove(item) : add(item)
|
if contains(item) {
|
||||||
|
remove(item)
|
||||||
|
} else {
|
||||||
|
add(item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(_ item: FavoriteItem) {
|
func add(_ item: FavoriteItem) {
|
||||||
|
@ -52,7 +52,6 @@ extension PlayerModel {
|
|||||||
let id = currentVideo.videoID
|
let id = currentVideo.videoID
|
||||||
let time = time ?? backend.currentTime
|
let time = time ?? backend.currentTime
|
||||||
let seconds = time?.seconds ?? 0
|
let seconds = time?.seconds ?? 0
|
||||||
let duration = playerTime.duration.seconds
|
|
||||||
if seconds < 3 {
|
if seconds < 3 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,8 @@ final class InstancesManifest: Service, ObservableObject {
|
|||||||
|
|
||||||
instancesList?.load().onSuccess { response in
|
instancesList?.load().onSuccess { response in
|
||||||
if let instances: [ManifestedInstance] = response.typedContent() {
|
if let instances: [ManifestedInstance] = response.typedContent() {
|
||||||
guard let instance = instances.filter { $0.country == country }.randomElement() else { return }
|
let countryInstances = instances.filter { $0.country == country }
|
||||||
|
guard let instance = countryInstances.randomElement() else { return }
|
||||||
let account = instance.anonymousAccount
|
let account = instance.anonymousAccount
|
||||||
AccountsModel.shared.publicAccount = account
|
AccountsModel.shared.publicAccount = account
|
||||||
if asCurrent {
|
if asCurrent {
|
||||||
|
@ -63,7 +63,7 @@ struct OpenVideosModel {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
func openURLsFromClipboard(removeQueueItems: Bool = false, playbackMode: OpenVideosModel.PlaybackMode = .playNow) {
|
func openURLsFromClipboard(removeQueueItems: Bool = false, playbackMode: Self.PlaybackMode = .playNow) {
|
||||||
if urlsFromClipboard.isEmpty {
|
if urlsFromClipboard.isEmpty {
|
||||||
NavigationModel.shared.alert = Alert(title: Text("Could not find any links to open in your clipboard".localized()))
|
NavigationModel.shared.alert = Alert(title: Text("Could not find any links to open in your clipboard".localized()))
|
||||||
if NavigationModel.shared.presentingOpenVideos {
|
if NavigationModel.shared.presentingOpenVideos {
|
||||||
@ -76,7 +76,7 @@ struct OpenVideosModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func openURLs(_ urls: [URL], removeQueueItems: Bool = false, playbackMode: OpenVideosModel.PlaybackMode = .playNow) {
|
func openURLs(_ urls: [URL], removeQueueItems: Bool = false, playbackMode: Self.PlaybackMode = .playNow) {
|
||||||
guard !urls.isEmpty else {
|
guard !urls.isEmpty else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,11 @@ final class AVPlayerBackend: PlayerBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func togglePlay() {
|
func togglePlay() {
|
||||||
isPlaying ? pause() : play()
|
if isPlaying {
|
||||||
|
pause()
|
||||||
|
} else {
|
||||||
|
play()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func stop() {
|
func stop() {
|
||||||
@ -414,9 +418,8 @@ final class AVPlayerBackend: PlayerBackend {
|
|||||||
private func playerItem(_: Stream) -> AVPlayerItem? {
|
private func playerItem(_: Stream) -> AVPlayerItem? {
|
||||||
if let asset {
|
if let asset {
|
||||||
return AVPlayerItem(asset: asset)
|
return AVPlayerItem(asset: asset)
|
||||||
} else {
|
|
||||||
return AVPlayerItem(asset: composition)
|
|
||||||
}
|
}
|
||||||
|
return AVPlayerItem(asset: composition)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func attachMetadata() {
|
private func attachMetadata() {
|
||||||
|
@ -356,7 +356,11 @@ final class MPVBackend: PlayerBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func togglePlay() {
|
func togglePlay() {
|
||||||
isPlaying ? pause() : play()
|
if isPlaying {
|
||||||
|
pause()
|
||||||
|
} else {
|
||||||
|
play()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cancelLoads() {
|
func cancelLoads() {
|
||||||
|
@ -471,9 +471,8 @@ final class MPVClient: ObservableObject {
|
|||||||
let data = Data(bufPtr)
|
let data = Data(bufPtr)
|
||||||
if let lastIndex = data.lastIndex(where: { $0 != 0 }) {
|
if let lastIndex = data.lastIndex(where: { $0 != 0 }) {
|
||||||
return String(data: data[0 ... lastIndex], encoding: .isoLatin1)!
|
return String(data: data[0 ... lastIndex], encoding: .isoLatin1)!
|
||||||
} else {
|
|
||||||
return String(data: data, encoding: .isoLatin1)!
|
|
||||||
}
|
}
|
||||||
|
return String(data: data, encoding: .isoLatin1)!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ final class PlayerControlsModel: ObservableObject {
|
|||||||
var timer: Timer?
|
var timer: Timer?
|
||||||
|
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
private(set) var reporter = PassthroughSubject<String, Never>()
|
private(set) var reporter = PassthroughSubject<String, Never>() // swiftlint:disable:this private_subject
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var player: PlayerModel! { .shared }
|
var player: PlayerModel! { .shared }
|
||||||
@ -106,7 +106,11 @@ final class PlayerControlsModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func toggle() {
|
func toggle() {
|
||||||
presentingControls ? hide() : show()
|
if presentingControls {
|
||||||
|
hide()
|
||||||
|
} else {
|
||||||
|
show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resetTimer() {
|
func resetTimer() {
|
||||||
|
@ -717,7 +717,11 @@ final class PlayerModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func togglePiPAction() {
|
func togglePiPAction() {
|
||||||
(pipController?.isPictureInPictureActive ?? false) ? closePiP() : startPiP()
|
if pipController?.isPictureInPictureActive ?? false {
|
||||||
|
closePiP()
|
||||||
|
} else {
|
||||||
|
startPiP()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
@ -812,12 +816,12 @@ final class PlayerModel: ObservableObject {
|
|||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
self.playerAPI(item.video)?.loadDetails(item, completionHandler: { newItem in
|
self.playerAPI(item.video)?.loadDetails(item, failureHandler: nil) { newItem in
|
||||||
guard newItem.videoID == self.autoplayItem?.videoID else { return }
|
guard newItem.videoID == self.autoplayItem?.videoID else { return }
|
||||||
self.autoplayItem = newItem
|
self.autoplayItem = newItem
|
||||||
self.updateRemoteCommandCenter()
|
self.updateRemoteCommandCenter()
|
||||||
self.controls.objectWillChange.send()
|
self.controls.objectWillChange.send()
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,13 +328,13 @@ extension PlayerModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
playerAPI(video)?
|
playerAPI(video)?
|
||||||
.loadDetails(item, completionHandler: { [weak self] newItem in
|
.loadDetails(item, failureHandler: nil) { [weak self] newItem in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
|
|
||||||
replaceQueueItem(newItem)
|
replaceQueueItem(newItem)
|
||||||
|
|
||||||
self.logger.info("LOADED queue details: \(videoID)")
|
self.logger.info("LOADED queue details: \(videoID)")
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func videoLoadFailureHandler(_ error: RequestError, video: Video? = nil) {
|
private func videoLoadFailureHandler(_ error: RequestError, video: Video? = nil) {
|
||||||
|
@ -60,7 +60,7 @@ struct Playlist: Identifiable, Equatable, Hashable {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func == (lhs: Playlist, rhs: Playlist) -> Bool {
|
static func == (lhs: Self, rhs: Self) -> Bool {
|
||||||
lhs.id == rhs.id && lhs.updated == rhs.updated
|
lhs.id == rhs.id && lhs.updated == rhs.updated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,8 @@ struct QualityProfile: Hashable, Identifiable, Defaults.Serializable {
|
|||||||
var formatsDescription: String {
|
var formatsDescription: String {
|
||||||
if formats.count == Format.allCases.count {
|
if formats.count == Format.allCases.count {
|
||||||
return "Any format".localized()
|
return "Any format".localized()
|
||||||
} else if formats.count <= 3 {
|
}
|
||||||
|
if formats.count <= 3 {
|
||||||
return formats.map(\.description).joined(separator: ", ")
|
return formats.map(\.description).joined(separator: ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import Siesta
|
|||||||
final class Store<Data>: ResourceObserver, ObservableObject {
|
final class Store<Data>: ResourceObserver, ObservableObject {
|
||||||
@Published private var all: Data?
|
@Published private var all: Data?
|
||||||
|
|
||||||
var collection: Data { all ?? ([] as! Data) }
|
var collection: Data { all ?? ([item].compactMap { $0 } as! Data) }
|
||||||
var item: Data? { all }
|
var item: Data? { all }
|
||||||
|
|
||||||
init(_ data: Data? = nil) {
|
init(_ data: Data? = nil) {
|
||||||
|
@ -54,11 +54,11 @@ class Stream: Equatable, Hashable, Identifiable {
|
|||||||
return Int(refreshRatePart.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()) ?? -1
|
return Int(refreshRatePart.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()) ?? -1
|
||||||
}
|
}
|
||||||
|
|
||||||
static func from(resolution: String, fps: Int? = nil) -> Resolution {
|
static func from(resolution: String, fps: Int? = nil) -> Self {
|
||||||
allCases.first { $0.rawValue.contains(resolution) && $0.refreshRate == (fps ?? 30) } ?? .unknown
|
allCases.first { $0.rawValue.contains(resolution) && $0.refreshRate == (fps ?? 30) } ?? .unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
static func < (lhs: Resolution, rhs: Resolution) -> Bool {
|
static func < (lhs: Self, rhs: Self) -> Bool {
|
||||||
lhs.height == rhs.height ? (lhs.refreshRate < rhs.refreshRate) : (lhs.height < rhs.height)
|
lhs.height == rhs.height ? (lhs.refreshRate < rhs.refreshRate) : (lhs.height < rhs.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ class Stream: Equatable, Hashable, Identifiable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func < (lhs: Kind, rhs: Kind) -> Bool {
|
static func < (lhs: Self, rhs: Self) -> Bool {
|
||||||
lhs.sortOrder < rhs.sortOrder
|
lhs.sortOrder < rhs.sortOrder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,15 +123,17 @@ class Stream: Equatable, Hashable, Identifiable {
|
|||||||
|
|
||||||
if lowercased.contains("webm") {
|
if lowercased.contains("webm") {
|
||||||
return .webm
|
return .webm
|
||||||
} else if lowercased.contains("avc1") {
|
|
||||||
return .avc1
|
|
||||||
} else if lowercased.contains("av01") {
|
|
||||||
return .av1
|
|
||||||
} else if lowercased.contains("mpeg_4") || lowercased.contains("mp4") {
|
|
||||||
return .mp4
|
|
||||||
} else {
|
|
||||||
return .unknown
|
|
||||||
}
|
}
|
||||||
|
if lowercased.contains("avc1") {
|
||||||
|
return .avc1
|
||||||
|
}
|
||||||
|
if lowercased.contains("av01") {
|
||||||
|
return .av1
|
||||||
|
}
|
||||||
|
if lowercased.contains("mpeg_4") || lowercased.contains("mp4") {
|
||||||
|
return .mp4
|
||||||
|
}
|
||||||
|
return .unknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,9 +192,8 @@ class Stream: Equatable, Hashable, Identifiable {
|
|||||||
|
|
||||||
if kind == .hls {
|
if kind == .hls {
|
||||||
return "HLS"
|
return "HLS"
|
||||||
} else {
|
|
||||||
return resolution?.name ?? "?"
|
|
||||||
}
|
}
|
||||||
|
return resolution?.name ?? "?"
|
||||||
}
|
}
|
||||||
|
|
||||||
var description: String {
|
var description: String {
|
||||||
@ -221,7 +222,8 @@ class Stream: Equatable, Hashable, Identifiable {
|
|||||||
|
|
||||||
if kind == .hls {
|
if kind == .hls {
|
||||||
return hlsURL
|
return hlsURL
|
||||||
} else if videoAssetContainsAudio {
|
}
|
||||||
|
if videoAssetContainsAudio {
|
||||||
return videoAsset.url
|
return videoAsset.url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ struct URLBookmarkModel {
|
|||||||
func saveBookmark(_ url: NSURL) {
|
func saveBookmark(_ url: NSURL) {
|
||||||
guard url.isFileURL else {
|
guard url.isFileURL else {
|
||||||
logger.error("trying to save bookmark for something that is not a file")
|
logger.error("trying to save bookmark for something that is not a file")
|
||||||
logger.error("not a file: \(url.absoluteString)")
|
logger.error("not a file: \(url.absoluteString ?? "unknown")")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ struct Video: Identifiable, Equatable, Hashable {
|
|||||||
dislikes: Int? = nil,
|
dislikes: Int? = nil,
|
||||||
keywords: [String] = [],
|
keywords: [String] = [],
|
||||||
streams: [Stream] = [],
|
streams: [Stream] = [],
|
||||||
related: [Video] = [],
|
related: [Self] = [],
|
||||||
chapters: [Chapter] = [],
|
chapters: [Chapter] = [],
|
||||||
captions: [Captions] = []
|
captions: [Captions] = []
|
||||||
) {
|
) {
|
||||||
@ -116,7 +116,7 @@ struct Video: Identifiable, Equatable, Hashable {
|
|||||||
self.captions = captions
|
self.captions = captions
|
||||||
}
|
}
|
||||||
|
|
||||||
static func local(_ url: URL) -> Video {
|
static func local(_ url: URL) -> Self {
|
||||||
Self(
|
Self(
|
||||||
app: .local,
|
app: .local,
|
||||||
videoID: url.absoluteString,
|
videoID: url.absoluteString,
|
||||||
@ -249,7 +249,7 @@ struct Video: Identifiable, Equatable, Hashable {
|
|||||||
thumbnails.first { $0.quality == quality }?.url
|
thumbnails.first { $0.quality == quality }?.url
|
||||||
}
|
}
|
||||||
|
|
||||||
static func == (lhs: Video, rhs: Video) -> Bool {
|
static func == (lhs: Self, rhs: Self) -> Bool {
|
||||||
let videoIDIsEqual = lhs.videoID == rhs.videoID
|
let videoIDIsEqual = lhs.videoID == rhs.videoID
|
||||||
|
|
||||||
if !lhs.indexID.isNil, !rhs.indexID.isNil {
|
if !lhs.indexID.isNil, !rhs.indexID.isNil {
|
||||||
|
@ -338,7 +338,8 @@ struct ChannelVideosView: View {
|
|||||||
private var resource: Resource? {
|
private var resource: Resource? {
|
||||||
guard let channel = presentedChannel else { return nil }
|
guard let channel = presentedChannel else { return nil }
|
||||||
|
|
||||||
let data = contentType != .videos ? channel.tabs.first(where: { $0.contentType == contentType })?.data : nil
|
let tabData = channel.tabs.first { $0.contentType == contentType }?.data
|
||||||
|
let data = contentType != .videos ? tabData : nil
|
||||||
let resource = accounts.api.channel(channel.id, contentType: contentType, data: data)
|
let resource = accounts.api.channel(channel.id, contentType: contentType, data: data)
|
||||||
|
|
||||||
if contentType == .videos {
|
if contentType == .videos {
|
||||||
@ -451,7 +452,8 @@ struct ChannelVideosView: View {
|
|||||||
next = next ?? ""
|
next = next ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = contentType != .videos ? channel.tabs.first(where: { $0.contentType == contentType })?.data : nil
|
let tabData = channel.tabs.first { $0.contentType == contentType }?.data
|
||||||
|
let data = contentType != .videos ? tabData : nil
|
||||||
accounts.api.channel(channel.id, contentType: contentType, data: data, page: next).load().onSuccess { response in
|
accounts.api.channel(channel.id, contentType: contentType, data: data, page: next).load().onSuccess { response in
|
||||||
if let page: ChannelPage = response.typedContent() {
|
if let page: ChannelPage = response.typedContent() {
|
||||||
self.page = page
|
self.page = page
|
||||||
|
@ -152,7 +152,8 @@ struct Sidebar: View {
|
|||||||
if case .recentlyOpened = selection {
|
if case .recentlyOpened = selection {
|
||||||
scrollView.scrollTo("recentlyOpened")
|
scrollView.scrollTo("recentlyOpened")
|
||||||
return
|
return
|
||||||
} else if case let .playlist(id) = selection {
|
}
|
||||||
|
if case let .playlist(id) = selection {
|
||||||
scrollView.scrollTo(id)
|
scrollView.scrollTo(id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,8 @@ struct OpeningStream: View {
|
|||||||
if let selection = player.streamSelection {
|
if let selection = player.streamSelection {
|
||||||
if selection.isLocal {
|
if selection.isLocal {
|
||||||
return "Opening file...".localized()
|
return "Opening file...".localized()
|
||||||
} else {
|
|
||||||
return String(format: "Opening %@ stream...".localized(), selection.shortQuality)
|
|
||||||
}
|
}
|
||||||
|
return String(format: "Opening %@ stream...".localized(), selection.shortQuality)
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Loading streams...".localized()
|
return "Loading streams...".localized()
|
||||||
|
@ -193,8 +193,11 @@ struct PlayerControls: View {
|
|||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
.onChange(of: model.presentingControls) { newValue in
|
.onChange(of: model.presentingControls) { newValue in
|
||||||
if newValue { focusedField = .play }
|
if newValue {
|
||||||
else { focusedField = nil }
|
focusedField = .play
|
||||||
|
} else {
|
||||||
|
focusedField = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: focusedField) { _ in model.resetTimer() }
|
.onChange(of: focusedField) { _ in model.resetTimer() }
|
||||||
#else
|
#else
|
||||||
|
@ -47,7 +47,7 @@ struct TVControls: UIViewRepresentable {
|
|||||||
|
|
||||||
func updateUIView(_: UIView, context _: Context) {}
|
func updateUIView(_: UIView, context _: Context) {}
|
||||||
|
|
||||||
func makeCoordinator() -> TVControls.Coordinator {
|
func makeCoordinator() -> Self.Coordinator {
|
||||||
Coordinator(controlsArea)
|
Coordinator(controlsArea)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,17 +70,15 @@ struct PlayerBackendView: View {
|
|||||||
|
|
||||||
if UIDevice.current.userInterfaceIdiom != .pad {
|
if UIDevice.current.userInterfaceIdiom != .pad {
|
||||||
return verticalSizeClass == .compact ? safeAreaModel.safeArea.top : 0
|
return verticalSizeClass == .compact ? safeAreaModel.safeArea.top : 0
|
||||||
} else {
|
|
||||||
return safeAreaModel.safeArea.top.isZero ? safeAreaModel.safeArea.bottom : safeAreaModel.safeArea.top
|
|
||||||
}
|
}
|
||||||
|
return safeAreaModel.safeArea.top.isZero ? safeAreaModel.safeArea.bottom : safeAreaModel.safeArea.top
|
||||||
}
|
}
|
||||||
|
|
||||||
var controlsBottomPadding: Double {
|
var controlsBottomPadding: Double {
|
||||||
if UIDevice.current.userInterfaceIdiom != .pad {
|
if UIDevice.current.userInterfaceIdiom != .pad {
|
||||||
return player.playingFullScreen || verticalSizeClass == .compact ? safeAreaModel.safeArea.bottom : 0
|
return player.playingFullScreen || verticalSizeClass == .compact ? safeAreaModel.safeArea.bottom : 0
|
||||||
} else {
|
|
||||||
return player.playingFullScreen ? safeAreaModel.safeArea.bottom : 0
|
|
||||||
}
|
}
|
||||||
|
return player.playingFullScreen ? safeAreaModel.safeArea.bottom : 0
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -177,7 +177,8 @@ struct VideoDescription: View {
|
|||||||
{
|
{
|
||||||
player.backend.seek(to: Double(time), seekType: .userInteracted)
|
player.backend.seek(to: Double(time), seekType: .userInteracted)
|
||||||
return
|
return
|
||||||
} else if destination != nil {
|
}
|
||||||
|
if destination != nil {
|
||||||
urlToOpen = yatteeURL
|
urlToOpen = yatteeURL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ struct VideoPlayerSizeModifier: ViewModifier {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
var ratio: CGFloat? {
|
var ratio: CGFloat? { // swiftlint:disable:this no_cgfloat
|
||||||
fullScreen ? detailsHiddenInFullScreen ? nil : usedAspectRatio : usedAspectRatio
|
fullScreen ? detailsHiddenInFullScreen ? nil : usedAspectRatio : usedAspectRatio
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,9 +57,9 @@ struct VideoPlayerSizeModifier: ViewModifier {
|
|||||||
guard !fullScreen else {
|
guard !fullScreen else {
|
||||||
if detailsHiddenInFullScreen {
|
if detailsHiddenInFullScreen {
|
||||||
return geometry.size.height
|
return geometry.size.height
|
||||||
} else {
|
|
||||||
return geometry.size.width / usedAspectRatio
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return geometry.size.width / usedAspectRatio
|
||||||
}
|
}
|
||||||
|
|
||||||
return max(geometry.size.height - VideoPlayerView.defaultMinimumHeightLeft, 0)
|
return max(geometry.size.height - VideoPlayerView.defaultMinimumHeightLeft, 0)
|
||||||
|
@ -274,7 +274,11 @@ struct VideoPlayerView: View {
|
|||||||
)
|
)
|
||||||
.onHover { hovering in
|
.onHover { hovering in
|
||||||
hoveringPlayer = hovering
|
hoveringPlayer = hovering
|
||||||
hovering ? player.controls.show() : player.controls.hide()
|
if hovering {
|
||||||
|
player.controls.show()
|
||||||
|
} else {
|
||||||
|
player.controls.hide()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.gesture(player.controls.presentingOverlays ? nil : playerDragGesture)
|
.gesture(player.controls.presentingOverlays ? nil : playerDragGesture)
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
|
@ -47,16 +47,16 @@ struct AccountValidationStatus: View {
|
|||||||
var validationStatusSystemImage: String {
|
var validationStatusSystemImage: String {
|
||||||
if isValidating {
|
if isValidating {
|
||||||
return "bolt.horizontal.fill"
|
return "bolt.horizontal.fill"
|
||||||
} else {
|
|
||||||
return isValid ? "checkmark.circle.fill" : "xmark.circle.fill"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isValid ? "checkmark.circle.fill" : "xmark.circle.fill"
|
||||||
}
|
}
|
||||||
|
|
||||||
var validationStatusColor: Color {
|
var validationStatusColor: Color {
|
||||||
if isValidating {
|
if isValidating {
|
||||||
return .accentColor
|
return .accentColor
|
||||||
} else {
|
|
||||||
return isValid ? .green : .red
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isValid ? .green : .red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ struct FeedView: View {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
.background(
|
.background(
|
||||||
Button("Refresh") {
|
Button("Refresh") {
|
||||||
feed.loadResources(force: true)
|
feed.loadResources(force: true)
|
||||||
}
|
}
|
||||||
@ -42,8 +42,8 @@ struct FeedView: View {
|
|||||||
)
|
)
|
||||||
#endif
|
#endif
|
||||||
#if !os(macOS)
|
#if !os(macOS)
|
||||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
|
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
|
||||||
feed.loadResources()
|
feed.loadResources()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,11 @@ struct URLParser {
|
|||||||
|
|
||||||
if hasAnyOfPrefixes(path, Self.prefixes[.playlist]!) || queryItemValue("v") == "playlist" {
|
if hasAnyOfPrefixes(path, Self.prefixes[.playlist]!) || queryItemValue("v") == "playlist" {
|
||||||
return .playlist
|
return .playlist
|
||||||
} else if hasAnyOfPrefixes(path, Self.prefixes[.channel]!) {
|
}
|
||||||
|
if hasAnyOfPrefixes(path, Self.prefixes[.channel]!) {
|
||||||
return .channel
|
return .channel
|
||||||
} else if hasAnyOfPrefixes(path, Self.prefixes[.search]!) {
|
}
|
||||||
|
if hasAnyOfPrefixes(path, Self.prefixes[.search]!) {
|
||||||
return .search
|
return .search
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct ListView: View {
|
struct ListView: View {
|
||||||
|
@ -253,11 +253,11 @@ struct VideoBanner: View {
|
|||||||
private var timeLabel: String? {
|
private var timeLabel: String? {
|
||||||
if let watch, let watchStoppedAtLabel, let videoDurationLabel, !watch.finished {
|
if let watch, let watchStoppedAtLabel, let videoDurationLabel, !watch.finished {
|
||||||
return "\(watchStoppedAtLabel) / \(videoDurationLabel)"
|
return "\(watchStoppedAtLabel) / \(videoDurationLabel)"
|
||||||
} else if let videoDurationLabel {
|
|
||||||
return videoDurationLabel
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
if let videoDurationLabel {
|
||||||
|
return videoDurationLabel
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder private var timeView: some View {
|
@ViewBuilder private var timeView: some View {
|
||||||
|
@ -3,7 +3,7 @@ import SwiftUI
|
|||||||
struct AccentButton: View {
|
struct AccentButton: View {
|
||||||
var text: String?
|
var text: String?
|
||||||
var imageSystemName: String?
|
var imageSystemName: String?
|
||||||
var maxWidth: CGFloat? = .infinity
|
var maxWidth: CGFloat? = .infinity // swiftlint:disable:this no_cgfloat
|
||||||
var bold = true
|
var bold = true
|
||||||
var verticalPadding = 10.0
|
var verticalPadding = 10.0
|
||||||
var horizontalPadding = 10.0
|
var horizontalPadding = 10.0
|
||||||
|
@ -98,7 +98,7 @@ struct YatteeApp: App {
|
|||||||
HostingWindowFinder { window in
|
HostingWindowFinder { window in
|
||||||
Windows.playerWindow = window
|
Windows.playerWindow = window
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(
|
NotificationCenter.default.addObserver( // swiftlint:disable:this discarded_notification_center_observer
|
||||||
forName: NSWindow.willExitFullScreenNotification,
|
forName: NSWindow.willExitFullScreenNotification,
|
||||||
object: window,
|
object: window,
|
||||||
queue: OperationQueue.main
|
queue: OperationQueue.main
|
||||||
|
@ -79,14 +79,16 @@ public class OrientationTracker {
|
|||||||
let threshold = 0.55
|
let threshold = 0.55
|
||||||
if accelerometerData.acceleration.x >= threshold {
|
if accelerometerData.acceleration.x >= threshold {
|
||||||
return .landscapeLeft
|
return .landscapeLeft
|
||||||
} else if accelerometerData.acceleration.x <= -threshold {
|
|
||||||
return .landscapeRight
|
|
||||||
} else if accelerometerData.acceleration.y <= -threshold {
|
|
||||||
return .portrait
|
|
||||||
} else if accelerometerData.acceleration.y >= threshold {
|
|
||||||
return .portraitUpsideDown
|
|
||||||
} else {
|
|
||||||
return currentDeviceOrientation
|
|
||||||
}
|
}
|
||||||
|
if accelerometerData.acceleration.x <= -threshold {
|
||||||
|
return .landscapeRight
|
||||||
|
}
|
||||||
|
if accelerometerData.acceleration.y <= -threshold {
|
||||||
|
return .portrait
|
||||||
|
}
|
||||||
|
if accelerometerData.acceleration.y >= threshold {
|
||||||
|
return .portraitUpsideDown
|
||||||
|
}
|
||||||
|
return currentDeviceOrientation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user