Vorschau mit Schreibtischhintergrund, Fenster breit genug für die Reiter
Die Vorschau der Auslösefläche war eine schwarze Fläche — als Bildschirm kaum zu erkennen. Jetzt liegt der echte Schreibtischhintergrund darunter. Apples eigene Bilder lassen sich nicht mitliefern (Lizenz, und ein Tahoe-Hintergrund wiegt zweistellige Megabyte); der eigene ist ohnehin der bessere Anker, weil man genau ihn wiedererkennt. Fehlt er, bleibt ein Verlauf in Onyx-Farben. Dabei fiel auf, dass Notch und Auslösefläche oberhalb des Bildschirms schwebten statt in ihm zu sitzen: die Rundung lag auf dem Hintergrund allein, nicht auf dem Ganzen. Sie schneidet jetzt Hintergrund, Menüleiste und Fläche gemeinsam ab. Und das Einstellungsfenster war zu schmal für sechs Reiter — die Leiste wurde rechts abgeschnitten, „Berechtigungen" war nicht mehr erreichbar. 780 statt 620 Punkte, Mindestbreite 740. Beim Nachrechnen der reinen Textbreiten kommt man auf 560 und liegt damit deutlich daneben: macOS legt je Reiter Innenabstand und Trenner dazu. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -48,7 +48,7 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
// Nur ein Mindestmaß, keine feste Größe: sonst kann das Fenster
|
// Nur ein Mindestmaß, keine feste Größe: sonst kann das Fenster
|
||||||
// wachsen, der Inhalt aber nicht mit.
|
// wachsen, der Inhalt aber nicht mit.
|
||||||
.frame(minWidth: 520, minHeight: 420)
|
.frame(minWidth: 740, minHeight: 460)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,8 +62,15 @@ final class SettingsWindowController: NSObject, NSWindowDelegate {
|
|||||||
// mehr, und ein Fenster, in dem man scrollen muss, obwohl der
|
// mehr, und ein Fenster, in dem man scrollen muss, obwohl der
|
||||||
// Bildschirm frei ist, ist eine Zumutung.
|
// Bildschirm frei ist, ist eine Zumutung.
|
||||||
window.styleMask = [.titled, .closable, .miniaturizable, .resizable]
|
window.styleMask = [.titled, .closable, .miniaturizable, .resizable]
|
||||||
window.setContentSize(NSSize(width: 620, height: 620))
|
window.setContentSize(NSSize(width: 780, height: 660))
|
||||||
window.contentMinSize = NSSize(width: 520, height: 420)
|
// Breit genug für die Reiterleiste.
|
||||||
|
//
|
||||||
|
// Sechs Reiter mit deutschen Beschriftungen brauchen mehr, als man
|
||||||
|
// beim Nachrechnen der reinen Textbreiten herausbekommt: macOS legt
|
||||||
|
// je Reiter Innenabstand und Trenner dazu. Ist das Fenster zu
|
||||||
|
// schmal, schneidet es die Leiste rechts einfach ab — der letzte
|
||||||
|
// Reiter ist dann nicht mehr erreichbar.
|
||||||
|
window.contentMinSize = NSSize(width: 740, height: 460)
|
||||||
window.isReleasedWhenClosed = false
|
window.isReleasedWhenClosed = false
|
||||||
window.delegate = self
|
window.delegate = self
|
||||||
Self.place(window)
|
Self.place(window)
|
||||||
|
|||||||
@@ -60,9 +60,10 @@ public struct TriggerAreaSettings: View {
|
|||||||
|
|
||||||
/// Der nachgebildete Bildschirm.
|
/// Der nachgebildete Bildschirm.
|
||||||
///
|
///
|
||||||
/// Absichtlich karg: es geht nur darum, wo die Notch sitzt und wie weit die
|
/// Mit dem echten Schreibtischhintergrund: Apples Bilder lassen sich nicht
|
||||||
/// Fläche darum herum reicht. Ein Schreibtischhintergrund oder Fenster darin
|
/// mitliefern — Lizenz, und ein Tahoe-Hintergrund wiegt zweistellige Megabyte.
|
||||||
/// wären Beiwerk, das von der einen Frage ablenkt.
|
/// Der eigene ist ohnehin der bessere Anker, weil man genau ihn wiedererkennt.
|
||||||
|
/// Fehlt er, bleibt ein Verlauf in Onyx-Farben.
|
||||||
private struct TriggerPreview: View {
|
private struct TriggerPreview: View {
|
||||||
let trigger: TriggerArea
|
let trigger: TriggerArea
|
||||||
|
|
||||||
@@ -79,32 +80,23 @@ private struct TriggerPreview: View {
|
|||||||
|
|
||||||
let notchWidth = width * notchWidthFraction
|
let notchWidth = width * notchWidthFraction
|
||||||
let notchHeight = height * notchHeightFraction
|
let notchHeight = height * notchHeightFraction
|
||||||
let areaWidth = notchWidth + 2 * trigger.extraWidth * scale
|
let areaWidth = min(notchWidth + 2 * trigger.extraWidth * scale, width)
|
||||||
let areaHeight = notchHeight + trigger.extraHeight * scale
|
let areaHeight = min(notchHeight + trigger.extraHeight * scale, height)
|
||||||
|
|
||||||
ZStack(alignment: .top) {
|
ZStack(alignment: .top) {
|
||||||
RoundedRectangle(cornerRadius: 8, style: .continuous)
|
wallpaper
|
||||||
.fill(Onyx.Color.surface)
|
|
||||||
.overlay {
|
|
||||||
RoundedRectangle(cornerRadius: 8, style: .continuous)
|
|
||||||
.strokeBorder(Onyx.Color.hairline, lineWidth: 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Die Menüleiste als dünner Streifen: sie erklärt, warum die
|
// Die Menüleiste als heller Streifen: sie erklärt, warum die
|
||||||
// Fläche nicht beliebig breit werden sollte.
|
// Fläche nicht beliebig breit werden sollte.
|
||||||
VStack(spacing: 0) {
|
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(.white.opacity(0.06))
|
.fill(.black.opacity(0.35))
|
||||||
.frame(height: notchHeight)
|
.frame(height: notchHeight)
|
||||||
Spacer(minLength: 0)
|
.frame(maxWidth: .infinity, alignment: .top)
|
||||||
}
|
|
||||||
|
|
||||||
// Die Auslösefläche.
|
// Die Auslösefläche.
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(Onyx.Color.accent.opacity(0.3))
|
.fill(Onyx.Color.accent.opacity(0.35))
|
||||||
.overlay {
|
.overlay { Rectangle().strokeBorder(Onyx.Color.accent, lineWidth: 1) }
|
||||||
Rectangle().strokeBorder(Onyx.Color.accent, lineWidth: 1)
|
|
||||||
}
|
|
||||||
.frame(width: areaWidth, height: areaHeight)
|
.frame(width: areaWidth, height: areaHeight)
|
||||||
|
|
||||||
// Die Notch selbst — undurchsichtig, wie in echt.
|
// Die Notch selbst — undurchsichtig, wie in echt.
|
||||||
@@ -114,9 +106,39 @@ private struct TriggerPreview: View {
|
|||||||
.frame(width: notchWidth, height: notchHeight)
|
.frame(width: notchWidth, height: notchHeight)
|
||||||
}
|
}
|
||||||
.frame(width: width, height: height)
|
.frame(width: width, height: height)
|
||||||
|
// Die Rundung zuletzt: sie schneidet Hintergrund, Menüleiste und
|
||||||
|
// Fläche gemeinsam ab, sonst ragt etwas über die Ecken hinaus.
|
||||||
|
.clipShape(.rect(cornerRadius: 8, style: .continuous))
|
||||||
|
.overlay {
|
||||||
|
RoundedRectangle(cornerRadius: 8, style: .continuous)
|
||||||
|
.strokeBorder(Onyx.Color.hairline, lineWidth: 1)
|
||||||
|
}
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.animation(Onyx.Motion.value, value: areaWidth)
|
.animation(Onyx.Motion.value, value: areaWidth)
|
||||||
.animation(Onyx.Motion.value, value: areaHeight)
|
.animation(Onyx.Motion.value, value: areaHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private var wallpaper: some View {
|
||||||
|
if let image = Self.desktopImage {
|
||||||
|
Image(nsImage: image)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fill)
|
||||||
|
} else {
|
||||||
|
LinearGradient(colors: [Onyx.Color.elevated, Onyx.Color.surface],
|
||||||
|
startPoint: .top, endPoint: .bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Der Schreibtischhintergrund des Hauptbildschirms.
|
||||||
|
///
|
||||||
|
/// Einmal geladen und behalten: es ist eine Datei von mehreren Megabyte,
|
||||||
|
/// und die Vorschau zeichnet sich bei jedem Zug am Regler neu.
|
||||||
|
private static let desktopImage: NSImage? = {
|
||||||
|
guard let screen = NSScreen.main,
|
||||||
|
let url = NSWorkspace.shared.desktopImageURL(for: screen)
|
||||||
|
else { return nil }
|
||||||
|
return NSImage(contentsOf: url)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user