Skip to content

Commit

Permalink
Merge pull request #2 from oscardoudou/develop
Browse files Browse the repository at this point in the history
launch shortcut, clearAll, fix some crash issue
  • Loading branch information
oscardoudou authored Dec 5, 2019
2 parents 4f1d8e1 + a153462 commit 0e905aa
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 279 deletions.
4 changes: 4 additions & 0 deletions Quick Paste.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
3B0F8CF821F68B0F001CF701 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3B0F8CF721F68B0F001CF701 /* Assets.xcassets */; };
3B10BAD023490CF50029AED3 /* Quick Paste.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 3B10BACE23490CF50029AED3 /* Quick Paste.xcdatamodeld */; };
3B10BAD223491C7F0029AED3 /* DataController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B10BAD123491C7F0029AED3 /* DataController.swift */; };
3B56842323978AF700338B07 /* NSFRCChangeConsolidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B56842223978AF700338B07 /* NSFRCChangeConsolidator.swift */; };
3B80A20521D1C2EF003C0156 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80A20421D1C2EF003C0156 /* AppDelegate.swift */; };
3B80A20721D1C2EF003C0156 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80A20621D1C2EF003C0156 /* ViewController.swift */; };
3B80A20C21D1C2F0003C0156 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3B80A20A21D1C2F0003C0156 /* Main.storyboard */; };
Expand All @@ -22,6 +23,7 @@
3B0F8CF721F68B0F001CF701 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
3B10BACF23490CF50029AED3 /* Quick Paste.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Quick Paste.xcdatamodel"; sourceTree = "<group>"; };
3B10BAD123491C7F0029AED3 /* DataController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataController.swift; sourceTree = "<group>"; };
3B56842223978AF700338B07 /* NSFRCChangeConsolidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSFRCChangeConsolidator.swift; sourceTree = "<group>"; };
3B80A20121D1C2EF003C0156 /* Quick Paste.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Quick Paste.app"; sourceTree = BUILT_PRODUCTS_DIR; };
3B80A20421D1C2EF003C0156 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
3B80A20621D1C2EF003C0156 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -66,6 +68,7 @@
3B0F8CF721F68B0F001CF701 /* Assets.xcassets */,
3B80A20421D1C2EF003C0156 /* AppDelegate.swift */,
3B10BAD123491C7F0029AED3 /* DataController.swift */,
3B56842223978AF700338B07 /* NSFRCChangeConsolidator.swift */,
3B80A20621D1C2EF003C0156 /* ViewController.swift */,
3BD1CE47235EB5F700F4E18A /* GlobalEventMonitor.swift */,
3B014F5F235C057600838648 /* LocalEventMonitor.swift */,
Expand Down Expand Up @@ -155,6 +158,7 @@
3BD1CE48235EB5F700F4E18A /* GlobalEventMonitor.swift in Sources */,
3B10BAD223491C7F0029AED3 /* DataController.swift in Sources */,
3B80A20721D1C2EF003C0156 /* ViewController.swift in Sources */,
3B56842323978AF700338B07 /* NSFRCChangeConsolidator.swift in Sources */,
3B80A20521D1C2EF003C0156 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
190 changes: 23 additions & 167 deletions Quick Paste/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
strongSelf.closePopover(sender: event)
}
}
lazy var globalBringUpMonitor: GlobalEventMonitor = GlobalEventMonitor(mask: .keyDown){ [weak self]
event in
if let strongSelf = self {
print(strongSelf.globalBringUpMonitor)
strongSelf.viewController.keyDown(with: event!)
}
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
// buildMenu()
Expand Down Expand Up @@ -77,6 +84,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let defaults = UserDefaults.standard
let defaultValue = ["maxId" : ""]
defaults.register(defaults: defaultValue)
globalBringUpMonitor.start()
togglePopover(statusItem.button)
}

@objc func togglePopover(_ sender: Any?) {
Expand Down Expand Up @@ -115,15 +124,19 @@ class AppDelegate: NSObject, NSApplicationDelegate {
@objc func onPasteboardChanged(_ notification: Notification){
guard let pb = notification.object as? NSPasteboard else { return }
guard let items = pb.pasteboardItems else { return }
guard let preferType = items.first?.availableType(from: preferTypes)! else {return}
let currentDateTime = Date()
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .medium
let copyTimeStamp = "\(dateFormatter.string(from: currentDateTime))"
//for now we only log copy event, could be searchable, before introducing duplicate will leave this as unsearchable
print("\(copyTimeStamp) | '\(preferType)'")
//index copy event
bindIt()
//only copy screenshot text and file, fix unsupport copy type unwrap nil crash
if let preferType = items.first?.availableType(from: preferTypes){
let currentDateTime = Date()
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .medium
let copyTimeStamp = "\(dateFormatter.string(from: currentDateTime))"
//for now we only log copy event, could be searchable, before introducing duplicate will leave this as unsearchable
print("\(copyTimeStamp) | '\(preferType)'")
//index copy event
bindIt()
}else{
return
}
}


Expand All @@ -137,7 +150,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
return
}
if(firstTime){
// menu.insertItem(NSMenuItem.separator(), at: 1)
firstTime = false
}
var path: String
Expand All @@ -155,10 +167,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
//NSPasteboard.general.clearContents()
print("plaintext is: \(title)")
dataController.createCopied(id: id, title: title, type: preferType.rawValue, timestamp:Date())
//let newItem = createMenuItem(id: id, title: title, type: preferType.rawValue)
let newSearchableItem = createSearhableItem(id: id, title: title, type: preferType.rawValue, data: nil)
//addItemToMenu(item: newItem)
indexItem(item: newSearchableItem)
}
else if preferType.rawValue == "public.file-url"{
path = item.string(forType: preferType) ?? "NoPath"
Expand All @@ -167,10 +175,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
//NSPasteboard.general.clearContents()
print("path is: \(path)")
dataController.createCopied(id: id, title: title, path: path, type: preferType.rawValue, data: data, timestamp:Date())
//let newItem = createMenuItem(id: id, title: title, type: preferType.rawValue, data: data)
let newSearchableItem = createSearhableItem(id: id, title: title, type: preferType.rawValue, path: path, data: data)
//addItemToMenu(item: newItem)
indexItem(item: newSearchableItem)
}
else if preferType.rawValue == "public.png"{
data = item.data(forType: NSPasteboard.PasteboardType.init("public.png")) ?? Data()
Expand All @@ -187,82 +191,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}
}
//deprecated createMenuItem
@objc func createMenuItem(id: Int, title: String, type: String, data: Data = Data())->NSMenuItem{
var newItem : NSMenuItem? = nil
print ("\(title), \(type)")
if type == "public.file-url" {
newItem = NSMenuItem(title: String(title), action: #selector(AppDelegate.copyIt), keyEquivalent: "\(id%9)")
let rawImage = NSImage(data: data)
newItem?.image = rawImage?.resizedImageTo(sourceImage: rawImage!, newSize: NSSize.init(width: 20, height: 20))

}
if type == "public.utf8-plain-text"{
let afterParse = parseResumeFormat(title: title)
newItem = NSMenuItem(title: afterParse, action: #selector(AppDelegate.copyIt), keyEquivalent: "\(id%9)")
if(afterParse == "stackoverflow"){
newItem?.image = NSImage(named: "stackoverflow")
newItem?.title = ""
}
if(afterParse == "linkedin"){
newItem?.image = NSImage(named: "linkedin")
newItem?.title = ""
}
if(afterParse == "github"){
newItem?.image = NSImage(named: "github")
newItem?.title = ""
}
}
newItem!.representedObject = id as Int
return newItem!
}
//depreacated addItemToMenu
@objc func addItemToMenu(item: NSMenuItem){
menu.insertItem(item, at: index + 1)
index+=1
}


//spotlight searchable
func createSearhableItem(id: Int, title: String, type: String, path: String = "", data: Data?)->CSSearchableItem{
let searchableAttributeSet = CSSearchableItemAttributeSet.init(itemContentType: kUTTypeData as String)
searchableAttributeSet.title = title
searchableAttributeSet.contentDescription = title
searchableAttributeSet.kind = type
//currently contentURL gives thumbnail, thumbnailURL do nothing
searchableAttributeSet.contentURL = URL.init(fileURLWithPath: path)
searchableAttributeSet.path = URL.init(fileURLWithPath: path).path
let searchableItem = CSSearchableItem.init(uniqueIdentifier: String(id), domainIdentifier: "", attributeSet: searchableAttributeSet)
return searchableItem
}

func indexItem(item: CSSearchableItem){
CSSearchableIndex.default().indexSearchableItems([item]){error in
if let error = error {
print("Indexing error: \(error.localizedDescription)")
} else {
print("Search item successfully indexed!")
}
}
}


//status bar copy
@objc func copyIt(sender: NSMenuItem){
print("---------copyIt--------------")
//important step
NSPasteboard.general.clearContents()
let item = dataController.fetch(id: sender.representedObject as! Int)
print ("Copied \(item.id): \(item.type)")
NSPasteboard.general.setString(item.path!, forType: NSPasteboard.PasteboardType.init(item.type!))
// if item.type! != "public.utf8-plain-text"{
NSPasteboard.general.setString(item.name!, forType: NSPasteboard.PasteboardType.init("public.utf8-plain-text"))
// }
print(sender.representedObject as! Int)
print("we copy entry content to pasteboard")
printPasteBoard()
}

@objc func printPasteBoard(){
//it is possible no copy at all, so it need to be optional
print("---------inside printPasteBoard---------")
Expand All @@ -278,7 +208,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {

//url scheme event handler
@objc func handleAppleEvent(event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
// menu.addItem(NSMenuItem.separator())
if let text = event.paramDescriptor(forKeyword: AEKeyword(keyDirectObject))?.stringValue?.removingPercentEncoding {
if text.contains("readlog://") {
if let indexOfSemiColon = text.firstIndex(of: ":") as String.Index?{
Expand All @@ -295,85 +224,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
//NSPasteboard.general.clearContents()
print("url scheme message is: \(paramFromCommandLine)")
dataController.createCopied(id: id, title: paramFromCommandLine, type: "public.utf8-plain-text", timestamp:Date())
let newItem = createMenuItem(id: id, title: paramFromCommandLine, type: "public.utf8-plain-text")
let newSearchableItem = createSearhableItem(id: id, title: paramFromCommandLine, type: "public.utf8-plain-text", data: nil)
//addItemToMenu(item: newItem)
indexItem(item: newSearchableItem)
}
}
}
}

//need refactor
@objc func parseResumeFormat(title: String)->String{
var res = ""
if let indexEndOfTitle = title.firstIndex(of: "(") as String.Index?{
//get string before "("
if(firstParenthesisEntry){
maxCharacterSize = indexEndOfTitle.encodedOffset < maxCharacterSize ? indexEndOfTitle.encodedOffset : maxCharacterSize
firstParenthesisEntry = false
}
else{
//utilize the space as much as possible as long as it doesn't exceed ( entry's max size
maxCharacterSize = indexEndOfTitle.encodedOffset > maxCharacterSize ? indexEndOfTitle.encodedOffset : maxCharacterSize
}
// print("\(index)" + ", " + "\(maxCharacterSize)")
// newItem = NSMenuItem(title: String(title[..<indexEndOfTitle]), action: #selector(AppDelegate.copyIt), keyEquivalent: "\(index)")
res = String(title[..<indexEndOfTitle])
}else{
//no "(" present in first line, link or email
if let indexOfAt = title.firstIndex(of: "@") as String.Index?{
//email
let start = title.index(indexOfAt, offsetBy: 1)
let end = title.lastIndex(of: ".")!
let institue = String(title[start..<end])
// newItem = NSMenuItem(title: institue.uppercased(), action: #selector(AppDelegate.copyIt), keyEquivalent: "\(index)")
res = institue.uppercased()
}else{
//only . present
if let end = title.lastIndex(of: ".") as String.Index?{
//default start form startIndex
var start = title.startIndex
//point to last . since end always be the last .
// let end = title.lastIndex(of: ".")!
//point to first .
let indexPossibleStartHost = title.firstIndex(of: ".")!
//if has http or https prefix, start from 3 offset from colon
if title.hasPrefix("http://")||title.hasPrefix("https://"){
let indexEndOfProtocol = title.firstIndex(of: ":")!
//point to first char after :// for link like github and leetcode
start = title.index(indexEndOfProtocol, offsetBy: 3)
}
if(indexPossibleStartHost.encodedOffset != end.encodedOffset){
//piont to first . for link like linkedin
start = title.index(indexPossibleStartHost, offsetBy: 1)
}
let host = String(title[start..<end])
print (host)
// newItem = NSMenuItem(title: host, action: #selector(AppDelegate.copyIt), keyEquivalent: "\(index)")
res = host
}else{
//no . use space to separate no space simply return first element in splitted array
let words = title.split(separator: " ")
var preview = words[0]
print(preview.count)
for word in words{
if(word == words[0]){continue}
//only preview whole word never cut in the middle
if(preview.count + word.count < maxCharacterSize){
preview += word + " "
// print(preview.count)
}else{
break
}
}
// newItem = NSMenuItem(title: String(preview), action: #selector(AppDelegate.copyIt), keyEquivalent: "\(index)")
res = String(preview)
}
}
}
return res
}

//deprecated system menu
func buildMenu(){
item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
Expand Down
17 changes: 0 additions & 17 deletions Quick Paste/Assets.xcassets/github.imageset/Contents.json

This file was deleted.

Binary file not shown.
17 changes: 0 additions & 17 deletions Quick Paste/Assets.xcassets/linkedin.imageset/Contents.json

This file was deleted.

Binary file not shown.
11 changes: 11 additions & 0 deletions Quick Paste/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,17 @@
<action selector="Quit:" target="XfG-lQ-9wD" id="iVg-oB-V12"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bza-zh-zbp">
<rect key="frame" x="78" y="-2" width="72" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Clear" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="lgF-fu-Q7T">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="clear:" target="XfG-lQ-9wD" id="lhY-YO-d0F"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="GPv-zd-rfn" secondAttribute="bottom" constant="30" id="2eH-Vn-o2B"/>
Expand Down
Loading

0 comments on commit 0e905aa

Please sign in to comment.