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] 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()
}
}