Mac: New sites.
[MOVED] Creation of new elements moved to shared code. [FIXED] When switching user, unset active key. [FIXED] Synchronize content calculation to avoid race issues while typing. [ADDED] Ability to create new sites. [FIXED] Unset active element when hitting backspace or escape.
This commit is contained in:
parent
8f4eb6df84
commit
e45b9985c2
@ -25,6 +25,8 @@ typedef enum {
|
|||||||
+ (BOOL)managedObjectContextPerformBlockAndWait:(void (^)(NSManagedObjectContext *))mocBlock;
|
+ (BOOL)managedObjectContextPerformBlockAndWait:(void (^)(NSManagedObjectContext *))mocBlock;
|
||||||
|
|
||||||
- (UbiquityStoreManager *)storeManager;
|
- (UbiquityStoreManager *)storeManager;
|
||||||
|
|
||||||
|
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(MPElementEntity *element))completion;
|
||||||
- (MPImportResult)importSites:(NSString *)importedSitesString
|
- (MPImportResult)importSites:(NSString *)importedSitesString
|
||||||
askImportPassword:(NSString *(^)(NSString *userName))importPassword
|
askImportPassword:(NSString *(^)(NSString *userName))importPassword
|
||||||
askUserPassword:(NSString *(^)(NSString *userName, NSUInteger importCount, NSUInteger deleteCount))userPassword;
|
askUserPassword:(NSString *(^)(NSString *userName, NSUInteger importCount, NSUInteger deleteCount))userPassword;
|
||||||
|
@ -384,7 +384,44 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma mark - Import / Export
|
#pragma mark - Utilities
|
||||||
|
|
||||||
|
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(MPElementEntity *element))completion {
|
||||||
|
|
||||||
|
if (![siteName length]) {
|
||||||
|
completion( nil );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MPAppDelegate_Shared managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||||
|
MPUserEntity *activeUser = [self activeUserInContext:moc];
|
||||||
|
assert(activeUser);
|
||||||
|
|
||||||
|
MPElementType type = activeUser.defaultType;
|
||||||
|
if (!type)
|
||||||
|
type = activeUser.defaultType = MPElementTypeGeneratedLong;
|
||||||
|
NSString *typeEntityClassName = [MPAlgorithmDefault classNameOfType:type];
|
||||||
|
|
||||||
|
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:typeEntityClassName
|
||||||
|
inManagedObjectContext:moc];
|
||||||
|
|
||||||
|
element.name = siteName;
|
||||||
|
element.user = activeUser;
|
||||||
|
element.type = type;
|
||||||
|
element.lastUsed = [NSDate date];
|
||||||
|
element.version = MPAlgorithmDefaultVersion;
|
||||||
|
[moc saveToStore];
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
if (element.objectID.isTemporaryID && ![moc obtainPermanentIDsForObjects:@[ element ] error:&error])
|
||||||
|
err(@"Failed to obtain a permanent object ID after creating new element: %@", error);
|
||||||
|
|
||||||
|
NSManagedObjectID *elementOID = [element objectID];
|
||||||
|
dispatch_async( dispatch_get_main_queue(), ^{
|
||||||
|
completion( (MPElementEntity *)[[MPAppDelegate_Shared managedObjectContextForThreadIfReady] objectRegisteredForID:elementOID] );
|
||||||
|
} );
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
- (MPImportResult)importSites:(NSString *)importedSitesString
|
- (MPImportResult)importSites:(NSString *)importedSitesString
|
||||||
askImportPassword:(NSString *(^)(NSString *userName))importPassword
|
askImportPassword:(NSString *(^)(NSString *userName))importPassword
|
||||||
|
@ -105,6 +105,8 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
|
|
||||||
- (void)selectUser:(NSMenuItem *)item {
|
- (void)selectUser:(NSMenuItem *)item {
|
||||||
|
|
||||||
|
[self signOutAnimated:NO];
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||||
self.activeUser = (MPUserEntity *)[moc existingObjectWithID:[item representedObject] error:&error];
|
self.activeUser = (MPUserEntity *)[moc existingObjectWithID:[item representedObject] error:&error];
|
||||||
|
@ -13,12 +13,14 @@
|
|||||||
|
|
||||||
#define MPAlertUnlockMP @"MPAlertUnlockMP"
|
#define MPAlertUnlockMP @"MPAlertUnlockMP"
|
||||||
#define MPAlertIncorrectMP @"MPAlertIncorrectMP"
|
#define MPAlertIncorrectMP @"MPAlertIncorrectMP"
|
||||||
|
#define MPAlertCreateSite @"MPAlertCreateSite"
|
||||||
|
|
||||||
@interface MPPasswordWindowController()
|
@interface MPPasswordWindowController()
|
||||||
|
|
||||||
@property(nonatomic) BOOL inProgress;
|
@property(nonatomic) BOOL inProgress;
|
||||||
@property(nonatomic) BOOL siteFieldPreventCompletion;
|
@property(nonatomic) BOOL siteFieldPreventCompletion;
|
||||||
|
|
||||||
|
@property(nonatomic, strong) NSOperationQueue *backgroundQueue;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation MPPasswordWindowController {
|
@implementation MPPasswordWindowController {
|
||||||
@ -32,6 +34,9 @@
|
|||||||
else
|
else
|
||||||
self.window.styleMask = NSTexturedBackgroundWindowMask | NSResizableWindowMask | NSTitledWindowMask | NSClosableWindowMask;
|
self.window.styleMask = NSTexturedBackgroundWindowMask | NSResizableWindowMask | NSTitledWindowMask | NSClosableWindowMask;
|
||||||
|
|
||||||
|
self.backgroundQueue = [NSOperationQueue new];
|
||||||
|
self.backgroundQueue.maxConcurrentOperationCount = 1;
|
||||||
|
|
||||||
[self setContent:@""];
|
[self setContent:@""];
|
||||||
[self.tipField setStringValue:@""];
|
[self.tipField setStringValue:@""];
|
||||||
|
|
||||||
@ -81,7 +86,7 @@
|
|||||||
|
|
||||||
if (![MPMacAppDelegate get].key)
|
if (![MPMacAppDelegate get].key)
|
||||||
// Ask the user to set the key through his master password.
|
// Ask the user to set the key through his master password.
|
||||||
dispatch_async( dispatch_get_main_queue(), ^{
|
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||||
if ([MPMacAppDelegate get].key)
|
if ([MPMacAppDelegate get].key)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -99,7 +104,7 @@
|
|||||||
[passwordField becomeFirstResponder];
|
[passwordField becomeFirstResponder];
|
||||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP];
|
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP];
|
||||||
} );
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||||
@ -112,9 +117,8 @@
|
|||||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||||
switch (returnCode) {
|
switch (returnCode) {
|
||||||
case NSAlertAlternateReturn:
|
case NSAlertAlternateReturn: {
|
||||||
// "Change" button.
|
// "Change" button.
|
||||||
{
|
|
||||||
NSInteger returnCode_ = [[NSAlert
|
NSInteger returnCode_ = [[NSAlert
|
||||||
alertWithMessageText:@"Changing Master Password" defaultButton:nil
|
alertWithMessageText:@"Changing Master Password" defaultButton:nil
|
||||||
alternateButton:[PearlStrings get].commonButtonCancel otherButton:nil informativeTextWithFormat:
|
alternateButton:[PearlStrings get].commonButtonCancel otherButton:nil informativeTextWithFormat:
|
||||||
@ -131,13 +135,14 @@
|
|||||||
[[MPMacAppDelegate get] signOutAnimated:YES];
|
[[MPMacAppDelegate get] signOutAnimated:YES];
|
||||||
[moc saveToStore];
|
[moc saveToStore];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NSAlertOtherReturn:
|
case NSAlertOtherReturn: {
|
||||||
// "Cancel" button.
|
// "Cancel" button.
|
||||||
[self.window close];
|
[self.window close];
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case NSAlertDefaultReturn: {
|
case NSAlertDefaultReturn: {
|
||||||
// "Unlock" button.
|
// "Unlock" button.
|
||||||
@ -156,7 +161,7 @@
|
|||||||
usingMasterPassword:password];
|
usingMasterPassword:password];
|
||||||
self.inProgress = NO;
|
self.inProgress = NO;
|
||||||
|
|
||||||
dispatch_async( dispatch_get_main_queue(), ^{
|
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||||
[self.progressView stopAnimation:nil];
|
[self.progressView stopAnimation:nil];
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
@ -167,8 +172,9 @@
|
|||||||
}]] beginSheetModalForWindow:self.window modalDelegate:self
|
}]] beginSheetModalForWindow:self.window modalDelegate:self
|
||||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP];
|
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP];
|
||||||
}
|
}
|
||||||
} );
|
}];
|
||||||
}];
|
}];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -177,12 +183,27 @@
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (contextInfo == MPAlertCreateSite) {
|
||||||
|
switch (returnCode) {
|
||||||
|
case NSAlertDefaultReturn: {
|
||||||
|
[[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element) {
|
||||||
|
if (element) {
|
||||||
|
_activeElementOID = element.objectID;
|
||||||
|
[self trySiteWithAction:NO];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words
|
- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words
|
||||||
forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index {
|
forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index {
|
||||||
|
|
||||||
NSString *query = [[control stringValue] substringWithRange:charRange];
|
NSString *query = [[textView string] substringWithRange:charRange];
|
||||||
if (![query length] || ![MPMacAppDelegate get].key)
|
if (![query length] || ![MPMacAppDelegate get].key)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
@ -203,12 +224,14 @@
|
|||||||
[mutableResults addObject:element.name];
|
[mutableResults addObject:element.name];
|
||||||
//[mutableResults addObject:query]; // For when the app should be able to create new sites.
|
//[mutableResults addObject:query]; // For when the app should be able to create new sites.
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
_activeElementOID = nil;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
if ([mutableResults count] == 1) {
|
if ([mutableResults count] < 2) {
|
||||||
//[textView setString:[(MPElementEntity *)[siteResults objectAtIndex:0] name]];
|
//[textView setString:[(MPElementEntity *)[siteResults objectAtIndex:0] name]];
|
||||||
//[textView setSelectedRange:NSMakeRange( [query length], [[textView string] length] - [query length] )];
|
//[textView setSelectedRange:NSMakeRange( [query length], [[textView string] length] - [query length] )];
|
||||||
[self trySiteAndCopyContent:NO];
|
[self trySiteWithAction:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
return mutableResults;
|
return mutableResults;
|
||||||
@ -216,14 +239,17 @@
|
|||||||
|
|
||||||
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
||||||
|
|
||||||
if (commandSelector == @selector(cancel:)) {
|
if (commandSelector == @selector(cancel:)) { // Escape without completion.
|
||||||
[self.window close];
|
[self.window close];
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
if ((self.siteFieldPreventCompletion = [NSStringFromSelector( commandSelector ) hasPrefix:@"delete"]))
|
if ((self.siteFieldPreventCompletion = [NSStringFromSelector( commandSelector ) hasPrefix:@"delete"])) { // Backspace any time.
|
||||||
|
_activeElementOID = nil;
|
||||||
|
[self trySiteWithAction:NO];
|
||||||
return NO;
|
return NO;
|
||||||
if (commandSelector == @selector(insertNewline:)) {
|
}
|
||||||
[self trySiteAndCopyContent:YES];
|
if (commandSelector == @selector(insertNewline:)) { // Return without completion.
|
||||||
|
[self trySiteWithAction:YES];
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +261,7 @@
|
|||||||
if (note.object != self.siteField)
|
if (note.object != self.siteField)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self trySiteAndCopyContent:NO];
|
[self trySiteWithAction:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)controlTextDidChange:(NSNotification *)note {
|
- (void)controlTextDidChange:(NSNotification *)note {
|
||||||
@ -244,12 +270,18 @@
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Update the site content as the site name changes.
|
// Update the site content as the site name changes.
|
||||||
BOOL enterPressed = [[NSApp currentEvent] type] == NSKeyDown &&
|
if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||||
[[[NSApp currentEvent] charactersIgnoringModifiers] isEqualToString:@"\r"];
|
[[[NSApp currentEvent] charactersIgnoringModifiers] isEqualToString:@"\r"]) { // Return while completing.
|
||||||
[self trySiteAndCopyContent:enterPressed];
|
[self trySiteWithAction:YES];
|
||||||
|
|
||||||
if (enterPressed)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||||
|
[[[NSApp currentEvent] charactersIgnoringModifiers] characterAtIndex:0] == 0x1b) { // Escape while completing.
|
||||||
|
_activeElementOID = nil;
|
||||||
|
[self trySiteWithAction:NO];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.siteFieldPreventCompletion) {
|
if (self.siteFieldPreventCompletion) {
|
||||||
self.siteFieldPreventCompletion = NO;
|
self.siteFieldPreventCompletion = NO;
|
||||||
@ -289,67 +321,75 @@
|
|||||||
}]];
|
}]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)trySiteAndCopyContent:(BOOL)copyContent {
|
- (void)trySiteWithAction:(BOOL)doAction {
|
||||||
|
|
||||||
[self setContent:@""];
|
[self.backgroundQueue addOperationWithBlock:^{
|
||||||
[self.tipField setStringValue:@"Generating..."];
|
|
||||||
|
|
||||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
|
|
||||||
NSString *content = [[self activeElementForThread].content description];
|
NSString *content = [[self activeElementForThread].content description];
|
||||||
if (!content)
|
if (!content)
|
||||||
content = @"";
|
content = @"";
|
||||||
if (copyContent) {
|
|
||||||
[[NSPasteboard generalPasteboard] declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
NSString *siteName = [self.siteField stringValue];
|
||||||
if (![[NSPasteboard generalPasteboard] setString:content forType:NSPasteboardTypeString]) {
|
dbg(@"name: %@, action: %d", siteName, doAction);
|
||||||
wrn(@"Couldn't copy password to pasteboard.");
|
if (doAction) {
|
||||||
|
if ([content length]) {
|
||||||
|
// Performing action while content is available. Copy it.
|
||||||
|
[self copyContent:content];
|
||||||
|
}
|
||||||
|
else if ([siteName length]) {
|
||||||
|
// Performing action without content but a site name is written.
|
||||||
|
[self createNewSite:siteName];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
|
||||||
MPElementEntity *activeElement = [self activeElementInContext:moc];
|
|
||||||
[activeElement use];
|
|
||||||
[moc saveToStore];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_async( dispatch_get_main_queue(), ^{
|
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||||
[self setContent:content];
|
[self setContent:content];
|
||||||
|
|
||||||
self.tipField.alphaValue = 1;
|
self.tipField.alphaValue = 1;
|
||||||
if (!copyContent)
|
if ([content length] == 0) {
|
||||||
|
if ([siteName length])
|
||||||
|
[self.tipField setStringValue:@"Hit ⌤ (ENTER) to create a new site."];
|
||||||
|
else
|
||||||
|
[self.tipField setStringValue:@""];
|
||||||
|
}
|
||||||
|
else if (!doAction)
|
||||||
[self.tipField setStringValue:@"Hit ⌤ (ENTER) to copy the password."];
|
[self.tipField setStringValue:@"Hit ⌤ (ENTER) to copy the password."];
|
||||||
else {
|
else {
|
||||||
[self.tipField setStringValue:@"Copied! Hit ⎋ (ESC) to close window."];
|
[self.tipField setStringValue:@"Copied! Hit ⎋ (ESC) to close window."];
|
||||||
dispatch_time_t popTime = dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) );
|
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) ), dispatch_get_main_queue(), ^{
|
||||||
dispatch_after( popTime, dispatch_get_main_queue(), ^{
|
|
||||||
[NSAnimationContext beginGrouping];
|
[NSAnimationContext beginGrouping];
|
||||||
[[NSAnimationContext currentContext] setDuration:0.2f];
|
[[NSAnimationContext currentContext] setDuration:0.2f];
|
||||||
[self.tipField.animator setAlphaValue:0];
|
[self.tipField.animator setAlphaValue:0];
|
||||||
[NSAnimationContext endGrouping];
|
[NSAnimationContext endGrouping];
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
} );
|
}];
|
||||||
} );
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
// For when the app should be able to create new sites.
|
- (void)copyContent:(NSString *)content {
|
||||||
/*
|
|
||||||
else
|
|
||||||
[[MPMacAppDelegate get].managedObjectContext performBlock:^{
|
|
||||||
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPElementGeneratedEntity class])
|
|
||||||
inManagedObjectContext:[MPMacAppDelegate get].managedObjectContext];
|
|
||||||
assert([element isKindOfClass:ClassFromMPElementType(element.type)]);
|
|
||||||
assert([MPMacAppDelegate get].keyID);
|
|
||||||
|
|
||||||
element.name = siteName;
|
[[NSPasteboard generalPasteboard] declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
||||||
element.keyID = [MPMacAppDelegate get].keyID;
|
if (![[NSPasteboard generalPasteboard] setString:content forType:NSPasteboardTypeString]) {
|
||||||
|
wrn(@"Couldn't copy password to pasteboard.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NSString *description = [element.content description];
|
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||||
[element use];
|
MPElementEntity *activeElement = [self activeElementInContext:moc];
|
||||||
|
[activeElement use];
|
||||||
|
[moc saveToStore];
|
||||||
|
}
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
- (void)createNewSite:(NSString *)siteName {
|
||||||
[self setContent:description];
|
|
||||||
});
|
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||||
}];
|
NSAlert *alert = [NSAlert alertWithMessageText:@"Create site?"
|
||||||
*/
|
defaultButton:@"Create" alternateButton:nil otherButton:@"Cancel"
|
||||||
|
informativeTextWithFormat:@"Do you want to create a new site named:\n\n%@", siteName];
|
||||||
|
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||||
|
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertCreateSite];
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -55,9 +55,11 @@
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
__weak MPElementListAllViewController *wSelf = self;
|
__weak MPElementListAllViewController *wSelf = self;
|
||||||
[self addElementNamed:[alert textFieldAtIndex:0].text completion:^(BOOL success) {
|
[[MPiOSAppDelegate get] addElementNamed:[alert textFieldAtIndex:0].text completion:^(MPElementEntity *element) {
|
||||||
if (success)
|
if (element) {
|
||||||
|
[wSelf.delegate didSelectElement:element];
|
||||||
[wSelf close:nil];
|
[wSelf close:nil];
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonOkay, nil];
|
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonOkay, nil];
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
@property(readonly) NSDateFormatter *dateFormatter;
|
@property(readonly) NSDateFormatter *dateFormatter;
|
||||||
|
|
||||||
- (void)updateData;
|
- (void)updateData;
|
||||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(BOOL success))completion;
|
|
||||||
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atTableIndexPath:(NSIndexPath *)indexPath;
|
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atTableIndexPath:(NSIndexPath *)indexPath;
|
||||||
- (void)customTableViewUpdates;
|
- (void)customTableViewUpdates;
|
||||||
|
|
||||||
|
@ -23,48 +23,6 @@
|
|||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(BOOL success))completion {
|
|
||||||
|
|
||||||
if (![siteName length]) {
|
|
||||||
if (completion)
|
|
||||||
completion( false );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
|
||||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
|
||||||
assert(activeUser);
|
|
||||||
|
|
||||||
MPElementType type = activeUser.defaultType;
|
|
||||||
if (!type)
|
|
||||||
type = activeUser.defaultType = MPElementTypeGeneratedLong;
|
|
||||||
NSString *typeEntityClassName = [MPAlgorithmDefault classNameOfType:type];
|
|
||||||
|
|
||||||
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:typeEntityClassName
|
|
||||||
inManagedObjectContext:moc];
|
|
||||||
|
|
||||||
element.name = siteName;
|
|
||||||
element.user = activeUser;
|
|
||||||
element.type = type;
|
|
||||||
element.lastUsed = [NSDate date];
|
|
||||||
element.version = MPAlgorithmDefaultVersion;
|
|
||||||
[moc saveToStore];
|
|
||||||
|
|
||||||
NSError *error = nil;
|
|
||||||
if (element.objectID.isTemporaryID && ![moc obtainPermanentIDsForObjects:@[ element ] error:&error])
|
|
||||||
err(@"Failed to obtain a permanent object ID after creating new element: %@", error);
|
|
||||||
|
|
||||||
NSManagedObjectID *elementOID = [element objectID];
|
|
||||||
dispatch_async( dispatch_get_main_queue(), ^{
|
|
||||||
MPElementEntity *element_ = (MPElementEntity *)[[MPiOSAppDelegate managedObjectContextForThreadIfReady]
|
|
||||||
objectRegisteredForID:elementOID];
|
|
||||||
[self.delegate didSelectElement:element_];
|
|
||||||
if (completion)
|
|
||||||
completion( true );
|
|
||||||
} );
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSFetchedResultsController *)fetchedResultsControllerByLastUsed {
|
- (NSFetchedResultsController *)fetchedResultsControllerByLastUsed {
|
||||||
|
|
||||||
if (!_fetchedResultsControllerByLastUsed) {
|
if (!_fetchedResultsControllerByLastUsed) {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#import "MPElementListSearchController.h"
|
#import "MPElementListSearchController.h"
|
||||||
#import "MPMainViewController.h"
|
#import "MPMainViewController.h"
|
||||||
#import "MPiOSAppDelegate.h"
|
#import "MPiOSAppDelegate.h"
|
||||||
|
#import "MPAppDelegate_Store.h"
|
||||||
|
|
||||||
@interface MPElementListSearchController()
|
@interface MPElementListSearchController()
|
||||||
|
|
||||||
@ -216,7 +217,11 @@
|
|||||||
if (buttonIndex == [alert cancelButtonIndex])
|
if (buttonIndex == [alert cancelButtonIndex])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self addElementNamed:siteName completion:nil];
|
__weak MPElementListController *wSelf = self;
|
||||||
|
[[MPiOSAppDelegate get] addElementNamed:siteName completion:^(MPElementEntity *element) {
|
||||||
|
if (element)
|
||||||
|
[wSelf.delegate didSelectElement:element];
|
||||||
|
}];
|
||||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil];
|
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user