From 42bf37af32ae6f20b32b447e54e5e208d95a9a2f Mon Sep 17 00:00:00 2001
From: Josh <36625023+JoshuaBrest@users.noreply.github.com>
Date: Sat, 19 Oct 2024 00:31:43 -0700
Subject: [PATCH 1/5] feat: Update about menu design to match macOS.
---
macos/Sources/Features/About/About.xib | 2 +-
.../Features/About/AboutController.swift | 1 +
macos/Sources/Features/About/AboutView.swift | 139 ++++++++++++++++--
3 files changed, 125 insertions(+), 17 deletions(-)
diff --git a/macos/Sources/Features/About/About.xib b/macos/Sources/Features/About/About.xib
index e884beff1..5803a32de 100644
--- a/macos/Sources/Features/About/About.xib
+++ b/macos/Sources/Features/About/About.xib
@@ -14,7 +14,7 @@
-
+
diff --git a/macos/Sources/Features/About/AboutController.swift b/macos/Sources/Features/About/AboutController.swift
index d2ae68ea7..efd7a515a 100644
--- a/macos/Sources/Features/About/AboutController.swift
+++ b/macos/Sources/Features/About/AboutController.swift
@@ -10,6 +10,7 @@ class AboutController: NSWindowController, NSWindowDelegate {
override func windowDidLoad() {
guard let window = window else { return }
window.center()
+ window.isMovableByWindowBackground = true
window.contentView = NSHostingView(rootView: AboutView())
}
diff --git a/macos/Sources/Features/About/AboutView.swift b/macos/Sources/Features/About/AboutView.swift
index 02f899cc4..a7b0834fc 100644
--- a/macos/Sources/Features/About/AboutView.swift
+++ b/macos/Sources/Features/About/AboutView.swift
@@ -1,35 +1,142 @@
import SwiftUI
struct AboutView: View {
+ @Environment(\.openURL) var openURL
+
+ /// Eventually this should be a redirect like https://go.ghostty.dev/discord or https://go.ghostty.dev/github
+ @State var discordLink: String = "https://discord.gg/ghostty"
+ @State var githubLink: String = "https://github.com/ghostty-org/ghostty"
+
/// Read the commit from the bundle.
var build: String? { Bundle.main.infoDictionary?["CFBundleVersion"] as? String }
var commit: String? { Bundle.main.infoDictionary?["GhosttyCommit"] as? String }
var version: String? { Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String }
+ var copyright: String? { Bundle.main.infoDictionary?["NSHumanReadableCopyright"] as? String }
+
+ struct ValuePair: Identifiable {
+ var id = UUID()
+ public let key: LocalizedStringResource
+ public let value: Value
+
+ }
+
+ var computedStrings: [ValuePair] {
+ let list: [ValuePair] = [
+ ValuePair(key: "Version", value: self.version),
+ ValuePair(key: "Build", value: self.build),
+ ValuePair(key: "Commit", value: self.commit == "" ? nil : self.commit)
+ ]
+
+ let strings: [ValuePair] = list.compactMap {
+ guard let value = $0.value else { return nil }
+
+ return ValuePair(key: $0.key, value: value)
+ }
+
+ return strings
+ }
+
+ #if os(macOS)
+ struct VisualEffectBackground: NSViewRepresentable {
+ let material: NSVisualEffectView.Material
+ let blendingMode: NSVisualEffectView.BlendingMode
+ let isEmphasized: Bool
+
+ init(material: NSVisualEffectView.Material, blendingMode: NSVisualEffectView.BlendingMode = .behindWindow, isEmphasized: Bool = false) {
+ self.material = material
+ self.blendingMode = blendingMode
+ self.isEmphasized = isEmphasized
+ }
+
+ func updateNSView(_ nsView: NSVisualEffectView, context: Context) {
+ nsView.material = material
+ nsView.blendingMode = blendingMode
+ nsView.isEmphasized = isEmphasized
+ }
+
+ func makeNSView(context: Context) -> NSVisualEffectView {
+ let visualEffect = NSVisualEffectView()
+
+ visualEffect.autoresizingMask = [.width, .height]
+
+ return visualEffect
+ }
+ }
+ #endif
var body: some View {
VStack(alignment: .center) {
Image("AppIconImage")
.resizable()
.aspectRatio(contentMode: .fit)
- .frame(maxHeight: 96)
+ .frame(height: 128)
- Text("Ghostty")
- .font(.title3)
- .textSelection(.enabled)
+ VStack(alignment: .center, spacing: 32) {
+ VStack(alignment: .center, spacing: 8) {
+ Text("Ghostty")
+ .bold()
+ .font(.title)
+ Text("Fast, native, feature-rich terminal emulator pushing modern features.")
+ .multilineTextAlignment(.center)
+ .fixedSize(horizontal: false, vertical: true)
+ .font(.caption)
+ .tint(.secondary)
+ .opacity(0.8)
+ }
+ VStack(spacing: 2) {
+ ForEach(computedStrings) { item in
- if let version = self.version {
- Text("Version: \(version)")
- .font(.body)
- .textSelection(.enabled)
- }
-
- if let build = self.build {
- Text("Build: \(build)")
- .font(.body)
- .textSelection(.enabled)
+ HStack(spacing: 4) {
+ Text(item.key)
+ .frame(width: 126, alignment: .trailing)
+ .padding(.trailing, 2)
+ Text(item.value)
+ .frame(width: 125, alignment: .leading)
+ .padding(.leading, 2)
+ .tint(.secondary)
+ .opacity(0.8)
+ }
+ .font(.callout)
+ .frame(maxWidth: .infinity)
+ }
+ }
+ .frame(maxWidth: .infinity)
+
+ HStack(spacing: 8) {
+ Button("Discord") {
+ guard let url = URL(string: discordLink) else { return
+ }
+ openURL(url)
+ }
+ Button("Github") {
+ guard let url = URL(string: githubLink) else { return
+ }
+ openURL(url)
+ }
+ }
+
+ if let copy = self.copyright {
+ Text(copy)
+ .font(.caption)
+ .tint(.secondary)
+ .opacity(0.8)
+ .multilineTextAlignment(.center)
+ .frame(maxWidth: .infinity)
+ }
}
+ .frame(maxWidth: .infinity)
}
- .frame(minWidth: 300)
- .padding()
+ .padding(.top, 8)
+ .padding(32)
+ .frame(minWidth: 256)
+ #if os(macOS)
+ .background(VisualEffectBackground(material: .underWindowBackground).ignoresSafeArea())
+ #endif
+ }
+}
+
+struct AboutView_Previews: PreviewProvider {
+ static var previews: some View {
+ AboutView()
}
}
From 4b08b3f8d8009a94c4c5fd5744e8a88c942ab764 Mon Sep 17 00:00:00 2001
From: Josh <36625023+JoshuaBrest@users.noreply.github.com>
Date: Sat, 19 Oct 2024 11:23:04 -0700
Subject: [PATCH 2/5] refactor: hide buttons when URLs are invalid and change
variable mutability and visibility.
---
macos/Sources/Features/About/AboutView.swift | 31 ++++++++++----------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/macos/Sources/Features/About/AboutView.swift b/macos/Sources/Features/About/AboutView.swift
index a7b0834fc..7c5c5de7f 100644
--- a/macos/Sources/Features/About/AboutView.swift
+++ b/macos/Sources/Features/About/AboutView.swift
@@ -4,23 +4,23 @@ struct AboutView: View {
@Environment(\.openURL) var openURL
/// Eventually this should be a redirect like https://go.ghostty.dev/discord or https://go.ghostty.dev/github
- @State var discordLink: String = "https://discord.gg/ghostty"
- @State var githubLink: String = "https://github.com/ghostty-org/ghostty"
+ private let discordLink = URL(string: "https://discord.gg/ghostty")
+ private let githubLink = URL(string: "https://github.com/ghostty-org/ghostty")
/// Read the commit from the bundle.
- var build: String? { Bundle.main.infoDictionary?["CFBundleVersion"] as? String }
- var commit: String? { Bundle.main.infoDictionary?["GhosttyCommit"] as? String }
- var version: String? { Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String }
- var copyright: String? { Bundle.main.infoDictionary?["NSHumanReadableCopyright"] as? String }
+ private var build: String? { Bundle.main.infoDictionary?["CFBundleVersion"] as? String }
+ private var commit: String? { Bundle.main.infoDictionary?["GhosttyCommit"] as? String }
+ private var version: String? { Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String }
+ private var copyright: String? { Bundle.main.infoDictionary?["NSHumanReadableCopyright"] as? String }
- struct ValuePair: Identifiable {
+ private struct ValuePair: Identifiable {
var id = UUID()
public let key: LocalizedStringResource
public let value: Value
}
- var computedStrings: [ValuePair] {
+ private var computedStrings: [ValuePair] {
let list: [ValuePair] = [
ValuePair(key: "Version", value: self.version),
ValuePair(key: "Build", value: self.build),
@@ -37,7 +37,7 @@ struct AboutView: View {
}
#if os(macOS)
- struct VisualEffectBackground: NSViewRepresentable {
+ private struct VisualEffectBackground: NSViewRepresentable {
let material: NSVisualEffectView.Material
let blendingMode: NSVisualEffectView.BlendingMode
let isEmphasized: Bool
@@ -103,16 +103,17 @@ struct AboutView: View {
.frame(maxWidth: .infinity)
HStack(spacing: 8) {
- Button("Discord") {
- guard let url = URL(string: discordLink) else { return
+ if let url = discordLink {
+ Button("Discord") {
+ openURL(url)
}
- openURL(url)
}
- Button("Github") {
- guard let url = URL(string: githubLink) else { return
+ if let url = githubLink {
+ Button("GitHub") {
+ openURL(url)
}
- openURL(url)
}
+
}
if let copy = self.copyright {
From d291fcfd526e6c4622226b29a3f55ccc58ab400a Mon Sep 17 00:00:00 2001
From: Josh <36625023+JoshuaBrest@users.noreply.github.com>
Date: Sat, 19 Oct 2024 11:45:24 -0700
Subject: [PATCH 3/5] style: add line break in the caption of the about dialog.
---
macos/Sources/Features/About/AboutView.swift | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/macos/Sources/Features/About/AboutView.swift b/macos/Sources/Features/About/AboutView.swift
index 7c5c5de7f..976207e9b 100644
--- a/macos/Sources/Features/About/AboutView.swift
+++ b/macos/Sources/Features/About/AboutView.swift
@@ -76,7 +76,7 @@ struct AboutView: View {
Text("Ghostty")
.bold()
.font(.title)
- Text("Fast, native, feature-rich terminal emulator pushing modern features.")
+ Text("Fast, native, feature-rich terminal \nemulator pushing modern features.")
.multilineTextAlignment(.center)
.fixedSize(horizontal: false, vertical: true)
.font(.caption)
From cc42dc57b942a342bd82e7e94ba0411434d6b6da Mon Sep 17 00:00:00 2001
From: Josh <36625023+JoshuaBrest@users.noreply.github.com>
Date: Sat, 19 Oct 2024 11:52:12 -0700
Subject: [PATCH 4/5] fix: add text-selection back in the about dialoge.
---
macos/Sources/Features/About/AboutView.swift | 3 +++
1 file changed, 3 insertions(+)
diff --git a/macos/Sources/Features/About/AboutView.swift b/macos/Sources/Features/About/AboutView.swift
index 976207e9b..f56faaa1e 100644
--- a/macos/Sources/Features/About/AboutView.swift
+++ b/macos/Sources/Features/About/AboutView.swift
@@ -83,6 +83,7 @@ struct AboutView: View {
.tint(.secondary)
.opacity(0.8)
}
+ .textSelection(.enabled)
VStack(spacing: 2) {
ForEach(computedStrings) { item in
@@ -97,6 +98,7 @@ struct AboutView: View {
.opacity(0.8)
}
.font(.callout)
+ .textSelection(.enabled)
.frame(maxWidth: .infinity)
}
}
@@ -119,6 +121,7 @@ struct AboutView: View {
if let copy = self.copyright {
Text(copy)
.font(.caption)
+ .textSelection(.enabled)
.tint(.secondary)
.opacity(0.8)
.multilineTextAlignment(.center)
From 85db4d0277a39368df2e15d4d64017544ed77a8b Mon Sep 17 00:00:00 2001
From: Mitchell Hashimoto
Date: Sat, 19 Oct 2024 14:06:55 -0700
Subject: [PATCH 5/5] macos: personal nitpicks and improvements
---
macos/Sources/Features/About/AboutView.swift | 50 ++++++++------------
1 file changed, 20 insertions(+), 30 deletions(-)
diff --git a/macos/Sources/Features/About/AboutView.swift b/macos/Sources/Features/About/AboutView.swift
index f56faaa1e..71fe9c252 100644
--- a/macos/Sources/Features/About/AboutView.swift
+++ b/macos/Sources/Features/About/AboutView.swift
@@ -3,8 +3,6 @@ import SwiftUI
struct AboutView: View {
@Environment(\.openURL) var openURL
- /// Eventually this should be a redirect like https://go.ghostty.dev/discord or https://go.ghostty.dev/github
- private let discordLink = URL(string: "https://discord.gg/ghostty")
private let githubLink = URL(string: "https://github.com/ghostty-org/ghostty")
/// Read the commit from the bundle.
@@ -13,36 +11,36 @@ struct AboutView: View {
private var version: String? { Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String }
private var copyright: String? { Bundle.main.infoDictionary?["NSHumanReadableCopyright"] as? String }
- private struct ValuePair: Identifiable {
+ private var properties: [KeyValue] {
+ let list: [KeyValue] = [
+ .init(key: "Version", value: version),
+ .init(key: "Build", value: build),
+ .init(key: "Commit", value: commit == "" ? nil : commit)
+ ]
+
+ return list.compactMap {
+ guard let value = $0.value else { return nil }
+ return .init(key: $0.key, value: value)
+ }
+ }
+
+ private struct KeyValue: Identifiable {
var id = UUID()
public let key: LocalizedStringResource
public let value: Value
-
- }
-
- private var computedStrings: [ValuePair] {
- let list: [ValuePair] = [
- ValuePair(key: "Version", value: self.version),
- ValuePair(key: "Build", value: self.build),
- ValuePair(key: "Commit", value: self.commit == "" ? nil : self.commit)
- ]
-
- let strings: [ValuePair] = list.compactMap {
- guard let value = $0.value else { return nil }
-
- return ValuePair(key: $0.key, value: value)
- }
-
- return strings
}
#if os(macOS)
+ // This creates a background style similar to the Apple "About My Mac" Window
private struct VisualEffectBackground: NSViewRepresentable {
let material: NSVisualEffectView.Material
let blendingMode: NSVisualEffectView.BlendingMode
let isEmphasized: Bool
- init(material: NSVisualEffectView.Material, blendingMode: NSVisualEffectView.BlendingMode = .behindWindow, isEmphasized: Bool = false) {
+ init(material: NSVisualEffectView.Material,
+ blendingMode: NSVisualEffectView.BlendingMode = .behindWindow,
+ isEmphasized: Bool = false)
+ {
self.material = material
self.blendingMode = blendingMode
self.isEmphasized = isEmphasized
@@ -56,9 +54,7 @@ struct AboutView: View {
func makeNSView(context: Context) -> NSVisualEffectView {
let visualEffect = NSVisualEffectView()
-
visualEffect.autoresizingMask = [.width, .height]
-
return visualEffect
}
}
@@ -85,8 +81,7 @@ struct AboutView: View {
}
.textSelection(.enabled)
VStack(spacing: 2) {
- ForEach(computedStrings) { item in
-
+ ForEach(properties) { item in
HStack(spacing: 4) {
Text(item.key)
.frame(width: 126, alignment: .trailing)
@@ -105,11 +100,6 @@ struct AboutView: View {
.frame(maxWidth: .infinity)
HStack(spacing: 8) {
- if let url = discordLink {
- Button("Discord") {
- openURL(url)
- }
- }
if let url = githubLink {
Button("GitHub") {
openURL(url)