mirror of
https://github.com/yattee/yattee.git
synced 2026-07-20 14:22:02 +00:00
Use native text Close button for sheet toolbars on macOS
Sheet dismiss buttons rendered as an iOS-style circular glass "X" on macOS 26, which looks foreign on the desktop. Add a shared sheetCloseToolbarItem helper that renders a native text "Close" button on macOS while keeping the compact icon-only xmark on iOS/tvOS, and replace the ~14 duplicated inline close buttons across sheets with it.
This commit is contained in:
50
Yattee/Extensions/ToolbarContent+Close.swift
Normal file
50
Yattee/Extensions/ToolbarContent+Close.swift
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// ToolbarContent+Close.swift
|
||||||
|
// Yattee
|
||||||
|
//
|
||||||
|
// Shared sheet-dismiss toolbar item.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
/// Standard sheet-dismiss toolbar item.
|
||||||
|
///
|
||||||
|
/// On macOS this renders a native text button (e.g. "Close"), which fits the desktop
|
||||||
|
/// convention. On iOS/tvOS it renders the compact icon-only xmark used by the rest of
|
||||||
|
/// the app's sheets.
|
||||||
|
///
|
||||||
|
/// Placement defaults to `.confirmationAction`; only the *label* changes per platform,
|
||||||
|
/// so it can be dropped into existing `.toolbar { }` blocks without changing layout.
|
||||||
|
@ToolbarContentBuilder
|
||||||
|
func sheetCloseToolbarItem(
|
||||||
|
placement: ToolbarItemPlacement = .confirmationAction,
|
||||||
|
titleKey: LocalizedStringResource = "common.close",
|
||||||
|
identifier: String? = nil,
|
||||||
|
action: @escaping () -> Void
|
||||||
|
) -> some ToolbarContent {
|
||||||
|
ToolbarItem(placement: placement) {
|
||||||
|
sheetCloseButton(titleKey: titleKey, identifier: identifier, action: action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func sheetCloseButton(
|
||||||
|
titleKey: LocalizedStringResource,
|
||||||
|
identifier: String?,
|
||||||
|
action: @escaping () -> Void
|
||||||
|
) -> some View {
|
||||||
|
let button = Button(role: .cancel, action: action) {
|
||||||
|
#if os(macOS)
|
||||||
|
Text(String(localized: titleKey))
|
||||||
|
#else
|
||||||
|
Label(String(localized: titleKey), systemImage: "xmark")
|
||||||
|
.labelStyle(.iconOnly)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if let identifier {
|
||||||
|
button.accessibilityIdentifier(identifier)
|
||||||
|
} else {
|
||||||
|
button
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -88,14 +88,7 @@ struct MediaBrowserViewOptionsSheet: View {
|
|||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { dismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,14 +31,7 @@ struct ChaptersView: View {
|
|||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { dismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.task {
|
.task {
|
||||||
await preloadChapterSheets()
|
await preloadChapterSheets()
|
||||||
|
|||||||
@@ -114,14 +114,7 @@ struct ErrorDetailsSheet: View {
|
|||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { dismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolbarItemGroup(placement: .primaryAction) {
|
ToolbarItemGroup(placement: .primaryAction) {
|
||||||
// Copy button
|
// Copy button
|
||||||
|
|||||||
@@ -276,14 +276,7 @@ struct QualitySelectorView: View {
|
|||||||
#endif
|
#endif
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { performDismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
performDismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
.navigationDestination(for: QualitySelectorDestination.self) { destination in
|
.navigationDestination(for: QualitySelectorDestination.self) { destination in
|
||||||
|
|||||||
@@ -125,14 +125,7 @@ struct QueueManagementSheet: View {
|
|||||||
ToolbarItem(placement: .cancellationAction) {
|
ToolbarItem(placement: .cancellationAction) {
|
||||||
queueModeMenu
|
queueModeMenu
|
||||||
}
|
}
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { performDismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
performDismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.presentationDragIndicator(.visible)
|
.presentationDragIndicator(.visible)
|
||||||
|
|||||||
@@ -24,14 +24,7 @@ struct RemoteDevicesSheet: View {
|
|||||||
.frame(minWidth: 400, minHeight: 300)
|
.frame(minWidth: 400, minHeight: 300)
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { dismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.navigationDestination(item: $selectedDevice) { device in
|
.navigationDestination(item: $selectedDevice) { device in
|
||||||
RemoteControlView(device: device)
|
RemoteControlView(device: device)
|
||||||
|
|||||||
@@ -64,14 +64,7 @@ struct AddSourceView: View {
|
|||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { dismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.navigationDestination(isPresented: $navigateToWebDAV) {
|
.navigationDestination(isPresented: $navigateToWebDAV) {
|
||||||
AddWebDAVView(
|
AddWebDAVView(
|
||||||
|
|||||||
@@ -54,14 +54,7 @@ struct InstancePickerSheet: View {
|
|||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { dismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.presentationDetents([.medium, .large])
|
.presentationDetents([.medium, .large])
|
||||||
|
|||||||
@@ -278,14 +278,7 @@ private struct LogEntryDetailView: View {
|
|||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { dismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.presentationDetents([.medium, .large])
|
.presentationDetents([.medium, .large])
|
||||||
|
|||||||
@@ -215,14 +215,7 @@ struct PeerTubeInstancesExploreView: View {
|
|||||||
@ToolbarContentBuilder
|
@ToolbarContentBuilder
|
||||||
private var toolbarContent: some ToolbarContent {
|
private var toolbarContent: some ToolbarContent {
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { dismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ToolbarItem(placement: .primaryAction) {
|
ToolbarItem(placement: .primaryAction) {
|
||||||
|
|||||||
@@ -187,14 +187,7 @@ struct TapGesturesSettingsView: View {
|
|||||||
|
|
||||||
TapZoneActionPicker(position: position, action: binding)
|
TapZoneActionPicker(position: position, action: binding)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { selectedZonePosition = nil }
|
||||||
Button(role: .cancel) {
|
|
||||||
selectedZonePosition = nil
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -328,15 +328,7 @@ struct SettingsView: View {
|
|||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
if showCloseButton {
|
if showCloseButton {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem(identifier: "settings.doneButton") { dismiss() }
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
.accessibilityIdentifier("settings.doneButton")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.accessibilityIdentifier("settings.view")
|
.accessibilityIdentifier("settings.view")
|
||||||
|
|||||||
@@ -89,22 +89,7 @@ struct PlaylistSelectorSheet: View {
|
|||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
#if os(macOS)
|
sheetCloseToolbarItem { dismiss() }
|
||||||
ToolbarItem(placement: .cancellationAction) {
|
|
||||||
Button(String(localized: "common.close"), role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
|
||||||
Button(role: .cancel) {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
.sheet(isPresented: $showingNewPlaylist) {
|
.sheet(isPresented: $showingNewPlaylist) {
|
||||||
|
|||||||
@@ -1973,14 +1973,7 @@ struct VideoInfoView: View {
|
|||||||
#endif
|
#endif
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .confirmationAction) {
|
sheetCloseToolbarItem { showingCommentsSheet = false }
|
||||||
Button(role: .cancel) {
|
|
||||||
showingCommentsSheet = false
|
|
||||||
} label: {
|
|
||||||
Label(String(localized: "common.close"), systemImage: "xmark")
|
|
||||||
.labelStyle(.iconOnly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user