commit 155be03f2175684e59741415de897d959eab6e9c
parent 98a6960605bc992ac070d7dae996293d0c881e83
Author: Michael Camilleri <[email protected]>
Date: Thu, 7 May 2026 13:41:43 +0900
Add About screen to Settings
Diffstat:
5 files changed, 111 insertions(+), 1 deletion(-)
diff --git a/Crossmate.xcodeproj/project.pbxproj b/Crossmate.xcodeproj/project.pbxproj
@@ -61,6 +61,7 @@
AA28425BD26F72A9E2B58742 /* BundledBrowseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A4B7C6A8A23C6E4CCEC759F /* BundledBrowseView.swift */; };
AA38A51862FC0AB8F7D34899 /* NYTToXDConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C54223FED97577A593B7964E /* NYTToXDConverterTests.swift */; };
AA992F67F509EC8EFDDFC7CB /* morning.xd in Resources */ = {isa = PBXBuildFile; fileRef = 0B73A791FD061430AE286E11 /* morning.xd */; };
+ AB05765D2C3F4841026344E5 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AF633D73818BD59F759FAC4 /* AboutView.swift */; };
AF4F1AE2A1F94E92C785C524 /* Square.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB851649DE78AAAC5A928C52 /* Square.swift */; };
B42454D72FAA219D60DEA334 /* garden.xd in Resources */ = {isa = PBXBuildFile; fileRef = 50992CDA4082429EBB17F65C /* garden.xd */; };
B762200F54C52E8377A80D15 /* NYTToXDConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6F111BE8750697C4BC7A17 /* NYTToXDConverter.swift */; };
@@ -128,6 +129,7 @@
465F2BB469EFE84CF3733398 /* Game.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Game.swift; sourceTree = "<group>"; };
47532AED239AEF476D8E9206 /* NotificationStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationStateTests.swift; sourceTree = "<group>"; };
4803C2E84FC5B3BFE593171D /* NameBroadcaster.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NameBroadcaster.swift; sourceTree = "<group>"; };
+ 4AF633D73818BD59F759FAC4 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
4DC7784917397BCD6B8D679D /* PuzzleCatalog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PuzzleCatalog.swift; sourceTree = "<group>"; };
4F4EBC0F07FF815274C028CA /* XDAcceptTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XDAcceptTests.swift; sourceTree = "<group>"; };
50992CDA4082429EBB17F65C /* garden.xd */ = {isa = PBXFileReference; path = garden.xd; sourceTree = "<group>"; };
@@ -312,6 +314,7 @@
84445EA9CACB6AAAEDE6965F /* Views */ = {
isa = PBXGroup;
children = (
+ 4AF633D73818BD59F759FAC4 /* AboutView.swift */,
9A4B7C6A8A23C6E4CCEC759F /* BundledBrowseView.swift */,
C0CAA5E17BD406AFEEF96196 /* CalendarDayCell.swift */,
F8E50E7BA98C88B4CAB39DC1 /* CellView.swift */,
@@ -517,6 +520,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ AB05765D2C3F4841026344E5 /* AboutView.swift in Sources */,
78802AFDF6273231781CC0DC /* AppServices.swift in Sources */,
197DDF45C36B9570BB9AE4B5 /* AuthorIdentity.swift in Sources */,
AA28425BD26F72A9E2B58742 /* BundledBrowseView.swift in Sources */,
diff --git a/Crossmate/Media.xcassets/AboutIcon.imageset/Contents.json b/Crossmate/Media.xcassets/AboutIcon.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "Icon.png",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Crossmate/Media.xcassets/AboutIcon.imageset/Icon.png b/Crossmate/Media.xcassets/AboutIcon.imageset/Icon.png
Binary files differ.
diff --git a/Crossmate/Views/AboutView.swift b/Crossmate/Views/AboutView.swift
@@ -0,0 +1,83 @@
+import SwiftUI
+
+struct AboutView: View {
+ private var appVersion: String {
+ Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown"
+ }
+
+ private var buildNumber: String {
+ Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "Unknown"
+ }
+
+ var body: some View {
+ List {
+ Section {
+ VStack(spacing: 8) {
+ Image("AboutIcon")
+ .resizable()
+ .scaledToFit()
+ .frame(width: 100, height: 100)
+ .clipShape(RoundedRectangle(cornerRadius: 22))
+
+ Text("Crossmate")
+ .font(.title2)
+ .fontWeight(.bold)
+
+ Text("Version \(appVersion) (\(buildNumber))")
+ .font(.subheadline)
+ .foregroundStyle(.secondary)
+ .padding(.bottom, 20)
+
+ VStack(spacing: 4) {
+ Text("Programming")
+ .font(.caption)
+ .textCase(.uppercase)
+ .tracking(0.8)
+ .foregroundStyle(.secondary)
+ Text("Claude Code and OpenAI Codex")
+ .font(.subheadline)
+ .foregroundStyle(.primary)
+ }
+ .padding(.bottom, 8)
+
+ VStack(spacing: 4) {
+ Text("Direction")
+ .font(.caption)
+ .textCase(.uppercase)
+ .tracking(0.8)
+ .foregroundStyle(.secondary)
+ Text("Michael Camilleri")
+ .font(.subheadline)
+ .foregroundStyle(.primary)
+ }
+ }
+ .frame(maxWidth: .infinity)
+ .padding(.bottom, 4)
+ .listRowBackground(Color.clear)
+ .listRowSeparator(.hidden)
+ }
+
+ Section {
+ Link(destination: URL(string: "https://apps.inqk.net/crossmate")!) {
+ Label("Website", systemImage: "globe")
+ }
+ Link(destination: URL(string: "https://code.inqk.net/crossmate")!) {
+ Label("Source Code", systemImage: "chevron.left.forwardslash.chevron.right")
+ }
+ }
+
+ Section {
+ Text("Thank you to my wife, daughter and sons for their love and inspiration.")
+ .font(.subheadline)
+ .foregroundStyle(.secondary)
+ .multilineTextAlignment(.center)
+ .frame(maxWidth: .infinity)
+ .listRowBackground(Color.clear)
+ .listRowSeparator(.hidden)
+ }
+ }
+ .contentMargins(.top, 0, for: .scrollContent)
+ .navigationTitle("About")
+ .navigationBarTitleDisplayMode(.inline)
+ }
+}
diff --git a/Crossmate/Views/SettingsView.swift b/Crossmate/Views/SettingsView.swift
@@ -30,7 +30,7 @@ struct SettingsView: View {
NavigationLink("Share Diagnostics") {
ShareDiagnosticsView()
}
- NavigationLink("CloudKit Record") {
+ NavigationLink("Record Editor") {
RecordEditorView()
}
@@ -49,6 +49,17 @@ struct SettingsView: View {
Text("This removes every game and clears the sync state on this device. Games on other devices and in iCloud are not affected.")
}
}
+
+ Section {
+ NavigationLink("About") {
+ AboutView()
+ }
+ } footer: {
+ Text("Made in Tokyo from natural ones and zeros")
+ .frame(maxWidth: .infinity)
+ .multilineTextAlignment(.center)
+ .padding(.top, 24)
+ }
}
.navigationTitle("Settings")
.navigationBarTitleDisplayMode(.inline)