11import SwiftUI
22import UniformTypeIdentifiers
3+ import UserNotifications
34
45struct 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}
0 commit comments