From 64171a9cfb79343441b475efa5fa959e71f6215b Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Thu, 21 May 2026 18:19:19 +0200 Subject: [PATCH] Add explicit sizing to sheets on macOS Give player, download, source, and login sheets minimum frame dimensions on macOS so they open at a usable size instead of collapsing. --- Yattee/Localizable.xcstrings | 309 +++++++++--------- Yattee/Views/Player/PlayerHelperViews.swift | 3 + Yattee/Views/Player/QualitySelectorView.swift | 5 + .../Views/Player/QueueManagementSheet.swift | 5 + .../Playlist/BatchDownloadQualitySheet.swift | 5 + Yattee/Views/Settings/EditSourceView.swift | 3 + Yattee/Views/Settings/InstanceLoginView.swift | 3 + .../Settings/NetworkShareDiscoverySheet.swift | 3 + Yattee/Views/Video/DownloadQualitySheet.swift | 5 + Yattee/Views/Video/VideoInfoView.swift | 3 + 10 files changed, 197 insertions(+), 147 deletions(-) diff --git a/Yattee/Localizable.xcstrings b/Yattee/Localizable.xcstrings index ea0a6cfe..73a143b8 100644 --- a/Yattee/Localizable.xcstrings +++ b/Yattee/Localizable.xcstrings @@ -139,16 +139,6 @@ }, "1.2M subscribers" : { - }, - "alert.ambiguousLink.title" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Open Link" - } - } - } }, "alert.ambiguousLink.message %@" : { "localizations" : { @@ -160,16 +150,6 @@ } } }, - "alert.ambiguousLink.tryInYattee" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Try in Yattee" - } - } - } - }, "alert.ambiguousLink.openInBrowser" : { "localizations" : { "en" : { @@ -180,6 +160,26 @@ } } }, + "alert.ambiguousLink.title" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open Link" + } + } + } + }, + "alert.ambiguousLink.tryInYattee" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Try in Yattee" + } + } + } + }, "alert.openVideo.message %@" : { "localizations" : { "en" : { @@ -200,16 +200,6 @@ } } }, - "alert.resolvedShortLink.title" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Open Link" - } - } - } - }, "alert.resolvedShortLink.message %@" : { "localizations" : { "en" : { @@ -220,6 +210,16 @@ } } }, + "alert.resolvedShortLink.openInBrowser" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open in Browser" + } + } + } + }, "alert.resolvedShortLink.openInYattee" : { "localizations" : { "en" : { @@ -230,12 +230,12 @@ } } }, - "alert.resolvedShortLink.openInBrowser" : { + "alert.resolvedShortLink.title" : { "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "Open in Browser" + "value" : "Open Link" } } } @@ -5684,6 +5684,7 @@ }, "migration.accountsHint" : { "comment" : "Hint about needing to re-add accounts after migration", + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5694,6 +5695,7 @@ } }, "migration.continue" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5704,6 +5706,7 @@ } }, "migration.error.invalidURL" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5714,6 +5717,7 @@ } }, "migration.failedItems" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5745,6 +5749,7 @@ }, "migration.noDataFound" : { "comment" : "Title when no legacy data found", + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5756,6 +5761,7 @@ }, "migration.noDataFoundDescription" : { "comment" : "Description when no legacy data found", + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5767,6 +5773,7 @@ }, "migration.partialMessage %lld %lld" : { "comment" : "Import result count", + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5777,6 +5784,7 @@ } }, "migration.partialTitle" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5787,6 +5795,7 @@ } }, "migration.retry" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5797,6 +5806,7 @@ } }, "migration.selectToImport" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5808,6 +5818,7 @@ }, "migration.settingsFooter" : { "comment" : "Footer text in settings migration view", + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5891,6 +5902,7 @@ } }, "migration.unreachableImport" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5901,6 +5913,7 @@ } }, "migration.unreachableMessage" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -5911,6 +5924,7 @@ } }, "migration.unreachableTitle" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -8979,6 +8993,7 @@ }, "settings.advanced.data.importLegacy" : { "comment" : "Button label for importing legacy v1 data", + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -12552,6 +12567,68 @@ } } }, + "settings.playback.tvAudioDelay" : { + "comment" : "Audio delay stepper label (tvOS only)", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Audio Delay" + } + } + } + }, + "settings.playback.tvAudioDelay.minus10" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "−10 ms" + } + } + } + }, + "settings.playback.tvAudioDelay.minus100" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "−100 ms" + } + } + } + }, + "settings.playback.tvAudioDelay.plus10" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "+10 ms" + } + } + } + }, + "settings.playback.tvAudioDelay.plus100" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "+100 ms" + } + } + } + }, + "settings.playback.tvAudioDelay.reset" : { + "comment" : "Reset audio delay button label (tvOS only)", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reset" + } + } + } + }, "settings.playback.tvDisplayMatching.dynamicRange" : { "comment" : "Toggle label (tvOS only)", "localizations" : { @@ -12594,64 +12671,32 @@ } } }, - "settings.playback.tvAudioDelay" : { - "comment" : "Audio delay stepper label (tvOS only)", + "settings.playback.tvOSMenuButtonClosesVideo" : { "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "Audio Delay" + "value" : "Menu Button Closes Video" } } } }, - "settings.playback.tvAudioDelay.minus100" : { + "settings.playback.tvOSMenuButtonClosesVideo.footer" : { "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "−100 ms" + "value" : "When enabled, the Siri remote Menu button stops playback and clears the queue. The close (X) button is hidden from the player. When disabled, Menu collapses the player and playback continues in the background." } } } }, - "settings.playback.tvAudioDelay.minus10" : { + "settings.playback.tvSyncDiagnostics.footer" : { "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "−10 ms" - } - } - } - }, - "settings.playback.tvAudioDelay.plus10" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "+10 ms" - } - } - } - }, - "settings.playback.tvAudioDelay.plus100" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "+100 ms" - } - } - } - }, - "settings.playback.tvAudioDelay.reset" : { - "comment" : "Reset audio delay button label (tvOS only)", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Reset" + "value" : "Audio Delay shifts audio relative to video to compensate for fixed HDMI/AVR output lag (positive = audio later). Video Sync Mode changes how MPV reconciles video frames with display refresh; the default is recommended unless you are debugging." } } } @@ -12677,16 +12722,6 @@ } } }, - "settings.playback.tvSyncDiagnostics.footer" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Audio Delay shifts audio relative to video to compensate for fixed HDMI/AVR output lag (positive = audio later). Video Sync Mode changes how MPV reconciles video frames with display refresh; the default is recommended unless you are debugging." - } - } - } - }, "settings.playback.tvVideoSyncMode" : { "comment" : "Picker label (tvOS only)", "localizations" : { @@ -12698,26 +12733,6 @@ } } }, - "settings.playback.tvVideoSyncMode.displayVdrop" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Display (drop/repeat) — default" - } - } - } - }, - "settings.playback.tvVideoSyncMode.displayResample" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Display (resample audio)" - } - } - } - }, "settings.playback.tvVideoSyncMode.audio" : { "localizations" : { "en" : { @@ -12728,22 +12743,22 @@ } } }, - "settings.playback.tvOSMenuButtonClosesVideo" : { + "settings.playback.tvVideoSyncMode.displayResample" : { "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "Menu Button Closes Video" + "value" : "Display (resample audio)" } } } }, - "settings.playback.tvOSMenuButtonClosesVideo.footer" : { + "settings.playback.tvVideoSyncMode.displayVdrop" : { "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "When enabled, the Siri remote Menu button stops playback and clears the queue. The close (X) button is hidden from the player. When disabled, Menu collapses the player and playback continues in the background." + "value" : "Display (drop/repeat) — default" } } } @@ -13778,6 +13793,16 @@ } } }, + "settings.resolveShortLinks.title" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resolve Short Links" + } + } + } + }, "settings.returnYouTubeDislike.about.description" : { "comment" : "Description of Return YouTube Dislike", "localizations" : { @@ -14854,6 +14879,16 @@ } } }, + "settings.youtubeEnhancements.resolveShortLinks.footer" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "When you tap a bit.ly, tinyurl, t.co, or similar short link in a description or comment, Yattee follows the redirect and opens the destination in-app if it's a supported video, channel, or playlist. Sends a network request to the shortener service." + } + } + } + }, "settings.youtubeEnhancements.returnYouTubeDislike.footer" : { "localizations" : { "en" : { @@ -14874,26 +14909,6 @@ } } }, - "settings.youtubeEnhancements.resolveShortLinks.footer" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "When you tap a bit.ly, tinyurl, t.co, or similar short link in a description or comment, Yattee follows the redirect and opens the destination in-app if it's a supported video, channel, or playlist. Sends a network request to the shortener service." - } - } - } - }, - "settings.resolveShortLinks.title" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Resolve Short Links" - } - } - } - }, "settings.youtubeEnhancements.title" : { "localizations" : { "en" : { @@ -15439,28 +15454,6 @@ } } }, - "sources.error.pipedBasicAuthUnsupported" : { - "comment" : "Error when a Piped instance is detected behind an HTTP Basic Auth proxy. Piped uses the same Authorization header for the user session, so the two cannot coexist.", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Piped sources can't be used behind an HTTP Basic Auth proxy. Piped reuses the Authorization header for the user session, so it conflicts with the proxy's credentials." - } - } - } - }, - "sources.error.pipedFrontendDetected" : { - "comment" : "Error when the URL points to the Piped web frontend (SPA) instead of its API backend. The frontend serves the same index.html for every path so detection cannot succeed.", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "This URL is the Piped web frontend, not its API. Please enter the Piped API URL instead (for example, the frontend may be at piped.example.com while the API is at piped-api.example.com or pipedapi.example.com — check with the instance operator)." - } - } - } - }, "sources.error.couldNotDetect" : { "comment" : "Error when source type could not be detected", "localizations" : { @@ -15516,6 +15509,28 @@ } } }, + "sources.error.pipedBasicAuthUnsupported" : { + "comment" : "Error when a Piped instance is detected behind an HTTP Basic Auth proxy. Piped uses the same Authorization header for the user session, so the two cannot coexist.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Piped sources can't be used behind an HTTP Basic Auth proxy. Piped reuses the Authorization header for the user session, so it conflicts with the proxy's credentials." + } + } + } + }, + "sources.error.pipedFrontendDetected" : { + "comment" : "Error when the URL points to the Piped web frontend (SPA) instead of its API backend. The frontend serves the same index.html for every path so detection cannot succeed.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This URL is the Piped web frontend, not its API. Please enter the Piped API URL instead (for example, the frontend may be at piped.example.com while the API is at piped-api.example.com or pipedapi.example.com — check with the instance operator)." + } + } + } + }, "sources.error.sslCertificate" : { "comment" : "Error when SSL certificate validation fails", "localizations" : { @@ -18359,4 +18374,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/Yattee/Views/Player/PlayerHelperViews.swift b/Yattee/Views/Player/PlayerHelperViews.swift index fa5f20b4..80fa15ff 100644 --- a/Yattee/Views/Player/PlayerHelperViews.swift +++ b/Yattee/Views/Player/PlayerHelperViews.swift @@ -144,6 +144,9 @@ struct ErrorDetailsSheet: View { #if os(iOS) .presentationDetents([.medium]) #endif + #if os(macOS) + .frame(minWidth: 450, minHeight: 300) + #endif } private func copyToClipboard() { diff --git a/Yattee/Views/Player/QualitySelectorView.swift b/Yattee/Views/Player/QualitySelectorView.swift index 4da45290..6298c03f 100644 --- a/Yattee/Views/Player/QualitySelectorView.swift +++ b/Yattee/Views/Player/QualitySelectorView.swift @@ -227,8 +227,13 @@ struct QualitySelectorView: View { NavigationStack { stackRoot } + #if os(iOS) .presentationDetents([.medium, .large]) #endif + #if os(macOS) + .frame(minWidth: 450, minHeight: 500) + #endif + #endif } @ViewBuilder diff --git a/Yattee/Views/Player/QueueManagementSheet.swift b/Yattee/Views/Player/QueueManagementSheet.swift index e473e9e5..40f8f465 100644 --- a/Yattee/Views/Player/QueueManagementSheet.swift +++ b/Yattee/Views/Player/QueueManagementSheet.swift @@ -136,7 +136,12 @@ struct QueueManagementSheet: View { } } .presentationDragIndicator(.visible) + #if os(iOS) .presentationDetents([.medium, .large]) + #endif + #if os(macOS) + .frame(minWidth: 450, minHeight: 500) + #endif } // MARK: - Views diff --git a/Yattee/Views/Playlist/BatchDownloadQualitySheet.swift b/Yattee/Views/Playlist/BatchDownloadQualitySheet.swift index 85184b54..aeec73aa 100644 --- a/Yattee/Views/Playlist/BatchDownloadQualitySheet.swift +++ b/Yattee/Views/Playlist/BatchDownloadQualitySheet.swift @@ -85,7 +85,12 @@ struct BatchDownloadQualitySheet: View { } } } + #if os(iOS) .presentationDetents([.medium]) + #endif + #if os(macOS) + .frame(minWidth: 450, minHeight: 300) + #endif } } diff --git a/Yattee/Views/Settings/EditSourceView.swift b/Yattee/Views/Settings/EditSourceView.swift index 7086bb31..a78d404e 100644 --- a/Yattee/Views/Settings/EditSourceView.swift +++ b/Yattee/Views/Settings/EditSourceView.swift @@ -531,6 +531,9 @@ private struct EditFileSourceContent: View { smbProtocolVersion = source.smbProtocolVersion ?? .auto } } + #if os(macOS) + .frame(minWidth: 500, minHeight: 450) + #endif #endif } diff --git a/Yattee/Views/Settings/InstanceLoginView.swift b/Yattee/Views/Settings/InstanceLoginView.swift index 9ab2190d..6362742c 100644 --- a/Yattee/Views/Settings/InstanceLoginView.swift +++ b/Yattee/Views/Settings/InstanceLoginView.swift @@ -43,6 +43,9 @@ struct InstanceLoginView: View { } .accessibilityIdentifier("instance.login.view") } + #if os(macOS) + .frame(minWidth: 450, minHeight: 350) + #endif #endif } diff --git a/Yattee/Views/Settings/NetworkShareDiscoverySheet.swift b/Yattee/Views/Settings/NetworkShareDiscoverySheet.swift index 8658638c..3ec96af4 100644 --- a/Yattee/Views/Settings/NetworkShareDiscoverySheet.swift +++ b/Yattee/Views/Settings/NetworkShareDiscoverySheet.swift @@ -54,6 +54,9 @@ struct NetworkShareDiscoverySheet: View { discoveryService?.stopDiscovery() } } + #if os(macOS) + .frame(minWidth: 450, minHeight: 400) + #endif } @ViewBuilder diff --git a/Yattee/Views/Video/DownloadQualitySheet.swift b/Yattee/Views/Video/DownloadQualitySheet.swift index cc6b1281..658536ee 100644 --- a/Yattee/Views/Video/DownloadQualitySheet.swift +++ b/Yattee/Views/Video/DownloadQualitySheet.swift @@ -345,7 +345,12 @@ struct DownloadQualitySheet: View { } } } + #if os(iOS) .presentationDetents([.medium, .large]) + #endif + #if os(macOS) + .frame(minWidth: 500, minHeight: 500) + #endif } // MARK: - Main Content Views diff --git a/Yattee/Views/Video/VideoInfoView.swift b/Yattee/Views/Video/VideoInfoView.swift index 922cf13b..c01ed6a9 100644 --- a/Yattee/Views/Video/VideoInfoView.swift +++ b/Yattee/Views/Video/VideoInfoView.swift @@ -1984,6 +1984,9 @@ struct VideoInfoView: View { } #endif } + #if os(macOS) + .frame(minWidth: 500, minHeight: 550) + #endif } }