Skip to content

Commit bf95d99

Browse files
committed
Add macOS notifications and skip already converted files
- Show notification when conversion completes (works even with app in foreground) - Skip files that already exist in Converted folder - New status "Skipped (already converted)" for previously processed files
1 parent 0bb436f commit bf95d99

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

S9ToS5/ContentView.swift

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import SwiftUI
22
import UniformTypeIdentifiers
3+
import UserNotifications
34

45
struct LogEntry: Identifiable {
56
let id = UUID()
@@ -9,20 +10,21 @@ struct LogEntry: Identifiable {
910
enum Status {
1011
case success
1112
case skipped
13+
case alreadyExists
1214
case error(String)
1315

1416
var icon: String {
1517
switch self {
1618
case .success: return "checkmark.circle.fill"
17-
case .skipped: return "minus.circle.fill"
19+
case .skipped, .alreadyExists: return "minus.circle.fill"
1820
case .error: return "xmark.circle.fill"
1921
}
2022
}
2123

2224
var color: Color {
2325
switch self {
2426
case .success: return .green
25-
case .skipped: return .orange
27+
case .skipped, .alreadyExists: return .orange
2628
case .error: return .red
2729
}
2830
}
@@ -31,6 +33,7 @@ struct LogEntry: Identifiable {
3133
switch self {
3234
case .success: return "Converted"
3335
case .skipped: return "Skipped (already DC-S5)"
36+
case .alreadyExists: return "Skipped (already converted)"
3437
case .error(let msg): return msg
3538
}
3639
}
@@ -193,6 +196,23 @@ struct ContentView: View {
193196
}
194197
}
195198

199+
private func sendCompletionNotification(successCount: Int, skippedCount: Int, errorCount: Int) {
200+
let content = UNMutableNotificationContent()
201+
content.title = "Conversion Complete"
202+
203+
if errorCount > 0 {
204+
content.body = "Converted \(successCount) files with \(errorCount) errors"
205+
} else if skippedCount > 0 {
206+
content.body = "Converted \(successCount) files, \(skippedCount) skipped"
207+
} else {
208+
content.body = "Successfully converted \(successCount) files"
209+
}
210+
content.sound = .default
211+
212+
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
213+
UNUserNotificationCenter.current().add(request)
214+
}
215+
196216
private func handleDrop(providers: [NSItemProvider]) -> Bool {
197217
guard let provider = providers.first else { return false }
198218

@@ -277,6 +297,9 @@ struct ContentView: View {
277297
case .skipped:
278298
skippedCount += 1
279299
logStatus = .skipped
300+
case .alreadyExists:
301+
skippedCount += 1
302+
logStatus = .alreadyExists
280303
case .error(let message):
281304
errors.append("\(file.lastPathComponent): \(message)")
282305
logStatus = .error(message)
@@ -305,6 +328,7 @@ struct ContentView: View {
305328
}
306329
showError = true
307330
}
331+
sendCompletionNotification(successCount: successCount, skippedCount: skippedCount, errorCount: errors.count)
308332
}
309333
} catch {
310334
await MainActor.run {
@@ -331,6 +355,7 @@ struct ContentView: View {
331355
enum ConvertResult {
332356
case success
333357
case skipped
358+
case alreadyExists
334359
case error(String)
335360
}
336361

@@ -340,6 +365,11 @@ struct ContentView: View {
340365
let fileManager = FileManager.default
341366
let outputURL = outputFolder.appendingPathComponent(fileURL.lastPathComponent)
342367

368+
// Check if converted file already exists
369+
if fileManager.fileExists(atPath: outputURL.path) {
370+
return .alreadyExists
371+
}
372+
343373
do {
344374
// Step 1: Analyze source file (read-only)
345375
let analysisResult = analyzeRW2File(fileURL)
@@ -601,6 +631,14 @@ struct ContentView: View {
601631
}
602632
}
603633

634+
class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
635+
static let shared = NotificationDelegate()
636+
637+
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions {
638+
return [.banner, .sound]
639+
}
640+
}
641+
604642
#Preview {
605643
ContentView()
606644
}

S9ToS5/S9ToS5App.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import SwiftUI
2+
import UserNotifications
23

34
@main
45
struct S9ToS5App: App {
6+
init() {
7+
let center = UNUserNotificationCenter.current()
8+
center.delegate = NotificationDelegate.shared
9+
center.requestAuthorization(options: [.alert, .sound, .badge]) { _, _ in }
10+
}
11+
512
var body: some Scene {
613
WindowGroup {
714
ContentView()

0 commit comments

Comments
 (0)