From fa02b7971d7274fddc4268a901dece55f70eb32c Mon Sep 17 00:00:00 2001 From: Patrick Kladek Date: Sun, 2 Jan 2022 18:31:23 +0400 Subject: [PATCH 1/4] Add image & language option to cli export --- Screenshot Framer CLI/Export.swift | 8 +++++- .../xcschemes/Screenshot-Framer-CLI.xcscheme | 6 ++-- .../ContentViewController.swift | 2 +- .../Help Controller/ExportController.swift | 28 ++++++++++++------- .../Help Controller/LanguageController.swift | 10 +++++-- .../Help Controller/LayoutController.swift | 2 +- Screenshot Framer/Model/OutputConfig.swift | 22 +++++++++++++++ 7 files changed, 60 insertions(+), 18 deletions(-) diff --git a/Screenshot Framer CLI/Export.swift b/Screenshot Framer CLI/Export.swift index 70f1030..17fd95d 100644 --- a/Screenshot Framer CLI/Export.swift +++ b/Screenshot Framer CLI/Export.swift @@ -17,6 +17,12 @@ final class Export: ParsableCommand { @Flag(help: "Ignore Warnings about potential issues like clipped text") var ignoreWarnings: Bool = false + @Option(help: "Export only image with given number") + var image: Int? + + @Option(help: "Export only the given language") + var language: String? + // MARK: - Export func run() throws { @@ -76,7 +82,7 @@ extension Export { exportController.delegate = self ConsoleIO.writeMessage("Project: \(project.lastPathComponent)") - let exportErrors = exportController.saveAllImages() + let exportErrors = exportController.saveAllImages(language: self.language, start: self.image, end: self.image) if self.checkedErrors(exportErrors).hasElements { ConsoleIO.writeMessage("Something went wrong while exporting. Please check the projects for detailed information", to: .error) diff --git a/Screenshot Framer.xcodeproj/xcshareddata/xcschemes/Screenshot-Framer-CLI.xcscheme b/Screenshot Framer.xcodeproj/xcshareddata/xcschemes/Screenshot-Framer-CLI.xcscheme index 15e0e76..5690c6f 100644 --- a/Screenshot Framer.xcodeproj/xcshareddata/xcschemes/Screenshot-Framer-CLI.xcscheme +++ b/Screenshot Framer.xcodeproj/xcshareddata/xcschemes/Screenshot-Framer-CLI.xcscheme @@ -61,12 +61,12 @@ + argument = "export --input /Users/patrick/Developer/Bikemap-AppStore/Input --language de-DE --image 7 --ignore-warnings" + isEnabled = "YES"> + isEnabled = "NO"> diff --git a/Screenshot Framer/Document Window/Content View Controller/ContentViewController.swift b/Screenshot Framer/Document Window/Content View Controller/ContentViewController.swift index a76569e..72445a9 100644 --- a/Screenshot Framer/Document Window/Content View Controller/ContentViewController.swift +++ b/Screenshot Framer/Document Window/Content View Controller/ContentViewController.swift @@ -300,7 +300,7 @@ final class ContentViewController: NSViewController, NSMenuItemValidation { self.layoutController.highlightLayer = self.tableView.selectedRow self.inspectorViewController?.updateUI() self.inspectorViewController?.updateUIFromViewState() - self.scrollView.documentView = self.layoutController.layouthierarchy(layers: self.lastLayerState.layers) + self.scrollView.documentView = self.layoutController.layoutHierarchy(layers: self.lastLayerState.layers) self.layoutWarningButton.isHidden = self.layoutController.layoutErrors.isEmpty self.textFieldOutput.stringValue = self.lastLayerState.outputConfig.output diff --git a/Screenshot Framer/Document Window/Content View Controller/Help Controller/ExportController.swift b/Screenshot Framer/Document Window/Content View Controller/Help Controller/ExportController.swift index 4582c2e..38b89c0 100644 --- a/Screenshot Framer/Document Window/Content View Controller/Help Controller/ExportController.swift +++ b/Screenshot Framer/Document Window/Content View Controller/Help Controller/ExportController.swift @@ -44,7 +44,7 @@ final class ExportController { let fileManager = FileManager() let viewStateController = ViewStateController(viewState: viewState) let layoutController = LayoutController(viewStateController: viewStateController, languageController: self.languageController, fileController: self.fileController) - guard let view = layoutController.layouthierarchy(layers: self.lastLayerState.layers) else { return [.noLayers] } + guard let view = layoutController.layoutHierarchy(layers: self.lastLayerState.layers) else { return [.noLayers] } let data = view.pngData() guard let url = self.fileController.outputURL(for: self.lastLayerState, viewState: viewState) else { return [.noOutputFile] } @@ -56,21 +56,24 @@ final class ExportController { } @discardableResult - func saveAllImages() -> [LayoutError] { + func saveAllImages(language: String? = nil, start: Int? = nil, end: Int? = nil) -> [LayoutError] { self.shouldCancel = false let viewStateController = ViewStateController() let layoutController = LayoutController(viewStateController: viewStateController, languageController: self.languageController, fileController: self.fileController) let fileManager = FileManager() - let totalSteps = self.calculatePossibleComabinations(languageController: self.languageController) + let totalSteps = self.calculatePossibleComabinations(languageController: self.languageController, langauge: language, start: start, end: end) var currentStep = 0 - for language in self.languageController.allLanguages() { + for language in self.languageController.allLanguages(prefered: language) { viewStateController.newViewState(language: language) - for index in self.lastLayerState.outputConfig.fromImageNumber...self.lastLayerState.outputConfig.toImageNumber { + guard let lower = self.lastLayerState.outputConfig.prefered(from: start) else { continue } + guard let upper = self.lastLayerState.outputConfig.prefered(end: end) else { continue } + + for index in lower...upper { viewStateController.newViewState(imageNumber: index) - guard let view = layoutController.layouthierarchy(layers: self.lastLayerState.layers) else { continue } // TODO: is called from a background thread + guard let view = layoutController.layoutHierarchy(layers: self.lastLayerState.layers) else { continue } // TODO: is called from a background thread let data = view.pngData() guard let url = self.fileController.outputURL(for: self.lastLayerState, viewState: viewStateController.viewState) else { return [.noOutputFile] } @@ -105,7 +108,7 @@ final class ExportController { for currentImageNumber in 0...numberOfImages { tempViewStateController.newViewState(imageNumber: currentImageNumber + firstImageNumber) - guard let image = tempLayoutController.layouthierarchy(layers: self.lastLayerState.layers) else { continue } + guard let image = tempLayoutController.layoutHierarchy(layers: self.lastLayerState.layers) else { continue } let offsetX = image.frame.width * CGFloat(currentImageNumber) image.frame = image.frame.offsetBy(dx: offsetX, dy: 0) @@ -142,7 +145,7 @@ final class ExportController { let language = allLanguages[currentImageNumber] tempViewStateController.newViewState(language: language) - guard let image = tempLayoutController.layouthierarchy(layers: self.lastLayerState.layers) else { continue } + guard let image = tempLayoutController.layoutHierarchy(layers: self.lastLayerState.layers) else { continue } let offsetX = image.frame.width * CGFloat(currentImageNumber) image.frame = image.frame.offsetBy(dx: offsetX, dy: 0) @@ -170,14 +173,19 @@ final class ExportController { private extension ExportController { - func calculatePossibleComabinations(languageController: LanguageController) -> Int { + func calculatePossibleComabinations(languageController: LanguageController, langauge: String? = nil, start: Int? = nil, end: Int? = nil) -> Int { let outputConfig = self.lastLayerState.outputConfig + if let lower = outputConfig.prefered(from: start), let upper = outputConfig.prefered(end: end) { + let totalSteps = upper - lower + 1 + return languageController.allLanguages(prefered: langauge).count * totalSteps + } + // because we use a for-loop and `for n in 1...1` would // mean 1 execution but (1 - 1 = 0) we handle this special case // by adding +1 so the progressBar is still updated correctly let totalSteps = outputConfig.toImageNumber - outputConfig.fromImageNumber + 1 - return languageController.allLanguages().count * totalSteps + return languageController.allLanguages(prefered: langauge).count * totalSteps } } diff --git a/Screenshot Framer/Document Window/Content View Controller/Help Controller/LanguageController.swift b/Screenshot Framer/Document Window/Content View Controller/Help Controller/LanguageController.swift index be27080..cd5a517 100644 --- a/Screenshot Framer/Document Window/Content View Controller/Help Controller/LanguageController.swift +++ b/Screenshot Framer/Document Window/Content View Controller/Help Controller/LanguageController.swift @@ -23,7 +23,7 @@ final class LanguageController { // MARK: - LanguageController - func allLanguages() -> [String] { + func allLanguages(prefered: String? = nil) -> [String] { let fileManager = FileManager() guard let projectURL = self.fileCapsule.projectURL else { return [] } guard let contents = try? fileManager.contentsOfDirectory(at: projectURL, includingPropertiesForKeys: nil, options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles]) else { return [] } @@ -35,6 +35,12 @@ final class LanguageController { }.compactMap { $0.lastPathComponent } let blackList = ["backgrounds", "device_frames", "export"] - return allLanguages.subtracting(blackList, caseSensitive: false) + let filteredLanguages = allLanguages.subtracting(blackList, caseSensitive: false) + if let prefered = prefered { + if filteredLanguages.contains(where: { $0.caseInsensitiveCompare(prefered) == .orderedSame }) { + return [prefered] + } + } + return filteredLanguages } } diff --git a/Screenshot Framer/Document Window/Content View Controller/Help Controller/LayoutController.swift b/Screenshot Framer/Document Window/Content View Controller/Help Controller/LayoutController.swift index d87bb5f..6964bf3 100644 --- a/Screenshot Framer/Document Window/Content View Controller/Help Controller/LayoutController.swift +++ b/Screenshot Framer/Document Window/Content View Controller/Help Controller/LayoutController.swift @@ -53,7 +53,7 @@ class LayoutController { // MARK: - Public Functions - func layouthierarchy(layers: [LayoutableObject]) -> NSView? { + func layoutHierarchy(layers: [LayoutableObject]) -> NSView? { self.layoutErrors = [] guard layers.hasElements else { self.layoutErrors = [.noLayers]; return nil } diff --git a/Screenshot Framer/Model/OutputConfig.swift b/Screenshot Framer/Model/OutputConfig.swift index 5e4fe6b..211c270 100644 --- a/Screenshot Framer/Model/OutputConfig.swift +++ b/Screenshot Framer/Model/OutputConfig.swift @@ -17,3 +17,25 @@ struct OutputConfig: Codable { let fromImageNumber: Int let toImageNumber: Int } + +extension OutputConfig { + + func prefered(from: Int?) -> Int? { + guard let from = from else { return nil } + + if from >= self.fromImageNumber && from <= self.toImageNumber { + return from + } + + return nil + } + + func prefered(end: Int?) -> Int? { + guard let end = end else { return nil } + + if end >= self.fromImageNumber && end <= self.toImageNumber { + return end + } + return nil + } +} From 0b752001fcb3ba048e5ca6d0cd2a00b91b51e3a0 Mon Sep 17 00:00:00 2001 From: Patrick Kladek Date: Sun, 2 Jan 2022 18:35:16 +0400 Subject: [PATCH 2/4] Migrate to swift5 --- Screenshot Framer.xcodeproj/project.pbxproj | 5 +++-- .../Help Controller/ExportController.swift | 13 +++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Screenshot Framer.xcodeproj/project.pbxproj b/Screenshot Framer.xcodeproj/project.pbxproj index 910fafa..3614d92 100644 --- a/Screenshot Framer.xcodeproj/project.pbxproj +++ b/Screenshot Framer.xcodeproj/project.pbxproj @@ -438,6 +438,7 @@ }; CD9395551FF6AC6D00D3D831 = { CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1310; ProvisioningStyle = Automatic; }; CDFF69941FD827B800E652EE = { @@ -802,7 +803,7 @@ ENABLE_HARDENED_RUNTIME = YES; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -815,7 +816,7 @@ ENABLE_HARDENED_RUNTIME = YES; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Screenshot Framer/Document Window/Content View Controller/Help Controller/ExportController.swift b/Screenshot Framer/Document Window/Content View Controller/Help Controller/ExportController.swift index 38b89c0..fe13714 100644 --- a/Screenshot Framer/Document Window/Content View Controller/Help Controller/ExportController.swift +++ b/Screenshot Framer/Document Window/Content View Controller/Help Controller/ExportController.swift @@ -44,13 +44,14 @@ final class ExportController { let fileManager = FileManager() let viewStateController = ViewStateController(viewState: viewState) let layoutController = LayoutController(viewStateController: viewStateController, languageController: self.languageController, fileController: self.fileController) - guard let view = layoutController.layoutHierarchy(layers: self.lastLayerState.layers) else { return [.noLayers] } - let data = view.pngData() + guard let view = layoutController.layoutHierarchy(layers: self.lastLayerState.layers) else { return [.noLayers] } guard let url = self.fileController.outputURL(for: self.lastLayerState, viewState: viewState) else { return [.noOutputFile] } try? fileManager.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil) - try? data?.write(to: url, options: .atomic) + if let data = view.pngData() { + try? data.write(to: url, options: .atomic) + } return layoutController.layoutErrors } @@ -74,12 +75,12 @@ final class ExportController { for index in lower...upper { viewStateController.newViewState(imageNumber: index) guard let view = layoutController.layoutHierarchy(layers: self.lastLayerState.layers) else { continue } // TODO: is called from a background thread - - let data = view.pngData() guard let url = self.fileController.outputURL(for: self.lastLayerState, viewState: viewStateController.viewState) else { return [.noOutputFile] } try? fileManager.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil) - try? data?.write(to: url, options: .atomic) + if let data = view.pngData() { + try? data.write(to: url, options: .atomic) + } currentStep += 1 let progress = Double(currentStep) / Double(totalSteps) From a6b3238094b14fd3dfd27988613a7ef6e17cb0dc Mon Sep 17 00:00:00 2001 From: Patrick Kladek Date: Sun, 2 Jan 2022 18:58:27 +0400 Subject: [PATCH 3/4] fix deprecation warning --- .../Supporting Files/Code/NSColor+Hex.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Screenshot Framer/Supporting Files/Code/NSColor+Hex.swift b/Screenshot Framer/Supporting Files/Code/NSColor+Hex.swift index 7d613c0..1b5c8a0 100644 --- a/Screenshot Framer/Supporting Files/Code/NSColor+Hex.swift +++ b/Screenshot Framer/Supporting Files/Code/NSColor+Hex.swift @@ -17,11 +17,11 @@ extension NSColor { * - returns: NSColor with rgba value */ convenience init?(hex: String) { - var cString = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() - cString.cleanHexPrefix() + var trimmed = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() + trimmed.cleanHexPrefix() - var hexNumber: UInt32 = 0 - Scanner(string: cString).scanHexInt32(&hexNumber) + var hexNumber: UInt64 = 0 + Scanner(string: trimmed).scanHexInt64(&hexNumber) self.init(red: CGFloat( (hexNumber & 0xFF000000) >> 24) / 255.0, green: CGFloat( (hexNumber & 0x00FF0000) >> 16) / 255.0, @@ -31,6 +31,7 @@ extension NSColor { func hexString() -> String { guard let standardizedColor = self.usingColorSpace(.sRGB) else { return "" } + let red = Int(standardizedColor.redComponent * 255.0) let green = Int(standardizedColor.greenComponent * 255.0) let blue = Int(standardizedColor.blueComponent * 255.0) From e9be543d1cb8988beb1df356c3b2aa099567cf3a Mon Sep 17 00:00:00 2001 From: Patrick Kladek Date: Sun, 2 Jan 2022 19:02:04 +0400 Subject: [PATCH 4/4] use system installed swiftlint version --- .swiftlint.yml | 1 + Screenshot Framer.xcodeproj/project.pbxproj | 4 ++-- .../Content View Controller/ContentViewController.swift | 2 +- .../Progress Window/ProgressWindowController.swift | 4 ++-- .../Time Travel/TimeTravelWindowController.swift | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index de4af09..7c4b365 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,6 +1,7 @@ --- disabled_rules: - line_length + - inclusive_language - nesting - todo excluded: diff --git a/Screenshot Framer.xcodeproj/project.pbxproj b/Screenshot Framer.xcodeproj/project.pbxproj index 3614d92..113fa07 100644 --- a/Screenshot Framer.xcodeproj/project.pbxproj +++ b/Screenshot Framer.xcodeproj/project.pbxproj @@ -512,7 +512,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Swift Lint\n(exec ./.tools/SwiftLint/swiftlint)\n"; + shellScript = "# Swift Lint\nexec swiftlint\n"; }; CDAEE1FC1FED46EE00F4B1BA /* Swift Lint */ = { isa = PBXShellScriptBuildPhase; @@ -526,7 +526,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Swift Lint\n(exec ./.tools/SwiftLint/swiftlint)\n"; + shellScript = "# Swift Lint\nexec swiftlint\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/Screenshot Framer/Document Window/Content View Controller/ContentViewController.swift b/Screenshot Framer/Document Window/Content View Controller/ContentViewController.swift index 72445a9..d7eb314 100644 --- a/Screenshot Framer/Document Window/Content View Controller/ContentViewController.swift +++ b/Screenshot Framer/Document Window/Content View Controller/ContentViewController.swift @@ -104,7 +104,7 @@ final class ContentViewController: NSViewController, NSMenuItemValidation { self.zoomToFit(nil) } - //swiftlint:disable:next cyclomatic_complexity + // swiftlint:disable:next cyclomatic_complexity func validateMenuItem(_ menuItem: NSMenuItem) -> Bool { self.updateMenuItem(menuItem) guard let action = menuItem.action else { return false } diff --git a/Screenshot Framer/Document Window/Content View Controller/Help Controller/Progress Window/ProgressWindowController.swift b/Screenshot Framer/Document Window/Content View Controller/Help Controller/Progress Window/ProgressWindowController.swift index c8b0cac..15ff60b 100644 --- a/Screenshot Framer/Document Window/Content View Controller/Help Controller/Progress Window/ProgressWindowController.swift +++ b/Screenshot Framer/Document Window/Content View Controller/Help Controller/Progress Window/ProgressWindowController.swift @@ -18,13 +18,13 @@ class ProgressWindowController: NSWindowController { // MARK: - Properties weak var delegate: ProgressWindowControllerDelegate? var maxProgress: Double { - set { self.progressBar.maxValue = newValue } get { return self.progressBar.maxValue } + set { self.progressBar.maxValue = newValue } } var progress: Double { - set { self.progressBar.doubleValue = newValue } get { return self.progressBar.doubleValue } + set { self.progressBar.doubleValue = newValue } } diff --git a/Screenshot Framer/Time Travel/TimeTravelWindowController.swift b/Screenshot Framer/Time Travel/TimeTravelWindowController.swift index fecf23b..64aee27 100644 --- a/Screenshot Framer/Time Travel/TimeTravelWindowController.swift +++ b/Screenshot Framer/Time Travel/TimeTravelWindowController.swift @@ -24,7 +24,7 @@ final class TimeTravelWindowController: NSWindowController { override var document: AnyObject? { get { return nil } - set {} + set {} // swiftlint:disable:this unused_setter_value }