mirror of
https://github.com/yattee/yattee.git
synced 2026-10-23 21:22:53 +00:00
Open Settings from yattee://settings
SettingsView owns its navigation stack, so pushing it onto a section's stack rendered nothing. Select the Settings section where the layout has one, otherwise present Home's settings sheet; open the Settings window on macOS.
This commit is contained in:
@@ -9,6 +9,9 @@ import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@Environment(\.appEnvironment) private var appEnvironment
|
||||
#if os(macOS)
|
||||
@Environment(\.openWindow) private var openWindow
|
||||
#endif
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
@@ -79,6 +82,9 @@ struct ContentView: View {
|
||||
ExpandedPlayerWindowManager.shared.endInlineOverlay()
|
||||
}
|
||||
}
|
||||
.onChange(of: appEnvironment.navigationCoordinator.openSettingsWindowRequest) { _, _ in
|
||||
openWindow(id: "settings")
|
||||
}
|
||||
.onChange(of: appEnvironment.navigationCoordinator.playerExpandTrigger) { _, _ in
|
||||
if appEnvironment.settingsManager.macPlayerSeparateWindow {
|
||||
presentExpandedPlayerWindow(appEnvironment: appEnvironment)
|
||||
|
||||
@@ -37,6 +37,12 @@ final class NavigationCoordinator {
|
||||
/// Sheets observe it via `.dismissesOnExternalNavigation(_:)`.
|
||||
var dismissPresentationsGeneration = 0
|
||||
|
||||
#if os(macOS)
|
||||
/// Bumped to ask the main window to open the Settings window, which only a
|
||||
/// view can do (`openWindow`).
|
||||
var openSettingsWindowRequest = 0
|
||||
#endif
|
||||
|
||||
/// Whether the mini player is expanded to full screen.
|
||||
var isPlayerExpanded = false {
|
||||
didSet {
|
||||
@@ -231,10 +237,27 @@ final class NavigationCoordinator {
|
||||
|
||||
/// Navigate to a destination by pushing it onto the selected section's stack.
|
||||
func navigate(to destination: NavigationDestination) {
|
||||
// Settings has its own navigation stack, so it can't be pushed onto a
|
||||
// section's stack: it is a section, a sheet, or a window instead.
|
||||
if case .settings = destination {
|
||||
openSettings()
|
||||
return
|
||||
}
|
||||
router.push(destination)
|
||||
handoffManager?.updateActivity(for: destination)
|
||||
}
|
||||
|
||||
/// Shows Settings the way the current layout presents it: the Settings
|
||||
/// section where the layout has one, otherwise the Home screen's sheet
|
||||
/// (`NavigationRouter.ensureSelectionIsAvailable`), or on macOS its window.
|
||||
func openSettings() {
|
||||
#if os(macOS)
|
||||
openSettingsWindowRequest += 1
|
||||
#else
|
||||
router.select(.settings)
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - Sheet Presentation
|
||||
|
||||
/// Dismiss the main window's sheets so external navigation lands on a
|
||||
|
||||
@@ -32,6 +32,11 @@ final class NavigationRouter {
|
||||
/// sidebar layout so it is created and loaded once.
|
||||
let sidebarManager = SidebarManager()
|
||||
|
||||
/// Set when Settings was requested in a layout without a Settings section
|
||||
/// (the iPhone tab bar, unless the user added the tab). Home presents its
|
||||
/// Settings sheet and clears it.
|
||||
var pendingSettingsSheet = false
|
||||
|
||||
@ObservationIgnored private var hasAppliedStartupTab = false
|
||||
@ObservationIgnored private var isSidebarManagerConfigured = false
|
||||
|
||||
@@ -139,6 +144,10 @@ final class NavigationRouter {
|
||||
case .sources:
|
||||
host = .home
|
||||
root = .mediaSources
|
||||
case .settings:
|
||||
host = .home
|
||||
root = nil
|
||||
pendingSettingsSheet = true
|
||||
default:
|
||||
host = .home
|
||||
root = current.navigationDestination()
|
||||
|
||||
@@ -198,6 +198,10 @@ struct HomeView: View {
|
||||
.liquidGlassSheetContent(sourceID: "homeSettings", in: sheetTransition)
|
||||
}
|
||||
.dismissesOnExternalNavigation($showingSettings)
|
||||
.onAppear { presentPendingSettingsSheet() }
|
||||
.onChange(of: appEnvironment?.navigationCoordinator.router.pendingSettingsSheet) { _, _ in
|
||||
presentPendingSettingsSheet()
|
||||
}
|
||||
#endif
|
||||
.sheet(isPresented: $showingRemoteControl) {
|
||||
RemoteDevicesSheet()
|
||||
@@ -306,6 +310,20 @@ struct HomeView: View {
|
||||
}
|
||||
}
|
||||
|
||||
#if !os(tvOS) && !os(macOS)
|
||||
/// Presents Settings for a request the layout had no Settings section for.
|
||||
/// Deferred a turn: the same external navigation also dismisses sheets,
|
||||
/// and that reset must not land after this one.
|
||||
private func presentPendingSettingsSheet() {
|
||||
guard let router = appEnvironment?.navigationCoordinator.router,
|
||||
router.pendingSettingsSheet else { return }
|
||||
router.pendingSettingsSheet = false
|
||||
Task { @MainActor in
|
||||
showingSettings = true
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// MARK: - Main Content
|
||||
|
||||
#if os(tvOS)
|
||||
|
||||
@@ -170,10 +170,6 @@ RSpec.describe 'URL Schemes', :smoke do
|
||||
@axe.screenshot('url-scheme-continue-watching')
|
||||
end
|
||||
|
||||
# NOTE: yattee://settings deep link is broken in the app -
|
||||
# handlePendingNavigation pushes .settings onto homePath but it doesn't render.
|
||||
# Skipping until the app's deep link handler is fixed to present Settings properly.
|
||||
|
||||
it 'opens Search via yattee://search?q=test' do
|
||||
open_url('yattee://search?q=test')
|
||||
sleep 1
|
||||
@@ -184,6 +180,16 @@ RSpec.describe 'URL Schemes', :smoke do
|
||||
expect(@axe).to have_element('Search')
|
||||
@axe.screenshot('url-scheme-search')
|
||||
end
|
||||
|
||||
# Last in the group: on iPhone Settings opens as a sheet over Home, and the
|
||||
# next deep link dismisses it.
|
||||
it 'opens Settings via yattee://settings' do
|
||||
open_url('yattee://settings')
|
||||
sleep 1
|
||||
wait_for_text('Appearance')
|
||||
expect(@axe).to have_text('Appearance')
|
||||
@axe.screenshot('url-scheme-settings')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user