Skip to content

Commit

Permalink
Support deleting history item by its position via Shortcuts
Browse files Browse the repository at this point in the history
  • Loading branch information
p0deje committed Nov 16, 2023
1 parent 0036904 commit 484dec4
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 5 deletions.
4 changes: 4 additions & 0 deletions Maccy.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
DAB65E0B2440B078000AECA8 /* HistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB65E0A2440B078000AECA8 /* HistoryItem.swift */; };
DAB65E0D2440B0D4000AECA8 /* HistoryItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB65E0C2440B0D4000AECA8 /* HistoryItemContent.swift */; };
DAB8CE4224E368F200A2500E /* container-migration.plist in Resources */ = {isa = PBXBuildFile; fileRef = DAB8CE4124E368F200A2500E /* container-migration.plist */; };
DAB9442D2B0583D700451E7C /* DeleteIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB9442C2B0583D700451E7C /* DeleteIntentHandler.swift */; };
DABDE97F2974706C005B32E9 /* KeyboardLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = DABDE97E2974706C005B32E9 /* KeyboardLayout.swift */; };
DAC14124232367B200FCFA30 /* Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC14123232367B200FCFA30 /* Search.swift */; };
DAC6CE9126E1AC19002B70B8 /* LaunchAtLogin in Frameworks */ = {isa = PBXBuildFile; productRef = DAC6CE9026E1AC19002B70B8 /* LaunchAtLogin */; };
Expand Down Expand Up @@ -286,6 +287,7 @@
DAB65E0C2440B0D4000AECA8 /* HistoryItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItemContent.swift; sourceTree = "<group>"; };
DAB8CE4024E3677F00A2500E /* Maccy.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Maccy.entitlements; sourceTree = "<group>"; };
DAB8CE4124E368F200A2500E /* container-migration.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "container-migration.plist"; sourceTree = "<group>"; };
DAB9442C2B0583D700451E7C /* DeleteIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteIntentHandler.swift; sourceTree = "<group>"; };
DABDE97E2974706C005B32E9 /* KeyboardLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardLayout.swift; sourceTree = "<group>"; };
DAC14123232367B200FCFA30 /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = "<group>"; };
DAC7AFAE2A801C92006081BB /* RunLoopLocalEventMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunLoopLocalEventMonitor.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -483,6 +485,7 @@
isa = PBXGroup;
children = (
DA68F91D28BD7DEA007E2F25 /* ClearIntentHandler.swift */,
DAB9442C2B0583D700451E7C /* DeleteIntentHandler.swift */,
DA83EC252974EEA400A95531 /* GetIntentHandler.swift */,
DA68F91B28BD76B8007E2F25 /* SelectIntentHandler.swift */,
);
Expand Down Expand Up @@ -820,6 +823,7 @@
DA6DB59720AA7D55003C255E /* GlobalHotKey.swift in Sources */,
DA68F91828BD6E21007E2F25 /* Intents.intentdefinition in Sources */,
2F3205B92AE3EDCA002EA545 /* MenuController.swift in Sources */,
DAB9442D2B0583D700451E7C /* DeleteIntentHandler.swift in Sources */,
DA11AE962693DD7100D640D2 /* MenuLoader.swift in Sources */,
DAD665662898A1C000975096 /* KeyChord.swift in Sources */,
DA83EC262974EEA400A95531 /* GetIntentHandler.swift in Sources */,
Expand Down
2 changes: 2 additions & 0 deletions Maccy/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
return ClearIntentHandler(maccy)
} else if intent is GetIntent {
return GetIntentHandler(maccy)
} else if intent is DeleteIntent {
return DeleteIntentHandler(maccy)
}

return nil
Expand Down
6 changes: 4 additions & 2 deletions Maccy/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<string>Clearintent</string>
<string>SelectIntent</string>
<string>GetIntent</string>
<string>DeleteIntent</string>
</array>
<key>LSApplicationCategoryType</key>
<string>public.app-category.productivity</string>
Expand All @@ -39,13 +40,14 @@
<key>NSUserActivityTypes</key>
<array>
<string>ClearIntent</string>
<string>DeleteIntent</string>
<string>GetIntent</string>
<string>SelectIntent</string>
</array>
<key>SUEnableInstallerLauncherService</key>
<true/>
<key>SUEnableDownloaderService</key>
<true/>
<key>SUEnableInstallerLauncherService</key>
<true/>
<key>SUFeedURL</key>
<string>https://raw.githubusercontent.com/p0deje/Maccy/master/appcast.xml</string>
</dict>
Expand Down
183 changes: 180 additions & 3 deletions Maccy/Intents.intentdefinition
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
<key>INIntentDefinitionNamespace</key>
<string>F3nH0s</string>
<key>INIntentDefinitionSystemVersion</key>
<string>22D5027d</string>
<string>23B73</string>
<key>INIntentDefinitionToolsBuildVersion</key>
<string>14C18</string>
<string>15A507</string>
<key>INIntentDefinitionToolsVersion</key>
<string>14.2</string>
<string>15.0.1</string>
<key>INIntents</key>
<array>
<dict>
Expand Down Expand Up @@ -51,6 +51,8 @@
<dict>
<key>INIntentParameterCombinationIsLinked</key>
<true/>
<key>INIntentParameterCombinationIsPrimary</key>
<true/>
<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
<true/>
<key>INIntentParameterCombinationTitle</key>
Expand Down Expand Up @@ -499,6 +501,181 @@
<key>INIntentVerb</key>
<string>Do</string>
</dict>
<dict>
<key>INIntentCategory</key>
<string>generic</string>
<key>INIntentConfigurable</key>
<true/>
<key>INIntentDescriptionID</key>
<string>I316c6</string>
<key>INIntentInput</key>
<string>number</string>
<key>INIntentKeyParameter</key>
<string>number</string>
<key>INIntentLastParameterTag</key>
<integer>2</integer>
<key>INIntentManagedParameterCombinations</key>
<dict>
<key>number</key>
<dict>
<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
<true/>
<key>INIntentParameterCombinationTitle</key>
<string>Delete ${number} Item from Clipboard History</string>
<key>INIntentParameterCombinationTitleID</key>
<string>XtEYLO</string>
<key>INIntentParameterCombinationUpdatesLinked</key>
<true/>
</dict>
</dict>
<key>INIntentName</key>
<string>Delete</string>
<key>INIntentParameterCombinations</key>
<dict>
<key>number</key>
<dict>
<key>INIntentParameterCombinationIsLinked</key>
<true/>
<key>INIntentParameterCombinationIsPrimary</key>
<true/>
<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
<true/>
<key>INIntentParameterCombinationTitle</key>
<string>Delete ${number} Item from Clipboard History</string>
<key>INIntentParameterCombinationTitleID</key>
<string>DYoBwp</string>
</dict>
</dict>
<key>INIntentParameters</key>
<array>
<dict>
<key>INIntentParameterConfigurable</key>
<true/>
<key>INIntentParameterDisplayName</key>
<string>Number</string>
<key>INIntentParameterDisplayNameID</key>
<string>Dlp6tH</string>
<key>INIntentParameterDisplayPriority</key>
<integer>1</integer>
<key>INIntentParameterMetadata</key>
<dict>
<key>INIntentParameterMetadataDefaultValue</key>
<integer>1</integer>
<key>INIntentParameterMetadataMaximumValue</key>
<integer>999</integer>
<key>INIntentParameterMetadataMinimumValue</key>
<integer>1</integer>
<key>INIntentParameterMetadataType</key>
<string>Stepper</string>
</dict>
<key>INIntentParameterName</key>
<string>number</string>
<key>INIntentParameterPromptDialogs</key>
<array>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogType</key>
<string>Configuration</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogFormatString</key>
<string>What is the number of the item?</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>BJwbnj</string>
<key>INIntentParameterPromptDialogType</key>
<string>Primary</string>
</dict>
</array>
<key>INIntentParameterSupportsResolution</key>
<true/>
<key>INIntentParameterTag</key>
<integer>2</integer>
<key>INIntentParameterType</key>
<string>Integer</string>
<key>INIntentParameterUnsupportedReasons</key>
<array>
<dict>
<key>INIntentParameterUnsupportedReasonCode</key>
<string>negativeNumbersNotSupported</string>
<key>INIntentParameterUnsupportedReasonDefault</key>
<true/>
<key>INIntentParameterUnsupportedReasonFormatString</key>
<string>${displayName} can’t be negative.</string>
<key>INIntentParameterUnsupportedReasonFormatStringID</key>
<string>SuzS3Z</string>
</dict>
<dict>
<key>INIntentParameterUnsupportedReasonCode</key>
<string>greaterThanMaximumValue</string>
<key>INIntentParameterUnsupportedReasonDefault</key>
<true/>
<key>INIntentParameterUnsupportedReasonFormatString</key>
<string>${displayName} can’t be higher than ${maximumValue}.</string>
<key>INIntentParameterUnsupportedReasonFormatStringID</key>
<string>3Ke3yQ</string>
</dict>
<dict>
<key>INIntentParameterUnsupportedReasonCode</key>
<string>lessThanMinimumValue</string>
<key>INIntentParameterUnsupportedReasonDefault</key>
<true/>
<key>INIntentParameterUnsupportedReasonFormatString</key>
<string>${displayName} can’t be lower than ${minimumValue}.</string>
<key>INIntentParameterUnsupportedReasonFormatStringID</key>
<string>m2PVN5</string>
</dict>
</array>
</dict>
</array>
<key>INIntentResponse</key>
<dict>
<key>INIntentResponseCodes</key>
<array>
<dict>
<key>INIntentResponseCodeName</key>
<string>success</string>
<key>INIntentResponseCodeSuccess</key>
<true/>
</dict>
<dict>
<key>INIntentResponseCodeName</key>
<string>failure</string>
</dict>
</array>
<key>INIntentResponseLastParameterTag</key>
<integer>1</integer>
<key>INIntentResponseParameters</key>
<array>
<dict>
<key>INIntentResponseParameterDisplayName</key>
<string>Value</string>
<key>INIntentResponseParameterDisplayNameID</key>
<string>AsA6IJ</string>
<key>INIntentResponseParameterDisplayPriority</key>
<integer>1</integer>
<key>INIntentResponseParameterName</key>
<string>value</string>
<key>INIntentResponseParameterTag</key>
<integer>1</integer>
<key>INIntentResponseParameterType</key>
<string>String</string>
</dict>
</array>
</dict>
<key>INIntentRestrictions</key>
<integer>2</integer>
<key>INIntentTitle</key>
<string>Delete Item from Clipboard History</string>
<key>INIntentTitleID</key>
<string>hTq78B</string>
<key>INIntentType</key>
<string>Custom</string>
<key>INIntentVerb</key>
<string>Do</string>
</dict>
</array>
<key>INTypes</key>
<array>
Expand Down
30 changes: 30 additions & 0 deletions Maccy/Intents/DeleteIntentHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Intents

@available(macOS 11.0, *)
class DeleteIntentHandler: NSObject, DeleteIntentHandling {
private let positionOffset = 1
private var maccy: Maccy!

init(_ maccy: Maccy) {
self.maccy = maccy
}

func handle(intent: DeleteIntent, completion: @escaping (DeleteIntentResponse) -> Void) {
guard let number = intent.number as? Int,
let value = maccy.delete(position: number - positionOffset) else {
return completion(DeleteIntentResponse(code: .failure, userActivity: nil))
}

let response = DeleteIntentResponse(code: .success, userActivity: nil)
response.value = value
return completion(response)
}

func resolveNumber(for intent: DeleteIntent, with completion: @escaping (DeleteNumberResolutionResult) -> Void) {
guard let number = intent.number as? Int else {
return completion(.needsValue())
}

return completion(.success(with: number))
}
}
4 changes: 4 additions & 0 deletions Maccy/Maccy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ class Maccy: NSObject {
return menu.select(position: position)
}

func delete(position: Int) -> String? {
return menu.delete(position: position)
}

func item(at position: Int) -> HistoryItem? {
return menu.historyItem(at: position)
}
Expand Down
16 changes: 16 additions & 0 deletions Maccy/Menu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,22 @@ class Menu: NSMenu, NSMenuDelegate {
}
}

func delete(position: Int) -> String? {
guard indexedItems.count > position else {
return nil
}

let indexedItem = indexedItems[position]
let value = indexedItem.value

removePopoverAnchor(indexedItem)
indexedItem.menuItems.forEach(safeRemoveItem)
history.remove(indexedItem.item)
indexedItems.remove(at: position)

return value
}

func pinOrUnpin() -> Bool {
guard let altItemToPin = highlightedItem as? HistoryMenuItem else {
return false
Expand Down

0 comments on commit 484dec4

Please sign in to comment.