Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix build + make screenshot open over where it was created #24

Merged
merged 17 commits into from
May 26, 2022
Merged
109 changes: 109 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: CI

on:
push:
branches: [ master ]
tags:
- 'v*'
pull_request:
branches: [ master ]

jobs:
build:
runs-on: [ macos-latest ]

steps:
- name: Select latest Xcode
run: "sudo xcode-select -s /Applications/Xcode_13.2.app"
- name: Install the Apple certificate and provisioning profile
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
# BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db

# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH
#echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_PATH

# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH

# import certificate to keychain
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH

# apply provisioning profile
# mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
# cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles

- name: Install deps
run: |
brew install make create-dmg ripgrep
echo "/usr/local/opt/make/libexec/gnubin" >> $GITHUB_PATH

- uses: actions/checkout@v2

- uses: actions/cache@v1
id: carthage-cache
with:
path: Carthage
key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}

- name: Carthage
if: steps.carthage-cache.outputs.cache-hit != 'true'
run: |
carthage bootstrap --use-xcframeworks

- name: Build and make dmg
run: |
make dmg

- name: Upload artifacts
uses: actions/[email protected]
with:
name: Fuwari
path: ./dist

pre-release:
needs: build
runs-on: [ macos-latest ]
if: "!startsWith(github.ref, 'refs/tags/v')"
steps:
- uses: actions/download-artifact@v2
with:
name: Fuwari
path: ./dist

- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
prerelease: true
title: "Development Build"
files: |
dist/Fuwari.dmg

release:
needs: build
runs-on: [ macos-latest ]
if: "startsWith(github.ref, 'refs/tags/v')"
steps:
- uses: actions/download-artifact@v2
with:
name: Fuwari
path: ./dist

- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
files: |
dist/Fuwari.dmg
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,6 @@ fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output

/dist
/artifacts
2 changes: 1 addition & 1 deletion Cartfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
github "Clipy/Magnet" == 3.2.0
github "Clipy/LoginServiceKit" == 2.2.0
github "Clipy/LoginServiceKit" == 2.3.0
github "Clipy/KeyHolder" == 4.0.0
github "Clipy/Sauce" == 2.1.0
2 changes: 1 addition & 1 deletion Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
github "Clipy/KeyHolder" "v4.0.0"
github "Clipy/LoginServiceKit" "v2.2.0"
github "Clipy/LoginServiceKit" "v2.3.0"
github "Clipy/Magnet" "v3.2.0"
github "Clipy/Sauce" "v2.1.0"
8 changes: 8 additions & 0 deletions ExportOptions.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>mac-application</string>
</dict>
</plist>
8 changes: 6 additions & 2 deletions Fuwari.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
30C4E09427CEC8B900EBDCBB /* Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4E09327CEC8B900EBDCBB /* Regex.swift */; };
BE23E42F1DFA1623004DA6B7 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE23E42E1DFA1623004DA6B7 /* Constants.swift */; };
BE38949F263C20EA00131366 /* KeyHolder.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CAD92F1F25FE3B6B008D6CF8 /* KeyHolder.xcframework */; };
BE3894A0263C20EA00131366 /* KeyHolder.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CAD92F1F25FE3B6B008D6CF8 /* KeyHolder.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -59,6 +60,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
30C4E09327CEC8B900EBDCBB /* Regex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Regex.swift; sourceTree = "<group>"; };
BE23E42E1DFA1623004DA6B7 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
BE357092263FE10900F8C5E0 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/GeneralPreferenceViewController.strings; sourceTree = "<group>"; };
BE3570932640406F00F8C5E0 /* Fuwari.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Fuwari.entitlements; sourceTree = "<group>"; };
Expand Down Expand Up @@ -172,6 +174,7 @@
children = (
BE23E42E1DFA1623004DA6B7 /* Constants.swift */,
BE5896A01DFCED26007CE7AC /* LocalizedString.swift */,
30C4E09327CEC8B900EBDCBB /* Regex.swift */,
);
name = Utility;
sourceTree = "<group>";
Expand Down Expand Up @@ -291,6 +294,7 @@
BE7E825B1DF74A2D00F3F2F8 /* FloatWindow.swift in Sources */,
BEF57FE51DFD46AE006595B6 /* PreferencesWindowController.swift in Sources */,
BE85482020F975E00035BC60 /* NSMenu+Extension.swift in Sources */,
30C4E09427CEC8B900EBDCBB /* Regex.swift in Sources */,
BEF57FEF1DFD58D4006595B6 /* NSColor+Fuwari.swift in Sources */,
BEC844F91DED859300A4A57A /* ViewController.swift in Sources */,
BE85482420FB5C640035BC60 /* FloatView.swift in Sources */,
Expand Down Expand Up @@ -489,7 +493,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.12;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.6.0;
PRODUCT_BUNDLE_IDENTIFIER = com.appknop.fuwari;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -518,7 +522,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.12;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.6.0;
PRODUCT_BUNDLE_IDENTIFIER = com.appknop.fuwari;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
2 changes: 1 addition & 1 deletion Fuwari/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {

override init() {
// Initialize UserDefaults value
defaults.register(defaults: [Constants.UserDefaults.movingOpacity: 0.4])
defaults.register(defaults: [Constants.UserDefaults.movingOpacity: 1.0])
defaults.register(defaults: [Constants.UserDefaults.uploadConfirmationItem: true])
}

Expand Down
6 changes: 5 additions & 1 deletion Fuwari/FloatWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Cocoa
import Magnet
import Carbon

protocol FloatDelegate: class {
protocol FloatDelegate: AnyObject {
func save(floatWindow: FloatWindow, image: CGImage)
func close(floatWindow: FloatWindow)
}
Expand Down Expand Up @@ -165,6 +165,10 @@ class FloatWindow: NSWindow {
override func mouseUp(with event: NSEvent) {
alphaValue = windowOpacity
closeButton.alphaValue = closeButtonOpacity
// Double click to close
if event.clickCount >= 2 {
closeWindow()
}
}

@objc private func saveImage() {
Expand Down
42 changes: 42 additions & 0 deletions Fuwari/Regex.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// Regex.swift
// Fuwari
//
// Created by Ben Lu on 01/03/2022.
// Copyright © 2022 AppKnop. All rights reserved.
//

import Foundation

struct Regex {
static func match(str: String, regexPattern: String) -> NSTextCheckingResult? {
let strRange = NSRange(str.startIndex..<str.endIndex, in: str)

let regex = try! NSRegularExpression(
pattern: regexPattern,
options: []
)
let matches = regex.matches(
in: str,
options: [],
range: strRange
)

return matches.first
}

static func getGroup(match: NSTextCheckingResult, name: String, str: String) throws -> String {
let matchRange = match.range(withName: name)

// Extract the substring matching the named capture group
if let substringRange = Range(matchRange, in: str) {
let capture = String(str[substringRange])
return capture
}
throw RegexError.missingGroup(name: name)
}
}

enum RegexError: Error {
case missingGroup(name: String)
}
48 changes: 40 additions & 8 deletions Fuwari/ScreenshotManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,59 @@
import Cocoa

class ScreenshotManager: NSObject {

static let shared = ScreenshotManager()

private var eventHandler: ((URL) -> Void)?
func eventHandler(eventHandler: @escaping (URL) -> Void) {
private var eventHandler: ((URL, NSRect?) -> Void)?

func eventHandler(eventHandler: @escaping (URL, NSRect?) -> Void) {
self.eventHandler = eventHandler
}

func startCapture() {
let fileUrl = FileManager.default.temporaryDirectory.appendingPathComponent("fuwari-temporary-screenshot.png")
let captureProcess = Process()
let pipe = Pipe()
captureProcess.launchPath = "/usr/sbin/screencapture"
captureProcess.arguments = ["-x", "-i"] + [fileUrl.path]
captureProcess.standardOutput = Pipe()
captureProcess.arguments = ["-x", "-i", "-o"] + [fileUrl.path]
captureProcess.environment = ["OS_ACTIVITY_DT_MODE": "YES"]
captureProcess.standardError = pipe
captureProcess.terminationHandler = { task in
guard task.terminationStatus == 0 else { return }
let output = pipe.fileHandleForReading.availableData
let str = String(decoding: output, as: UTF8.self)
let rect = self.extractCoordinates(str: str)
DispatchQueue.main.async { [weak self] in
self?.eventHandler?(fileUrl)
self?.eventHandler?(fileUrl, rect)
}
}
captureProcess.launch()
}

func extractCoordinates(str: String) -> NSRect? {
// Note, not found when capturing a window, rather than a selection
let capturePattern = #"captureRect = \((?<x>[\d.]+), (?<y>[\d.]+), (?<width>[\d.]+), (?<height>[\d.]+)\)"#

guard let match = Regex.match(str: str, regexPattern: capturePattern) else {
return nil
}

let getIntFromRegexGroup = {(name: String) throws -> Int in
Int(round(Float(try Regex.getGroup(match: match, name: name, str: str))!))
}

do {
return try NSRect(
x: getIntFromRegexGroup("x"),
y: getIntFromRegexGroup("y"),
width: getIntFromRegexGroup("width"),
height: getIntFromRegexGroup("height")
)
} catch RegexError.missingGroup(let name) {
print("missing group: \(name)")
return nil
} catch {
return nil
}
}
}
22 changes: 18 additions & 4 deletions Fuwari/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class ViewController: NSViewController, NSWindowDelegate {
oldApp = NSWorkspace.shared.frontmostApplication
oldApp?.activate(options: .activateIgnoringOtherApps)

ScreenshotManager.shared.eventHandler {
imageUrl in
ScreenshotManager.shared.eventHandler { imageUrl, rectMaybeConst in
let mainScreen = NSScreen.screens.first
let currentScreen = NSScreen.screens.first { $0.frame.contains(NSEvent.mouseLocation) }
guard let currentScaleFactor = currentScreen?.backingScaleFactor else { return }
let mouseLocation = NSEvent.mouseLocation
Expand All @@ -34,8 +34,22 @@ class ViewController: NSViewController, NSWindowDelegate {
let context = CIContext(options: nil)

guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else { return }

self.createFloatWindow(rect: NSRect(x: Int(mouseLocation.x) - cgImage.width / Int(2 * currentScaleFactor), y: Int(mouseLocation.y) - cgImage.height / Int(2 * currentScaleFactor), width: Int(CGFloat(cgImage.width) / currentScaleFactor), height: Int(CGFloat(cgImage.height) / currentScaleFactor)), image: cgImage)
var rectMaybe = rectMaybeConst
if let height = mainScreen?.frame.size.height, let rect = rectMaybe {
rectMaybe = NSRect(
x: rect.minX,
y: height - rect.maxY,
width: rect.width,
height: rect.height
)
}
let rect = rectMaybe ?? NSRect(
x: Int(mouseLocation.x) - cgImage.width / Int(2 * currentScaleFactor),
y: Int(mouseLocation.y) - cgImage.height / Int(2 * currentScaleFactor),
width: Int(CGFloat(cgImage.width) / currentScaleFactor),
height: Int(CGFloat(cgImage.height) / currentScaleFactor)
)
self.createFloatWindow(rect: rect, image: cgImage)
try? FileManager.default.removeItem(at: imageUrl)
}
}
Expand Down
Loading