diff --git a/ImagePlace.swift b/ImagePlace.swift index a397961..752d1be 100644 --- a/ImagePlace.swift +++ b/ImagePlace.swift @@ -7,7 +7,7 @@ import Foundation import SwiftUI - +import os class ImagePlace: ObservableObject { @Published var image: NSImage? var imageFiles: [URL] = [] @@ -16,6 +16,7 @@ class ImagePlace: ObservableObject { func loadImg(url:URL) { do {let data = try Data(contentsOf: url) let img = NSImage(dataIgnoringOrientation: data) + Logger.events.info("Loading file \(url.lastPathComponent, privacy: .public) index \(self.current+1, privacy: .public) of \(self.imageFiles.count, privacy: .public)") image = img } catch { } @@ -31,7 +32,7 @@ class ImagePlace: ObservableObject { } func prev() { - if(current <= 1 ) { + if(current < 1 ) { return } else { current = current - 1 diff --git a/InfraLogger.swift b/InfraLogger.swift index ffea53b..c4c5eb1 100644 --- a/InfraLogger.swift +++ b/InfraLogger.swift @@ -6,3 +6,12 @@ // import Foundation + +import OSLog + +extension Logger { + /// Using your bundle identifier is a great way to ensure a unique identifier. + private static var subsystem = Bundle.main.bundleIdentifier! +/// All logs related to tracking and analytics. + static let events = Logger(subsystem: subsystem, category: "events") +} diff --git a/InfranMac.xcodeproj/project.pbxproj b/InfranMac.xcodeproj/project.pbxproj index d9294db..2389fc8 100644 --- a/InfranMac.xcodeproj/project.pbxproj +++ b/InfranMac.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 484AFE322AFED5D300DB4763 /* InfranMacTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 484AFE312AFED5D300DB4763 /* InfranMacTests.swift */; }; 484AFE3C2AFED5D300DB4763 /* InfranMacUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 484AFE3B2AFED5D300DB4763 /* InfranMacUITests.swift */; }; 484AFE3E2AFED5D300DB4763 /* InfranMacUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 484AFE3D2AFED5D300DB4763 /* InfranMacUITestsLaunchTests.swift */; }; + 4857227D2B003496009E26E8 /* InfraLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4857227C2B003496009E26E8 /* InfraLogger.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,6 +51,7 @@ 484AFE372AFED5D300DB4763 /* InfranMacUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InfranMacUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 484AFE3B2AFED5D300DB4763 /* InfranMacUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfranMacUITests.swift; sourceTree = ""; }; 484AFE3D2AFED5D300DB4763 /* InfranMacUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfranMacUITestsLaunchTests.swift; sourceTree = ""; }; + 4857227C2B003496009E26E8 /* InfraLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfraLogger.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -80,6 +82,7 @@ 484AFE132AFED5D200DB4763 = { isa = PBXGroup; children = ( + 4857227C2B003496009E26E8 /* InfraLogger.swift */, 483653602AFFACCE00120E09 /* DirectoryResult.swift */, 4836535E2AFF8A0500120E09 /* ImagePlace.swift */, 484AFE1E2AFED5D200DB4763 /* InfranMac */, @@ -268,6 +271,7 @@ buildActionMask = 2147483647; files = ( 483653612AFFACCE00120E09 /* DirectoryResult.swift in Sources */, + 4857227D2B003496009E26E8 /* InfraLogger.swift in Sources */, 484AFE222AFED5D200DB4763 /* ContentView.swift in Sources */, 484AFE202AFED5D200DB4763 /* InfranMacApp.swift in Sources */, 4836535F2AFF8A0500120E09 /* ImagePlace.swift in Sources */, @@ -420,6 +424,7 @@ MACOSX_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; }; diff --git a/InfranMac/ContentView.swift b/InfranMac/ContentView.swift index 70b375e..cfad517 100644 --- a/InfranMac/ContentView.swift +++ b/InfranMac/ContentView.swift @@ -24,7 +24,8 @@ struct ContentView: View { Text("No image") } } - } + } + } #Preview { diff --git a/InfranMac/Info.plist b/InfranMac/Info.plist index 0451416..2429bbd 100644 --- a/InfranMac/Info.plist +++ b/InfranMac/Info.plist @@ -3,57 +3,19 @@ CFBundleDocumentTypes - + + CFBundleTypeIconFiles + CFBundleTypeName - Jpeg + Images CFBundleTypeRole Viewer LSHandlerRank - Default + Alternate LSItemContentTypes - public.jpeg - - NSDocumentClass - NSDocument - - - CFBundleTypeName - GIf - CFBundleTypeRole - Viewer - LSHandlerRank - Default - LSItemContentTypes - - com.compuserve.gif - - - - CFBundleIdentifier - - CFBundleTypeName - Heic - CFBundleTypeRole - Viewer - LSHandlerRank - Default - LSItemContentTypes - - public.heic - - - - CFBundleTypeName - Png - CFBundleTypeRole - Viewer - LSHandlerRank - Default - LSItemContentTypes - - public.png + public.image diff --git a/InfranMac/InfranMacApp.swift b/InfranMac/InfranMacApp.swift index 59d7232..2153957 100644 --- a/InfranMac/InfranMacApp.swift +++ b/InfranMac/InfranMacApp.swift @@ -6,23 +6,40 @@ // import SwiftUI +import Combine +import os @main struct InfranMacApp: App { + @NSApplicationDelegateAdaptor private var appDelegate : AppDelegate + @StateObject private var imageP : ImagePlace = ImagePlace() + + var body: some Scene { WindowGroup { ContentView(model: imageP) .frame(maxWidth: .infinity, maxHeight: .infinity) .edgesIgnoringSafeArea(.all) .onAppear { - DispatchQueue.main.async { - if let window = NSApplication.shared.windows.last { - window.toggleFullScreen(nil) - } - } - } + appDelegate.$url.sink{ urlOpt in + Logger.events.info("onAppear \(String(describing: urlOpt), privacy: .public)") + if let url = urlOpt { + if let dirResult = openUrl(url:url) { + imageP.imageFiles = dirResult.images + imageP.image = dirResult.image + imageP.current = dirResult.myIndex + } + } + }.store(in: &appDelegate.cancellables) + DispatchQueue.main.async { + if let window = NSApplication.shared.windows.last { + window.toggleFullScreen(nil) + } + } + } } + .handlesExternalEvents(matching: []) .commands{ CommandGroup(replacing: .newItem) { Button("OpenFile") { @@ -40,56 +57,70 @@ struct InfranMacApp: App { }.keyboardShortcut(KeyEquivalent.leftArrow) } } + } + + func openUrl(url: URL) -> DirectoryResult? { + let knownImageTypes = ["public.jpeg","public.heic","com.compuserve.gif","public.png"] + let fm = FileManager.default + let options: FileManager.DirectoryEnumerationOptions = [.skipsHiddenFiles, .skipsPackageDescendants, .skipsSubdirectoryDescendants] + let keys: [URLResourceKey] = [.isRegularFileKey, .typeIdentifierKey] + var imageFiles: [URL] = [] + var myIndex = -1 + if let enumerator = fm.enumerator(at: url.deletingLastPathComponent(), includingPropertiesForKeys: keys, options: options, errorHandler: nil) { + for case let fileURL as URL in enumerator { + do { + let resourceValues = try fileURL.resourceValues(forKeys: Set(keys)) + if let isRegularFile = resourceValues.isRegularFile, isRegularFile { + if let typeIdentifier = resourceValues.typeIdentifier, knownImageTypes.contains(where: {typeIdentifier.contains($0)}){ + imageFiles.append(fileURL) + } + } + } catch { + Logger.events.warning("Error getting resource values for \(fileURL.path, privacy: .public): \(error.localizedDescription, privacy: .public)") + } + } + imageFiles.sort(by: {$0.lastPathComponent < $1.lastPathComponent }) + myIndex = imageFiles.lastIndex(of: url) ?? -1 + } + do {let data = try Data(contentsOf: url) + let img = NSImage(dataIgnoringOrientation: data) + let res = DirectoryResult( + image: img, + images: imageFiles, + myIndex: myIndex, + path:url.deletingLastPathComponent() + ) + return res + } catch { + Logger.events.warning("Exception \(error.localizedDescription, privacy: .public)") + return nil + } + } + func openFile() -> DirectoryResult? { let openPanel = NSOpenPanel() openPanel.allowedContentTypes = [.image] openPanel.allowsMultipleSelection = false - let knownImageTypes = ["public.jpeg","public.heic","com.compuserve.gif","public.png"] if openPanel.runModal() == .OK { if let url = openPanel.url { - let fm = FileManager.default - let options: FileManager.DirectoryEnumerationOptions = [.skipsHiddenFiles, .skipsPackageDescendants, .skipsSubdirectoryDescendants] - let keys: [URLResourceKey] = [.isRegularFileKey, .typeIdentifierKey] - var imageFiles: [URL] = [] - var myIndex = -1 - var fileIndex = -1 - if let enumerator = fm.enumerator(at: url.deletingLastPathComponent(), includingPropertiesForKeys: keys, options: options, errorHandler: nil) { - for case let fileURL as URL in enumerator { - do { - let resourceValues = try fileURL.resourceValues(forKeys: Set(keys)) - if let isRegularFile = resourceValues.isRegularFile, isRegularFile { - if let typeIdentifier = resourceValues.typeIdentifier, knownImageTypes.contains(where: {typeIdentifier.contains($0)}){ - imageFiles.append(fileURL) - fileIndex = fileIndex + 1 - if(fileURL == url) { - myIndex = fileIndex - } - } - } - } catch { - print("Error getting resource values for \(fileURL.path): \(error)") - } - } - } - do {let data = try Data(contentsOf: url) - let img = NSImage(dataIgnoringOrientation: data) - let res = DirectoryResult( - image: img, - images: imageFiles, - myIndex: myIndex, - path:url.deletingLastPathComponent() - ) - return res - } catch { - print("Exception \(error.localizedDescription)") - } + return openUrl(url: url) } else { - print("open panel url failed") + Logger.events.info("open panel url failed") } } return nil } } + +class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { + @Published var url: URL? + func application(_ application: NSApplication, open urls: [URL]) { + url = urls.first + let last = url?.lastPathComponent ?? "" + Logger.events.warning("application \(last, privacy: .public)") + } + var cancellables = Set() +}