diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index 1d6dd70e..428329dd 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -264,7 +264,6 @@ 4CE8246F16E2E93400573141 /* MPOverlayWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8246E16E2E93400573141 /* MPOverlayWindowController.m */; }; 4CE8247516E2F2B900573141 /* MPOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8247416E2F2B900573141 /* MPOverlayView.m */; }; 4CE88B9717BA651C0042E078 /* contextTriangleTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4CE88B9617BA651C0042E078 /* contextTriangleTemplate.pdf */; }; - 4CE97BAA216FA968006BF25D /* MPPluginBrowserTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE97BA9216FA968006BF25D /* MPPluginBrowserTableCellView.m */; }; 4CEE46DD181C301D006BF1E5 /* MPAutotypeDaemon.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE46DC181C301D006BF1E5 /* MPAutotypeDaemon.m */; }; 4CEED1C617D7BD0E007180F1 /* NSError+Messages.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CEED1C517D7BD0E007180F1 /* NSError+Messages.m */; }; 4CF29BF417879D0000851B60 /* 26_FileSaveTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4CF29BF317879D0000851B60 /* 26_FileSaveTemplate.pdf */; }; @@ -824,8 +823,6 @@ 4CE88B9617BA651C0042E078 /* contextTriangleTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = contextTriangleTemplate.pdf; path = Icons/contextTriangleTemplate.pdf; sourceTree = ""; }; 4CE88C2417C163FE00BFD195 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 4CE88C3317C1647400BFD195 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 4CE97BA8216FA968006BF25D /* MPPluginBrowserTableCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPluginBrowserTableCellView.h; sourceTree = ""; }; - 4CE97BA9216FA968006BF25D /* MPPluginBrowserTableCellView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginBrowserTableCellView.m; sourceTree = ""; }; 4CEE46DB181C301D006BF1E5 /* MPAutotypeDaemon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAutotypeDaemon.h; sourceTree = ""; }; 4CEE46DC181C301D006BF1E5 /* MPAutotypeDaemon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAutotypeDaemon.m; sourceTree = ""; }; 4CEED1C417D7BD0E007180F1 /* NSError+Messages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+Messages.h"; sourceTree = ""; }; @@ -1051,8 +1048,6 @@ 4C0F043F2147A6FA000B8568 /* MPCustomFieldTableView.m */, 4C370EFC215B76CB00703AAE /* MPOutlineTableCellView.h */, 4C370EFD215B76CB00703AAE /* MPOutlineTableCellView.m */, - 4CE97BA8216FA968006BF25D /* MPPluginBrowserTableCellView.h */, - 4CE97BA9216FA968006BF25D /* MPPluginBrowserTableCellView.m */, ); name = Views; sourceTree = ""; @@ -1246,6 +1241,9 @@ 4C25703C1BF11C2300D39416 /* MPPluginSettingsController.h */, 4C25703D1BF11C2300D39416 /* MPPluginSettingsController.m */, 4C0DBEF71BF508DE00F9B287 /* PluginSettings.xib */, + 4CC663E4216F7A7100E33965 /* MPPluginRepositoryBrowserViewController.h */, + 4CC663E5216F7A7100E33965 /* MPPluginRepositoryBrowserViewController.m */, + 4CC663E6216F7A7100E33965 /* PluginRepositoryBrowserView.xib */, ); name = Settings; sourceTree = ""; @@ -1566,9 +1564,6 @@ 4C73B6EE215E64A7009787F7 /* MPWelcomeViewController.h */, 4C73B6EF215E64A7009787F7 /* MPWelcomeViewController.m */, 4C7F8B6A1A10B68400CCB83D /* WelcomeView.xib */, - 4CC663E4216F7A7100E33965 /* MPPluginRepositoryBrowserViewController.h */, - 4CC663E5216F7A7100E33965 /* MPPluginRepositoryBrowserViewController.m */, - 4CC663E6216F7A7100E33965 /* PluginRepositoryBrowserView.xib */, ); name = "View Controller"; sourceTree = ""; @@ -1953,7 +1948,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4CE97BAA216FA968006BF25D /* MPPluginBrowserTableCellView.m in Sources */, 4CD034AC1BFE113B003C002C /* MPPluginHost.m in Sources */, 4C77E37315B84A240093A587 /* main.m in Sources */, 4C0F04402147A6FA000B8568 /* MPCustomFieldTableView.m in Sources */, diff --git a/MacPass/Base.lproj/WelcomeView.xib b/MacPass/Base.lproj/WelcomeView.xib index 95d7f820..3234201f 100644 --- a/MacPass/Base.lproj/WelcomeView.xib +++ b/MacPass/Base.lproj/WelcomeView.xib @@ -15,17 +15,17 @@ - + - - + + - + - + @@ -33,7 +33,7 @@ - + @@ -82,19 +82,19 @@ - + - + - + - + @@ -108,7 +108,7 @@ - + @@ -120,15 +120,12 @@ - + - - - @@ -159,7 +156,7 @@ diff --git a/MacPass/MPAppDelegate.m b/MacPass/MPAppDelegate.m index eecae298..eeae01e5 100644 --- a/MacPass/MPAppDelegate.m +++ b/MacPass/MPAppDelegate.m @@ -284,7 +284,7 @@ NSString *const MPDidChangeStoredKeyFilesSettings = @"com.hicknhack.macpass.MPDi #if defined(DEBUG) || defined(NO_SPARKLE) NSAlert *alert = [[NSAlert alloc] init]; alert.messageText = NSLocalizedString(@"ALERT_UPDATES_DISABLED_MESSAGE_TEXT", @"Message text for disabled updates alert!"); - alert.informativeText = [NSString stringWithFormat:@"ALERT_UPDATED_DISABLED_INFORMATIVE_TEXT_%@!", NSApp.applicationName]; + alert.informativeText = [NSString stringWithFormat:NSLocalizedString(@"ALERT_UPDATES_DISABLED_INFORMATIVE_TEXT_%@!", @"Infromative text of the disabled updates alert!"), NSApp.applicationName]; [alert addButtonWithTitle:NSLocalizedString(@"OK", @"Ok Button to dismiss disabled updates alert")]; [alert runModal]; #else diff --git a/MacPass/MPPlugin.h b/MacPass/MPPlugin.h index 526c0ab4..4722c9fc 100644 --- a/MacPass/MPPlugin.h +++ b/MacPass/MPPlugin.h @@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @class KPKEntry; @class KPKAttribute; @class KPKTree; +@class MPPluginVersion; FOUNDATION_EXPORT NSString *const MPPluginUnkownVersion; @@ -36,6 +37,7 @@ FOUNDATION_EXPORT NSString *const MPPluginUnkownVersion; @property (copy, readonly) NSString *identifier; @property (copy, readonly) NSString *name; @property (nonatomic, copy, readonly, nullable) NSString *humanVersionString; +@property (nonatomic, copy, readonly, nullable) MPPluginVersion *version; @property (nonatomic, copy, readonly) NSString *versionString; @property (nonatomic, strong, readonly) NSBundle *bundle; diff --git a/MacPass/MPPlugin.m b/MacPass/MPPlugin.m index 83305309..6bc1081e 100644 --- a/MacPass/MPPlugin.m +++ b/MacPass/MPPlugin.m @@ -25,12 +25,14 @@ #import "MPPluginHost.h" #import "MPSettingsHelper.h" #import "MPPluginConstants.h" +#import "MPPluginVersion.h" NSString *const MPPluginUnkownVersion = @"unkown.plugin.version"; @implementation MPPlugin @synthesize bundle = _bundle; +@synthesize version = _version; - (instancetype)initWithPluginHost:(MPPluginHost *)host { self = [super init]; @@ -72,6 +74,14 @@ NSString *const MPPluginUnkownVersion = @"unkown.plugin.version"; return self.bundle.infoDictionary[@"CFBundleShortVersionString"]; } +- (MPPluginVersion *)version { + if(!_versionInitialized) { + _version = [MPPluginVersion versionWithVersionString:self.humanVersionString]; + _versionInitialized = YES; + } + return _version; +} + - (NSString *)versionString { if(self.bundle) { NSString *humanVersion = self.humanVersionString; diff --git a/MacPass/MPPluginBrowserTableCellView.h b/MacPass/MPPluginBrowserTableCellView.h deleted file mode 100644 index 234148e0..00000000 --- a/MacPass/MPPluginBrowserTableCellView.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// MPPluginBrowserTableCellView.h -// MacPass -// -// Created by Michael Starke on 11.10.18. -// Copyright © 2018 HicknHack Software GmbH. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface MPPluginBrowserTableCellView : NSTableCellView - -@property (strong) IBOutlet NSTextField *statusTextField; - -@end - -NS_ASSUME_NONNULL_END diff --git a/MacPass/MPPluginBrowserTableCellView.m b/MacPass/MPPluginBrowserTableCellView.m deleted file mode 100644 index 85f919e0..00000000 --- a/MacPass/MPPluginBrowserTableCellView.m +++ /dev/null @@ -1,27 +0,0 @@ -// -// MPPluginBrowserTableCellView.m -// MacPass -// -// Created by Michael Starke on 11.10.18. -// Copyright © 2018 HicknHack Software GmbH. All rights reserved. -// - -#import "MPPluginBrowserTableCellView.h" - -@implementation MPPluginBrowserTableCellView - -- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle { - super.backgroundStyle = backgroundStyle; - switch(backgroundStyle) { - case NSBackgroundStyleNormal: - case NSBackgroundStyleLowered: - self.statusTextField.textColor = NSColor.controlTextColor; - break; - case NSBackgroundStyleRaised: - case NSBackgroundStyleEmphasized: - self.statusTextField.textColor = NSColor.selectedControlTextColor; - break; - } -} - -@end diff --git a/MacPass/MPPluginHost.h b/MacPass/MPPluginHost.h index 3830f533..1aabdec8 100644 --- a/MacPass/MPPluginHost.h +++ b/MacPass/MPPluginHost.h @@ -31,13 +31,14 @@ FOUNDATION_EXPORT NSString *const MPPluginHostPluginBundleIdentifiyerKey; @class MPPlugin; @class KPKEntry; +@class MPPluginVersion; @interface MPPluginHost : NSObject /* List of all plugins known to the plugin manager. Disabled plugins are also present! */ @property (readonly, copy) NSArray *plugins; @property (nonatomic, readonly) BOOL loadUnsecurePlugins; -@property (readonly, copy) NSString *version; +@property (readonly, copy) MPPluginVersion *version; + (instancetype)sharedHost; diff --git a/MacPass/MPPluginHost.m b/MacPass/MPPluginHost.m index 7ca9f85a..75dd024c 100644 --- a/MacPass/MPPluginHost.m +++ b/MacPass/MPPluginHost.m @@ -28,6 +28,7 @@ #import "MPPluginEntryActionContext.h" #import "MPPluginRepository.h" #import "MPPluginRepositoryItem.h" +#import "MPPluginVersion.h" #import "NSApplication+MPAdditions.h" #import "MPSettingsHelper.h" @@ -80,6 +81,7 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun _loadUnsecurePlugins = [NSUserDefaults.standardUserDefaults boolForKey:kMPSettingsKeyLoadUnsecurePlugins]; _entryActionPluginIdentifiers = [[NSMutableArray alloc] init]; _customAttributePluginIdentifiers = [[NSMutableArray alloc] init]; + _version = [[MPPluginVersion alloc] initWithVersionString:NSBundle.mainBundle.infoDictionary[@"CFBundleShortVersionString"]]; [self bind:NSStringFromSelector(@selector(loadUnsecurePlugins)) toObject:NSUserDefaultsController.sharedUserDefaultsController @@ -93,11 +95,6 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun return self; } -- (NSString *)version { - NSString *version = NSBundle.mainBundle.infoDictionary[@"CFBundleShortVersionString"]; - return version; -} - - (NSArray *)plugins { return [self.mutablePlugins copy]; } @@ -273,8 +270,8 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun repoItem = item; } } - NSString *shortVersion = bundle.infoDictionary[@"CFBundleShortVersionString"]; - return [repoItem isPluginVersion:shortVersion compatibleWithHost:self]; + MPPluginVersion *version = [MPPluginVersion versionWithVersionString:bundle.infoDictionary[@"CFBundleShortVersionString"]]; + return [repoItem isPluginVersionCompatibleWithHost:version]; } - (BOOL)_isValidPluginURL:(NSURL *)url { diff --git a/MacPass/MPPluginRepository.m b/MacPass/MPPluginRepository.m index 392404b0..6f6fd0ec 100644 --- a/MacPass/MPPluginRepository.m +++ b/MacPass/MPPluginRepository.m @@ -24,13 +24,8 @@ #import "MPConstants.h" #import "MPPluginRepositoryItem.h" -const NSTimeInterval MPPluginRepositoryCacheTimeOut = 60*3; // 1 Minute cache time - @interface MPPluginRepository () -@property NSTimeInterval lastPluginCheckTime; -@property BOOL didLoadData; - @end @implementation MPPluginRepository @@ -44,13 +39,6 @@ const NSTimeInterval MPPluginRepositoryCacheTimeOut = 60*3; // 1 Minute cache ti return instance; } -- (instancetype)init { - self = [super init]; - if(self) { - self.lastPluginCheckTime = NSDate.distantPast.timeIntervalSinceReferenceDate; - } - return self; -} - (void)fetchRepositoryDataCompletionHandler:(void (^)(NSArray * _Nonnull))completionHandler { NSString *urlString = NSBundle.mainBundle.infoDictionary[MPBundlePluginRepositoryURLKey]; diff --git a/MacPass/MPPluginRepositoryBrowserViewController.m b/MacPass/MPPluginRepositoryBrowserViewController.m index f15afb44..951126be 100644 --- a/MacPass/MPPluginRepositoryBrowserViewController.m +++ b/MacPass/MPPluginRepositoryBrowserViewController.m @@ -11,7 +11,14 @@ #import "MPPluginHost.h" #import "MPPluginRepository.h" #import "MPPluginRepositoryItem.h" -#import "MPPluginBrowserTableCellView.h" +#import "MPPluginVersion.h" + + +typedef NS_ENUM(NSUInteger, MPPluginTableColumn) { + MPPluginTableColumnName, + MPPluginTableColumnCurrentVersion, + MPPluginTableColumnStatus +}; @interface MPPluginRepositoryBrowserViewController () @@ -44,21 +51,38 @@ } - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { - MPPluginBrowserTableCellView *view = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self]; + NSTableCellView *view = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self]; MPPluginRepositoryItem *item = self.repositoryItems.firstObject; - view.textField.stringValue = item.name; - MPPlugin *plugin = [MPPluginHost.sharedHost pluginWithBundleIdentifier:item.bundleIdentifier]; - if(plugin) { - if([plugin.humanVersionString isEqualToString:item.currentVersion]) { - view.statusTextField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"INSTALLED_VERSION_%@_(UP_TO_DATE)", "Info displayed when an installed plugin is up to date"), plugin.humanVersionString]; + NSUInteger column = [tableView.tableColumns indexOfObjectIdenticalTo:tableColumn]; + + if(column == MPPluginTableColumnName) { + view.textField.stringValue = item.name; + } + else if(column == MPPluginTableColumnCurrentVersion) { + view.textField.stringValue = item.currentVersion.versionString; + } + else if(column == MPPluginTableColumnStatus) { + MPPlugin *plugin = [MPPluginHost.sharedHost pluginWithBundleIdentifier:item.bundleIdentifier]; + if(!plugin) { + switch([plugin.version compare:item.currentVersion]) { + case NSOrderedSame: + view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_LATEST_VERSION_INSTALLED", "Status for an up-to-date plugin in the plugin browser")]; + break; + case NSOrderedAscending: + view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_NEWER_VERSION_%@_AVAILABLE", "Status for an outdated plugin version in the plugin browser"), item.currentVersion.versionString]; + break; + case NSOrderedDescending: + view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_UNKNOWN_PLUGIN_VERSION", "Status for an unkonw plugin version in the plugin browser")]; + break; + } } else { - view.statusTextField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"CURRENT_VERSION_%@_(INSTALLED_VERSION_%@)", "Info displayed when a plugin is loaded and "), item.currentVersion, plugin.humanVersionString]; + view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_PLUGIN_NOT_INSTALLED", "Status for an uninstalled plugin in the plugin browser")]; } } else { - view.statusTextField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"CURRENT_VERSION_%@_(NOT_INSTALLED)", "Info displayed when an plugin is not installed"), plugin.humanVersionString]; + view.textField.stringValue = @"-"; } return view; diff --git a/MacPass/MPPluginRepositoryItem.h b/MacPass/MPPluginRepositoryItem.h index cfb590e9..ba0f38f9 100644 --- a/MacPass/MPPluginRepositoryItem.h +++ b/MacPass/MPPluginRepositoryItem.h @@ -24,13 +24,12 @@ NS_ASSUME_NONNULL_BEGIN -@class MPPluginHost; +@class MPPluginVersion; @interface MPPluginRepositoryItem : NSObject - @property (copy,readonly, nullable) NSString *name; -@property (copy,readonly, nullable) NSString *currentVersion; +@property (copy,readonly, nullable) MPPluginVersion *currentVersion; @property (copy,readonly, nullable) NSString *descriptionText; @property (copy,readonly, nullable) NSURL *sourceURL; @property (copy,readonly, nullable) NSURL *downloadURL; @@ -40,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)pluginItemFromDictionary:(NSDictionary *)dict; - (instancetype)initWithDictionary:(NSDictionary *)dict; -- (BOOL)isPluginVersion:(NSString * _Nullable )pluginVersionString compatibleWithHost:(MPPluginHost *)host; +- (BOOL)isPluginVersionCompatibleWithHost:(MPPluginVersion *)pluginVersion; @end diff --git a/MacPass/MPPluginRepositoryItem.m b/MacPass/MPPluginRepositoryItem.m index ceb757d2..e9feb0f6 100644 --- a/MacPass/MPPluginRepositoryItem.m +++ b/MacPass/MPPluginRepositoryItem.m @@ -24,7 +24,6 @@ #import "MPPluginRepositoryItemVersionInfo.h" #import "MPPluginVersion.h" #import "MPPluginHost.h" -#import "MPPlugin.h" #import "NSError+Messages.h" @@ -39,7 +38,7 @@ NSString *const MPPluginItemCompatibiltyKey = @"compatibilty"; @interface MPPluginRepositoryItem () @property (copy) NSString *name; -@property (copy) NSString *currentVersion; +@property (copy) MPPluginVersion *currentVersion; @property (copy) NSString *descriptionText; @property (copy) NSURL *sourceURL; @property (copy) NSURL *downloadURL; @@ -64,7 +63,7 @@ NSString *const MPPluginItemCompatibiltyKey = @"compatibilty"; self.descriptionText = dict[MPPluginItemDescriptionKey]; self.downloadURL = [NSURL URLWithString:dict[MPPluginItemDownloadURLKey]]; self.sourceURL = [NSURL URLWithString:dict[MPPluginItemSourceURLKey]]; - self.currentVersion = dict[MPPluginItemCurrentVersionKey]; + self.currentVersion = [MPPluginVersion versionWithVersionString:dict[MPPluginItemCurrentVersionKey]]; self.bundleIdentifier = dict[MPPluginItemBundleIdentifierKey]; [self _buildVersionInfos:dict[MPPluginItemCompatibiltyKey]]; @@ -77,19 +76,12 @@ NSString *const MPPluginItemCompatibiltyKey = @"compatibilty"; return (self.name.length > 0 && self.downloadURL); } -- (BOOL)isPluginVersion:(NSString *)pluginVersionString compatibleWithHost:(MPPluginHost *)host { - if(pluginVersionString.length == 0) { - return NO; - } - MPPluginVersion *pluginVersion = [MPPluginVersion versionWithVersionString:pluginVersionString]; +- (BOOL)isPluginVersionCompatibleWithHost:(MPPluginVersion *)pluginVersion { if(!pluginVersion) { return NO; } - if(host.version.length == 0) { - return NO; - } - - MPPluginVersion *hostVersion = [MPPluginVersion versionWithVersionString:host.version]; + + MPPluginVersion *hostVersion = MPPluginHost.sharedHost.version; if(!hostVersion) { return NO; } diff --git a/MacPass/MPPlugin_Private.h b/MacPass/MPPlugin_Private.h index ffba26d5..bd55a972 100644 --- a/MacPass/MPPlugin_Private.h +++ b/MacPass/MPPlugin_Private.h @@ -22,7 +22,9 @@ #import "MPPlugin.h" -@interface MPPlugin () +@interface MPPlugin () { + BOOL _versionInitialized; +} @property (nonatomic, strong) NSBundle *bundle; @property (copy) NSString *errorMessage; diff --git a/MacPass/PluginRepositoryBrowserView.xib b/MacPass/PluginRepositoryBrowserView.xib index 9da97920..382af136 100644 --- a/MacPass/PluginRepositoryBrowserView.xib +++ b/MacPass/PluginRepositoryBrowserView.xib @@ -15,68 +15,117 @@ - + - - + + - + - - + + - - + + - + - + - - + + - - - + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -101,7 +150,7 @@ - + @@ -116,7 +165,7 @@