mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-14 14:02:28 +00:00
Using NSFileCoordinator to manage file access in presentedItemDidChange
This commit is contained in:
@@ -39,6 +39,7 @@
|
|||||||
#import "NSError+Messages.h"
|
#import "NSError+Messages.h"
|
||||||
#import "NSString+MPPasswordCreation.h"
|
#import "NSString+MPPasswordCreation.h"
|
||||||
#import "NSString+MPHash.h"
|
#import "NSString+MPHash.h"
|
||||||
|
#import "NSApplication+MPAdditions.h"
|
||||||
|
|
||||||
NSString *const MPDocumentDidAddGroupNotification = @"com.hicknhack.macpass.MPDocumentDidAddGroupNotification";
|
NSString *const MPDocumentDidAddGroupNotification = @"com.hicknhack.macpass.MPDocumentDidAddGroupNotification";
|
||||||
NSString *const MPDocumentDidAddEntryNotification = @"com.hicknhack.macpass.MPDocumentDidAddEntryNotification";
|
NSString *const MPDocumentDidAddEntryNotification = @"com.hicknhack.macpass.MPDocumentDidAddEntryNotification";
|
||||||
@@ -264,66 +265,70 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)presentedItemDidChange {
|
- (void)presentedItemDidChange {
|
||||||
[super presentedItemDidChange];
|
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:self];
|
||||||
/* If we are locked we have the data written back to file - just revert */
|
|
||||||
if(self.encrypted) {
|
|
||||||
[self revertDocumentToSaved:nil];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.fileURL.path error:nil];
|
|
||||||
NSDate *modificationDate = attributes[NSFileModificationDate];
|
|
||||||
if(NSOrderedSame == [self.fileModificationDate compare:modificationDate]) {
|
|
||||||
return; // Just metadata has changed
|
|
||||||
}
|
|
||||||
|
|
||||||
if(self.lockedForFileChange) {
|
[coordinator coordinateReadingItemAtURL:self.fileURL options:NSFileCoordinatorReadingWithoutChanges error:nil byAccessor:^(NSURL * _Nonnull newURL) {
|
||||||
return; // We are already displaying an alert
|
NSDictionary *attributes = [NSFileManager.defaultManager attributesOfItemAtPath:newURL.path error:nil];
|
||||||
}
|
if(NSOrderedSame == [attributes.fileModificationDate compare:self.fileModificationDate]) {
|
||||||
|
return; // no content change
|
||||||
/* Set the flag in this call! */
|
|
||||||
self.lockedForFileChange = YES;
|
|
||||||
|
|
||||||
/* TODO read file to check if changes took place! */
|
|
||||||
|
|
||||||
/* Dispatch the alert to the main queue */
|
|
||||||
__weak MPDocument *welf = self;
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
|
||||||
MPFileChangeStrategy strategy = (MPFileChangeStrategy)[NSUserDefaults.standardUserDefaults integerForKey:kMPSettingsKeyFileChangeStrategy];
|
|
||||||
if(strategy != MPFileChangeStrategyAsk) {
|
|
||||||
[welf _handleFileChangeWithStrategy:strategy setAsDefault:NO];
|
|
||||||
self.lockedForFileChange = NO;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
NSAlert *alert = [[NSAlert alloc] init];
|
|
||||||
alert.alertStyle = NSWarningAlertStyle;
|
if(self.encrypted) {
|
||||||
alert.messageText = NSLocalizedString(@"FILE_CHANGED_BY_OTHERS_MESSAGE_TEXT", @"Message displayed when an open file was changed from another application");
|
__weak MPDocument *welf = self;
|
||||||
alert.informativeText = NSLocalizedString(@"FILE_CHANGED_BY_OTHERS_INFO_TEXT", @"Informative text displayed when the file was change from another application");
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
alert.showsSuppressionButton = YES;
|
[welf _handleFileChangeWithStrategy:MPFileChangeStrategyUseOther setAsDefault:NO];
|
||||||
alert.suppressionButton.title = NSLocalizedString(@"SET_AS_DEFAULT_FILE_CHANGE_STRATEGY", @"Set the selection as default file change strategy!");
|
});
|
||||||
[alert addButtonWithTitle:NSLocalizedString(@"FILE_CHANGE_STRATEGY_MERGE", @"Merge changes into file!")];
|
return; // Done!
|
||||||
[alert addButtonWithTitle:NSLocalizedString(@"FILE_CHANGE_STRATEGY_USE_OTHER", @"Reopen the file!")];
|
}
|
||||||
[alert addButtonWithTitle:NSLocalizedString(@"FILE_CHANGE_STRATEGY_KEEP_MINE", @"Ignore the changes to an open file!")];
|
|
||||||
[alert beginSheetModalForWindow:welf.windowForSheet completionHandler:^(NSModalResponse returnCode) {
|
if(self.lockedForFileChange) {
|
||||||
BOOL useAsDefault = (alert.suppressionButton.state == NSOnState);
|
return; // We are already displaying an alert
|
||||||
switch(returnCode) {
|
}
|
||||||
case NSAlertFirstButtonReturn: {
|
|
||||||
[welf _handleFileChangeWithStrategy:MPFileChangeStrategyMerge setAsDefault:useAsDefault];
|
/* Set the flag in this call! */
|
||||||
break;
|
self.lockedForFileChange = YES;
|
||||||
}
|
|
||||||
case NSAlertSecondButtonReturn:
|
/* Dispatch the alert to the main queue */
|
||||||
[welf _handleFileChangeWithStrategy:MPFileChangeStrategyUseOther setAsDefault:useAsDefault];
|
__weak MPDocument *welf = self;
|
||||||
break;
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
case NSAlertThirdButtonReturn:
|
MPFileChangeStrategy strategy = (MPFileChangeStrategy)[NSUserDefaults.standardUserDefaults integerForKey:kMPSettingsKeyFileChangeStrategy];
|
||||||
[welf _handleFileChangeWithStrategy:MPFileChangeStrategyKeepMine setAsDefault:useAsDefault];
|
if(strategy != MPFileChangeStrategyAsk) {
|
||||||
default:
|
[welf _handleFileChangeWithStrategy:strategy setAsDefault:NO];
|
||||||
break;
|
self.lockedForFileChange = NO;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
welf.lockedForFileChange = NO;
|
NSAlert *alert = [[NSAlert alloc] init];
|
||||||
}];
|
alert.alertStyle = NSWarningAlertStyle;
|
||||||
});
|
alert.messageText = NSLocalizedString(@"FILE_CHANGED_BY_OTHERS_MESSAGE_TEXT", @"Message displayed when an open file was changed from another application");
|
||||||
|
alert.informativeText = NSLocalizedString(@"FILE_CHANGED_BY_OTHERS_INFO_TEXT", @"Informative text displayed when the file was change from another application");
|
||||||
|
alert.showsSuppressionButton = YES;
|
||||||
|
alert.suppressionButton.title = NSLocalizedString(@"SET_AS_DEFAULT_FILE_CHANGE_STRATEGY", @"Set the selection as default file change strategy!");
|
||||||
|
[alert addButtonWithTitle:NSLocalizedString(@"FILE_CHANGE_STRATEGY_MERGE", @"Merge changes into file!")];
|
||||||
|
[alert addButtonWithTitle:NSLocalizedString(@"FILE_CHANGE_STRATEGY_USE_OTHER", @"Reopen the file!")];
|
||||||
|
[alert addButtonWithTitle:NSLocalizedString(@"FILE_CHANGE_STRATEGY_KEEP_MINE", @"Ignore the changes to an open file!")];
|
||||||
|
[alert beginSheetModalForWindow:welf.windowForSheet completionHandler:^(NSModalResponse returnCode) {
|
||||||
|
BOOL useAsDefault = (alert.suppressionButton.state == NSOnState);
|
||||||
|
switch(returnCode) {
|
||||||
|
case NSAlertFirstButtonReturn: {
|
||||||
|
[welf _handleFileChangeWithStrategy:MPFileChangeStrategyMerge setAsDefault:useAsDefault];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NSAlertSecondButtonReturn:
|
||||||
|
[welf _handleFileChangeWithStrategy:MPFileChangeStrategyUseOther setAsDefault:useAsDefault];
|
||||||
|
break;
|
||||||
|
case NSAlertThirdButtonReturn:
|
||||||
|
[welf _handleFileChangeWithStrategy:MPFileChangeStrategyKeepMine setAsDefault:useAsDefault];
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
welf.lockedForFileChange = NO;
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_handleFileChangeWithStrategy:(MPFileChangeStrategy)strategy setAsDefault:(BOOL)setAsDefault {
|
- (void)_handleFileChangeWithStrategy:(MPFileChangeStrategy)strategy setAsDefault:(BOOL)setAsDefault {
|
||||||
|
NSAssert(NSThread.currentThread.isMainThread, @"Invoke only on main thread!");
|
||||||
if(setAsDefault) {
|
if(setAsDefault) {
|
||||||
[NSUserDefaults.standardUserDefaults setInteger:strategy forKey:kMPSettingsKeyFileChangeStrategy];
|
[NSUserDefaults.standardUserDefaults setInteger:strategy forKey:kMPSettingsKeyFileChangeStrategy];
|
||||||
}
|
}
|
||||||
@@ -366,6 +371,12 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
[self.tree syncronizeWithTree:otherTree options:KPKSynchronizationSynchronizeOption];
|
[self.tree syncronizeWithTree:otherTree options:KPKSynchronizationSynchronizeOption];
|
||||||
|
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
||||||
|
notification.title = NSApp.applicationName;
|
||||||
|
notification.informativeText = NSLocalizedString(@"AUTO_MERGE_NOTIFICATION_TEXT", @"");
|
||||||
|
notification.deliveryDate = NSDate.date;
|
||||||
|
[NSUserNotificationCenter.defaultUserNotificationCenter scheduleNotification:notification];
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,7 +414,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
|
|||||||
}
|
}
|
||||||
self.tree = nil;
|
self.tree = nil;
|
||||||
self.compositeKey = nil;
|
self.compositeKey = nil;
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidLockDatabaseNotification object:self];
|
[NSNotificationCenter.defaultCenter postNotificationName:MPDocumentDidLockDatabaseNotification object:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -417,7 +428,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
|
|||||||
/* only clear the data if we actually do not need it anymore */
|
/* only clear the data if we actually do not need it anymore */
|
||||||
self.encryptedData = nil;
|
self.encryptedData = nil;
|
||||||
self.unlockCount += 1;
|
self.unlockCount += 1;
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidUnlockDatabaseNotification object:self];
|
[NSNotificationCenter.defaultCenter postNotificationName:MPDocumentDidUnlockDatabaseNotification object:self];
|
||||||
[self _storeKeyURL:keyFileURL];
|
[self _storeKeyURL:keyFileURL];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -452,7 +463,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
|
|||||||
if(!delegate.isAllowedToStoreKeyFile) {
|
if(!delegate.isAllowedToStoreKeyFile) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
NSDictionary *keysForFiles = [[NSUserDefaults standardUserDefaults] dictionaryForKey:kMPSettingsKeyRememeberdKeysForDatabases];
|
NSDictionary *keysForFiles = [NSUserDefaults.standardUserDefaults dictionaryForKey:kMPSettingsKeyRememeberdKeysForDatabases];
|
||||||
NSString *keyPath = keysForFiles[self.fileURL.path.sha1HexDigest];
|
NSString *keyPath = keysForFiles[self.fileURL.path.sha1HexDigest];
|
||||||
if(!keyPath) {
|
if(!keyPath) {
|
||||||
return nil;
|
return nil;
|
||||||
@@ -823,7 +834,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
|
|||||||
break;
|
break;
|
||||||
case MPActionPerformAutotypeForSelectedEntry:
|
case MPActionPerformAutotypeForSelectedEntry:
|
||||||
valid &= (nil != targetEntry);
|
valid &= (nil != targetEntry);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user