Skip to content

Commit

Permalink
Menubar app created
Browse files Browse the repository at this point in the history
- Added timer to finder ext.
  • Loading branch information
stevenselcuk committed Mar 12, 2021
1 parent 578db59 commit 1b1385d
Show file tree
Hide file tree
Showing 34 changed files with 666 additions and 21 deletions.
4 changes: 4 additions & 0 deletions PasteBoard.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
0A65B48425F9318100FB2DD4 /* PasteBoardFinderExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0A65B47C25F9318100FB2DD4 /* PasteBoardFinderExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
0A65B48A25F931DD00FB2DD4 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0A65B48925F931DD00FB2DD4 /* Media.xcassets */; };
0A65B48C25F9326200FB2DD4 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A65B48B25F9326200FB2DD4 /* Utils.swift */; };
0AB29AE525FA8D5F00667C7D /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB29AE425FA8D5F00667C7D /* Utils.swift */; };
0ACF11CE25F9399600AAA8D4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0ACF11CD25F9399600AAA8D4 /* Main.storyboard */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -52,6 +53,7 @@
0A65B48125F9318100FB2DD4 /* PasteBoardFinderExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PasteBoardFinderExtension.entitlements; sourceTree = "<group>"; };
0A65B48925F931DD00FB2DD4 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
0A65B48B25F9326200FB2DD4 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
0AB29AE425FA8D5F00667C7D /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
0ACF11CD25F9399600AAA8D4 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -99,6 +101,7 @@
0A65B47125F9315800FB2DD4 /* Info.plist */,
0ACF11CD25F9399600AAA8D4 /* Main.storyboard */,
0A65B47225F9315800FB2DD4 /* PasteBoard.entitlements */,
0AB29AE425FA8D5F00667C7D /* Utils.swift */,
);
path = PasteBoard;
sourceTree = "<group>";
Expand Down Expand Up @@ -216,6 +219,7 @@
buildActionMask = 2147483647;
files = (
0A65B46925F9315600FB2DD4 /* AppDelegate.swift in Sources */,
0AB29AE525FA8D5F00667C7D /* Utils.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
86 changes: 82 additions & 4 deletions PasteBoard/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,92 @@ import Cocoa
import FinderSync
@main
class AppDelegate: NSObject, NSApplicationDelegate {
var statusBarItem: NSStatusItem!
let defaults = UserDefaults.standard
var timer: Timer!
var savedItems: [String] = UserDefaults.standard.stringArray(forKey: "SavedPasteBoardItems") ?? [String]()
var lastChangeCount: Int = 0
let pasteboard: NSPasteboard = .general
var selectedItemIndex: Int = 0
func applicationDidFinishLaunching(_ aNotification: Notification) {
// For first install, trigger Extensions screen
statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))

if let button = statusBarItem.button {
button.image = NSImage(named: "menubar-icon")
button.action = #selector(togglePopover(_:))
button.sendAction(on: [.leftMouseUp, .rightMouseUp])
}

timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [self] _ in
if self.lastChangeCount != self.pasteboard.changeCount {
self.lastChangeCount = self.pasteboard.changeCount

let pasteItems = self.pasteboard.pasteboardItems

for case let pasteItem? in pasteItems ?? [] {
if self.savedItems.count >= 11 {
self.savedItems.removeFirst(1)
}

if !self.savedItems.contains(pasteItem.string(forType: .string)!) {
self.savedItems.append(pasteItem.string(forType: .string)!.trimmingCharacters(in: .whitespacesAndNewlines))
defaults.set(self.savedItems, forKey: "SavedPasteBoardItems")
}
}
}
}
}

@objc func togglePopover(_ sender: AnyObject?) {
let event = NSApp.currentEvent!

if event.type == NSEvent.EventType.leftMouseUp {
let menu = NSMenu()

for (index, item) in savedItems.enumerated().reversed() {
let menuItem = NSMenuItem(title: item.truncated(limit: 40, position: .tail, leader: "..."), action: #selector(copyAction(_:)), keyEquivalent: "\(index + 1)")
menu.addItem(menuItem)
}

menu.addItem(NSMenuItem.separator())
if savedItems.count > 0 {
menu.addItem(withTitle: "🧹 Clear PasteBoard", action: #selector(clear(_:)), keyEquivalent: "c")
}

menu.addItem(withTitle: "Activate Finder Extension", action: #selector(activateExt), keyEquivalent: "e")
menu.addItem(withTitle: "Quit App", action: #selector(quit), keyEquivalent: "q")

statusBarItem.menu = menu
statusBarItem.button?.performClick(nil)
statusBarItem.menu = nil
}
}

@objc func activateExt(_ sender: AnyObject?) {
FIFinderSyncController.showExtensionManagementInterface()
// Terminate the application
NSApplication.shared.terminate(self)
}

@objc func clear(_ sender: AnyObject?) {
savedItems = []
NSPasteboard.general.clearContents()
defaults.set(self.savedItems, forKey: "SavedPasteBoardItems")
}

@objc func copyAction(_ sender: NSMenuItem?) {
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
selectedItemIndex = Int(sender!.keyEquivalent)!
if self.savedItems.count >= selectedItemIndex {
pasteboard.setString(self.savedItems[selectedItemIndex - 1], forType: NSPasteboard.PasteboardType.string)
}
NSSound(named: "Pop")?.play()
}

@objc func quit() {
NSApp.terminate(self)
}

func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
timer.invalidate()
}
}
56 changes: 56 additions & 0 deletions PasteBoard/Assets.xcassets/menubar-icon.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"images" : [
{
"filename" : "paste (9).png",
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "paste (10).png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "paste (9)-1.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "paste (10)-1.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "paste (9)-2.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "paste (10)-2.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions PasteBoard/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>LSUIElement</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
Expand Down
35 changes: 35 additions & 0 deletions PasteBoard/Utils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Utils.swift
// PasteBoard
//
// Created by Steven J. Selcuk on 11.03.2021.
//

import Cocoa

extension String {
enum TruncationPosition {
case head
case middle
case tail
}

func truncated(limit: Int, position: TruncationPosition = .tail, leader: String = "...") -> String {
guard count > limit else { return self }

switch position {
case .head:
return leader + suffix(limit)
case .middle:
let headCharactersCount = Int(ceil(Float(limit - leader.count) / 2.0))

let tailCharactersCount = Int(floor(Float(limit - leader.count) / 2.0))

return "\(prefix(headCharactersCount))\(leader)\(suffix(tailCharactersCount))"
case .tail:
return prefix(limit) + leader
}
}
}


49 changes: 35 additions & 14 deletions PasteBoardFinderExtension/FinderSync.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,36 @@ import Cocoa
import FinderSync

class FinderSync: FIFinderSync {
var savedItems: [String] = []
let defaults = UserDefaults.standard
var timer: Timer!
var savedItems: [String] = UserDefaults.standard.stringArray(forKey: "SavedPasteBoardItems") ?? [String]()
var lastChangeCount: Int = 0
let pasteboard: NSPasteboard = .general
var selectedItemIndex: Int = 0

override init() {
super.init()
if(!NSWorkspace.shared.runningApplications.contains { $0.bundleIdentifier == "org.tabbycatllc.PasteBoard" }) {
timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [self] _ in
if self.lastChangeCount != self.pasteboard.changeCount {
self.lastChangeCount = self.pasteboard.changeCount

let pasteItems = self.pasteboard.pasteboardItems

for case let pasteItem? in pasteItems ?? [] {
if self.savedItems.count >= 11 {
self.savedItems.removeFirst(1)
}

if !self.savedItems.contains(pasteItem.string(forType: .string)!) {
self.savedItems.append(pasteItem.string(forType: .string)!.trimmingCharacters(in: .whitespacesAndNewlines))
defaults.set(self.savedItems, forKey: "SavedPasteBoardItems")
}
}
}
}
}

}

override var toolbarItemName: String {
Expand All @@ -29,23 +55,14 @@ class FinderSync: FIFinderSync {

override func menu(for menuKind: FIMenuKind) -> NSMenu {
let menu = NSMenu(title: "")
let pasteItems = NSPasteboard.general.pasteboardItems

for case let pasteItem? in pasteItems ?? [] {
if savedItems.count > 10 {
savedItems.removeFirst(1)
}
savedItems.append(pasteItem.string(forType: .string)!)
}

for item in savedItems {
let menuItem = NSMenuItem(title: "👉 " + item.truncated(limit: 30, position: .tail, leader: "..."), action: #selector(copyAction(_:)), keyEquivalent: "")
for item in savedItems.reversed() {
let menuItem = NSMenuItem(title: item.truncated(limit: 30, position: .tail, leader: "..."), action: #selector(copyAction(_:)), keyEquivalent: "")
menuItem.pasteBoardContextItem = item
menu.addItem(menuItem)
}

if savedItems.count > 0 {
menu.addItem(withTitle: "🧹 Clear Stash", action: #selector(clear(_:)), keyEquivalent: "")
menu.addItem(withTitle: "🧹 Clear PasteBoard", action: #selector(clear(_:)), keyEquivalent: "")
}

return menu
Expand All @@ -54,12 +71,16 @@ class FinderSync: FIFinderSync {
@objc func clear(_ sender: AnyObject?) {
savedItems = []
NSPasteboard.general.clearContents()
defaults.set(self.savedItems, forKey: "SavedPasteBoardItems")
}

@objc func copyAction(_ sender: NSMenuItem?) {
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
pasteboard.setString(sender!.pasteBoardContextItem, forType: NSPasteboard.PasteboardType.string)
selectedItemIndex = Int(sender!.keyEquivalent)!
if self.savedItems.count >= selectedItemIndex {
pasteboard.setString(self.savedItems[selectedItemIndex - 1], forType: NSPasteboard.PasteboardType.string)
}
NSSound(named: "Pop")?.play()
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,50 @@
{
"images" : [
{
"filename" : "paste (6).png",
"filename" : "paste (9).png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "paste (7).png",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "paste (10).png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "paste (9)-1.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "paste (10)-1.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "paste (8).png",
"filename" : "paste (9)-2.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "paste (10)-2.png",
"idiom" : "universal",
"scale" : "3x"
}
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1b1385d

Please sign in to comment.