Skip to content

Commit 1c48d71

Browse files
committed
Settings: About and epsilon updtate section
1 parent dd69954 commit 1c48d71

3 files changed

Lines changed: 164 additions & 6 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//
2+
// MITLiscence.swift
3+
// NumworksApplication
4+
//
5+
// Created by van Egmond Dascon on 08/02/2026.
6+
//
7+
8+
import SwiftUI
9+
import AppKit
10+
11+
enum MITLiscence {
12+
static func present() {
13+
let panel = NSPanel(
14+
contentRect: NSRect(x: 0, y: 0, width: 560, height: 520),
15+
styleMask: [.titled, .closable],
16+
backing: .buffered,
17+
defer: false
18+
)
19+
panel.title = "Copyright (c) 2026 EllandeVED"
20+
panel.center()
21+
22+
panel.standardWindowButton(.miniaturizeButton)?.isHidden = true
23+
panel.standardWindowButton(.zoomButton)?.isHidden = true
24+
25+
panel.contentView = NSHostingView(rootView: MITLiscenceView())
26+
27+
panel.makeKeyAndOrderFront(nil)
28+
NSApp.activate(ignoringOtherApps: true)
29+
}
30+
}
31+
32+
private struct MITLiscenceView: View {
33+
private let text = """
34+
MIT License
35+
36+
Copyright (c) 2026 EllandeVED
37+
38+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
39+
40+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
41+
42+
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43+
"""
44+
45+
var body: some View {
46+
VStack(alignment: .leading, spacing: 12) {
47+
ScrollView {
48+
Text(text)
49+
.font(.system(.body, design: .monospaced))
50+
.textSelection(.enabled)
51+
.frame(maxWidth: .infinity, alignment: .leading)
52+
}
53+
}
54+
.padding(16)
55+
}
56+
}

NumWorksMac/UI/Settings/SettingsView.swift

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,14 +185,33 @@ private struct AppUpdateSettingsPane: View {
185185
}
186186

187187
private struct EpsilonUpdateSettingsPane: View {
188+
@State private var currentSimulatorVersion: String = ""
189+
@State private var isChecking = false
190+
188191
var body: some View {
189192
VStack(alignment: .leading, spacing: 12) {
190193
Text("Epsilon Update")
191194
.font(.title2)
192195
.bold()
193196

194-
Text("Add Epsilon-specific update options here.")
195-
.foregroundStyle(.secondary)
197+
HStack(spacing: 8) {
198+
Text("Current version:")
199+
Text(currentSimulatorVersion)
200+
.monospaced()
201+
.foregroundStyle(.secondary)
202+
}
203+
204+
Button {
205+
checkForUpdates()
206+
} label: {
207+
if isChecking {
208+
ProgressView()
209+
.controlSize(.small)
210+
} else {
211+
Text("Check for updates")
212+
}
213+
}
214+
.disabled(isChecking)
196215

197216
Spacer()
198217
}
@@ -207,18 +226,90 @@ private struct EpsilonUpdateSettingsPane: View {
207226
.foregroundStyle(.white)
208227
}
209228
}
229+
.onAppear {
230+
currentSimulatorVersion = simulatorVersionString()
231+
}
232+
}
233+
234+
private func simulatorVersionString() -> String {
235+
UserDefaults.standard.string(forKey: "installedSimulatorVersion") ?? EpsilonVersions.bundledSimulator
236+
}
237+
238+
private func checkForUpdates() {
239+
guard !isChecking else { return }
240+
isChecking = true
241+
242+
Task { @MainActor in
243+
defer { isChecking = false }
244+
do {
245+
let current = simulatorVersionString()
246+
let report = try await EpsilonUpdateChecker.checkLatest(currentVersionString: current)
247+
248+
if report.needsUpdate {
249+
NotificationCenter.default.post(
250+
name: .requestEpsilonUpdateUI,
251+
object: nil,
252+
userInfo: [
253+
"remoteURL": report.remoteURL,
254+
"remoteVersion": report.remoteVersion.string,
255+
"required": false
256+
]
257+
)
258+
}
259+
260+
currentSimulatorVersion = simulatorVersionString()
261+
} catch {
262+
print("[Settings] epsilon update check failed: \(error)")
263+
}
264+
}
210265
}
211266
}
212267

213268
private struct AboutSettingsPane: View {
269+
private let repoURL = URL(string: "https://github.com/EllandeVED/NumworksApplication")!
270+
214271
var body: some View {
215272
VStack(alignment: .leading, spacing: 12) {
216273
Text("About")
217274
.font(.title2)
218275
.bold()
219276

220-
Text("Build info, credits, links, etc.")
221-
.foregroundStyle(.secondary)
277+
HStack(spacing: 8) {
278+
Text("App version")
279+
.fontWeight(.bold)
280+
Text(appVersionString())
281+
.monospaced()
282+
.foregroundStyle(.secondary)
283+
}
284+
285+
HStack(spacing: 8) {
286+
Text("Running on Epsilon")
287+
Text(simulatorVersionString())
288+
.monospaced()
289+
.foregroundStyle(.secondary)
290+
}
291+
292+
Divider().padding(.vertical, 6)
293+
294+
HStack(spacing: 8) {
295+
Text("Made by")
296+
.fontWeight(.bold)
297+
Text("Ellande VED")
298+
}
299+
300+
Link("See on GitHub: NumworksApplication", destination: repoURL)
301+
302+
Link("Report an issue/request: Report", destination: repoURL)
303+
304+
Divider().padding(.vertical, 6)
305+
306+
Button {
307+
MITLiscence.present()
308+
} label: {
309+
Text("MIT LISCENCE")
310+
.foregroundStyle(.blue)
311+
}
312+
.buttonStyle(.plain)
222313

223314
Spacer()
224315
}
@@ -234,6 +325,16 @@ private struct AboutSettingsPane: View {
234325
}
235326
}
236327
}
328+
329+
private func appVersionString() -> String {
330+
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
331+
?? Bundle.main.infoDictionary?["CFBundleVersion"] as? String
332+
?? ""
333+
}
334+
335+
private func simulatorVersionString() -> String {
336+
UserDefaults.standard.string(forKey: "installedSimulatorVersion") ?? EpsilonVersions.bundledSimulator
337+
}
237338
}
238339

239340
extension KeyboardShortcuts.Name {
@@ -245,3 +346,4 @@ extension Notification.Name {
245346
static let settingsWindowDidAppear = Notification.Name("settingsWindowDidAppear")
246347
static let settingsWindowDidDisappear = Notification.Name("settingsWindowDidDisappear")
247348
}
349+

NumworksApplication.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@
5959
Core/WindowManagement.swift,
6060
README_STRUCTURE.txt,
6161
Resources/Assets.xcassets,
62-
"Resources/DefaultSimulator/numworks-simulator.html",
6362
UI/Calculator/CalculatorView.swift,
6463
UI/Calculator/CalculatorWebView.swift,
6564
UI/Calculator/CalculatorWindow.swift,
6665
UI/MenuBar/MenuBarPopoverView.swift,
6766
UI/RootView.swift,
67+
UI/Settings/MITLicence.swift,
6868
UI/Settings/SettingsView.swift,
6969
UI/Updates/AppUpdateView.swift,
7070
UI/Updates/SimulatorUpdateView.swift,
@@ -93,12 +93,12 @@
9393
Core/WindowManagement.swift,
9494
README_STRUCTURE.txt,
9595
Resources/Assets.xcassets,
96-
"Resources/DefaultSimulator/numworks-simulator.html",
9796
UI/Calculator/CalculatorView.swift,
9897
UI/Calculator/CalculatorWebView.swift,
9998
UI/Calculator/CalculatorWindow.swift,
10099
UI/MenuBar/MenuBarPopoverView.swift,
101100
UI/RootView.swift,
101+
UI/Settings/MITLicence.swift,
102102
UI/Settings/SettingsView.swift,
103103
UI/Updates/AppUpdateView.swift,
104104
UI/Updates/SimulatorUpdateView.swift,

0 commit comments

Comments
 (0)