Skip to content

Commit 388972d

Browse files
committed
v1.9
1 parent 8532f15 commit 388972d

3 files changed

Lines changed: 39 additions & 10 deletions

File tree

Sources/Models.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ class RouteManager: ObservableObject {
266266
/// Result of last apply operation for toast display
267267
enum ApplyResult { case success(Int), error(String), none }
268268
@Published var applyResult: ApplyResult = .none
269+
/// Result of last refresh for toast display
270+
enum RefreshResult: Equatable { case success(String, Int), error(String), none }
271+
@Published var refreshResult: RefreshResult = .none
269272

270273
private let rulesKey = "TunnelGuardRules"
271274

@@ -360,11 +363,15 @@ class RouteManager: ObservableObject {
360363
await MainActor.run {
361364
if ips.isEmpty {
362365
lastError = "Could not resolve \(rule.domain)"
366+
refreshResult = .error("Could not resolve \(rule.domain)")
363367
log("⚠️ Resolution failed for \(rule.domain)")
364368
if !debugOutput.isEmpty {
365369
log(" output: \(debugOutput)")
366370
}
367-
DispatchQueue.main.asyncAfter(deadline: .now() + 4) { self.lastError = nil }
371+
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
372+
self.lastError = nil
373+
self.refreshResult = .none
374+
}
368375
} else {
369376
lastError = nil
370377
rules[idx].resolvedIPs = ips
@@ -373,7 +380,11 @@ class RouteManager: ObservableObject {
373380
applyRoutes(for: rules[idx])
374381
}
375382
saveRules()
383+
refreshResult = .success(rule.domain, ips.count)
376384
log("Refreshed IPs for \(rule.domain)\(ips.joined(separator: ", "))")
385+
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
386+
self.refreshResult = .none
387+
}
377388
}
378389
}
379390
}

Sources/Views.swift

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ struct ContentView: View {
8282
@State private var showApplyToast = false
8383
@State private var applyToastMessage = ""
8484
@State private var applyToastIsError = false
85+
@State private var showRefreshToast = false
86+
@State private var refreshToastMessage = ""
87+
@State private var refreshToastIsError = false
8588

8689
enum AppTab: String, CaseIterable {
8790
case rules = "Rules"
@@ -172,14 +175,13 @@ struct ContentView: View {
172175
.environmentObject(settings)
173176
.preferredColorScheme(settings.themeMode == .dark ? .dark : settings.themeMode == .light ? .light : nil)
174177
.modifier(ToastOverlay(
175-
message: applyToastMessage,
176-
icon: applyToastIsError ? "exclamationmark.triangle.fill" : "checkmark.circle.fill",
177-
iconColor: applyToastIsError ? colors.accentOrange : colors.accentGreen,
178-
isShowing: showApplyToast,
178+
message: showRefreshToast ? refreshToastMessage : applyToastMessage,
179+
icon: (showRefreshToast ? refreshToastIsError : applyToastIsError) ? "exclamationmark.triangle.fill" : "checkmark.circle.fill",
180+
iconColor: (showRefreshToast ? refreshToastIsError : applyToastIsError) ? colors.accentOrange : colors.accentGreen,
181+
isShowing: showApplyToast || showRefreshToast,
179182
colors: colors
180183
))
181184
.onChange(of: routeManager.isApplying) { applying in
182-
// When applying finishes, check the result
183185
if !applying {
184186
switch routeManager.applyResult {
185187
case .success(let count):
@@ -197,6 +199,22 @@ struct ContentView: View {
197199
}
198200
}
199201
}
202+
.onChange(of: routeManager.refreshResult) { result in
203+
switch result {
204+
case .success(let domain, let count):
205+
refreshToastMessage = "\(domain)\(count) IP\(count == 1 ? "" : "s") resolved"
206+
refreshToastIsError = false
207+
withAnimation { showRefreshToast = true }
208+
DispatchQueue.main.asyncAfter(deadline: .now() + 3) { withAnimation { showRefreshToast = false } }
209+
case .error(let msg):
210+
refreshToastMessage = msg
211+
refreshToastIsError = true
212+
withAnimation { showRefreshToast = true }
213+
DispatchQueue.main.asyncAfter(deadline: .now() + 4) { withAnimation { showRefreshToast = false } }
214+
case .none:
215+
break
216+
}
217+
}
200218
}
201219
}
202220

TunnelGuard.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@
280280
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
281281
CODE_SIGN_STYLE = Automatic;
282282
COMBINE_HIDPI_IMAGES = YES;
283-
CURRENT_PROJECT_VERSION = 60;
283+
CURRENT_PROJECT_VERSION = 66;
284284
DEAD_CODE_STRIPPING = YES;
285285
DEVELOPMENT_TEAM = DFDRW6TJH5;
286286
ENABLE_APP_SANDBOX = NO;
@@ -297,7 +297,7 @@
297297
"@executable_path/../Frameworks",
298298
);
299299
MACOSX_DEPLOYMENT_TARGET = 13.0;
300-
MARKETING_VERSION = 1.8.0;
300+
MARKETING_VERSION = 1.9.0;
301301
PRODUCT_BUNDLE_IDENTIFIER = com.amirhpcom.tunnelguard;
302302
PRODUCT_NAME = "$(TARGET_NAME)";
303303
SDKROOT = macosx;
@@ -315,7 +315,7 @@
315315
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
316316
CODE_SIGN_STYLE = Automatic;
317317
COMBINE_HIDPI_IMAGES = YES;
318-
CURRENT_PROJECT_VERSION = 60;
318+
CURRENT_PROJECT_VERSION = 66;
319319
DEAD_CODE_STRIPPING = YES;
320320
DEVELOPMENT_TEAM = DFDRW6TJH5;
321321
ENABLE_APP_SANDBOX = NO;
@@ -332,7 +332,7 @@
332332
"@executable_path/../Frameworks",
333333
);
334334
MACOSX_DEPLOYMENT_TARGET = 13.0;
335-
MARKETING_VERSION = 1.8.0;
335+
MARKETING_VERSION = 1.9.0;
336336
PRODUCT_BUNDLE_IDENTIFIER = com.amirhpcom.tunnelguard;
337337
PRODUCT_NAME = "$(TARGET_NAME)";
338338
SDKROOT = macosx;

0 commit comments

Comments
 (0)