mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 13:33:42 +00:00
chore: address linter warnings
Signed-off-by: Toni Förster <toni.foerster@gmail.com>
This commit is contained in:
parent
af75afa912
commit
94577332a1
@ -6,8 +6,10 @@ extension UIViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class func swizzleHomeIndicatorProperty() {
|
public class func swizzleHomeIndicatorProperty() {
|
||||||
swizzle(origSelector: #selector(getter: UIViewController.prefersHomeIndicatorAutoHidden),
|
swizzle(
|
||||||
withSelector: #selector(getter: UIViewController.swizzle_prefersHomeIndicatorAutoHidden),
|
origSelector: #selector(getter: UIViewController.prefersHomeIndicatorAutoHidden),
|
||||||
forClass: UIViewController.self)
|
withSelector: #selector(getter: UIViewController.swizzle_prefersHomeIndicatorAutoHidden),
|
||||||
|
forClass: UIViewController.self
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
|||||||
|
|
||||||
configureTransformer(pathPattern("search/suggestions"), requestMethods: [.get]) { (content: Entity<JSON>) -> [String] in
|
configureTransformer(pathPattern("search/suggestions"), requestMethods: [.get]) { (content: Entity<JSON>) -> [String] in
|
||||||
if let suggestions = content.json.dictionaryValue["suggestions"] {
|
if let suggestions = content.json.dictionaryValue["suggestions"] {
|
||||||
return suggestions.arrayValue.map { $0.stringValue.replacingHTMLEntities }
|
return suggestions.arrayValue.map(\.stringValue).map(\.replacingHTMLEntities)
|
||||||
}
|
}
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
@ -22,7 +22,7 @@ struct FeedCacheModel: CacheModel {
|
|||||||
let date = iso8601DateFormatter.string(from: Date())
|
let date = iso8601DateFormatter.string(from: Date())
|
||||||
logger.info("caching feed \(account.feedCacheKey) -- \(date)")
|
logger.info("caching feed \(account.feedCacheKey) -- \(date)")
|
||||||
let feedTimeObject: JSON = ["date": date]
|
let feedTimeObject: JSON = ["date": date]
|
||||||
let videosObject: JSON = ["videos": videos.prefix(cacheLimit).map { $0.json.object }]
|
let videosObject: JSON = ["videos": videos.prefix(cacheLimit).map(\.json.object)]
|
||||||
try? storage?.setObject(feedTimeObject, forKey: feedTimeCacheKey(account.feedCacheKey))
|
try? storage?.setObject(feedTimeObject, forKey: feedTimeCacheKey(account.feedCacheKey))
|
||||||
try? storage?.setObject(videosObject, forKey: account.feedCacheKey)
|
try? storage?.setObject(videosObject, forKey: account.feedCacheKey)
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ struct PlaylistsCacheModel: CacheModel {
|
|||||||
let date = iso8601DateFormatter.string(from: Date())
|
let date = iso8601DateFormatter.string(from: Date())
|
||||||
logger.info("caching \(playlistCacheKey(account)) -- \(date)")
|
logger.info("caching \(playlistCacheKey(account)) -- \(date)")
|
||||||
let feedTimeObject: JSON = ["date": date]
|
let feedTimeObject: JSON = ["date": date]
|
||||||
let playlistsObject: JSON = ["playlists": playlists.map { $0.json.object }]
|
let playlistsObject: JSON = ["playlists": playlists.map(\.json.object)]
|
||||||
try? storage?.setObject(feedTimeObject, forKey: playlistTimeCacheKey(account))
|
try? storage?.setObject(feedTimeObject, forKey: playlistTimeCacheKey(account))
|
||||||
try? storage?.setObject(playlistsObject, forKey: playlistCacheKey(account))
|
try? storage?.setObject(playlistsObject, forKey: playlistCacheKey(account))
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ struct Channel: Identifiable, Hashable {
|
|||||||
"subscriptionsText": subscriptionsText as Any,
|
"subscriptionsText": subscriptionsText as Any,
|
||||||
"totalViews": totalViews as Any,
|
"totalViews": totalViews as Any,
|
||||||
"verified": verified as Any,
|
"verified": verified as Any,
|
||||||
"videos": videos.map { $0.json.object }
|
"videos": videos.map(\.json.object)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ struct ChannelPlaylist: Identifiable {
|
|||||||
"title": title,
|
"title": title,
|
||||||
"thumbnailURL": thumbnailURL?.absoluteString ?? "",
|
"thumbnailURL": thumbnailURL?.absoluteString ?? "",
|
||||||
"channel": channel?.json.object ?? "",
|
"channel": channel?.json.object ?? "",
|
||||||
"videos": videos.map { $0.json.object },
|
"videos": videos.map(\.json.object),
|
||||||
"videosCount": String(videosCount ?? 0)
|
"videosCount": String(videosCount ?? 0)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ final class CommentsModel: ObservableObject {
|
|||||||
.comments(video.videoID, page: page)?
|
.comments(video.videoID, page: page)?
|
||||||
.load()
|
.load()
|
||||||
.onSuccess { [weak self] response in
|
.onSuccess { [weak self] response in
|
||||||
guard let self = self else { return }
|
guard let self else { return }
|
||||||
if let commentsPage: CommentsPage = response.typedContent() {
|
if let commentsPage: CommentsPage = response.typedContent() {
|
||||||
self.all += commentsPage.comments
|
self.all += commentsPage.comments
|
||||||
self.nextPage = commentsPage.nextPage
|
self.nextPage = commentsPage.nextPage
|
||||||
|
@ -274,7 +274,7 @@ extension Country {
|
|||||||
|
|
||||||
private static func filteredCountries(_ predicate: (String) -> Bool) -> [Country] {
|
private static func filteredCountries(_ predicate: (String) -> Bool) -> [Country] {
|
||||||
Country.allCases
|
Country.allCases
|
||||||
.map { $0.name }
|
.map(\.name)
|
||||||
.filter(predicate)
|
.filter(predicate)
|
||||||
.compactMap { string in Country.allCases.first { $0.name == string } }
|
.compactMap { string in Country.allCases.first { $0.name == string } }
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ final class FeedModel: ObservableObject, CacheModel {
|
|||||||
backgroundContext.perform { [weak self] in
|
backgroundContext.perform { [weak self] in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
|
|
||||||
let watched = self.watchFetchRequestResult(feed, context: self.backgroundContext).filter { $0.finished }
|
let watched = self.watchFetchRequestResult(feed, context: self.backgroundContext).filter(\.finished)
|
||||||
let unwatched = feed.filter { video in !watched.contains { $0.videoID == video.videoID } }
|
let unwatched = feed.filter { video in !watched.contains { $0.videoID == video.videoID } }
|
||||||
let unwatchedCount = max(0, feed.count - watched.count)
|
let unwatchedCount = max(0, feed.count - watched.count)
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ final class PlayerModel: ObservableObject {
|
|||||||
}}
|
}}
|
||||||
@Published var aspectRatio = VideoPlayerView.defaultAspectRatio
|
@Published var aspectRatio = VideoPlayerView.defaultAspectRatio
|
||||||
@Published var stream: Stream?
|
@Published var stream: Stream?
|
||||||
@Published var currentRate: Double = 1.0 { didSet { handleCurrentRateChange() } }
|
@Published var currentRate = 1.0 { didSet { handleCurrentRateChange() } }
|
||||||
|
|
||||||
@Published var qualityProfileSelection: QualityProfile? { didSet { handleQualityProfileChange() } }
|
@Published var qualityProfileSelection: QualityProfile? { didSet { handleQualityProfileChange() } }
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ extension PlayerModel {
|
|||||||
preservedTime = currentItem.playbackTime
|
preservedTime = currentItem.playbackTime
|
||||||
|
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self else { return }
|
||||||
guard let video = item.video else {
|
guard let video = item.video else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,12 @@ struct ScreenSaverManager {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
noSleepReturn = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep as CFString,
|
noSleepReturn = IOPMAssertionCreateWithName(
|
||||||
IOPMAssertionLevel(kIOPMAssertionLevelOn),
|
kIOPMAssertionTypeNoDisplaySleep as CFString,
|
||||||
reason as CFString,
|
IOPMAssertionLevel(kIOPMAssertionLevelOn),
|
||||||
&noSleepAssertion)
|
reason as CFString,
|
||||||
|
&noSleepAssertion
|
||||||
|
)
|
||||||
return noSleepReturn == kIOReturnSuccess
|
return noSleepReturn == kIOReturnSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ struct QualityProfileBridge: Defaults.Bridge {
|
|||||||
"name": value.name ?? "",
|
"name": value.name ?? "",
|
||||||
"backend": value.backend.rawValue,
|
"backend": value.backend.rawValue,
|
||||||
"resolution": value.resolution.rawValue,
|
"resolution": value.resolution.rawValue,
|
||||||
"formats": value.formats.map { $0.rawValue }.joined(separator: Self.formatsSeparator),
|
"formats": value.formats.map(\.rawValue).joined(separator: Self.formatsSeparator),
|
||||||
"order": value.order.map { String($0) }.joined(separator: Self.formatsSeparator) // New line
|
"order": value.order.map { String($0) }.joined(separator: Self.formatsSeparator) // New line
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -607,7 +607,7 @@ enum SponsorBlockColors: String {
|
|||||||
case music_offtopic = "#FF9900" // Orange
|
case music_offtopic = "#FF9900" // Orange
|
||||||
|
|
||||||
// Define all cases, can be used to iterate over the colors
|
// Define all cases, can be used to iterate over the colors
|
||||||
static let allCases: [SponsorBlockColors] = [.sponsor, .selfpromo, .interaction, .intro, .outro, .preview, .filler, .music_offtopic]
|
static let allCases: [SponsorBlockColors] = [Self.sponsor, Self.selfpromo, Self.interaction, Self.intro, Self.outro, Self.preview, Self.filler, Self.music_offtopic]
|
||||||
|
|
||||||
// Create a dictionary with the category names as keys and colors as values
|
// Create a dictionary with the category names as keys and colors as values
|
||||||
static let dictionary: [String: String] = {
|
static let dictionary: [String: String] = {
|
||||||
|
@ -51,59 +51,108 @@ enum LanguageCodes: String, CaseIterable {
|
|||||||
|
|
||||||
var description: String {
|
var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .Afrikaans: return "Afrikaans"
|
case .Afrikaans:
|
||||||
case .Arabic: return "Arabic"
|
return "Afrikaans"
|
||||||
case .Azerbaijani: return "Azerbaijani"
|
case .Arabic:
|
||||||
case .Bengali: return "Bengali"
|
return "Arabic"
|
||||||
case .Catalan: return "Catalan"
|
case .Azerbaijani:
|
||||||
case .Czech: return "Czech"
|
return "Azerbaijani"
|
||||||
case .Welsh: return "Welsh"
|
case .Bengali:
|
||||||
case .Danish: return "Danish"
|
return "Bengali"
|
||||||
case .German: return "German"
|
case .Catalan:
|
||||||
case .Greek: return "Greek"
|
return "Catalan"
|
||||||
case .English: return "English"
|
case .Czech:
|
||||||
case .English_GB: return "English (United Kingdom)"
|
return "Czech"
|
||||||
case .Spanish: return "Spanish"
|
case .Welsh:
|
||||||
case .Persian: return "Persian"
|
return "Welsh"
|
||||||
case .Finnish: return "Finnish"
|
case .Danish:
|
||||||
case .Filipino: return "Filipino"
|
return "Danish"
|
||||||
case .French: return "French"
|
case .German:
|
||||||
case .Irish: return "Irish"
|
return "German"
|
||||||
case .Hebrew: return "Hebrew"
|
case .Greek:
|
||||||
case .Hindi: return "Hindi"
|
return "Greek"
|
||||||
case .Hungarian: return "Hungarian"
|
case .English:
|
||||||
case .Indonesian: return "Indonesian"
|
return "English"
|
||||||
case .Italian: return "Italian"
|
case .English_GB:
|
||||||
case .Japanese: return "Japanese"
|
return "English (United Kingdom)"
|
||||||
case .Javanese: return "Javanese"
|
case .Spanish:
|
||||||
case .Korean: return "Korean"
|
return "Spanish"
|
||||||
case .Lithuanian: return "Lithuanian"
|
case .Persian:
|
||||||
case .Malay: return "Malay"
|
return "Persian"
|
||||||
case .Maltese: return "Maltese"
|
case .Finnish:
|
||||||
case .Dutch: return "Dutch"
|
return "Finnish"
|
||||||
case .Norwegian: return "Norwegian"
|
case .Filipino:
|
||||||
case .Polish: return "Polish"
|
return "Filipino"
|
||||||
case .Portuguese: return "Portuguese"
|
case .French:
|
||||||
case .Romanian: return "Romanian"
|
return "French"
|
||||||
case .Russian: return "Russian"
|
case .Irish:
|
||||||
case .Slovak: return "Slovak"
|
return "Irish"
|
||||||
case .Slovene: return "Slovene"
|
case .Hebrew:
|
||||||
case .Swedish: return "Swedish"
|
return "Hebrew"
|
||||||
case .Swahili: return "Swahili"
|
case .Hindi:
|
||||||
case .Thai: return "Thai"
|
return "Hindi"
|
||||||
case .Tagalog: return "Tagalog"
|
case .Hungarian:
|
||||||
case .Turkish: return "Turkish"
|
return "Hungarian"
|
||||||
case .Ukrainian: return "Ukrainian"
|
case .Indonesian:
|
||||||
case .Urdu: return "Urdu"
|
return "Indonesian"
|
||||||
case .Uzbek: return "Uzbek"
|
case .Italian:
|
||||||
case .Vietnamese: return "Vietnamese"
|
return "Italian"
|
||||||
case .Xhosa: return "Xhosa"
|
case .Japanese:
|
||||||
case .Chinese: return "Chinese"
|
return "Japanese"
|
||||||
case .Zulu: return "Zulu"
|
case .Javanese:
|
||||||
|
return "Javanese"
|
||||||
|
case .Korean:
|
||||||
|
return "Korean"
|
||||||
|
case .Lithuanian:
|
||||||
|
return "Lithuanian"
|
||||||
|
case .Malay:
|
||||||
|
return "Malay"
|
||||||
|
case .Maltese:
|
||||||
|
return "Maltese"
|
||||||
|
case .Dutch:
|
||||||
|
return "Dutch"
|
||||||
|
case .Norwegian:
|
||||||
|
return "Norwegian"
|
||||||
|
case .Polish:
|
||||||
|
return "Polish"
|
||||||
|
case .Portuguese:
|
||||||
|
return "Portuguese"
|
||||||
|
case .Romanian:
|
||||||
|
return "Romanian"
|
||||||
|
case .Russian:
|
||||||
|
return "Russian"
|
||||||
|
case .Slovak:
|
||||||
|
return "Slovak"
|
||||||
|
case .Slovene:
|
||||||
|
return "Slovene"
|
||||||
|
case .Swedish:
|
||||||
|
return "Swedish"
|
||||||
|
case .Swahili:
|
||||||
|
return "Swahili"
|
||||||
|
case .Thai:
|
||||||
|
return "Thai"
|
||||||
|
case .Tagalog:
|
||||||
|
return "Tagalog"
|
||||||
|
case .Turkish:
|
||||||
|
return "Turkish"
|
||||||
|
case .Ukrainian:
|
||||||
|
return "Ukrainian"
|
||||||
|
case .Urdu:
|
||||||
|
return "Urdu"
|
||||||
|
case .Uzbek:
|
||||||
|
return "Uzbek"
|
||||||
|
case .Vietnamese:
|
||||||
|
return "Vietnamese"
|
||||||
|
case .Xhosa:
|
||||||
|
return "Xhosa"
|
||||||
|
case .Chinese:
|
||||||
|
return "Chinese"
|
||||||
|
case .Zulu:
|
||||||
|
return "Zulu"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func languageName(for code: String) -> String {
|
static func languageName(for code: String) -> String {
|
||||||
return LanguageCodes(rawValue: code)?.description ?? "Unknown"
|
return Self(rawValue: code)?.description ?? "Unknown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ struct OpenURLHandler {
|
|||||||
return accounts.api.channelByName(name)
|
return accounts.api.channelByName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let instance = InstancesModel.shared.all.first(where: { $0.app.supportsOpeningChannelsByName }) {
|
if let instance = InstancesModel.shared.all.first(where: \.app.supportsOpeningChannelsByName) {
|
||||||
return instance.anonymous.channelByName(name)
|
return instance.anonymous.channelByName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ struct OpenURLHandler {
|
|||||||
return accounts.api.channelByUsername(username)
|
return accounts.api.channelByUsername(username)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let instance = InstancesModel.shared.all.first(where: { $0.app.supportsOpeningChannelsByName }) {
|
if let instance = InstancesModel.shared.all.first(where: \.app.supportsOpeningChannelsByName) {
|
||||||
return instance.anonymous.channelByUsername(username)
|
return instance.anonymous.channelByUsername(username)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,8 @@ final class AppleAVPlayerViewController: UIViewController {
|
|||||||
_ sections: [NowPlayingView.ViewSection],
|
_ sections: [NowPlayingView.ViewSection],
|
||||||
title: String
|
title: String
|
||||||
) -> UIHostingController<AnyView> {
|
) -> UIHostingController<AnyView> {
|
||||||
let controller = UIHostingController(rootView:
|
let controller = UIHostingController(
|
||||||
|
rootView:
|
||||||
AnyView(
|
AnyView(
|
||||||
NowPlayingView(sections: sections, inInfoViewController: true)
|
NowPlayingView(sections: sections, inInfoViewController: true)
|
||||||
.frame(maxHeight: 600)
|
.frame(maxHeight: 600)
|
||||||
|
@ -33,7 +33,7 @@ struct TimelineView: View {
|
|||||||
@State private var dragOffset: Double = 0
|
@State private var dragOffset: Double = 0
|
||||||
@State private var draggedFrom: Double = 0
|
@State private var draggedFrom: Double = 0
|
||||||
|
|
||||||
private var start: Double = 0.0
|
private var start = 0.0
|
||||||
private var height = 8.0
|
private var height = 8.0
|
||||||
|
|
||||||
var cornerRadius: Double
|
var cornerRadius: Double
|
||||||
|
@ -90,8 +90,9 @@ final class PlayerViewController: UIViewController {
|
|||||||
_ sections: [NowPlayingView.ViewSection],
|
_ sections: [NowPlayingView.ViewSection],
|
||||||
title: String
|
title: String
|
||||||
) -> UIHostingController<AnyView> {
|
) -> UIHostingController<AnyView> {
|
||||||
let controller = UIHostingController(rootView:
|
let controller = UIHostingController(
|
||||||
AnyView(
|
rootView:
|
||||||
|
AnyV‚iew(
|
||||||
NowPlayingView(sections: sections, inInfoViewController: true)
|
NowPlayingView(sections: sections, inInfoViewController: true)
|
||||||
.frame(maxHeight: 600)
|
.frame(maxHeight: 600)
|
||||||
.environmentObject(commentsModel)
|
.environmentObject(commentsModel)
|
||||||
|
@ -208,6 +208,7 @@ struct VideoDetails: View {
|
|||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.padding(.horizontal, 16)
|
.padding(.horizontal, 16)
|
||||||
|
// swiftlint:disable trailing_closure
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
.tapRecognizer(
|
.tapRecognizer(
|
||||||
tapSensitivity: 0.2,
|
tapSensitivity: 0.2,
|
||||||
@ -218,6 +219,7 @@ struct VideoDetails: View {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
#endif
|
#endif
|
||||||
|
// swiftlint:enable trailing_closure
|
||||||
|
|
||||||
VideoActions(video: player.videoForDisplay)
|
VideoActions(video: player.videoForDisplay)
|
||||||
.padding(.vertical, 5)
|
.padding(.vertical, 5)
|
||||||
|
@ -281,7 +281,7 @@ struct VideoPlayerView: View {
|
|||||||
}
|
}
|
||||||
.gesture(player.controls.presentingOverlays ? nil : playerDragGesture)
|
.gesture(player.controls.presentingOverlays ? nil : playerDragGesture)
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
.onAppear(perform: {
|
.onAppear {
|
||||||
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) {
|
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) {
|
||||||
hoverThrottle.execute {
|
hoverThrottle.execute {
|
||||||
if !player.currentItem.isNil, hoveringPlayer {
|
if !player.currentItem.isNil, hoveringPlayer {
|
||||||
@ -291,7 +291,7 @@ struct VideoPlayerView: View {
|
|||||||
|
|
||||||
return $0
|
return $0
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.background(Color.black)
|
.background(Color.black)
|
||||||
|
@ -15,7 +15,7 @@ struct SearchTextField: View {
|
|||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
Image(systemName: "magnifyingglass")
|
Image(systemName: "magnifyingglass")
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fill)
|
.scaledToFill()
|
||||||
.frame(width: 12, height: 12)
|
.frame(width: 12, height: 12)
|
||||||
.padding(.horizontal, 8)
|
.padding(.horizontal, 8)
|
||||||
.opacity(0.8)
|
.opacity(0.8)
|
||||||
|
@ -380,7 +380,7 @@ struct QualityProfileForm: View {
|
|||||||
func submitForm() {
|
func submitForm() {
|
||||||
guard valid else { return }
|
guard valid else { return }
|
||||||
|
|
||||||
let activeFormats = orderedFormats.filter { $0.isActive }.map { $0.format }
|
let activeFormats = orderedFormats.filter(\.isActive).map(\.format)
|
||||||
|
|
||||||
let formProfile = QualityProfile(
|
let formProfile = QualityProfile(
|
||||||
id: qualityProfile?.id ?? UUID().uuidString,
|
id: qualityProfile?.id ?? UUID().uuidString,
|
||||||
|
@ -15,7 +15,7 @@ struct FeedView: View {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
var videos: [ContentItem] {
|
var videos: [ContentItem] {
|
||||||
guard let selectedChannel = selectedChannel else {
|
guard let selectedChannel else {
|
||||||
return ContentItem.array(of: feed.videos)
|
return ContentItem.array(of: feed.videos)
|
||||||
}
|
}
|
||||||
return ContentItem.array(of: feed.videos.filter {
|
return ContentItem.array(of: feed.videos.filter {
|
||||||
@ -24,9 +24,7 @@ struct FeedView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var channels: [Channel] {
|
var channels: [Channel] {
|
||||||
feed.videos.map {
|
feed.videos.map(\.channel).unique()
|
||||||
$0.channel
|
|
||||||
}.unique()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@State private var selectedChannel: Channel?
|
@State private var selectedChannel: Channel?
|
||||||
@ -272,7 +270,7 @@ struct FeedView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var channelHeaderView: some View {
|
var channelHeaderView: some View {
|
||||||
guard let selectedChannel = selectedChannel else {
|
guard let selectedChannel else {
|
||||||
return AnyView(
|
return AnyView(
|
||||||
Text("All Channels")
|
Text("All Channels")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
|
@ -6,7 +6,7 @@ struct TrendingCountry: View {
|
|||||||
|
|
||||||
@StateObject private var store = Store(Country.allCases)
|
@StateObject private var store = Store(Country.allCases)
|
||||||
|
|
||||||
@State private var query: String = ""
|
@State private var query = ""
|
||||||
@State private var selection: Country?
|
@State private var selection: Country?
|
||||||
|
|
||||||
@Environment(\.colorScheme) private var colorScheme
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
|
@ -26,8 +26,7 @@ struct URLParser {
|
|||||||
urlString.contains("youtube.com") ||
|
urlString.contains("youtube.com") ||
|
||||||
urlString.contains("youtu.be") ||
|
urlString.contains("youtu.be") ||
|
||||||
urlString.contains("youtube-nocookie.com"),
|
urlString.contains("youtube-nocookie.com"),
|
||||||
let url = URL(string: "https://\(urlString)"
|
let url = URL(string: "https://\(urlString)")
|
||||||
)
|
|
||||||
{
|
{
|
||||||
self.url = url
|
self.url = url
|
||||||
}
|
}
|
||||||
@ -176,10 +175,8 @@ struct URLParser {
|
|||||||
private func removePrefixes(_ value: String, _ prefixes: [String]) -> String {
|
private func removePrefixes(_ value: String, _ prefixes: [String]) -> String {
|
||||||
var value = value
|
var value = value
|
||||||
|
|
||||||
for prefix in prefixes {
|
for prefix in prefixes where value.hasPrefix(prefix) {
|
||||||
if value.hasPrefix(prefix) {
|
value.removeFirst(prefix.count)
|
||||||
value.removeFirst(prefix.count)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
@ -100,7 +100,7 @@ struct YatteeApp: App {
|
|||||||
.commands {
|
.commands {
|
||||||
SidebarCommands()
|
SidebarCommands()
|
||||||
|
|
||||||
CommandGroup(replacing: .newItem, addition: {})
|
CommandGroup(replacing: .newItem) {}
|
||||||
|
|
||||||
MenuCommands(model: Binding<MenuModel>(get: { MenuModel.shared }, set: { _ in }))
|
MenuCommands(model: Binding<MenuModel>(get: { MenuModel.shared }, set: { _ in }))
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,11 @@ public class OrientationTracker {
|
|||||||
guard newDeviceOrientation != self.currentDeviceOrientation else { return }
|
guard newDeviceOrientation != self.currentDeviceOrientation else { return }
|
||||||
self.currentDeviceOrientation = newDeviceOrientation
|
self.currentDeviceOrientation = newDeviceOrientation
|
||||||
|
|
||||||
NotificationCenter.default.post(name: Self.deviceOrientationChangedNotification,
|
NotificationCenter.default.post(
|
||||||
object: nil,
|
name: Self.deviceOrientationChangedNotification,
|
||||||
userInfo: nil)
|
object: nil,
|
||||||
|
userInfo: nil
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import SwiftUI
|
|||||||
struct ShareSheet: UIViewControllerRepresentable {
|
struct ShareSheet: UIViewControllerRepresentable {
|
||||||
typealias Callback = (_ activityType: UIActivity.ActivityType?,
|
typealias Callback = (_ activityType: UIActivity.ActivityType?,
|
||||||
_ completed: Bool,
|
_ completed: Bool,
|
||||||
_ returnedItems: [Any]?,
|
_ returnedItems: [Any],
|
||||||
_ error: Error?) -> Void
|
_ error: Error?) -> Void
|
||||||
|
|
||||||
let activityItems: [Any]
|
let activityItems: [Any]
|
||||||
@ -19,7 +19,10 @@ struct ShareSheet: UIViewControllerRepresentable {
|
|||||||
)
|
)
|
||||||
|
|
||||||
controller.excludedActivityTypes = excludedActivityTypes
|
controller.excludedActivityTypes = excludedActivityTypes
|
||||||
controller.completionWithItemsHandler = callback
|
|
||||||
|
controller.completionWithItemsHandler = { activityType, completed, returnedItems, error in
|
||||||
|
callback?(activityType, completed, returnedItems ?? [], error)
|
||||||
|
}
|
||||||
|
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,12 @@ final class VideoLayer: CAOpenGLLayer {
|
|||||||
glGetIntegerv(GLenum(GL_DRAW_FRAMEBUFFER_BINDING), &i)
|
glGetIntegerv(GLenum(GL_DRAW_FRAMEBUFFER_BINDING), &i)
|
||||||
|
|
||||||
if client.mpvGL != nil {
|
if client.mpvGL != nil {
|
||||||
var data = mpv_opengl_fbo(fbo: Int32(i),
|
var data = mpv_opengl_fbo(
|
||||||
w: Int32(bounds.size.width),
|
fbo: Int32(i),
|
||||||
h: Int32(bounds.size.height),
|
w: Int32(bounds.size.width),
|
||||||
internal_format: 0)
|
h: Int32(bounds.size.height),
|
||||||
|
internal_format: 0
|
||||||
|
)
|
||||||
var params: [mpv_render_param] = [
|
var params: [mpv_render_param] = [
|
||||||
mpv_render_param(type: MPV_RENDER_PARAM_OPENGL_FBO, data: &data),
|
mpv_render_param(type: MPV_RENDER_PARAM_OPENGL_FBO, data: &data),
|
||||||
mpv_render_param(type: MPV_RENDER_PARAM_FLIP_Y, data: &flip),
|
mpv_render_param(type: MPV_RENDER_PARAM_FLIP_Y, data: &flip),
|
||||||
@ -106,8 +108,10 @@ final class VideoLayer: CAOpenGLLayer {
|
|||||||
let displayId = UInt32(NSScreen.main?.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as! Int)
|
let displayId = UInt32(NSScreen.main?.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as! Int)
|
||||||
|
|
||||||
CVDisplayLinkCreateWithCGDisplay(displayId, &client.link)
|
CVDisplayLinkCreateWithCGDisplay(displayId, &client.link)
|
||||||
CVDisplayLinkSetOutputCallback(client.link!, displayLinkCallback,
|
CVDisplayLinkSetOutputCallback(
|
||||||
UnsafeMutableRawPointer(Unmanaged.passUnretained(client.layer).toOpaque()))
|
client.link!, displayLinkCallback,
|
||||||
|
UnsafeMutableRawPointer(Unmanaged.passUnretained(client.layer).toOpaque())
|
||||||
|
)
|
||||||
CVDisplayLinkStart(client.link!)
|
CVDisplayLinkStart(client.link!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user