mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-14 16:22:21 +00:00
Fixed responder chain issues with ViewControllers
Context menu and copy actions now working (unfinished)
This commit is contained in:
@@ -8,6 +8,14 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
typedef enum {
|
||||
MPContextMenuCreate = 1<<0,
|
||||
MPContextMenuDelete = 1<<1,
|
||||
MPContextMenuCopy = 1<<2,
|
||||
MPContextMenuMinimal = MPContextMenuCreate | MPContextMenuDelete,
|
||||
MPContextMenuFull = MPContextMenuMinimal | MPContextMenuCopy,
|
||||
}MPContextMenuItemsFlags;
|
||||
|
||||
@class MPDatabaseDocument;
|
||||
|
||||
@interface MPAppDelegate : NSObject <NSApplicationDelegate>
|
||||
@@ -16,4 +24,10 @@
|
||||
|
||||
- (NSString *)applicationName;
|
||||
|
||||
/*
|
||||
Creates an array of menuitems to be used as a menu
|
||||
Automatically sets up actions, so you need to take care of the responder chain
|
||||
*/
|
||||
- (NSArray *)contextMenuItemsWithItems:(MPContextMenuItemsFlags)flags;
|
||||
|
||||
@end
|
||||
@@ -22,8 +22,7 @@
|
||||
|
||||
@implementation MPAppDelegate
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
self.mainWindowController = [[[MPMainWindowController alloc] init] autorelease];
|
||||
[self.mainWindowController showWindow:[self.mainWindowController window]];
|
||||
}
|
||||
@@ -51,8 +50,40 @@
|
||||
[self.settingsController showWindow:_settingsController.window];
|
||||
}
|
||||
|
||||
- (void)toolbarItemPressed:(id)sender {
|
||||
NSLog(@"Pressed %@", sender);
|
||||
- (NSArray *)contextMenuItemsWithItems:(MPContextMenuItemsFlags)flags {
|
||||
BOOL insertCreate = (0 != (flags & MPContextMenuCreate));
|
||||
BOOL insertDelete = (0 != (flags & MPContextMenuDelete));
|
||||
BOOL insertCopy = (0 != (flags & MPContextMenuCopy));
|
||||
|
||||
NSMutableArray *items = [NSMutableArray arrayWithCapacity:7];
|
||||
if(insertCreate) {
|
||||
NSMenuItem *newGroup = [[NSMenuItem alloc] initWithTitle:@"New Group" action:@selector(createGroup:) keyEquivalent:@"G"];
|
||||
NSMenuItem *newEntry = [[NSMenuItem alloc] initWithTitle:@"New Entry" action:@selector(createEntry:) keyEquivalent:@"E"];
|
||||
[items addObjectsFromArray:@[ newGroup, newEntry ]];
|
||||
[newEntry release];
|
||||
[newGroup release];
|
||||
}
|
||||
if(insertDelete) {
|
||||
if([items count] > 0) {
|
||||
[items addObject:[NSMenuItem separatorItem]];
|
||||
}
|
||||
NSMenuItem *delete = [[NSMenuItem alloc] initWithTitle:@"Delete" action:@selector(deleteEntry:) keyEquivalent:@""];
|
||||
[items addObject:delete];
|
||||
[delete release];
|
||||
}
|
||||
if(insertCopy) {
|
||||
if([items count] > 0) {
|
||||
[items addObject:[NSMenuItem separatorItem]];
|
||||
}
|
||||
NSMenuItem *copyUsername = [[NSMenuItem alloc] initWithTitle:@"Copy Username" action:@selector(copyUsername:) keyEquivalent:@"C"];
|
||||
NSMenuItem *copyPassword = [[NSMenuItem alloc] initWithTitle:@"Copy Password" action:@selector(copyPassword:) keyEquivalent:@"c"];
|
||||
NSMenuItem *openURL = [[NSMenuItem alloc] initWithTitle:@"Open URL" action:@selector(openURL:) keyEquivalent:@"U"];
|
||||
[items addObjectsFromArray:@[ copyUsername, copyPassword, openURL]];
|
||||
[copyPassword release];
|
||||
[copyUsername release];
|
||||
[openURL release];
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
[borderGradient drawInRect:drawingRect relativeCenterPosition:NSMakePoint(-1.0, 0)];
|
||||
drawingRect.origin.x = [self bounds].size.width - 5;
|
||||
[borderGradient drawInRect:drawingRect relativeCenterPosition:NSMakePoint(1.0, 0)];
|
||||
[borderGradient release];
|
||||
}
|
||||
[super drawRect:dirtyRect];
|
||||
}
|
||||
|
||||
@@ -14,6 +14,13 @@ APPKIT_EXTERN NSString *const MPEntryTablePasswordColumnIdentifier;
|
||||
APPKIT_EXTERN NSString *const MPEntryTableParentColumnIdentifier;
|
||||
APPKIT_EXTERN NSString *const MPEntryTableURLColumnIdentifier;
|
||||
|
||||
/* Tags to determine what to copy */
|
||||
typedef enum {
|
||||
MPCopyUsername,
|
||||
MPCopyPassword,
|
||||
MPCopyURL,
|
||||
MPCopyWholeEntry,
|
||||
} MPCopyContentTypeTag;
|
||||
|
||||
@class KdbGroup;
|
||||
@class MPOutlineViewDelegate;
|
||||
@@ -27,4 +34,10 @@ APPKIT_EXTERN NSString *const MPEntryTableURLColumnIdentifier;
|
||||
/* Clear the Search filter*/
|
||||
- (void)clearFilter;
|
||||
|
||||
- (void)copyUsername:(id)sender;
|
||||
- (void)copyPassword:(id)sender;
|
||||
//- (void)copyURL:(id)sender;
|
||||
//- (void)createEntry:(id)sender;
|
||||
//- (void)deleteEntry:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "MPEntryViewController.h"
|
||||
#import "MPAppDelegate.h"
|
||||
#import "MPOutlineViewDelegate.h"
|
||||
#import "MPDatabaseController.h"
|
||||
#import "MPDatabaseDocument.h"
|
||||
@@ -27,12 +28,6 @@ typedef enum {
|
||||
MPFilterTitles = 8,
|
||||
} MPFilterModeType;
|
||||
|
||||
typedef enum {
|
||||
MPCopyUsername,
|
||||
MPCopyPassword,
|
||||
MPCopyURL,
|
||||
MPCopyWholeEntry,
|
||||
} MPCopyContentTypeTag;
|
||||
|
||||
NSString *const MPEntryTableUserNameColumnIdentifier = @"MPUserNameColumnIdentifier";
|
||||
NSString *const MPEntryTableTitleColumnIdentifier = @"MPTitleColumnIdentifier";
|
||||
@@ -83,8 +78,8 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
- (void)_showFilterBarAnimated:(BOOL)animate;
|
||||
- (void)_hideStatusBarAnimated:(BOOL)animate;
|
||||
|
||||
- (void)_copyEntryData:(id)sender;
|
||||
- (void)_quickCopyEntryData:(id)sender;
|
||||
- (KdbEntry *)_selectedEntry;
|
||||
|
||||
@end
|
||||
|
||||
@@ -333,7 +328,7 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
|
||||
|
||||
animate = NO;
|
||||
|
||||
|
||||
if(!self.isStatusBarVisible) {
|
||||
return; // nothing to do;
|
||||
}
|
||||
@@ -357,84 +352,65 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
#pragma mark EntryMenu
|
||||
|
||||
- (void)_setupEntryMenu {
|
||||
NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
|
||||
NSMenuItem *copyUserItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:@"Copy Username"
|
||||
action:@selector(_copyEntryData:)
|
||||
keyEquivalent:@"C"];
|
||||
[copyUserItem setTag:MPCopyUsername];
|
||||
[copyUserItem setTarget:self];
|
||||
NSMenuItem *copyPasswordItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:@"Copy Password"
|
||||
action:@selector(_copyEntryData:)
|
||||
keyEquivalent:@"c"];
|
||||
[copyPasswordItem setTag:MPCopyPassword];
|
||||
[copyPasswordItem setTarget:self];
|
||||
|
||||
[menu addItem:copyUserItem];
|
||||
[menu addItem:copyPasswordItem];
|
||||
[copyUserItem release];
|
||||
[copyPasswordItem release];
|
||||
|
||||
NSMenu *menu = [[NSMenu alloc] init];
|
||||
NSArray *items = [(MPAppDelegate *)[NSApp delegate] contextMenuItemsWithItems:MPContextMenuFull];
|
||||
for(NSMenuItem *item in items) {
|
||||
[menu addItem:item];
|
||||
}
|
||||
[self.entryTable setMenu:menu];
|
||||
[menu release];
|
||||
}
|
||||
|
||||
#pragma makr Action Helper
|
||||
|
||||
- (KdbEntry *)_selectedEntry {
|
||||
NSInteger activeRow = [self.entryTable clickedRow];
|
||||
/* Fallback to selection e.g. for toolbar actions */
|
||||
if(activeRow < 0 ) {
|
||||
activeRow = [self.entryTable selectedRow];
|
||||
}
|
||||
if(activeRow >= 0 && activeRow <= [[self.entryArrayController arrangedObjects] count]) {
|
||||
return [self.entryArrayController arrangedObjects][activeRow];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark Actions
|
||||
|
||||
- (void)_quickCopyEntryData:(id)sender {
|
||||
NSInteger clickedRow = [self.entryTable clickedRow];
|
||||
if(clickedRow < 0 || clickedRow > [[self.entryArrayController arrangedObjects] count]) {
|
||||
return;
|
||||
}
|
||||
KdbEntry *selectedEntry = [self.entryArrayController arrangedObjects][clickedRow];
|
||||
NSTableColumn *column = [self.entryTable tableColumns][[self.entryTable clickedColumn]];
|
||||
NSString *identifier = [column identifier];
|
||||
NSImage *image = nil;
|
||||
NSString *lable = nil;
|
||||
if([identifier isEqualToString:MPEntryTablePasswordColumnIdentifier]) {
|
||||
[[MPPasteBoardController defaultController] copyObjects:@[ selectedEntry.password ]];
|
||||
image = [[NSBundle mainBundle] imageForResource:@"00_PasswordTemplate"];
|
||||
lable = @"Password copied!";
|
||||
[self copyPassword:nil];
|
||||
}
|
||||
else if([identifier isEqualToString:MPEntryTableUserNameColumnIdentifier]) {
|
||||
[[MPPasteBoardController defaultController] copyObjects:@[ selectedEntry.username ]];
|
||||
image = [[NSBundle mainBundle] imageForResource:@"09_IdentityTemplate"];
|
||||
lable = @"Username copied!";
|
||||
}
|
||||
if(image || lable) {
|
||||
[[MPOverlayWindowController sharedController] displayOverlayImage:image label:lable atView:self.view];
|
||||
[self copyUsername:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_copyEntryData:(id)sender {
|
||||
NSInteger clickedRow = [self.entryTable clickedRow];
|
||||
if(clickedRow < 0 || clickedRow > [[self.entryArrayController arrangedObjects] count]) {
|
||||
return;
|
||||
}
|
||||
KdbEntry *selectedEntry = [self.entryArrayController arrangedObjects][clickedRow];
|
||||
|
||||
if([sender respondsToSelector:@selector(tag)]) {
|
||||
MPCopyContentTypeTag contentTag = (MPCopyContentTypeTag)[sender tag];
|
||||
SEL contentTypeSelector = @selector(description);
|
||||
switch (contentTag) {
|
||||
case MPCopyPassword:
|
||||
contentTypeSelector = @selector(password);
|
||||
break;
|
||||
|
||||
case MPCopyUsername:
|
||||
contentTypeSelector = @selector(username);
|
||||
break;
|
||||
|
||||
case MPCopyURL:
|
||||
contentTypeSelector = @selector(URL);
|
||||
break;
|
||||
|
||||
case MPCopyWholeEntry:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[[MPPasteBoardController defaultController] copyObjects:@[ [selectedEntry performSelector:contentTypeSelector] ]];
|
||||
}
|
||||
- (void)copyPassword:(id)sender {
|
||||
KdbEntry *selectedEntry = [self _selectedEntry];
|
||||
if(!selectedEntry) {
|
||||
return; // nothing found to work with;
|
||||
}
|
||||
[[MPPasteBoardController defaultController] copyObjects:@[ selectedEntry.password ]];
|
||||
NSImage *image = [[NSBundle mainBundle] imageForResource:@"00_PasswordTemplate"];
|
||||
NSString *lable = @"Password copied!";
|
||||
[[MPOverlayWindowController sharedController] displayOverlayImage:image label:lable atView:self.view];
|
||||
}
|
||||
|
||||
- (void)copyUsername:(id)sender {
|
||||
KdbEntry *selectedEntry = [self _selectedEntry];
|
||||
if(!selectedEntry) {
|
||||
return; // No entry to work with;
|
||||
}
|
||||
[[MPPasteBoardController defaultController] copyObjects:@[ selectedEntry.username ] ];
|
||||
|
||||
[[MPPasteBoardController defaultController] copyObjects:@[ selectedEntry.username ]];
|
||||
NSImage *image = [[NSBundle mainBundle] imageForResource:@"09_IdentityTemplate"];
|
||||
NSString *lable = @"Username copied!";
|
||||
[[MPOverlayWindowController sharedController] displayOverlayImage:image label:lable atView:self.view];
|
||||
}
|
||||
|
||||
- (void)_toggleFilterSpace:(id)sender {
|
||||
@@ -453,7 +429,6 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)setFilterMode:(MPFilterModeType)newFilterMode {
|
||||
|
||||
@@ -20,4 +20,5 @@
|
||||
Clears the Search filter
|
||||
*/
|
||||
- (void)clearFilter:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
@interface MPMainWindowController ()
|
||||
|
||||
|
||||
@property (assign) IBOutlet NSView *outlineView;
|
||||
@property (assign) IBOutlet NSSplitView *splitView;
|
||||
@property (assign) IBOutlet NSView *contentView;
|
||||
@@ -84,7 +85,7 @@
|
||||
{
|
||||
[super windowDidLoad];
|
||||
[self _updateWindowTitle];
|
||||
|
||||
|
||||
[[self.welcomeText cell] setBackgroundStyle:NSBackgroundStyleRaised];
|
||||
|
||||
const CGFloat minimumWindowWidth = MPMainWindowSplitViewDelegateMinimumContentWidth + MPMainWindowSplitViewDelegateMinimumOutlineWidth + [self.splitView dividerThickness];
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
@interface MPOutlineViewController : MPViewController
|
||||
|
||||
@property (retain, readonly) NSMenu *menu;
|
||||
|
||||
- (void)clearSelection;
|
||||
|
||||
- (void)createGroup:(id)sender;
|
||||
- (void)deleteEntry:(id)sender;
|
||||
@end
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#import "MPOutlineDataSource.h"
|
||||
#import "MPDatabaseController.h"
|
||||
#import "MPDatabaseDocument.h"
|
||||
#import "MPAppDelegate.h"
|
||||
|
||||
@interface MPOutlineViewController ()
|
||||
|
||||
@@ -22,8 +23,7 @@
|
||||
|
||||
|
||||
- (void)_didOpenDocument:(NSNotification *)notification;
|
||||
- (void)_setupMenu;
|
||||
- (void)_addEntry:(id)sender;
|
||||
- (NSMenu *)_contextMenu;
|
||||
|
||||
@end
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
selector:@selector(_didOpenDocument:)
|
||||
name:MPDatabaseControllerDidLoadDatabaseNotification
|
||||
object:nil];
|
||||
[self _setupMenu];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -61,7 +60,7 @@
|
||||
- (void)didLoadView {
|
||||
[self.outlineView setDataSource:self.datasource];
|
||||
[self.outlineView setDelegate:self.outlineDelegate];
|
||||
[self.outlineView setMenu:self.menu];
|
||||
[self.outlineView setMenu:[self _contextMenu]];
|
||||
[self.outlineView setAllowsEmptySelection:YES];
|
||||
}
|
||||
|
||||
@@ -83,21 +82,23 @@
|
||||
[self.outlineView deselectAll:nil];
|
||||
}
|
||||
|
||||
- (void)_setupMenu {
|
||||
NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
|
||||
[menu addItemWithTitle:@"Add Group" action:@selector(_addEntry:) keyEquivalent:@""];
|
||||
[menu addItem: [NSMenuItem separatorItem]];
|
||||
[menu addItemWithTitle:@"Delete" action:NULL keyEquivalent:@""];
|
||||
for(NSMenuItem *item in [menu itemArray]) {
|
||||
[item setTarget:self];
|
||||
- (NSMenu *)_contextMenu {
|
||||
NSMenu *menu = [[NSMenu alloc] init];
|
||||
NSArray *items = [(MPAppDelegate *)[NSApp delegate] contextMenuItemsWithItems:MPContextMenuMinimal];
|
||||
for(NSMenuItem *item in items) {
|
||||
[menu addItem:item];
|
||||
}
|
||||
|
||||
self.menu = menu;
|
||||
[menu release];
|
||||
return [menu autorelease];
|
||||
}
|
||||
|
||||
- (void)_addEntry:(id)sender {
|
||||
NSLog(@"Add Entry");
|
||||
- (void)createGroup:(id)sender {
|
||||
NSLog(@"%@: Create Group", [self class]);
|
||||
}
|
||||
|
||||
- (void)deleteEntry:(id)sender {
|
||||
NSLog(@"%@: Delete Entry", [self class]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
|
||||
#import "MPToolbarDelegate.h"
|
||||
#import "MPIconHelper.h"
|
||||
#import "MPMainWindowController.h"
|
||||
#import "MPPathBar.h"
|
||||
#import "MPAppDelegate.h"
|
||||
#import "MPToolbarButton.h"
|
||||
|
||||
NSString *const MPToolbarItemAddGroup = @"AddGroup";
|
||||
@@ -30,13 +29,12 @@ NSString *const MPToolbarItemSearch = @"Search";
|
||||
@implementation MPToolbarDelegate
|
||||
|
||||
|
||||
- (id)init
|
||||
{
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.toolbarIdentifiers = @[ MPToolbarItemAddEntry, MPToolbarItemDelete, MPToolbarItemEdit, MPToolbarItemAddGroup, MPToolbarItemAction, NSToolbarFlexibleSpaceItemIdentifier, MPToolbarItemSearch ];
|
||||
self.toolbarImages = [self createToolbarImages];
|
||||
self.toolbarItems = [[NSMutableDictionary alloc] initWithCapacity:[self.toolbarIdentifiers count]];
|
||||
_toolbarIdentifiers = [@[ MPToolbarItemAddEntry, MPToolbarItemDelete, MPToolbarItemEdit, MPToolbarItemAddGroup, MPToolbarItemAction, NSToolbarFlexibleSpaceItemIdentifier, MPToolbarItemSearch ] retain];
|
||||
_toolbarImages = [[self createToolbarImages] retain];
|
||||
_toolbarItems = [[NSMutableDictionary alloc] initWithCapacity:[self.toolbarIdentifiers count]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -53,7 +51,6 @@ NSString *const MPToolbarItemSearch = @"Search";
|
||||
NSToolbarItem *item = self.toolbarItems[itemIdentifier];
|
||||
if(!item) {
|
||||
item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
|
||||
[item setAction:@selector(toolbarItemPressed:)];
|
||||
NSString *label = NSLocalizedString(itemIdentifier, @"");
|
||||
[item setLabel:label];
|
||||
|
||||
@@ -73,25 +70,25 @@ NSString *const MPToolbarItemSearch = @"Search";
|
||||
[[popupButton cell] setImageScaling:NSImageScaleProportionallyDown];
|
||||
[popupButton setTitle:@""];
|
||||
[popupButton sizeToFit];
|
||||
/*
|
||||
Built menu
|
||||
*/
|
||||
NSMenu *menu = [NSMenu allocWithZone:[NSMenu menuZone]];
|
||||
NSMenuItem *menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:@"" action:NULL keyEquivalent:@""];
|
||||
[menuItem setImage:self.toolbarImages[itemIdentifier]];
|
||||
[menu addItem:menuItem];
|
||||
[menu addItemWithTitle:@"Foo" action:NULL keyEquivalent:@""];
|
||||
[menu addItemWithTitle:@"Bar" action:NULL keyEquivalent:@""];
|
||||
|
||||
NSRect newFrame = [popupButton frame];
|
||||
newFrame.size.width += 20;
|
||||
|
||||
|
||||
|
||||
NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
|
||||
NSMenuItem *actionImageItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:@"" action:NULL keyEquivalent:@""];
|
||||
[actionImageItem setImage:self.toolbarImages[MPToolbarItemAction]];
|
||||
[menu addItem:actionImageItem];
|
||||
[actionImageItem release];
|
||||
NSArray *menuItems = [(MPAppDelegate *)[NSApp delegate] contextMenuItemsWithItems:MPContextMenuFull];
|
||||
for(NSMenuItem *item in menuItems) {
|
||||
[menu addItem:item];
|
||||
}
|
||||
[popupButton setFrame:newFrame];
|
||||
[popupButton setMenu:menu];
|
||||
/*
|
||||
Cleanup
|
||||
*/
|
||||
[menuItem release];
|
||||
[menu release];
|
||||
|
||||
[item setView:popupButton];
|
||||
[popupButton release];
|
||||
}
|
||||
@@ -142,5 +139,4 @@ NSString *const MPToolbarItemSearch = @"Search";
|
||||
return imageDict;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
- (void)didLoadView;
|
||||
- (NSResponder *)reconmendedFirstResponder;
|
||||
|
||||
- (void)updateResponderChain;
|
||||
|
||||
@end
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
- (void)updateResponderChain {
|
||||
if(self.view) {
|
||||
NSLog(@"Updated responder chain");
|
||||
NSResponder *nextResponder = [[self view] nextResponder];
|
||||
[[self view] setNextResponder:self];
|
||||
[self setNextResponder:nextResponder];
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>3C8</string>
|
||||
<string>3E4</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
|
||||
Reference in New Issue
Block a user