Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Goetz <markus@woboq.com>2018-04-11 14:40:27 +0300
committerMarkus Goetz <markus@woboq.com>2018-04-12 14:12:42 +0300
commitaceff1f8632d159922d49dbcaa1aaf930a4a2fed (patch)
treeacf7cc789a48a34e450237367a31622578112f90 /shell_integration
parent113f56fdc5a895cb0893da89904d77374e1a7762 (diff)
macOS: Implement new dynamic Finder menu items #6328
Diffstat (limited to 'shell_integration')
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h1
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m103
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.h2
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.m38
4 files changed, 85 insertions, 59 deletions
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h
index 67a436094..803c5270f 100644
--- a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h
@@ -23,6 +23,7 @@
NSMutableSet *_registeredDirectories;
NSString *_shareMenuTitle;
NSMutableDictionary *_strings;
+ NSMutableArray *_menuItems;
}
@end
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m
index 2e917d132..a0f791882 100644
--- a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m
@@ -21,7 +21,7 @@
- (instancetype)init
{
self = [super init];
-
+
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
NSBundle *extBundle = [NSBundle bundleForClass:[self class]];
// This was added to the bundle's Info.plist to get it from the build system
@@ -43,7 +43,7 @@
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW+SWM"];
[syncController setBadgeImage:warning label:@"Ignored" forBadgeIdentifier:@"IGNORE+SWM"];
[syncController setBadgeImage:error label:@"Error" forBadgeIdentifier:@"ERROR+SWM"];
-
+
// The Mach port name needs to:
// - Be prefixed with the code signing Team ID
// - Then infixed with the sandbox App Group
@@ -55,12 +55,12 @@
// the sandboxed App Extension needs.
// https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24
NSString *serverName = [socketApiPrefix stringByAppendingString:@".socketApi"];
- // NSLog(@"FinderSync serverName %@", serverName);
+ //NSLog(@"FinderSync serverName %@", serverName);
_syncClientProxy = [[SyncClientProxy alloc] initWithDelegate:self serverName:serverName];
_registeredDirectories = [[NSMutableSet alloc] init];
_strings = [[NSMutableDictionary alloc] init];
-
+
[_syncClientProxy start];
return self;
}
@@ -74,13 +74,27 @@
NSLog(@"ERROR: Could not determine file type of %@", [url path]);
isDir = NO;
}
-
+
NSString* normalizedPath = [[url path] decomposedStringWithCanonicalMapping];
[_syncClientProxy askForIcon:normalizedPath isDirectory:isDir];
}
#pragma mark - Menu and toolbar item support
+- (NSString*) selectedPathsSeparatedByRecordSeparator
+{
+ FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
+ NSMutableString *string = [[NSMutableString alloc] init];
+ [syncController.selectedItemURLs enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
+ if (string.length > 0) {
+ [string appendString:@"\x1e"]; // record separator
+ }
+ NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
+ [string appendString:normalizedPath];
+ }];
+ return string;
+}
+
- (NSMenu *)menuForMenuKind:(FIMenuKind)whichMenu
{
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
@@ -101,54 +115,43 @@
}
}];
+ NSString *paths = [self selectedPathsSeparatedByRecordSeparator];
+ // calling this IPC calls us back from client with several MENU_ITEM entries and then our askOnSocket returns again
+ [_syncClientProxy askOnSocket:paths query:@"GET_MENU_ITEMS"];
+
id contextMenuTitle = [_strings objectForKey:@"CONTEXT_MENU_TITLE"];
- id shareTitle = [_strings objectForKey:@"SHARE_MENU_TITLE"];
- id copyLinkTitle = [_strings objectForKey:@"COPY_PRIVATE_LINK_MENU_TITLE"];
- id emailLinkTitle = [_strings objectForKey:@"EMAIL_PRIVATE_LINK_MENU_TITLE"];
if (contextMenuTitle && !onlyRootsSelected) {
- NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
- NSMenu *subMenu = [[NSMenu alloc] initWithTitle:@""];
- NSMenuItem *subMenuItem = [menu addItemWithTitle:contextMenuTitle action:nil keyEquivalent:@""];
- subMenuItem.submenu = subMenu;
- subMenuItem.image = [[NSBundle mainBundle] imageForResource:@"app.icns"];
-
- [subMenu addItemWithTitle:shareTitle action:@selector(shareMenuAction:) keyEquivalent:@""];
- [subMenu addItemWithTitle:copyLinkTitle action:@selector(copyLinkMenuAction:) keyEquivalent:@""];
- [subMenu addItemWithTitle:emailLinkTitle action:@selector(emailLinkMenuAction:) keyEquivalent:@""];
-
+ NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
+ NSMenu *subMenu = [[NSMenu alloc] initWithTitle:@""];
+ NSMenuItem *subMenuItem = [menu addItemWithTitle:contextMenuTitle action:nil keyEquivalent:@""];
+ subMenuItem.submenu = subMenu;
+ subMenuItem.image = [[NSBundle mainBundle] imageForResource:@"app.icns"];
+
+ // There is an annoying bug in macOS (at least 10.13.3), it does not use/copy over the representedObject of a menu item
+ // So we have to use tag instead.
+ int idx = 0;
+ for (NSArray* item in _menuItems) {
+ NSMenuItem *actionItem = [subMenu addItemWithTitle:[item valueForKey:@"text"]
+ action:@selector(subMenuActionClicked:)
+ keyEquivalent:@""];
+ [actionItem setTag:idx];
+ [actionItem setTarget:self];
+ NSString *flags = [item valueForKey:@"flags"]; // e.g. "d"
+ if ([flags rangeOfString:@"d"].location != NSNotFound) {
+ [actionItem setEnabled:false];
+ }
+ idx++;
+ }
return menu;
}
return nil;
}
-- (IBAction)shareMenuAction:(id)sender
-{
- NSArray* items = [[FIFinderSyncController defaultController] selectedItemURLs];
-
- [items enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
- NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
- [_syncClientProxy askOnSocket:normalizedPath query:@"SHARE"];
- }];
-}
-
-- (IBAction)copyLinkMenuAction:(id)sender
-{
- NSArray* items = [[FIFinderSyncController defaultController] selectedItemURLs];
-
- [items enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
- NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
- [_syncClientProxy askOnSocket:normalizedPath query:@"COPY_PRIVATE_LINK"];
- }];
-}
-
-- (IBAction)emailLinkMenuAction:(id)sender
-{
- NSArray* items = [[FIFinderSyncController defaultController] selectedItemURLs];
-
- [items enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
- NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
- [_syncClientProxy askOnSocket:normalizedPath query:@"EMAIL_PRIVATE_LINK"];
- }];
+- (void)subMenuActionClicked:(id)sender {
+ long idx = [(NSMenuItem*)sender tag];
+ NSString *command = [[_menuItems objectAtIndex:idx] valueForKey:@"command"];
+ NSString *paths = [self selectedPathsSeparatedByRecordSeparator];
+ [_syncClientProxy askOnSocket:paths query:command];
}
#pragma mark - SyncClientProxyDelegate implementation
@@ -181,6 +184,14 @@
[_strings setObject:value forKey:key];
}
+- (void)resetMenuItems
+{
+ _menuItems = [[NSMutableArray alloc] init];
+}
+- (void)addMenuItem:(NSDictionary *)item {
+ [_menuItems addObject:item];
+}
+
- (void)connectionDidDie
{
[_strings removeAllObjects];
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.h
index 8f9633416..1d0fd74b8 100644
--- a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.h
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.h
@@ -21,6 +21,8 @@
- (void)registerPath:(NSString*)path;
- (void)unregisterPath:(NSString*)path;
- (void)setString:(NSString*)key value:(NSString*)value;
+- (void)resetMenuItems;
+- (void)addMenuItem:(NSDictionary *)item;
- (void)connectionDidDie;
@end
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.m
index b7b64571f..656f77003 100644
--- a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.m
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.m
@@ -27,7 +27,7 @@
- (instancetype)initWithDelegate:(id)arg1 serverName:(NSString*)serverName
{
self = [super init];
-
+
self.delegate = arg1;
_serverName = serverName;
_remoteEnd = nil;
@@ -41,20 +41,20 @@
{
if (_remoteEnd)
return;
-
+
// Lookup the server connection
NSConnection *conn = [NSConnection connectionWithRegisteredName:_serverName host:nil];
-
+
if (!conn) {
// Could not connect to the sync client
[self scheduleRetry];
return;
}
-
+
[[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(connectionDidDie:)
- name:NSConnectionDidDieNotification
- object:conn];
+ selector:@selector(connectionDidDie:)
+ name:NSConnectionDidDieNotification
+ object:conn];
NSDistantObject <ServerProtocol> *server = (NSDistantObject <ServerProtocol> *)[conn rootProxy];
assert(server);
@@ -71,7 +71,7 @@
// The server replied with the distant object that we will use for tx
_remoteEnd = (NSDistantObject <ChannelProtocol> *)tx;
[_remoteEnd setProtocolForProxy:@protocol(ChannelProtocol)];
-
+
// Everything is set up, start querying
[self askOnSocket:@"" query:@"GET_STRINGS"];
}
@@ -83,7 +83,7 @@
- (void)connectionDidDie:(NSNotification*)notification
{
-#pragma unused(notification)
+#pragma unused(notification)
_remoteEnd = nil;
[_delegate connectionDidDie];
@@ -95,11 +95,11 @@
- (void)sendMessage:(NSData*)msg
{
NSString *answer = [[NSString alloc] initWithData:msg encoding:NSUTF8StringEncoding];
-
- // Cut the trailing newline
+
+ // Cut the trailing newline. We always only receive one line from the client.
answer = [answer substringToIndex:[answer length] - 1];
NSArray *chunks = [answer componentsSeparatedByString: @":"];
-
+
if( [[chunks objectAtIndex:0] isEqualToString:@"STATUS"] ) {
NSString *result = [chunks objectAtIndex:1];
NSString *path = [chunks objectAtIndex:2];
@@ -123,6 +123,18 @@
// BEGIN and END messages, do nothing.
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"STRING"] ) {
[_delegate setString:[chunks objectAtIndex:1] value:[chunks objectAtIndex:2]];
+ } else if( [[chunks objectAtIndex:0 ] isEqualToString:@"GET_MENU_ITEMS"] ) {
+ if ([[chunks objectAtIndex:1] isEqualToString:@"BEGIN"]) {
+ [_delegate resetMenuItems];
+ } else if ([[chunks objectAtIndex:1] isEqualToString:@"END"]) {
+ // Don't do anything special, the askOnSocket call in FinderSync menuForMenuKind will return after this line
+ }
+ } else if( [[chunks objectAtIndex:0 ] isEqualToString:@"MENU_ITEM"] ) {
+ NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
+ [item setValue:[chunks objectAtIndex:1] forKey:@"command"]; // e.g. "COPY_PRIVATE_LINK"
+ [item setValue:[chunks objectAtIndex:2] forKey:@"flags"]; // e.g. "d"
+ [item setValue:[chunks objectAtIndex:3] forKey:@"text"]; // e.g. "Copy private link to clipboard"
+ [_delegate addMenuItem:item];
} else {
NSLog(@"SyncState: Unknown command %@", [chunks objectAtIndex:0]);
}
@@ -131,7 +143,7 @@
- (void)askOnSocket:(NSString*)path query:(NSString*)verb
{
NSString *query = [NSString stringWithFormat:@"%@:%@\n", verb,path];
-
+
@try {
[_remoteEnd sendMessage:[query dataUsingEncoding:NSUTF8StringEncoding]];
} @catch(NSException* e) {