diff --git a/ProcreateViewer.xcodeproj/project.pbxproj b/ProcreateViewer.xcodeproj/project.pbxproj index 865cc8d..a7b6a0d 100644 --- a/ProcreateViewer.xcodeproj/project.pbxproj +++ b/ProcreateViewer.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ 036AFC11241800350075400A /* ThumbnailProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036AFC10241800350075400A /* ThumbnailProvider.swift */; }; 036AFC16241800350075400A /* Thumbnail.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 036AFC0B241800350075400A /* Thumbnail.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 036AFC1B241800850075400A /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 036AFC1A241800850075400A /* ZIPFoundation */; }; + 037B4042241821D200392452 /* InfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037B4041241821D200392452 /* InfoViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -77,6 +78,7 @@ 036AFC10241800350075400A /* ThumbnailProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThumbnailProvider.swift; sourceTree = ""; }; 036AFC12241800350075400A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 036AFC13241800350075400A /* Thumbnail.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Thumbnail.entitlements; sourceTree = ""; }; + 037B4041241821D200392452 /* InfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -141,6 +143,7 @@ 030F6FFD2415C5E400A43F01 /* Info.plist */, 030F6FFE2415C5E400A43F01 /* ProcreateViewer.entitlements */, 036AFBB924168C030075400A /* ViewController.swift */, + 037B4041241821D200392452 /* InfoViewController.swift */, ); path = ProcreateViewer; sourceTree = ""; @@ -319,6 +322,7 @@ files = ( 036AFBBA24168C030075400A /* ViewController.swift in Sources */, 030F6FF42415C5E300A43F01 /* Document.swift in Sources */, + 037B4042241821D200392452 /* InfoViewController.swift in Sources */, 030F6FF22415C5E300A43F01 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ProcreateViewer/AppDelegate.swift b/ProcreateViewer/AppDelegate.swift index c391a90..e090107 100644 --- a/ProcreateViewer/AppDelegate.swift +++ b/ProcreateViewer/AppDelegate.swift @@ -1,6 +1,17 @@ import Cocoa @NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { +class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations { + @IBAction func showInfoAction(_ sender: Any) { + NSApplication.shared.keyWindow?.contentViewController?.performSegue(withIdentifier: "showInfo", sender: self) + } + + func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool { + if(item.tag == 67) { + return NSApplication.shared.keyWindow != nil + } + + return true + } } diff --git a/ProcreateViewer/Base.lproj/Main.storyboard b/ProcreateViewer/Base.lproj/Main.storyboard index 110504d..eb2e8b3 100644 --- a/ProcreateViewer/Base.lproj/Main.storyboard +++ b/ProcreateViewer/Base.lproj/Main.storyboard @@ -90,25 +90,13 @@ - - - - - - - + - + - - - - - - @@ -164,9 +152,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -210,11 +245,12 @@ + - + diff --git a/ProcreateViewer/Document.swift b/ProcreateViewer/Document.swift index ada6f52..48db52b 100644 --- a/ProcreateViewer/Document.swift +++ b/ProcreateViewer/Document.swift @@ -1,8 +1,14 @@ import Cocoa import ZIPFoundation +struct DocumentInfo { + var tracked_time: Int = 0 +} + class Document: NSDocument { - var image: NSImage? + var info = DocumentInfo() + + var thumbnail: NSImage? = nil override init() { super.init() @@ -19,6 +25,7 @@ class Document: NSDocument { return } + // load thumbnail guard let entry = archive["QuickLook/Thumbnail.png"] else { return } @@ -33,7 +40,39 @@ class Document: NSDocument { Swift.print("Extracting entry from archive failed with error:\(error)") } - image = NSImage(data: top_data) + thumbnail = NSImage(data: top_data) + + // load doc info + guard let document_entry = archive["Document.archive"] else { + return + } + + var doc_data = Data() + + do { + try archive.extract(document_entry, consumer: { (d) in + doc_data.append(d) + }) + } catch { + Swift.print("Extracting entry from archive failed with error:\(error)") + } + + // Document.archive is a binary plist (specifically a NSKeyedArchive), luckily swift has a built-in solution to decode it + var plistFormat = PropertyListSerialization.PropertyListFormat.binary + let plistBinary = doc_data + + guard let propertyList = try? PropertyListSerialization.propertyList(from: plistBinary, options: [], format: &plistFormat) else { + fatalError("failed to deserialize") + } + + // this is temporary, as we're just hoping that the keyed archive fits our requirements... + let dict = (propertyList as! NSDictionary); + + let objects = dict["$objects"] as! NSArray + + let tracked_time = (objects[1] as! NSDictionary)["SilicaDocumentTrackedTimeKey"] + + info.tracked_time = (tracked_time as! NSNumber).intValue } } diff --git a/ProcreateViewer/InfoViewController.swift b/ProcreateViewer/InfoViewController.swift new file mode 100644 index 0000000..b94d3fa --- /dev/null +++ b/ProcreateViewer/InfoViewController.swift @@ -0,0 +1,20 @@ +import Foundation +import Cocoa + +class InfoViewController: NSViewController { + var document: Document? + + @IBOutlet weak var timeSpentLabel: NSTextField! + + override func viewDidAppear() { + super.viewDidAppear() + + let formatter = DateComponentsFormatter() + formatter.allowedUnits = [.hour, .minute, .second] + formatter.unitsStyle = .full + + let formattedString = formatter.string(from: TimeInterval(document!.info.tracked_time))! + + timeSpentLabel.stringValue = "Time Spent: " + formattedString + } +} diff --git a/ProcreateViewer/ViewController.swift b/ProcreateViewer/ViewController.swift index d14927d..26c8cca 100644 --- a/ProcreateViewer/ViewController.swift +++ b/ProcreateViewer/ViewController.swift @@ -7,6 +7,13 @@ class ViewController: NSViewController { override func viewWillAppear() { let document = self.view.window?.windowController?.document as? Document - imageView.image = document?.image + imageView.image = document?.thumbnail + } + + override func prepare(for segue: NSStoryboardSegue, sender: Any?) { + if(segue.identifier == "showInfo") { + // TODO: there HAS to be a better way to pass the Document class along... + (segue.destinationController as! InfoViewController).document = self.view.window?.windowController?.document as? Document + } } }