Skip to content

Commit d3061de

Browse files
CLEAR ACTION: introducing new action to clear all data + code refactoring + documentation update
1 parent 265d8b4 commit d3061de

File tree

12 files changed

+104
-29
lines changed

12 files changed

+104
-29
lines changed
189 KB
Binary file not shown.
8.58 KB
Binary file not shown.

Sources/MyStreamDeckPlugin.m

Lines changed: 77 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#import "ESDUtilities.h"
1818
#import <AppKit/AppKit.h>
1919

20+
#define STORE_ACT @"net.localhost.streamdeck.clipboard-buddy"
21+
#define NUKE_ACT @"net.localhost.streamdeck.clipboard-buddy-nuke"
2022

2123
#define MIN_LONG_PRESS 0.5
2224
#define SECURE_PRESS 1.0
@@ -241,6 +243,50 @@ static CGImageRef ComposeImage(NSString *inImagePath, NSString *overlayText, NSC
241243
}
242244

243245

246+
//
247+
// Utility function to init/reset the storage dict
248+
//
249+
static NSMutableDictionary * ResetDictContent(NSInteger thisDevHeight, NSInteger thisDevWidth) {
250+
251+
// A basic dict for our row-column to string transformation
252+
NSMutableDictionary * tmpDict = [[NSMutableDictionary alloc] initWithCapacity:1];
253+
254+
// The final dict with the default values inside
255+
NSMutableDictionary * rdyDict = [[NSMutableDictionary alloc] initWithCapacity: thisDevWidth*thisDevHeight];
256+
257+
// We need to initialize the dict for text (max the whole size of the device)
258+
for (NSInteger row=0; row < thisDevWidth; row++) {
259+
for (NSInteger col=0; col < thisDevHeight; col++) {
260+
//
261+
// We need to fake the usual structure we get while running to use the common keyFromCoord() method
262+
// Unfortunately, a dict requires String or string-like elements so we have to do a formatting :(
263+
//
264+
tmpDict[@"row"] = [NSString stringWithFormat:@"%ld", row];
265+
tmpDict[@"column"] = [NSString stringWithFormat:@"%ld", col];
266+
267+
rdyDict[ keyFromCoord(tmpDict) ] = keyFromCoord(tmpDict);
268+
// using the key as default value should make any code misbehavior visible
269+
}
270+
}
271+
return rdyDict;
272+
}
273+
274+
275+
//
276+
// Utility function to properly clear a key (background + title)
277+
//
278+
static BOOL ClearKey(ESDConnectionManager *conMan, id thisContext, NSString *backgroundImage) {
279+
280+
// Changing the background to convey we have purged the data
281+
[conMan setImage:backgroundImage withContext:thisContext withTarget:kESDSDKTarget_HardwareAndSoftware];
282+
283+
// And clearing the text if it was a secure entry
284+
[conMan setTitle:@"" withContext:thisContext withTarget:kESDSDKTarget_HardwareAndSoftware];
285+
286+
return true;
287+
}
288+
289+
244290
// MARK: - MyStreamDeckPlugin
245291

246292
@interface MyStreamDeckPlugin ()
@@ -253,6 +299,8 @@ @interface MyStreamDeckPlugin ()
253299
// The text we want to hold (one entry per key)
254300
@property (strong) NSMutableDictionary *tileText;
255301
@property BOOL dictInitialized;
302+
@property (strong) NSMutableDictionary *tileContext;
303+
// The context of each tile to simplify global actions (like the nuke)
256304

257305
// The global clipboard
258306
@property NSPasteboard *pboard;
@@ -268,6 +316,10 @@ @interface MyStreamDeckPlugin ()
268316
// For secure entries we store objects to reuse
269317
@property (strong) NSDateFormatter *daFo;
270318

319+
// The information about the device we use to deal properly with the storage dict
320+
@property NSInteger devHeight;
321+
@property NSInteger devWidth;
322+
271323
@end
272324

273325

@@ -328,7 +380,21 @@ - (void)setupIfNeeded
328380

329381
- (void)keyDownForAction:(NSString *)action withContext:(id)context withPayload:(NSDictionary *)payload forDevice:(NSString *)deviceID
330382
{
331-
_keyPressed = [[NSDate alloc]init];
383+
// Useful only when dealing with STORE_ACT actions but does not hurt for others
384+
_keyPressed = [[NSDate alloc] init];
385+
386+
if([action isEqualToString:NUKE_ACT]) {
387+
388+
// We check which key holds data and make sure it gets purged properly (visually)
389+
for(NSString * key in [_tileContext allKeys]) {
390+
ClearKey(_connectionManager, _tileContext[key], _base64PostitSleepy);
391+
[_tileContext removeObjectForKey:key];
392+
}
393+
// At this point, everything should be visually clean and we must ensure the text storage is too ;)
394+
_tileText = [NSMutableDictionary dictionaryWithDictionary:ResetDictContent(_devHeight, _devWidth)];
395+
396+
[_connectionManager showOKForContext:context];
397+
}
332398
}
333399

334400

@@ -348,6 +414,7 @@ - (void)keyUpForAction:(NSString *)action withContext:(id)context withPayload:(N
348414
// Making sure we store the clipboard data into a separate entry specific to our button
349415
NSString * dictKey = keyFromCoord(payload[@"coordinates"]);
350416
_tileText[dictKey] = clipboardContent;
417+
_tileContext[dictKey] = context;
351418

352419
// Picking also a pseudo-random color for the text we will display on the button
353420
NSColor *thisColor = _textColorMatrix[ arc4random_uniform(sizeof(_textColorMatrix)) ];
@@ -374,12 +441,9 @@ - (void)keyUpForAction:(NSString *)action withContext:(id)context withPayload:(N
374441
// Purging the struct by resetting to the default value
375442
NSString * dictKey = keyFromCoord(payload[@"coordinates"]);
376443
_tileText[dictKey] = dictKey;
444+
[_tileContext removeObjectForKey:dictKey];
377445

378-
// Changing the background to convey we have purged the data
379-
[_connectionManager setImage:_base64PostitSleepy withContext:context withTarget:kESDSDKTarget_HardwareAndSoftware];
380-
381-
// And clearing the text if it was a secure entry
382-
[_connectionManager setTitle:@"" withContext:context withTarget:kESDSDKTarget_HardwareAndSoftware];
446+
ClearKey(_connectionManager, context, _base64PostitSleepy);
383447
}
384448
else {
385449
NSString * textToDisplay = _tileText[ keyFromCoord(payload[@"coordinates"]) ];
@@ -463,33 +527,20 @@ - (void)willDisappearForAction:(NSString *)action withContext:(id)context withPa
463527
- (void)deviceDidConnect:(NSString *)deviceID withDeviceInfo:(NSDictionary *)deviceInfo
464528
{
465529
// Relaying the dimensions of the current device as integers
466-
NSInteger devWidth = [deviceInfo[@"size"][@"rows"] integerValue];
467-
NSInteger devHeight= [deviceInfo[@"size"][@"columns"] integerValue];
530+
_devHeight= [deviceInfo[@"size"][@"columns"] integerValue];
531+
_devWidth = [deviceInfo[@"size"][@"rows"] integerValue];
468532

469533
// Making sure we do not loose data if the computer is locked or goes to sleep ;)
470534
if( _dictInitialized ) {
471535
[_connectionManager logMessage:[NSString stringWithFormat:@"[DID-CONNECT] No need to re-intialize the internal text storage in order to avoid loosing existing data..."]];
472536
}
473537
else {
474-
// Preparing our dictionary objects (as we need the device's buttons info)
475-
_tileText = [[NSMutableDictionary alloc] initWithCapacity: devWidth*devHeight];
476-
NSMutableDictionary * tmpDict = [[NSMutableDictionary alloc] initWithCapacity:1];
477-
478-
// We need to initialize the dict for text (max the whole size of the device)
479-
for (NSInteger row=0; row < devWidth; row++) {
480-
for (NSInteger col=0; col < devHeight; col++) {
481-
//
482-
// We need to fake the usual structure we get while running to use the common keyFromCoord() method
483-
// Unfortunately, a dict requires String or string-like elements so we have to do a formatting :(
484-
//
485-
tmpDict[@"row"] = [NSString stringWithFormat:@"%ld", row];
486-
tmpDict[@"column"] = [NSString stringWithFormat:@"%ld", col];
487-
488-
_tileText[ keyFromCoord(tmpDict) ] = keyFromCoord(tmpDict);
489-
// using the key as default value should make any code misbehavior visible
490-
}
491-
}
538+
// Preparing text dictionary (as we need the device's buttons info)
539+
_tileText = [NSMutableDictionary dictionaryWithDictionary:ResetDictContent(_devHeight, _devWidth)];
492540
_dictInitialized = TRUE;
541+
542+
// Preparing also the context dictionary (without any content for now)
543+
_tileContext = [[NSMutableDictionary alloc] initWithCapacity: _devWidth*_devHeight];
493544
}
494545
}
495546

Sources/net.localhost.streamdeck.clipboard-buddy.sdPlugin/manifest.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@
1414
"SupportedInMultiActions": false,
1515
"Tooltip": "",
1616
"UUID": "net.localhost.streamdeck.clipboard-buddy"
17+
},
18+
{
19+
"Icon": "postit-action",
20+
"Name": "All clear slot",
21+
"States": [
22+
{
23+
"Image": "postit-nuke",
24+
"TitleAlignment": "middle",
25+
"FontSize": "12",
26+
"TitleColor": "cyan"
27+
}
28+
],
29+
"SupportedInMultiActions": false,
30+
"Tooltip": "",
31+
"UUID": "net.localhost.streamdeck.clipboard-buddy-nuke"
1732
}
1833
],
1934
"SDKVersion": 2,
6.88 KB
Loading
12.6 KB
Loading
8.25 KB
Loading

USAGE.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22

33
- [Plugin usage with a Stream Deck device](#plugin-usage-with-a-stream-deck-device)
44
- [Overview](#overview)
5-
- [Step-by-step guides](#step-by-step-guides)
5+
- [Step-by-step guide (for the Clipboard action)](#step-by-step-guide-for-the-clipboard-action)
66
- [Saving text](#saving-text)
77
- [Saving sensitive text](#saving-sensitive-text)
88
- [Clearing a key](#clearing-a-key)
9+
- [Guide for the Clear All action](#guide-for-the-clear-all-action)
910

1011
## Overview
1112

1213
The point of this plugin is to enable you to set aside some **text data** you have in your clipboard for later.
1314
Once a key holds some text, you can paste it in most text areas by doing a quick press on the key.
1415

15-
## Step-by-step guides
16+
## Step-by-step guide (for the Clipboard action)
1617

1718
### Saving text
1819

@@ -33,3 +34,8 @@ Once a key holds some text, you can paste it in most text areas by doing a quick
3334
- First, your key will contain either a regular text ![Regular text](documentation_images/regular-text.png) or secure text ![Secure text](documentation_images/secure-text.png)
3435
- Do a long press on the key (**3 seconds or longer**)
3536
- When you release the key it should be back to the empty image ![Empty key](documentation_images/unused.png)
37+
38+
## Guide for the Clear All action
39+
40+
This action is very simple: you activate it, it clears all the Clipboard actions on the Stream Deck (be careful !).
41+
![Clear All](documentation_images/clear-all.png)

documentation_images/clear-all.png

7.65 KB
Loading
-3.57 KB
Loading

0 commit comments

Comments
 (0)