diff --git a/.swiftlint.yml b/.swiftlint.yml index 452cd357..492f4ad7 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -7,6 +7,7 @@ disabled_rules: - number_separator - multiline_arguments - implicit_return + - closure_end_indentation excluded: - Vendor - Tests Apple TV diff --git a/Model/Applications/InvidiousAPI.swift b/Model/Applications/InvidiousAPI.swift index de270505..f8922275 100644 --- a/Model/Applications/InvidiousAPI.swift +++ b/Model/Applications/InvidiousAPI.swift @@ -687,7 +687,8 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI { func extractXTags(from urlString: String) -> [String: String] { guard let urlComponents = URLComponents(string: urlString), let queryItems = urlComponents.queryItems, - let xtagsValue = queryItems.first(where: { $0.name == "xtags" })?.value else { + let xtagsValue = queryItems.first(where: { $0.name == "xtags" })?.value + else { return [:] } diff --git a/Model/Applications/PipedAPI.swift b/Model/Applications/PipedAPI.swift index 38e77c3d..c918c5fe 100644 --- a/Model/Applications/PipedAPI.swift +++ b/Model/Applications/PipedAPI.swift @@ -722,10 +722,10 @@ final class PipedAPI: Service, ObservableObject, VideosAPI { } .sorted { track1, track2 in // Sort: ORIGINAL first, then DUBBED, then others - if track1.content == "ORIGINAL" && track2.content != "ORIGINAL" { + if track1.content == "ORIGINAL", track2.content != "ORIGINAL" { return true } - if track1.content != "ORIGINAL" && track2.content == "ORIGINAL" { + if track1.content != "ORIGINAL", track2.content == "ORIGINAL" { return false } // If both are same type, sort by language diff --git a/Model/NavigationModel.swift b/Model/NavigationModel.swift index 641ef6ad..c107ef25 100644 --- a/Model/NavigationModel.swift +++ b/Model/NavigationModel.swift @@ -318,7 +318,7 @@ final class NavigationModel: ObservableObject { func multipleTapHandler() { switch tabSelection { case .search: - self.search.focused = true + search.focused = true default: print("not implemented") } diff --git a/Model/NetworkStateModel.swift b/Model/NetworkStateModel.swift index 25a55d72..34b83d27 100644 --- a/Model/NetworkStateModel.swift +++ b/Model/NetworkStateModel.swift @@ -26,7 +26,7 @@ final class NetworkStateModel: ObservableObject { } var bufferingStateText: String? { - guard detailsAvailable && player.hasStarted else { return nil } + guard detailsAvailable, player.hasStarted else { return nil } return String(format: "%.0f%%", bufferingState) } diff --git a/Model/Player/Backends/AVPlayerBackend.swift b/Model/Player/Backends/AVPlayerBackend.swift index 30ac6ebc..2b2c1df0 100644 --- a/Model/Player/Backends/AVPlayerBackend.swift +++ b/Model/Player/Backends/AVPlayerBackend.swift @@ -190,8 +190,8 @@ final class AVPlayerBackend: PlayerBackend { } // After the video has ended, hitting play restarts the video from the beginning. - if currentTime?.seconds.formattedAsPlaybackTime() == model.playerTime.duration.seconds.formattedAsPlaybackTime() && - currentTime!.seconds > 0 && model.playerTime.duration.seconds > 0 + if currentTime?.seconds.formattedAsPlaybackTime() == model.playerTime.duration.seconds.formattedAsPlaybackTime(), + currentTime!.seconds > 0, model.playerTime.duration.seconds > 0 { seek(to: 0, seekType: .loopRestart) } diff --git a/Model/Player/Backends/MPVBackend.swift b/Model/Player/Backends/MPVBackend.swift index e25a0bdf..23308963 100644 --- a/Model/Player/Backends/MPVBackend.swift +++ b/Model/Player/Backends/MPVBackend.swift @@ -97,7 +97,7 @@ final class MPVBackend: PlayerBackend { var controlsUpdates = false private var timeObserverThrottle = Throttle(interval: 2) - + // Retry mechanism private var retryCount = 0 private let maxRetries = 3 @@ -227,7 +227,7 @@ final class MPVBackend: PlayerBackend { // Store stream and video for potential retries currentRetryStream = stream currentRetryVideo = video - + #if !os(macOS) if model.presentingPlayer { DispatchQueue.main.async { @@ -247,7 +247,7 @@ final class MPVBackend: PlayerBackend { video.captions.first { $0.code.contains(captionsDefaultLanguageCode) } // If there are still no captions, try to get captions with the fallback language code - if captions.isNil && !captionsFallbackLanguageCode.isEmpty { + if captions.isNil, !captionsFallbackLanguageCode.isEmpty { captions = video.captions.first { $0.code == captionsFallbackLanguageCode } ?? video.captions.first { $0.code.contains(captionsFallbackLanguageCode) } } @@ -369,7 +369,7 @@ final class MPVBackend: PlayerBackend { replaceItem(self.model.preservedTime) } } else { - replaceItem(self.model.preservedTime) + replaceItem(model.preservedTime) } } else { replaceItem(nil) @@ -400,8 +400,8 @@ final class MPVBackend: PlayerBackend { setRate(model.currentRate) // After the video has ended, hitting play restarts the video from the beginning. - if let currentTime, currentTime.seconds.formattedAsPlaybackTime() == model.playerTime.duration.seconds.formattedAsPlaybackTime() && - currentTime.seconds > 0 && model.playerTime.duration.seconds > 0 + if let currentTime, currentTime.seconds.formattedAsPlaybackTime() == model.playerTime.duration.seconds.formattedAsPlaybackTime(), + currentTime.seconds > 0, model.playerTime.duration.seconds > 0 { seek(to: 0, seekType: .loopRestart) } @@ -466,23 +466,23 @@ final class MPVBackend: PlayerBackend { func closeItem() { pause() stop() - self.video = nil - self.stream = nil + video = nil + stream = nil } func closePiP() {} func startControlsUpdates() { guard model.presentingPlayer, model.controls.presentingControls, !model.controls.presentingOverlays else { - self.logger.info("ignored controls update start") + logger.info("ignored controls update start") return } - self.logger.info("starting controls updates") + logger.info("starting controls updates") controlsUpdates = true } func stopControlsUpdates() { - self.logger.info("stopping controls updates") + logger.info("stopping controls updates") controlsUpdates = false } @@ -514,7 +514,7 @@ final class MPVBackend: PlayerBackend { self.model.updateWatch(time: currentTime) } - self.model.updateTime(currentTime) + model.updateTime(currentTime) } private func stopClientUpdates() { @@ -641,7 +641,7 @@ final class MPVBackend: PlayerBackend { } eofPlaybackModeAction() } - + private func handleFileLoadError() { guard let stream = currentRetryStream, let video = currentRetryVideo else { // No stream info available, show error immediately @@ -651,13 +651,13 @@ final class MPVBackend: PlayerBackend { eofPlaybackModeAction() return } - + if retryCount < maxRetries { retryCount += 1 let delay = TimeInterval(retryCount * 2) // 2, 4, 6 seconds - + logger.warning("File load failed. Retry attempt \(retryCount) of \(maxRetries) after \(delay) seconds...") - + DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in guard let self else { return } self.logger.info("Retrying file load (attempt \(self.retryCount))...") @@ -670,12 +670,12 @@ final class MPVBackend: PlayerBackend { model.closeCurrentItem(finished: true) getTimeUpdates() eofPlaybackModeAction() - + // Reset retry counter for next attempt resetRetryState() } } - + private func resetRetryState() { retryCount = 0 currentRetryStream = nil @@ -807,7 +807,7 @@ final class MPVBackend: PlayerBackend { guard let stream, let video else { return } // Validate the index is within bounds - guard index >= 0 && index < stream.audioTracks.count else { + guard index >= 0, index < stream.audioTracks.count else { logger.error("Invalid audio track index: \(index), available tracks: \(stream.audioTracks.count)") return } diff --git a/Model/Player/Backends/PlayerBackend.swift b/Model/Player/Backends/PlayerBackend.swift index e9a11fd7..827ca1d2 100644 --- a/Model/Player/Backends/PlayerBackend.swift +++ b/Model/Player/Backends/PlayerBackend.swift @@ -217,7 +217,7 @@ extension PlayerBackend { // If rhs has no resolution, it's "less than" lhs (prefer lhs) return lhs.resolution == nil } - + if lhsResolution == rhsResolution { guard let lhsFormat = QualityProfile.Format(rawValue: lhs.format.rawValue), let rhsFormat = QualityProfile.Format(rawValue: rhs.format.rawValue) diff --git a/Model/Player/PlayerModel.swift b/Model/Player/PlayerModel.swift index af9755cc..575ec78a 100644 --- a/Model/Player/PlayerModel.swift +++ b/Model/Player/PlayerModel.swift @@ -620,7 +620,7 @@ final class PlayerModel: ObservableObject { } Defaults[.activeBackend] = to - self.activeBackend = to + activeBackend = to let fromBackend: PlayerBackend = from == .appleAVPlayer ? avPlayerBackend : mpvBackend let toBackend: PlayerBackend = to == .appleAVPlayer ? avPlayerBackend : mpvBackend @@ -628,13 +628,13 @@ final class PlayerModel: ObservableObject { toBackend.cancelLoads() fromBackend.cancelLoads() - if !self.backend.canPlayAtRate(currentRate) { - currentRate = self.backend.suggestedPlaybackRates.last { $0 < currentRate } ?? 1.0 + if !backend.canPlayAtRate(currentRate) { + currentRate = backend.suggestedPlaybackRates.last { $0 < currentRate } ?? 1.0 } - self.rateToRestore = Float(currentRate) + rateToRestore = Float(currentRate) - self.backend.didChangeTo() + backend.didChangeTo() if wasPlaying { fromBackend.pause() @@ -664,7 +664,7 @@ final class PlayerModel: ObservableObject { self.stream = stream streamSelection = stream - self.upgradeToStream(stream, force: true) + upgradeToStream(stream, force: true) return } @@ -1086,7 +1086,7 @@ final class PlayerModel: ObservableObject { logger.info("entering fullscreen") toggleFullscreen(false, showControls: showControls) - self.playingFullScreen = true + playingFullScreen = true } func exitFullScreen(showControls: Bool = true) { @@ -1094,7 +1094,7 @@ final class PlayerModel: ObservableObject { logger.info("exiting fullscreen") toggleFullscreen(true, showControls: showControls) - self.playingFullScreen = false + playingFullScreen = false } func updateNowPlayingInfo() { @@ -1284,7 +1284,7 @@ final class PlayerModel: ObservableObject { } private func chapterForTime(_ time: Double) -> Int? { - guard let chapters = self.videoForDisplay?.chapters else { + guard let chapters = videoForDisplay?.chapters else { return nil } diff --git a/Model/Player/PlayerQueue.swift b/Model/Player/PlayerQueue.swift index 8e2ad023..b24dec4f 100644 --- a/Model/Player/PlayerQueue.swift +++ b/Model/Player/PlayerQueue.swift @@ -130,7 +130,7 @@ extension PlayerModel { logger.error("Backend is nil when trying to select stream by quality profile") return nil } - + let profile = qualityProfile ?? .defaultProfile // First attempt: Filter by both `canPlay` and `isPreferred` diff --git a/Shared/Channels/ChannelVideosView.swift b/Shared/Channels/ChannelVideosView.swift index 9c2f1bf2..feccb472 100644 --- a/Shared/Channels/ChannelVideosView.swift +++ b/Shared/Channels/ChannelVideosView.swift @@ -186,11 +186,7 @@ struct ChannelVideosView: View { .background(Color.background(scheme: colorScheme)) .focusScope(focusNamespace) #elseif os(macOS) - if #available(macOS 12.0, *) { - return content.focusScope(focusNamespace) - } else { - return content - } + return content.focusScope(focusNamespace) #else return content #endif diff --git a/Shared/Constants.swift b/Shared/Constants.swift index 27e381c7..399a5896 100644 --- a/Shared/Constants.swift +++ b/Shared/Constants.swift @@ -45,7 +45,7 @@ enum Constants { .filter({ $0.activationState == .foregroundActive }) .compactMap({ $0 as? UIWindowScene }) .first, - let window = windowScene.windows.first + let window = windowScene.windows.first else { return false } @@ -55,13 +55,13 @@ enum Constants { // Check if window size matches screen bounds (accounting for small differences) return abs(windowBounds.width - screenBounds.width) < 1 && - abs(windowBounds.height - screenBounds.height) < 1 + abs(windowBounds.height - screenBounds.height) < 1 #else return false #endif } - static var iPadSystemControlsWidth: CGFloat { + static var iPadSystemControlsWidth: Double { 50 } diff --git a/Shared/Home/FavoriteItemView.swift b/Shared/Home/FavoriteItemView.swift index aa8f9fd2..86e432ea 100644 --- a/Shared/Home/FavoriteItemView.swift +++ b/Shared/Home/FavoriteItemView.swift @@ -64,13 +64,13 @@ struct FavoriteItemView: View { #else .padding(.horizontal, 15) #endif - .frame(height: expectedContentHeight) + .frame(height: expectedContentHeight) } else { ZStack(alignment: .topLeading) { // Reserve space immediately to prevent layout shift Color.clear .frame(height: expectedContentHeight) - + // Actual content renders within the reserved space Group { switch widgetListingStyle { diff --git a/Shared/Navigation/AccountsView.swift b/Shared/Navigation/AccountsView.swift index d2c5992e..ff9200f2 100644 --- a/Shared/Navigation/AccountsView.swift +++ b/Shared/Navigation/AccountsView.swift @@ -4,7 +4,7 @@ struct AccountsView: View { @StateObject private var model = AccountsViewModel() @Environment(\.presentationMode) private var presentationMode #if os(tvOS) - @Environment(\.colorScheme) private var colorScheme + @Environment(\.colorScheme) private var colorScheme #endif var body: some View { diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index 694b1a96..6952d1cb 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -69,94 +69,94 @@ struct ContentView: View { } #else .background( - EmptyView().sheet(isPresented: $navigation.presentingSettings) { - SettingsView() - } - ) + EmptyView().sheet(isPresented: $navigation.presentingSettings) { + SettingsView() + } + ) #endif - .modifier(ImportSettingsSheetViewModifier(isPresented: $navigation.presentingSettingsImportSheet, settingsFile: $navigation.settingsImportURL)) + .modifier(ImportSettingsSheetViewModifier(isPresented: $navigation.presentingSettingsImportSheet, settingsFile: $navigation.settingsImportURL)) #if os(tvOS) - .fullScreenCover(isPresented: $navigation.presentingAccounts) { - AccountsView() - } - #else - .background( - EmptyView().sheet(isPresented: $navigation.presentingAccounts) { + .fullScreenCover(isPresented: $navigation.presentingAccounts) { AccountsView() } - ) - #endif - .background( - EmptyView().sheet(isPresented: $navigation.presentingHomeSettings) { - #if os(macOS) - VStack(alignment: .leading) { - Button("Done") { - navigation.presentingHomeSettings = false - } - .padding() - .keyboardShortcut(.cancelAction) - - HomeSettings() + #else + .background( + EmptyView().sheet(isPresented: $navigation.presentingAccounts) { + AccountsView() } - .frame(width: 500, height: 800) - #else - NavigationView { - HomeSettings() - #if os(iOS) - .toolbar { - ToolbarItem(placement: .navigation) { - Button { - navigation.presentingHomeSettings = false - } label: { - Text("Done") - } + ) + #endif + .background( + EmptyView().sheet(isPresented: $navigation.presentingHomeSettings) { + #if os(macOS) + VStack(alignment: .leading) { + Button("Done") { + navigation.presentingHomeSettings = false } + .padding() + .keyboardShortcut(.cancelAction) + + HomeSettings() + } + .frame(width: 500, height: 800) + #else + NavigationView { + HomeSettings() + #if os(iOS) + .toolbar { + ToolbarItem(placement: .navigation) { + Button { + navigation.presentingHomeSettings = false + } label: { + Text("Done") + } + } + } + #endif } #endif } - #endif - } - ) + ) #if !os(tvOS) - .fileImporter( - isPresented: $navigation.presentingFileImporter, - allowedContentTypes: [.audiovisualContent], - allowsMultipleSelection: true - ) { result in - do { - let selectedFiles = try result.get() - let urlsToOpen = selectedFiles.map { url in - if let bookmarkURL = URLBookmarkModel.shared.loadBookmark(url) { - return bookmarkURL + .fileImporter( + isPresented: $navigation.presentingFileImporter, + allowedContentTypes: [.audiovisualContent], + allowsMultipleSelection: true + ) { result in + do { + let selectedFiles = try result.get() + let urlsToOpen = selectedFiles.map { url in + if let bookmarkURL = URLBookmarkModel.shared.loadBookmark(url) { + return bookmarkURL + } + + if url.startAccessingSecurityScopedResource() { + URLBookmarkModel.shared.saveBookmark(url) + } + + return url + } + + OpenVideosModel.shared.openURLs(urlsToOpen) + } catch { + NavigationModel.shared.presentAlert(title: "Could not open Files") } - if url.startAccessingSecurityScopedResource() { - URLBookmarkModel.shared.saveBookmark(url) - } - - return url + NavigationModel.shared.presentingOpenVideos = false } - - OpenVideosModel.shared.openURLs(urlsToOpen) - } catch { - NavigationModel.shared.presentAlert(title: "Could not open Files") - } - - NavigationModel.shared.presentingOpenVideos = false - } - .background( - EmptyView().sheet(isPresented: $navigation.presentingAddToPlaylist) { - AddToPlaylistView(video: navigation.videoToAddToPlaylist) - } - ) - .background( - EmptyView().sheet(isPresented: $navigation.presentingPlaylistForm) { - PlaylistFormView(playlist: $navigation.editedPlaylist) - } - ) + .background( + EmptyView().sheet(isPresented: $navigation.presentingAddToPlaylist) { + AddToPlaylistView(video: navigation.videoToAddToPlaylist) + } + ) + .background( + EmptyView().sheet(isPresented: $navigation.presentingPlaylistForm) { + PlaylistFormView(playlist: $navigation.editedPlaylist) + } + ) #endif #if os(iOS) - .background( + .background( EmptyView().sheet(isPresented: $navigation.presentingPlaybackSettings) { PlaybackSettings() } diff --git a/Shared/Player/Controls/PlayerControls.swift b/Shared/Player/Controls/PlayerControls.swift index c00df64c..46f6df67 100644 --- a/Shared/Player/Controls/PlayerControls.swift +++ b/Shared/Player/Controls/PlayerControls.swift @@ -111,7 +111,7 @@ struct PlayerControls: View { } .offset(y: playerControlsLayout.osdVerticalOffset + 5) #if os(iOS) - .padding(.horizontal, Constants.isIPad && !Constants.isWindowFullscreen ? 10 : 0) + .padding(.horizontal, Constants.isIPad && !Constants.isWindowFullscreen ? 10 : 0) #endif Section { @@ -125,7 +125,7 @@ struct PlayerControls: View { } .font(.system(size: playerControlsLayout.bigButtonFontSize)) #if os(iOS) - .padding(.horizontal, Constants.isIPad && !Constants.isWindowFullscreen ? 10 : 0) + .padding(.horizontal, Constants.isIPad && !Constants.isWindowFullscreen ? 10 : 0) #endif #endif @@ -178,9 +178,9 @@ struct PlayerControls: View { .zIndex(1) .padding(.top, 2) #if os(iOS) - .padding(.horizontal, Constants.isIPad && !Constants.isWindowFullscreen ? 10 : 0) + .padding(.horizontal, Constants.isIPad && !Constants.isWindowFullscreen ? 10 : 0) #endif - .transition(.opacity) + .transition(.opacity) HStack(spacing: playerControlsLayout.buttonsSpacing) { #if os(tvOS) @@ -217,7 +217,7 @@ struct PlayerControls: View { #else .offset(y: -playerControlsLayout.timelineHeight - 5) #if os(iOS) - .padding(.horizontal, Constants.isIPad && !Constants.isWindowFullscreen ? 10 : 0) + .padding(.horizontal, Constants.isIPad && !Constants.isWindowFullscreen ? 10 : 0) #endif #endif } diff --git a/Shared/Player/Controls/VideoDetailsOverlay.swift b/Shared/Player/Controls/VideoDetailsOverlay.swift index aa00f3de..30849bb9 100644 --- a/Shared/Player/Controls/VideoDetailsOverlay.swift +++ b/Shared/Player/Controls/VideoDetailsOverlay.swift @@ -20,7 +20,7 @@ struct VideoDetailsOverlay: View { } #if os(iOS) - private var overlayLeadingPadding: CGFloat { + private var overlayLeadingPadding: Double { // On iPad in non-fullscreen mode, add left padding for system controls if Constants.isIPad && !Constants.isWindowFullscreen { return Constants.iPadSystemControlsWidth + 15 @@ -28,7 +28,7 @@ struct VideoDetailsOverlay: View { return 0 } #else - private var overlayLeadingPadding: CGFloat { + private var overlayLeadingPadding: Double { return 0 } #endif diff --git a/Shared/Player/MPV/MPVOGLView.swift b/Shared/Player/MPV/MPVOGLView.swift index b83887f1..26201260 100644 --- a/Shared/Player/MPV/MPVOGLView.swift +++ b/Shared/Player/MPV/MPVOGLView.swift @@ -140,7 +140,7 @@ final class MPVOGLView: GLKView { glGetIntegerv(UInt32(GL_FRAMEBUFFER_BINDING), &defaultFBO!) // Ensure the framebuffer is valid - guard defaultFBO != nil && defaultFBO! != 0 else { + guard defaultFBO != nil, defaultFBO! != 0 else { logger.error("Invalid framebuffer ID.") return } diff --git a/Shared/Player/PlaybackSettings.swift b/Shared/Player/PlaybackSettings.swift index d4f64ec5..09bf0054 100644 --- a/Shared/Player/PlaybackSettings.swift +++ b/Shared/Player/PlaybackSettings.swift @@ -64,10 +64,10 @@ struct PlaybackSettings: View { .padding(.vertical, 10) if player.activeBackend == .mpv || !player.avPlayerUsesSystemControls { - HStack(alignment: .center) { + HStack { controlsHeader("Rate".localized()) Spacer() - HStack(alignment: .center, spacing: rateButtonsSpacing) { + HStack(spacing: rateButtonsSpacing) { decreaseRateButton #if os(tvOS) .focused($focusedField, equals: .decreaseRate) @@ -243,18 +243,18 @@ struct PlaybackSettings: View { } } label: { #if os(macOS) - Image(systemName: "plus") - .imageScale(.large) - .frame(width: 16, height: 16) + Image(systemName: "plus") + .imageScale(.large) + .frame(width: 16, height: 16) #else - Label("Increase rate", systemImage: "plus") - .imageScale(.large) - .labelStyle(.iconOnly) - .foregroundColor(.accentColor) - .padding(12) - .frame(width: 40, height: 40) - .background(RoundedRectangle(cornerRadius: 4).strokeBorder(Color.accentColor, lineWidth: 1)) - .contentShape(Rectangle()) + Label("Increase rate", systemImage: "plus") + .imageScale(.large) + .labelStyle(.iconOnly) + .foregroundColor(.accentColor) + .padding(12) + .frame(width: 40, height: 40) + .background(RoundedRectangle(cornerRadius: 4).strokeBorder(Color.accentColor, lineWidth: 1)) + .contentShape(Rectangle()) #endif } #if os(macOS) @@ -280,18 +280,18 @@ struct PlaybackSettings: View { } } label: { #if os(macOS) - Image(systemName: "minus") - .imageScale(.large) - .frame(width: 16, height: 16) + Image(systemName: "minus") + .imageScale(.large) + .frame(width: 16, height: 16) #else - Label("Decrease rate", systemImage: "minus") - .imageScale(.large) - .labelStyle(.iconOnly) - .foregroundColor(.accentColor) - .padding(12) - .frame(width: 40, height: 40) - .background(RoundedRectangle(cornerRadius: 4).strokeBorder(Color.accentColor, lineWidth: 1)) - .contentShape(Rectangle()) + Label("Decrease rate", systemImage: "minus") + .imageScale(.large) + .labelStyle(.iconOnly) + .foregroundColor(.accentColor) + .padding(12) + .frame(width: 40, height: 40) + .background(RoundedRectangle(cornerRadius: 4).strokeBorder(Color.accentColor, lineWidth: 1)) + .contentShape(Rectangle()) #endif } #if os(macOS) diff --git a/Shared/Player/PlayerLayerView.swift b/Shared/Player/PlayerLayerView.swift index 7f19f269..7cc06945 100644 --- a/Shared/Player/PlayerLayerView.swift +++ b/Shared/Player/PlayerLayerView.swift @@ -16,7 +16,7 @@ import Foundation player.avPlayerBackend.playerLayer } - override init(frame frameRect: NSRect) { + override init(frame frameRect: CGRect) { super.init(frame: frameRect) wantsLayer = true } diff --git a/Shared/Player/StreamControl.swift b/Shared/Player/StreamControl.swift index 9e8d4fdf..659bb5e4 100644 --- a/Shared/Player/StreamControl.swift +++ b/Shared/Player/StreamControl.swift @@ -21,10 +21,10 @@ struct StreamControl: View { ForEach(kinds, id: \.self) { key in ForEach(availableStreamsByKind[key] ?? []) { stream in Text(stream.description) - #if os(macOS) + #if os(macOS) .lineLimit(1) .truncationMode(.middle) - #endif + #endif .tag(Stream?.some(stream)) } diff --git a/Shared/Player/Video Details/CommentView.swift b/Shared/Player/Video Details/CommentView.swift index 70b49894..1058ffae 100644 --- a/Shared/Player/Video Details/CommentView.swift +++ b/Shared/Player/Video Details/CommentView.swift @@ -256,11 +256,7 @@ struct CommentView: View { #if os(macOS) struct TextSelectionModifier: ViewModifier { func body(content: Content) -> some View { - if #available(macOS 12.0, *) { - content.textSelection(.enabled) - } else { - content - } + content.textSelection(.enabled) } } #endif diff --git a/Shared/Player/Video Details/VideoDescription.swift b/Shared/Player/Video Details/VideoDescription.swift index 7335e528..737ee929 100644 --- a/Shared/Player/Video Details/VideoDescription.swift +++ b/Shared/Player/Video Details/VideoDescription.swift @@ -58,30 +58,19 @@ struct VideoDescription: View { @ViewBuilder var textDescription: some View { #if canImport(AppKit) - if #available(macOS 12.0, *) { - DescriptionWithLinks(description: description, detailsSize: detailsSize) - .frame(maxWidth: .infinity, alignment: .leading) - .lineLimit(expand ? 500 : collapsedLinesDescription) - .textSelection(.enabled) - .multilineTextAlignment(.leading) - .font(.system(size: 14)) - .lineSpacing(3) - .allowsHitTesting(expand) - } else { - Text(description) - .frame(maxWidth: .infinity, alignment: .leading) - .lineLimit(expand ? 500 : collapsedLinesDescription) - .multilineTextAlignment(.leading) - .font(.system(size: 14)) - .lineSpacing(3) - .allowsHitTesting(expand) - } + DescriptionWithLinks(description: description, detailsSize: detailsSize) + .frame(maxWidth: .infinity, alignment: .leading) + .lineLimit(expand ? 500 : collapsedLinesDescription) + .textSelection(.enabled) + .multilineTextAlignment(.leading) + .font(.system(size: 14)) + .lineSpacing(3) + .allowsHitTesting(expand) #endif } // If possibe convert URLs to clickable links #if canImport(AppKit) - @available(macOS 12.0, *) struct DescriptionWithLinks: View { let description: String let detailsSize: CGSize? diff --git a/Shared/Player/VideoPlayerView.swift b/Shared/Player/VideoPlayerView.swift index e9811650..4ec4d19a 100644 --- a/Shared/Player/VideoPlayerView.swift +++ b/Shared/Player/VideoPlayerView.swift @@ -314,17 +314,17 @@ struct VideoPlayerView: View { ) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) #if os(macOS) - // TODO: Check whether this is needed on macOS. - .onDisappear { - if player.presentingPlayer { - player.setNeedsDrawing(true) + // TODO: Check whether this is needed on macOS. + .onDisappear { + if player.presentingPlayer { + player.setNeedsDrawing(true) + } } - } #endif - .id(player.currentVideo?.cacheKey) - .transition(.opacity) - .offset(y: detailViewDragOffset) - .gesture(detailsDragGesture) + .id(player.currentVideo?.cacheKey) + .transition(.opacity) + .offset(y: detailViewDragOffset) + .gesture(detailsDragGesture) } else { VStack {} } diff --git a/Shared/Playlists/PlaylistsView.swift b/Shared/Playlists/PlaylistsView.swift index f093edf3..9f927ee1 100644 --- a/Shared/Playlists/PlaylistsView.swift +++ b/Shared/Playlists/PlaylistsView.swift @@ -151,9 +151,9 @@ struct PlaylistsView: View { } #else .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in - model.load() - loadResource() - } + model.load() + loadResource() + } #endif #if !os(tvOS) .background( diff --git a/Shared/Search/SearchView.swift b/Shared/Search/SearchView.swift index 290c3249..c15214ba 100644 --- a/Shared/Search/SearchView.swift +++ b/Shared/Search/SearchView.swift @@ -648,23 +648,23 @@ struct SearchView: View { } #if os(iOS) - private func searchFieldWidth(_ viewWidth: Double) -> Double { - // Base padding for internal SearchTextField padding (16pt each side = 32 total) - var totalDeduction: Double = 32 + private func searchFieldWidth(_ viewWidth: Double) -> Double { + // Base padding for internal SearchTextField padding (16pt each side = 32 total) + var totalDeduction: Double = 32 - // Add space for trailing menu button - totalDeduction += 44 - - // Add space for sidebar toggle button if in sidebar navigation style - if navigationStyle == .sidebar { + // Add space for trailing menu button totalDeduction += 44 + + // Add space for sidebar toggle button if in sidebar navigation style + if navigationStyle == .sidebar { + totalDeduction += 44 + } + + // Minimum width to ensure usability + let minWidth: Double = 200 + + return max(minWidth, viewWidth - totalDeduction) } - - // Minimum width to ensure usability - let minWidth: Double = 200 - - return max(minWidth, viewWidth - totalDeduction) - } #endif var shouldDisplayHeader: Bool { diff --git a/Shared/Settings/PlayerControlsSettings.swift b/Shared/Settings/PlayerControlsSettings.swift index ffbed612..36f50ec8 100644 --- a/Shared/Settings/PlayerControlsSettings.swift +++ b/Shared/Settings/PlayerControlsSettings.swift @@ -151,52 +151,52 @@ struct PlayerControlsSettings: View { } #if os(tvOS) - // Custom implementation for tvOS to avoid focus overlay - return VStack(alignment: .leading, spacing: 0) { - Text("System controls buttons") - .font(.headline) - .padding(.vertical, 8) + // Custom implementation for tvOS to avoid focus overlay + return VStack(alignment: .leading, spacing: 0) { + Text("System controls buttons") + .font(.headline) + .padding(.vertical, 8) - Button(action: { systemControlsCommands = .seek }) { - HStack { - Text(labelText("Seek".localized())) - Spacer() - if systemControlsCommands == .seek { - Image(systemName: "checkmark") - .foregroundColor(.accentColor) + Button(action: { systemControlsCommands = .seek }) { + HStack { + Text(labelText("Seek".localized())) + Spacer() + if systemControlsCommands == .seek { + Image(systemName: "checkmark") + .foregroundColor(.accentColor) + } } + .contentShape(Rectangle()) } - .contentShape(Rectangle()) - } - .buttonStyle(.plain) - .padding(.vertical, 4) + .buttonStyle(.plain) + .padding(.vertical, 4) - Button(action: { - systemControlsCommands = .restartAndAdvanceToNext - player.updateRemoteCommandCenter() - }) { - HStack { - Text(labelText("Restart/Play next".localized())) - Spacer() - if systemControlsCommands == .restartAndAdvanceToNext { - Image(systemName: "checkmark") - .foregroundColor(.accentColor) + Button(action: { + systemControlsCommands = .restartAndAdvanceToNext + player.updateRemoteCommandCenter() + }) { + HStack { + Text(labelText("Restart/Play next".localized())) + Spacer() + if systemControlsCommands == .restartAndAdvanceToNext { + Image(systemName: "checkmark") + .foregroundColor(.accentColor) + } } + .contentShape(Rectangle()) } - .contentShape(Rectangle()) + .buttonStyle(.plain) + .padding(.vertical, 4) } - .buttonStyle(.plain) - .padding(.vertical, 4) - } #else - return Picker("System controls buttons", selection: $systemControlsCommands) { - Text(labelText("Seek".localized())).tag(SystemControlsCommands.seek) - Text(labelText("Restart/Play next".localized())).tag(SystemControlsCommands.restartAndAdvanceToNext) - } - .onChange(of: systemControlsCommands) { _ in - player.updateRemoteCommandCenter() - } - .modifier(SettingsPickerModifier()) + return Picker("System controls buttons", selection: $systemControlsCommands) { + Text(labelText("Seek".localized())).tag(SystemControlsCommands.seek) + Text(labelText("Restart/Play next".localized())).tag(SystemControlsCommands.restartAndAdvanceToNext) + } + .onChange(of: systemControlsCommands) { _ in + player.updateRemoteCommandCenter() + } + .modifier(SettingsPickerModifier()) #endif } diff --git a/Shared/Settings/QualityProfileForm.swift b/Shared/Settings/QualityProfileForm.swift index a4a73552..30a58e7e 100644 --- a/Shared/Settings/QualityProfileForm.swift +++ b/Shared/Settings/QualityProfileForm.swift @@ -242,11 +242,7 @@ struct QualityProfileForm: View { #if os(macOS) let list = filteredFormatList - if #available(macOS 12.0, *) { - list.listStyle(.inset(alternatesRowBackgrounds: true)) - } else { - list.listStyle(.inset) - } + list.listStyle(.inset(alternatesRowBackgrounds: true)) Spacer() #else filteredFormatList diff --git a/Shared/Settings/QualitySettings.swift b/Shared/Settings/QualitySettings.swift index 1ab182d4..98715e17 100644 --- a/Shared/Settings/QualitySettings.swift +++ b/Shared/Settings/QualitySettings.swift @@ -183,17 +183,10 @@ struct QualitySettings: View { } #if os(macOS) - if #available(macOS 12.0, *) { - List { - list - } - .listStyle(.inset(alternatesRowBackgrounds: true)) - } else { - List { - list - } - .listStyle(.inset) + List { + list } + .listStyle(.inset(alternatesRowBackgrounds: true)) #else list #endif diff --git a/Shared/Settings/TVOSPlainToggleStyle.swift b/Shared/Settings/TVOSPlainToggleStyle.swift index 2c88a43d..aa666486 100644 --- a/Shared/Settings/TVOSPlainToggleStyle.swift +++ b/Shared/Settings/TVOSPlainToggleStyle.swift @@ -1,17 +1,17 @@ import SwiftUI #if os(tvOS) -struct TVOSPlainToggleStyle: ToggleStyle { - func makeBody(configuration: Configuration) -> some View { - Button(action: { configuration.isOn.toggle() }) { - HStack { - configuration.label - Spacer() - Image(systemName: configuration.isOn ? "checkmark.circle.fill" : "circle") - .foregroundColor(configuration.isOn ? .accentColor : .secondary) + struct TVOSPlainToggleStyle: ToggleStyle { + func makeBody(configuration: Configuration) -> some View { + Button(action: { configuration.isOn.toggle() }) { + HStack { + configuration.label + Spacer() + Image(systemName: configuration.isOn ? "checkmark.circle.fill" : "circle") + .foregroundColor(configuration.isOn ? .accentColor : .secondary) + } } + .buttonStyle(.plain) } - .buttonStyle(.plain) } -} #endif diff --git a/Shared/Subscriptions/ChannelsView.swift b/Shared/Subscriptions/ChannelsView.swift index b60172e3..b0b22702 100644 --- a/Shared/Subscriptions/ChannelsView.swift +++ b/Shared/Subscriptions/ChannelsView.swift @@ -188,19 +188,19 @@ struct ChannelsView: View { } #if os(iOS) -struct CompactListRowModifier: ViewModifier { - func body(content: Content) -> some View { - // swiftlint:disable:next deployment_target - if #available(iOS 15.0, *) { - content - .listRowSpacing(0) - .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)) - } else { - content - .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)) + struct CompactListRowModifier: ViewModifier { + func body(content: Content) -> some View { + // swiftlint:disable:next deployment_target + if #available(iOS 15.0, *) { + content + .listRowSpacing(0) + .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)) + } else { + content + .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)) + } } } -} #endif struct ChannelsView_Previews: PreviewProvider { diff --git a/Shared/Subscriptions/FeedView.swift b/Shared/Subscriptions/FeedView.swift index ed748270..da3a8423 100644 --- a/Shared/Subscriptions/FeedView.swift +++ b/Shared/Subscriptions/FeedView.swift @@ -111,76 +111,76 @@ struct FeedView: View { Text("Channels") .font(.subheadline) List(selection: $selectedChannel) { + Button(action: { + self.selectedChannel = nil + self.feedChannelsViewVisible = false + }) { + HStack(spacing: 16) { + Image(systemName: RecentsModel.symbolSystemImage("A")) + .imageScale(.large) + .foregroundColor(.accentColor) + .frame(width: 35, height: 35) + Text("All") + Spacer() + feedCount.unwatchedText + } + } + .padding(.all) + .background(RoundedRectangle(cornerRadius: 8.0) + .fill(self.selectedChannel == nil ? Color.secondary : Color.clear)) + .font(.caption) + .buttonStyle(PlainButtonStyle()) + .focused(self.$focusedChannel, equals: "all") + + ForEach(channels, id: \.self) { channel in Button(action: { - self.selectedChannel = nil + self.selectedChannel = channel self.feedChannelsViewVisible = false }) { HStack(spacing: 16) { - Image(systemName: RecentsModel.symbolSystemImage("A")) - .imageScale(.large) - .foregroundColor(.accentColor) - .frame(width: 35, height: 35) - Text("All") + ChannelAvatarView(channel: channel, subscribedBadge: false) + .frame(width: 50, height: 50) + Text(channel.name) + .lineLimit(1) Spacer() - feedCount.unwatchedText + if let unwatchedCount = feedCount.unwatchedByChannelText(channel) { + unwatchedCount + } } } .padding(.all) .background(RoundedRectangle(cornerRadius: 8.0) - .fill(self.selectedChannel == nil ? Color.secondary : Color.clear)) + .fill(self.selectedChannel == channel ? Color.secondary : Color.clear)) .font(.caption) .buttonStyle(PlainButtonStyle()) - .focused(self.$focusedChannel, equals: "all") - - ForEach(channels, id: \.self) { channel in - Button(action: { - self.selectedChannel = channel - self.feedChannelsViewVisible = false - }) { - HStack(spacing: 16) { - ChannelAvatarView(channel: channel, subscribedBadge: false) - .frame(width: 50, height: 50) - Text(channel.name) - .lineLimit(1) - Spacer() - if let unwatchedCount = feedCount.unwatchedByChannelText(channel) { - unwatchedCount - } - } - } - .padding(.all) - .background(RoundedRectangle(cornerRadius: 8.0) - .fill(self.selectedChannel == channel ? Color.secondary : Color.clear)) - .font(.caption) - .buttonStyle(PlainButtonStyle()) - .focused(self.$focusedChannel, equals: channel.id) - } + .focused(self.$focusedChannel, equals: channel.id) + } } .onChange(of: self.focusedChannel) { _ in - if self.focusedChannel == "all" { - withAnimation { - self.selectedChannel = nil - } - } else if self.focusedChannel == dismiss_channel_list_id { - self.feedChannelsViewVisible = false - } else { - withAnimation { - self.selectedChannel = channels.first { - $0.id == self.focusedChannel - } + if self.focusedChannel == "all" { + withAnimation { + self.selectedChannel = nil + } + } else if self.focusedChannel == dismiss_channel_list_id { + self.feedChannelsViewVisible = false + } else { + withAnimation { + self.selectedChannel = channels.first { + $0.id == self.focusedChannel } } + } } .onAppear { - guard let selectedChannel = self.selectedChannel else { - return - } - proxy.scrollTo(selectedChannel, anchor: .top) + guard let selectedChannel = self.selectedChannel else { + return + } + proxy.scrollTo(selectedChannel, anchor: .top) } .onExitCommand { - withAnimation { - self.feedChannelsViewVisible = false - } + withAnimation { + self.feedChannelsViewVisible = false + } } } } @@ -216,44 +216,28 @@ struct FeedView: View { #if !os(macOS) .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in feed.loadResources() - } + } #endif } var header: some View { HStack(spacing: 16) { #if os(tvOS) - if #available(tvOS 17.0, *) { - Menu { - accountsPicker - } label: { - Label("Channels", systemImage: "filemenu.and.selection") - .labelStyle(.iconOnly) - .imageScale(.small) - .font(.caption) - } primaryAction: { - withAnimation { - self.feedChannelsViewVisible = true - self.focusedChannel = selectedChannel?.id ?? "all" - } + Menu { + accountsPicker + } label: { + Label("Channels", systemImage: "filemenu.and.selection") + .labelStyle(.iconOnly) + .imageScale(.small) + .font(.caption) + } primaryAction: { + withAnimation { + self.feedChannelsViewVisible = true + self.focusedChannel = selectedChannel?.id ?? "all" } - .opacity(feedChannelsViewVisible ? 0 : 1) - .frame(minWidth: feedChannelsViewVisible ? 0 : nil, maxWidth: feedChannelsViewVisible ? 0 : nil) - } else { - Button { - withAnimation { - self.feedChannelsViewVisible = true - self.focusedChannel = selectedChannel?.id ?? "all" - } - } label: { - Label("Channels", systemImage: "filemenu.and.selection") - .labelStyle(.iconOnly) - .imageScale(.small) - .font(.caption) - } - .opacity(feedChannelsViewVisible ? 0 : 1) - .frame(minWidth: feedChannelsViewVisible ? 0 : nil, maxWidth: feedChannelsViewVisible ? 0 : nil) } + .opacity(feedChannelsViewVisible ? 0 : 1) + .frame(minWidth: feedChannelsViewVisible ? 0 : nil, maxWidth: feedChannelsViewVisible ? 0 : nil) channelHeaderView if selectedChannel == nil { Spacer() diff --git a/Shared/Trending/TrendingCountry.swift b/Shared/Trending/TrendingCountry.swift index f2c4fda1..b69c56fb 100644 --- a/Shared/Trending/TrendingCountry.swift +++ b/Shared/Trending/TrendingCountry.swift @@ -58,11 +58,7 @@ struct TrendingCountry: View { return Group { #if os(macOS) - if #available(macOS 12.0, *) { - list.listStyle(.inset(alternatesRowBackgrounds: true)) - } else { - list.listStyle(.inset) - } + list.listStyle(.inset(alternatesRowBackgrounds: true)) #else list #endif diff --git a/Shared/Trending/TrendingView.swift b/Shared/Trending/TrendingView.swift index afe2f2e8..73d15135 100644 --- a/Shared/Trending/TrendingView.swift +++ b/Shared/Trending/TrendingView.swift @@ -78,12 +78,12 @@ struct TrendingView: View { } #else .sheet(isPresented: $presentingCountrySelection) { - TrendingCountry(selectedCountry: $country) - #if os(macOS) - .frame(minWidth: 400, minHeight: 400) - #endif - } - .background( + TrendingCountry(selectedCountry: $country) + #if os(macOS) + .frame(minWidth: 400, minHeight: 400) + #endif + } + .background( Button("Refresh") { resource.load() .onFailure { self.error = $0 } @@ -131,10 +131,10 @@ struct TrendingView: View { } #else .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in - resource.loadIfNeeded()? - .onFailure { self.error = $0 } - .onSuccess { _ in self.error = nil } - } + resource.loadIfNeeded()? + .onFailure { self.error = $0 } + .onSuccess { _ in self.error = nil } + } #endif } diff --git a/Shared/Videos/ThumbnailView.swift b/Shared/Videos/ThumbnailView.swift index 26e77a4a..cb82ce6f 100644 --- a/Shared/Videos/ThumbnailView.swift +++ b/Shared/Videos/ThumbnailView.swift @@ -9,7 +9,7 @@ struct ThumbnailView: View { init(url: URL?) { self.url = url - self.thumbnailExtension = Self.extractExtension(from: url) + thumbnailExtension = Self.extractExtension(from: url) } private static func extractExtension(from url: URL?) -> String? { diff --git a/Shared/Videos/VerticalCells.swift b/Shared/Videos/VerticalCells.swift index aa8e3614..6e633925 100644 --- a/Shared/Videos/VerticalCells.swift +++ b/Shared/Videos/VerticalCells.swift @@ -54,8 +54,8 @@ struct VerticalCells: View { .edgesIgnoringSafeArea(navigationStyle == .sidebar ? [] : edgesIgnoringSafeArea) #endif #if os(macOS) - .background(Color.secondaryBackground) - .frame(minWidth: Constants.contentViewMinWidth) + .background(Color.secondaryBackground) + .frame(minWidth: Constants.contentViewMinWidth) #endif } diff --git a/Shared/Views/ControlsBar.swift b/Shared/Views/ControlsBar.swift index ed78e63c..425d2880 100644 --- a/Shared/Views/ControlsBar.swift +++ b/Shared/Views/ControlsBar.swift @@ -341,6 +341,7 @@ struct ControlsBar_Previews: PreviewProvider { } // MARK: - View Extension for Conditional Modifiers + extension View { @ViewBuilder func `if`(_ condition: Bool, transform: (Self) -> Transform) -> some View { @@ -355,16 +356,40 @@ extension View { func applyControlsBackground(enabled: Bool, cornerRadius: Double) -> some View { if enabled { #if os(iOS) - if #available(iOS 26.0, *) { - // Use Liquid Glass on iOS 26+ - self.glassEffect( - .regular.interactive(), - in: .rect(cornerRadius: cornerRadius) - ) - } else { - // Fallback to ultraThinMaterial + if #available(iOS 26.0, *) { + // Use Liquid Glass on iOS 26+ + self.glassEffect( + .regular.interactive(), + in: .rect(cornerRadius: cornerRadius) + ) + } else { + // Fallback to ultraThinMaterial + // swiftlint:disable:next deployment_target + if #available(iOS 15.0, *) { + self + .background( + RoundedRectangle(cornerRadius: cornerRadius) + .fill(.ultraThinMaterial) + ) + .overlay( + RoundedRectangle(cornerRadius: cornerRadius) + .stroke(Color("ControlsBorderColor"), lineWidth: 0.5) + ) + } else { + background( + RoundedRectangle(cornerRadius: cornerRadius) + .fill(Color.gray.opacity(0.3)) + ) + .overlay( + RoundedRectangle(cornerRadius: cornerRadius) + .stroke(Color("ControlsBorderColor"), lineWidth: 0.5) + ) + } + } + #else + // Fallback to ultraThinMaterial for macOS and tvOS // swiftlint:disable:next deployment_target - if #available(iOS 15.0, *) { + if #available(macOS 12.0, tvOS 15.0, *) { self .background( RoundedRectangle(cornerRadius: cornerRadius) @@ -375,33 +400,7 @@ extension View { .stroke(Color("ControlsBorderColor"), lineWidth: 0.5) ) } else { - self - .background( - RoundedRectangle(cornerRadius: cornerRadius) - .fill(Color.gray.opacity(0.3)) - ) - .overlay( - RoundedRectangle(cornerRadius: cornerRadius) - .stroke(Color("ControlsBorderColor"), lineWidth: 0.5) - ) - } - } - #else - // Fallback to ultraThinMaterial for macOS and tvOS - // swiftlint:disable:next deployment_target - if #available(macOS 12.0, tvOS 15.0, *) { - self - .background( - RoundedRectangle(cornerRadius: cornerRadius) - .fill(.ultraThinMaterial) - ) - .overlay( - RoundedRectangle(cornerRadius: cornerRadius) - .stroke(Color("ControlsBorderColor"), lineWidth: 0.5) - ) - } else { - self - .background( + background( RoundedRectangle(cornerRadius: cornerRadius) .fill(Color.gray.opacity(0.3)) ) @@ -409,10 +408,10 @@ extension View { RoundedRectangle(cornerRadius: cornerRadius) .stroke(Color("ControlsBorderColor"), lineWidth: 0.5) ) - } + } #endif } else { - self.background(Color.clear) + background(Color.clear) } } } diff --git a/Shared/Views/PopularView.swift b/Shared/Views/PopularView.swift index a1b427b4..df782c4e 100644 --- a/Shared/Views/PopularView.swift +++ b/Shared/Views/PopularView.swift @@ -81,10 +81,10 @@ struct PopularView: View { } #else .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in - resource?.loadIfNeeded()? - .onFailure { self.error = $0 } - .onSuccess { _ in self.error = nil } - } + resource?.loadIfNeeded()? + .onFailure { self.error = $0 } + .onSuccess { _ in self.error = nil } + } #endif } diff --git a/Shared/Views/SettingsPickerModifier.swift b/Shared/Views/SettingsPickerModifier.swift index e0e8c6e6..e9a5e2b2 100644 --- a/Shared/Views/SettingsPickerModifier.swift +++ b/Shared/Views/SettingsPickerModifier.swift @@ -4,28 +4,28 @@ import SwiftUI struct SettingsPickerModifier: ViewModifier { func body(content: Content) -> some View { #if os(tvOS) - content - .pickerStyle(.inline) - .onAppear { - // Force refresh to apply button style to picker options - } + content + .pickerStyle(.inline) + .onAppear { + // Force refresh to apply button style to picker options + } #elseif os(iOS) - content - .pickerStyle(.automatic) + content + .pickerStyle(.automatic) #else - content - .labelsHidden() - .pickerStyle(.menu) + content + .labelsHidden() + .pickerStyle(.menu) #endif } } #if os(tvOS) -// Extension to help remove picker row backgrounds -extension View { - func pickerRowStyle() -> some View { - self.buttonStyle(.plain) - .listRowBackground(Color.clear) + // Extension to help remove picker row backgrounds + extension View { + func pickerRowStyle() -> some View { + buttonStyle(.plain) + .listRowBackground(Color.clear) + } } -} #endif diff --git a/Shared/YatteeApp.swift b/Shared/YatteeApp.swift index a49aca3a..a072d909 100644 --- a/Shared/YatteeApp.swift +++ b/Shared/YatteeApp.swift @@ -73,15 +73,15 @@ struct YatteeApp: App { ) #else .onReceive( - NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification) - ) { _ in - player.handleEnterForeground() - } - .onReceive( - NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification) - ) { _ in - player.handleEnterBackground() - } + NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification) + ) { _ in + player.handleEnterForeground() + } + .onReceive( + NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification) + ) { _ in + player.handleEnterBackground() + } #endif #if os(iOS) .handlesExternalEvents(preferring: Set(["*"]), allowing: Set(["*"])) diff --git a/macOS/InstancesSettings.swift b/macOS/InstancesSettings.swift index 2ea61445..748d1fe0 100644 --- a/macOS/InstancesSettings.swift +++ b/macOS/InstancesSettings.swift @@ -71,11 +71,7 @@ struct InstancesSettings: View { } } - if #available(macOS 12.0, *) { - list.listStyle(.inset(alternatesRowBackgrounds: true)) - } else { - list.listStyle(.inset) - } + list.listStyle(.inset(alternatesRowBackgrounds: true)) } if selectedInstance != nil, selectedInstance.app.hasFrontendURL { diff --git a/macOS/VideoLayer.swift b/macOS/VideoLayer.swift index 6ee3caa8..c24bb6fe 100644 --- a/macOS/VideoLayer.swift +++ b/macOS/VideoLayer.swift @@ -37,7 +37,7 @@ final class VideoLayer: CAOpenGLLayer { displayTime _: UnsafePointer? ) { needsRedraw = false - + var i: GLint = 0 var flip: CInt = 1 var ditherDepth = 8 @@ -103,7 +103,7 @@ final class VideoLayer: CAOpenGLLayer { needsRedraw = true super.display() } - + func requestRedraw() { // Called from MPV's glUpdate callback - use setNeedsDisplay for efficient batching DispatchQueue.main.async { [weak self] in