Skip to content

Commit d7456b8

Browse files
nnmrtshronro
authored andcommitted
🐛 fix config file read on startup
1 parent 156bb9c commit d7456b8

File tree

3 files changed

+70
-23
lines changed

3 files changed

+70
-23
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
- Fix loading configuration file on startup.
12+
1013
## [1.0.0]
1114

1215
### Added

ui/iPortForwarder/Views/SettingsView.swift

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ class LaunchingAtLogin: ObservableObject {
2929
return false
3030
}
3131
}
32-
32+
3333
set {
3434
if #available(macOS 13, *) {
3535
if newValue {
3636
if SMAppService.mainApp.status == .enabled {
3737
try? SMAppService.mainApp.unregister()
3838
}
39-
39+
4040
try? SMAppService.mainApp.register()
4141
} else {
4242
try? SMAppService.mainApp.unregister()
@@ -53,11 +53,11 @@ struct SettingsView: View {
5353
return NSApplication.shared.windows.first
5454
}
5555
}
56-
56+
5757
@StateObject private var launchingAtLogin = LaunchingAtLogin()
5858

5959
@AppStorage("loadConfigurationsOnStartup") private var loadConfigurationsOnStartup = false
60-
@AppStorage("configurationsWillBeLoaded") private var configurationsWillBeLoaded: [URL] = []
60+
@AppStorage("configurationsWillBeLoadedBookmarks") private var configurationsWillBeLoadedBookmarks: [Data] = []
6161

6262
var body: some View {
6363
VStack(alignment: .leading) {
@@ -85,9 +85,16 @@ struct SettingsView: View {
8585
openPanel.title = "Choose a configuration"
8686
openPanel.message = "Add a new configuration that loads at startup."
8787
openPanel.beginSheetModal(for: window) {
88-
if $0 == .OK {
89-
if let openUrl = openPanel.url {
90-
configurationsWillBeLoaded.append(openUrl)
88+
if $0 == .OK, let openUrl = openPanel.url {
89+
do {
90+
let bookmarkData = try openUrl.bookmarkData(
91+
options: [.withSecurityScope],
92+
includingResourceValuesForKeys: nil,
93+
relativeTo: nil
94+
)
95+
configurationsWillBeLoadedBookmarks.append(bookmarkData)
96+
} catch {
97+
showErrorDialog(error)
9198
}
9299
}
93100
}
@@ -99,15 +106,29 @@ struct SettingsView: View {
99106
Spacer()
100107
}
101108

102-
if configurationsWillBeLoaded.count > 0 {
109+
if configurationsWillBeLoadedBookmarks.count > 0 {
103110
VStack {
104-
ForEach(configurationsWillBeLoaded, id: \.absoluteString) {configFile in
111+
ForEach(configurationsWillBeLoadedBookmarks, id: \.self) { bookmarkData in
112+
let displayName: String = {
113+
var stale = false
114+
if let url = try? URL(
115+
resolvingBookmarkData: bookmarkData,
116+
options: [.withSecurityScope],
117+
relativeTo: nil,
118+
bookmarkDataIsStale: &stale
119+
) {
120+
return url.lastPathComponent
121+
}
122+
return "Unknown"
123+
}()
124+
105125
HStack {
106-
Text(configFile.lastPathComponent)
126+
Text(displayName)
107127
Spacer()
108128
Button {
109-
let index = configurationsWillBeLoaded.firstIndex(where: { $0 == configFile })
110-
configurationsWillBeLoaded.remove(at: index!)
129+
if let index = configurationsWillBeLoadedBookmarks.firstIndex(of: bookmarkData) {
130+
configurationsWillBeLoadedBookmarks.remove(at: index)
131+
}
111132
} label: {
112133
Label("Delete Configuration", systemImage: "trash.fill")
113134
.labelStyle(.iconOnly)
@@ -122,7 +143,7 @@ struct SettingsView: View {
122143
Color(NSColor.controlBackgroundColor)
123144
}
124145
.cornerRadius(8)
125-
.animation(.spring, value: configurationsWillBeLoaded)
146+
.animation(.spring, value: configurationsWillBeLoadedBookmarks)
126147
}
127148
}
128149
.transition(.move(edge: .top).combined(with: .opacity))

ui/iPortForwarder/iPortForwarderApp.swift

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,48 @@ import Libipf
55
@main
66
struct iPortForwarderApp: App {
77
@AppStorage("loadConfigurationsOnStartup") private var loadConfigurationsOnStartup = false
8-
@AppStorage("configurationsWillBeLoaded") private var configurationsWillBeLoaded: [URL] = []
8+
@AppStorage("configurationsWillBeLoadedBookmarks") private var configurationsWillBeLoadedBookmarks: [Data] = []
99

1010
init() {
1111
initLibipfErrorHandler()
1212

1313
if loadConfigurationsOnStartup {
14-
for configFile in configurationsWillBeLoaded {
14+
for (index, bookmarkData) in configurationsWillBeLoadedBookmarks.enumerated() {
15+
var stale = false
1516
do {
16-
var jsonString: String
17-
if #available(macOS 13, *) {
18-
jsonString = try String(contentsOfFile: configFile.path(percentEncoded: false))
19-
} else {
20-
jsonString = try String(contentsOfFile: configFile.path)
17+
let configFileURL = try URL(
18+
resolvingBookmarkData: bookmarkData,
19+
options: [.withSecurityScope],
20+
relativeTo: nil,
21+
bookmarkDataIsStale: &stale
22+
)
23+
24+
if stale {
25+
let newBookmarkData = try configFileURL.bookmarkData(
26+
options: [.withSecurityScope],
27+
includingResourceValuesForKeys: nil,
28+
relativeTo: nil
29+
)
30+
configurationsWillBeLoadedBookmarks[index] = newBookmarkData
2131
}
2232

23-
let list = try JSONDecoder().decode([ForwardedItemInfo].self, from: jsonString.data(using: .utf8)!)
33+
if configFileURL.startAccessingSecurityScopedResource() {
34+
defer { configFileURL.stopAccessingSecurityScopedResource() }
35+
36+
let jsonString: String
37+
if #available(macOS 13, *) {
38+
jsonString = try String(contentsOfFile: configFileURL.path(percentEncoded: false))
39+
} else {
40+
jsonString = try String(contentsOfFile: configFileURL.path)
41+
}
2442

25-
for item in list {
26-
globalState.items.append(try ForwardedItem(item: item))
43+
let list = try JSONDecoder().decode([ForwardedItemInfo].self, from: jsonString.data(using: .utf8)!)
44+
45+
for item in list {
46+
globalState.items.append(try ForwardedItem(item: item))
47+
}
48+
} else {
49+
showErrorDialog("Unable to access the configuration file. Please ensure the file exists and that you have granted the necessary permissions.")
2750
}
2851
} catch {
2952
showErrorDialog(error)

0 commit comments

Comments
 (0)