mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
Merge pull request #12144 from keymanapp/change/mac/2542-use-partial-keyboard-paths
change(mac): store partial path in UserDefaults
This commit is contained in:
commit
0aa4be5584
10 changed files with 296 additions and 185 deletions
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#import "KMConfigurationWindowController.h"
|
||||
#import "KMDownloadKBWindowController.h"
|
||||
#import "KMDataRepository.h"
|
||||
#import "KMLogs.h"
|
||||
|
||||
@interface KMConfigurationWindowController ()
|
||||
|
|
@ -134,8 +135,10 @@
|
|||
NSArray *pArray = (NSArray *)obj;
|
||||
NSString *packageFolder = [self packageFolderFromPath:[pArray objectAtIndex:0]];
|
||||
NSString *packageName = [self.AppDelegate packageNameFromPackageInfo:packageFolder];
|
||||
os_log_debug([KMLogs uiLog], "tableContents, packageFolder: %{public}@, packageName: %{public}@", packageFolder, packageName);
|
||||
[_tableContents addObject:[NSDictionary dictionaryWithObjectsAndKeys:packageName, @"HeaderTitle", nil]];
|
||||
for (NSString *path in pArray) {
|
||||
os_log_debug([KMLogs uiLog], "tableContents, path = '%{public}@'", path);
|
||||
NSDictionary *info = [KMXFile keyboardInfoFromKmxFile:path];
|
||||
if (!info) {
|
||||
info = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||
|
|
@ -150,6 +153,7 @@
|
|||
}
|
||||
else {
|
||||
NSString *path = (NSString *)obj;
|
||||
os_log_debug([KMLogs uiLog], "tableContents, path = '%{public}@'", path);
|
||||
NSDictionary *info = [KMXFile keyboardInfoFromKmxFile:path];
|
||||
if (!info) {
|
||||
info = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||
|
|
@ -241,22 +245,27 @@
|
|||
BOOL isHeader = (headerTitle != nil);
|
||||
BOOL isOthers = NO;
|
||||
NSString *kmxFilePath = [self kmxFilePathAtIndex:row];
|
||||
if (kmxFilePath != nil)
|
||||
if (kmxFilePath != nil) {
|
||||
isOthers = [[self packageFolderFromPath:kmxFilePath] isEqualToString:@"Others"];
|
||||
else if (isHeader && [headerTitle isEqualToString:@"Others"])
|
||||
}
|
||||
else if (isHeader && [headerTitle isEqualToString:@"Others"]) {
|
||||
isOthers = YES;
|
||||
|
||||
}
|
||||
if ([identifier isEqualToString:@"Column1"]) {
|
||||
KMConfigColumn1CellView *cellView = [tableView makeViewWithIdentifier:identifier owner:self];
|
||||
|
||||
if (isHeader)
|
||||
if (isHeader) {
|
||||
[cellView setHidden:YES];
|
||||
}
|
||||
else {
|
||||
[cellView setHidden:NO];
|
||||
cellView.imageView.objectValue = [info objectForKey:kKMKeyboardIconKey];
|
||||
[cellView.checkBox setTag:row];
|
||||
[cellView.checkBox setAction:@selector(checkBoxAction:)];
|
||||
[cellView.checkBox setState:([self.activeKeyboards containsObject:[self kmxFilePathAtIndex:row]])?NSOnState:NSOffState];
|
||||
NSString *kmxFilePath = [self kmxFilePathAtIndex:row];
|
||||
NSString *partialPath = [KMDataRepository.shared trimToPartialPath:kmxFilePath];
|
||||
os_log_debug([KMLogs uiLog], "tableView:viewForTableColumn, kmxFilePath = %{public}@ for row %li, partialPath = %{public}@", kmxFilePath, (long)row, partialPath);
|
||||
[cellView.checkBox setState:([self.activeKeyboards containsObject:partialPath])?NSOnState:NSOffState];
|
||||
}
|
||||
|
||||
return cellView;
|
||||
|
|
@ -357,14 +366,16 @@
|
|||
- (void)checkBoxAction:(id)sender {
|
||||
NSButton *checkBox = (NSButton *)sender;
|
||||
NSString *kmxFilePath = [self kmxFilePathAtIndex:checkBox.tag];
|
||||
NSString *partialPath = [KMDataRepository.shared trimToPartialPath:kmxFilePath];
|
||||
os_log_debug([KMLogs uiLog], "checkBoxAction, kmxFilePath = %{public}@ for checkBox.tag %li, partialPath = %{public}@", kmxFilePath, checkBox.tag, partialPath);
|
||||
if (checkBox.state == NSOnState) {
|
||||
os_log_debug([KMLogs uiLog], "Adding active keyboard: %{public}@", kmxFilePath);
|
||||
[self.activeKeyboards addObject:kmxFilePath];
|
||||
[self.activeKeyboards addObject:partialPath];
|
||||
[self saveActiveKeyboards];
|
||||
}
|
||||
else if (checkBox.state == NSOffState) {
|
||||
os_log_debug([KMLogs uiLog], "Disabling active keyboard: %{public}@", kmxFilePath);
|
||||
[self.activeKeyboards removeObject:kmxFilePath];
|
||||
[self.activeKeyboards removeObject:partialPath];
|
||||
[self saveActiveKeyboards];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (void)createDataDirectoryIfNecessary;
|
||||
- (void)createKeyboardsDirectoryIfNecessary;
|
||||
- (BOOL)migrateData;
|
||||
- (NSString*)buildFullPath:(NSString *)fromPartialPath;
|
||||
- (NSString*)trimToPartialPath:(NSString *)fromFullPath;
|
||||
- (NSString *)buildPartialPathFrom:(NSString *)keyboardSubdirectory keyboardFile:(NSString *)kmxFilename;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ NSString *const kKeymanSubdirectoryName = @"keyman.inputmethod.Keyman";
|
|||
BOOL didMoveData = NO;
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
BOOL dataExistsInOldLocation = [self keyboardsExistInObsoleteDirectory];
|
||||
os_log([KMLogs dataLog], "obsolete keyman keyboards directory exists: %@", dataExistsInOldLocation?@"YES":@"NO");
|
||||
os_log_debug([KMLogs dataLog], "obsolete keyman keyboards directory exists: %@", dataExistsInOldLocation?@"YES":@"NO");
|
||||
|
||||
// only move data if there is something to move
|
||||
if (dataExistsInOldLocation) {
|
||||
|
|
@ -196,4 +196,35 @@ NSString *const kKeymanSubdirectoryName = @"keyman.inputmethod.Keyman";
|
|||
return didMoveData;
|
||||
}
|
||||
|
||||
- (NSString*)buildFullPath:(NSString *)fromPartialPath {
|
||||
NSString *fullPath = [self.keymanKeyboardsDirectory.path stringByAppendingString:fromPartialPath];
|
||||
os_log_debug([KMLogs dataLog], "buildFullPath: '%{public}@' fromPartialPath '%{public}@'",
|
||||
fullPath, fromPartialPath);
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
- (NSString *)trimToPartialPath:(NSString *)fromFullPath {
|
||||
NSString *partialPath = fromFullPath;
|
||||
if(fromFullPath != nil) {
|
||||
NSRange range = [fromFullPath rangeOfString:kKeyboardsDirectoryName];
|
||||
if (range.length > 0) {
|
||||
partialPath = [fromFullPath substringFromIndex:range.location + range.length];
|
||||
os_log_debug([KMLogs dataLog], "trimToPartialPath: fromFullPath: '%{public}@' to partialPath: '%{public}@'", fromFullPath, partialPath);
|
||||
}
|
||||
}
|
||||
return partialPath;
|
||||
}
|
||||
|
||||
- (NSString *)buildPartialPathFrom:(NSString *)keyboardSubdirectory keyboardFile:(NSString *)kmxFilename {
|
||||
NSMutableArray *pathComponents = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
[pathComponents addObject:@"/"];
|
||||
[pathComponents addObject:keyboardSubdirectory];
|
||||
[pathComponents addObject:kmxFilename];
|
||||
NSString *keyboardPartialPath = [NSString pathWithComponents:pathComponents];
|
||||
os_log_debug([KMLogs keyboardLog], "buildPartialPathFrom, keyboardSubdirectory: %{public}@, kmxFileName: %{public}@, keyboardPartialPath : %{public}@",
|
||||
keyboardSubdirectory, kmxFilename, keyboardPartialPath);
|
||||
return keyboardPartialPath;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
typedef void(^PostEventCallback)(CGEventRef eventToPost);
|
||||
|
||||
extern NSString *const kKMSelectedKeyboardKey;
|
||||
extern NSString *const kKMActiveKeyboardsKey;
|
||||
extern NSString *const kKeymanKeyboardDownloadCompletedNotification;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -99,8 +97,7 @@ static const int KEYMAN_FIRST_KEYBOARD_MENUITEM_INDEX = 0;
|
|||
|
||||
- (NSMenu *)menu;
|
||||
- (void)saveActiveKeyboards;
|
||||
- (void)readPersistedOptions;
|
||||
- (void)writePersistedOptions:(NSString *)storeKey withValue:(NSString* )value;
|
||||
- (void)applyPersistedOptions;
|
||||
- (void)showAboutWindow;
|
||||
- (void)showOSK;
|
||||
- (void)showConfigurationWindow;
|
||||
|
|
|
|||
|
|
@ -6,15 +6,6 @@
|
|||
// Copyright (c) 2017 SIL International. All rights reserved.
|
||||
//
|
||||
|
||||
// *** TO INVESTIGATE ***
|
||||
// Keyman4MacIM[6245]: IMK Stall detected, *please Report* your user scenario in <rdar://problem/16792073> - (activateServerWithReply:) block performed very slowly (0.00 secs)
|
||||
// Keyman4MacIM[6245]: IMK Stall detected, *please Report* your user scenario in <rdar://problem/16792073> - (deactivateServerWithReply:) block performed very slowly (0.00 secs)
|
||||
// Keyman4MacIM[6245]: IMK Stall detected, *please Report* your user scenario in <rdar://problem/16792073> - (menusDictionaryWithClientAsync:reply:) block performed very slowly (0.00 secs)
|
||||
// Keyman4MacIM[6245]: IMK Stall detected, *please Report* your user scenario in <rdar://problem/16792073> - (modesWithClientAsync:reply:) block performed very slowly (0.00 secs)
|
||||
// Keyman4MacIM[6245]: IMK Stall detected, *please Report* your user scenario in <rdar://problem/16792073> - (commitCompositionWithReply:) block performed very slowly (0.00 secs)
|
||||
// Keyman4MacIM[6245]: IMK Stall detected, *please Report* your user scenario in <rdar://problem/16792073> - (hidePalettes) block performed very slowly (0.00 secs)
|
||||
// Keyman4MacIM[6245]: IMK Stall detected, *please Report* your user scenario in <rdar://problem/16792073> - (sessionFinished) block performed very slowly (0.00 secs)
|
||||
|
||||
#import "KMInputMethodAppDelegate.h"
|
||||
#import "KMSettingsRepository.h"
|
||||
#import "KMDataRepository.h"
|
||||
|
|
@ -28,21 +19,6 @@
|
|||
#import "KMLogs.h"
|
||||
@import Sentry;
|
||||
|
||||
/** NSUserDefaults keys */
|
||||
NSString *const kKMSelectedKeyboardKey = @"KMSelectedKeyboardKey";
|
||||
NSString *const kKMActiveKeyboardsKey = @"KMActiveKeyboardsKey";
|
||||
/**
|
||||
The following constant "KMSavedStoresKey" is left here for documentation
|
||||
though we have abandoned stores written to UserDefaults with this key because
|
||||
they used a less-reliable numeric key prior to integration with Keyman Core.
|
||||
It is replaced by the renamed "KMPersistedOptionsKey" which directly
|
||||
represents what it is saving.
|
||||
*/
|
||||
NSString *const kKMDeprecatedPersistedOptionsKey = @"KMSavedStoresKey";
|
||||
NSString *const kKMPersistedOptionsKey = @"KMPersistedOptionsKey";
|
||||
NSString *const kKMAlwaysShowOSKKey = @"KMAlwaysShowOSKKey";
|
||||
NSString *const kKMUseVerboseLogging = @"KMUseVerboseLogging";
|
||||
|
||||
NSString *const kKeymanKeyboardDownloadCompletedNotification = @"kKeymanKeyboardDownloadCompletedNotification";
|
||||
|
||||
@implementation NSString (VersionNumbers)
|
||||
|
|
@ -169,12 +145,9 @@ id _lastServerWithOSKShowing = nil;
|
|||
[[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions": @YES }];
|
||||
|
||||
[KMLogs reportLogStatus];
|
||||
|
||||
[self startSentry];
|
||||
|
||||
[self setDefaultKeymanMenuItems];
|
||||
[self updateKeyboardMenuItems];
|
||||
|
||||
[self setPostLaunchKeymanSentryTags];
|
||||
// [SentrySDK captureMessage:@"Starting Keyman [test message]"];
|
||||
}
|
||||
|
|
@ -412,7 +385,6 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
- (KMPackageReader *)packageReader {
|
||||
if (_packageReader == nil) {
|
||||
_packageReader = [[KMPackageReader alloc] init];
|
||||
[_packageReader setDebugMode:self.debugMode];
|
||||
}
|
||||
|
||||
return _packageReader;
|
||||
|
|
@ -443,55 +415,17 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
[_oskWindow.window setTitle:self.oskWindowTitle];
|
||||
}
|
||||
|
||||
- (void)readPersistedOptions {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
NSDictionary *allPersistedOptions = [userData dictionaryForKey:kKMPersistedOptionsKey];
|
||||
if (!allPersistedOptions) {
|
||||
return;
|
||||
}
|
||||
NSDictionary *persistedOptionsForSelectedKeyboard = [allPersistedOptions objectForKey:_selectedKeyboard];
|
||||
if (!persistedOptionsForSelectedKeyboard) {
|
||||
os_log_info([KMLogs configLog], "no persisted options found in UserDefaults for keyboard %{public}@ ", _selectedKeyboard);
|
||||
return;
|
||||
}
|
||||
- (void)applyPersistedOptions {
|
||||
NSDictionary *selectedPersistedOptions = [[KMSettingsRepository shared] readOptionsForSelectedKeyboard];
|
||||
|
||||
// TODO: pass array instead of making repeated calls
|
||||
for (NSString *key in persistedOptionsForSelectedKeyboard) {
|
||||
NSString *value = [persistedOptionsForSelectedKeyboard objectForKey:key];
|
||||
for (NSString *key in selectedPersistedOptions) {
|
||||
NSString *value = [selectedPersistedOptions objectForKey:key];
|
||||
os_log_info([KMLogs configLog], "persisted options found in UserDefaults for keyboard %{public}@, key: %{public}@, value: %{public}@", _selectedKeyboard, key, value);
|
||||
[self.kme setCoreOptions:key withValue:value];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)writePersistedOptions:(NSString *)storeKey withValue:(NSString* )value {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
NSDictionary *allPersistedOptions = [userData dictionaryForKey:kKMPersistedOptionsKey];
|
||||
NSDictionary *persistedOptionsForSelectedKeyboard;
|
||||
|
||||
if (allPersistedOptions) {
|
||||
persistedOptionsForSelectedKeyboard = [allPersistedOptions objectForKey:_selectedKeyboard];
|
||||
}
|
||||
|
||||
if (persistedOptionsForSelectedKeyboard) {
|
||||
NSMutableDictionary *newSavedStores = [persistedOptionsForSelectedKeyboard mutableCopy];
|
||||
[newSavedStores setObject:value forKey:storeKey];
|
||||
persistedOptionsForSelectedKeyboard = newSavedStores;
|
||||
} else {
|
||||
persistedOptionsForSelectedKeyboard = [[NSDictionary alloc] initWithObjectsAndKeys:value, storeKey, nil];
|
||||
}
|
||||
|
||||
if (allPersistedOptions) {
|
||||
NSMutableDictionary *newAllSavedStores = [allPersistedOptions mutableCopy];
|
||||
[newAllSavedStores setObject:persistedOptionsForSelectedKeyboard forKey:_selectedKeyboard];
|
||||
allPersistedOptions = newAllSavedStores;
|
||||
} else {
|
||||
allPersistedOptions = [[NSDictionary alloc] initWithObjectsAndKeys:persistedOptionsForSelectedKeyboard, _selectedKeyboard, nil];
|
||||
}
|
||||
|
||||
[userData setObject:allPersistedOptions forKey:kKMPersistedOptionsKey];
|
||||
[userData synchronize];
|
||||
}
|
||||
|
||||
- (NSString *)oskWindowTitle {
|
||||
if (_keyboardName == nil || !_keyboardName.length)
|
||||
return [NSString stringWithFormat:@"Keyman"];
|
||||
|
|
@ -501,9 +435,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
|
||||
- (void)setAlwaysShowOSK:(BOOL)alwaysShowOSK {
|
||||
_alwaysShowOSK = alwaysShowOSK;
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setBool:alwaysShowOSK forKey:kKMAlwaysShowOSKKey];
|
||||
[userData synchronize];
|
||||
[[KMSettingsRepository shared] writeAlwaysShowOsk:alwaysShowOSK];
|
||||
}
|
||||
|
||||
- (void)setUseVerboseLogging:(BOOL)useVerboseLogging {
|
||||
|
|
@ -511,23 +443,17 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
_debugMode = useVerboseLogging;
|
||||
if (_kme != nil)
|
||||
[_kme setUseVerboseLogging:useVerboseLogging];
|
||||
if (_packageReader != nil) {
|
||||
[_packageReader setDebugMode:useVerboseLogging];
|
||||
}
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setBool:useVerboseLogging forKey:kKMUseVerboseLogging];
|
||||
[userData synchronize];
|
||||
|
||||
[[KMSettingsRepository shared] writeUseVerboseLogging:useVerboseLogging];
|
||||
}
|
||||
|
||||
- (BOOL)alwaysShowOSK {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
_alwaysShowOSK = [userData boolForKey:kKMAlwaysShowOSKKey];
|
||||
_alwaysShowOSK = [[KMSettingsRepository shared] readAlwaysShowOsk];
|
||||
return _alwaysShowOSK;
|
||||
}
|
||||
|
||||
- (BOOL)useVerboseLogging {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
return [userData boolForKey:kKMUseVerboseLogging];
|
||||
return [[KMSettingsRepository shared] readUseVerboseLogging];
|
||||
}
|
||||
|
||||
#pragma mark - Keyman Data
|
||||
|
|
@ -544,12 +470,13 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
}
|
||||
|
||||
- (NSArray *)kmxFileList {
|
||||
os_log_debug([KMLogs dataLog], "kmxFileList");
|
||||
if (_kmxFileList == nil) {
|
||||
NSArray *kmxFiles = [self KMXFiles];
|
||||
os_log_debug([KMLogs dataLog], "creating kmxFileList");
|
||||
NSArray *kmxFiles = [self getKmxFilesInKeyboardsDirectory];
|
||||
_kmxFileList = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
NSMutableArray *others = nil;
|
||||
for (NSString *filePath in kmxFiles) {
|
||||
os_log_debug([KMLogs dataLog], "kmxFileList, filePath: %{public}@", filePath);
|
||||
NSString *packageFolder = [self packageFolderFromPath:filePath];
|
||||
NSInteger index = [self indexForPackageFolder:packageFolder];
|
||||
if ([packageFolder isEqualToString:@"Others"]) {
|
||||
|
|
@ -666,7 +593,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
- (NSArray *)keyboardNamesFromFolder:(NSString *)packageFolder {
|
||||
os_log_debug([KMLogs dataLog], "keyboardNamesFromFolder, folder = %{public}@", packageFolder);
|
||||
NSMutableArray *kbNames = [[NSMutableArray alloc] initWithCapacity:0];;
|
||||
for (NSString *kmxFile in [self KMXFilesAtPath:packageFolder]) {
|
||||
for (NSString *kmxFile in [self getKmxFilesAtPath:packageFolder]) {
|
||||
NSDictionary * infoDict = [KMXFile keyboardInfoFromKmxFile:kmxFile];
|
||||
if (infoDict != nil) {
|
||||
NSString *name = [infoDict objectForKey:kKMKeyboardNameKey];
|
||||
|
|
@ -681,52 +608,56 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
|
||||
- (NSString *)selectedKeyboard {
|
||||
if (_selectedKeyboard == nil) {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
_selectedKeyboard = [userData objectForKey:kKMSelectedKeyboardKey];
|
||||
_selectedKeyboard = [[KMSettingsRepository shared] readSelectedKeyboard];
|
||||
}
|
||||
|
||||
os_log_debug([KMLogs dataLog], "selectedKeyboard = %{public}@", _selectedKeyboard);
|
||||
|
||||
return _selectedKeyboard;
|
||||
}
|
||||
|
||||
- (void)setSelectedKeyboard:(NSString *)selectedKeyboard {
|
||||
[[KMSettingsRepository shared] writeSelectedKeyboard:selectedKeyboard];
|
||||
_selectedKeyboard = selectedKeyboard;
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setObject:_selectedKeyboard forKey:kKMSelectedKeyboardKey];
|
||||
[userData synchronize];
|
||||
}
|
||||
|
||||
- (NSMutableArray *)activeKeyboards {
|
||||
if (!_activeKeyboards) {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
_activeKeyboards = [[userData arrayForKey:kKMActiveKeyboardsKey] mutableCopy];
|
||||
if (!_activeKeyboards)
|
||||
_activeKeyboards = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
os_log_debug([KMLogs dataLog], "initializing activeKeyboards");
|
||||
_activeKeyboards = [[KMSettingsRepository.shared readActiveKeyboards] mutableCopy];
|
||||
}
|
||||
|
||||
|
||||
return _activeKeyboards;
|
||||
}
|
||||
|
||||
- (void)saveActiveKeyboards {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setObject:_activeKeyboards forKey:kKMActiveKeyboardsKey];
|
||||
[userData synchronize];
|
||||
os_log_debug([KMLogs dataLog], "saveActiveKeyboards");
|
||||
[KMSettingsRepository.shared writeActiveKeyboards:_activeKeyboards];
|
||||
[self resetActiveKeyboards];
|
||||
[self updateKeyboardMenuItems];
|
||||
}
|
||||
|
||||
- (void)clearActiveKeyboards {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setObject:nil forKey:kKMActiveKeyboardsKey];
|
||||
[userData synchronize];
|
||||
[KMSettingsRepository.shared clearActiveKeyboards];
|
||||
[self updateKeyboardMenuItems];
|
||||
}
|
||||
|
||||
- (void)addActiveKeyboard:(NSString *) partialPath {
|
||||
if (![self.activeKeyboards containsObject:partialPath]) {
|
||||
os_log_debug([KMLogs keyboardLog], "addActiveKeyboard, adding '%{public}@' to list of active keyboards: ", partialPath);
|
||||
[self.activeKeyboards addObject:partialPath];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resetActiveKeyboards {
|
||||
// Remove entries with missing files
|
||||
NSMutableArray *pathsToRemove = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
for (NSString *path in self.activeKeyboards) {
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:path])
|
||||
NSString *fullPath = [KMDataRepository.shared buildFullPath:path];
|
||||
os_log_debug([KMLogs dataLog], "resetActiveKeyboards, checking fullPath: '%{public}@' for path: '%{public}@'", fullPath, path);
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:fullPath]) {
|
||||
os_log_debug([KMLogs dataLog], "resetActiveKeyboards, need to remove non-existent path: %{public}@", fullPath);
|
||||
[pathsToRemove addObject:path];
|
||||
}
|
||||
}
|
||||
|
||||
BOOL found = FALSE;
|
||||
|
|
@ -749,9 +680,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
}
|
||||
|
||||
if (found) {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setObject:_activeKeyboards forKey:kKMActiveKeyboardsKey];
|
||||
[userData synchronize];
|
||||
[KMSettingsRepository.shared writeActiveKeyboards:_activeKeyboards];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -814,6 +743,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
}
|
||||
|
||||
- (int)calculateNumberOfKeyboardMenuItems {
|
||||
os_log_debug([KMLogs uiLog], "calculateNumberOfKeyboardMenuItems, entered");
|
||||
if (self.activeKeyboards.count == 0) {
|
||||
// if there are no active keyboards, then we will insert one placeholder menu item 'No Active Keyboards'
|
||||
return 1;
|
||||
|
|
@ -835,6 +765,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
}
|
||||
|
||||
- (void)addDynamicKeyboardMenuItems {
|
||||
os_log_debug([KMLogs startupLog], "addDynamicKeyboardMenuItems, entered");
|
||||
BOOL didSetSelectedKeyboard = NO;
|
||||
NSInteger itag = KEYMAN_FIRST_KEYBOARD_MENUITEM_TAG;
|
||||
NSString *keyboardMenuName = @"";
|
||||
|
|
@ -846,7 +777,9 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
|
||||
// loop through the active keyboards list and add them to the menu
|
||||
for (NSString *path in self.activeKeyboards) {
|
||||
NSDictionary *infoDict = [KMXFile keyboardInfoFromKmxFile:path];
|
||||
NSString *fullPath = [KMDataRepository.shared buildFullPath:path];
|
||||
os_log_debug([KMLogs dataLog], "addDynamicKeyboardMenuItems, path = '%{public}@', full path = '%{public}@'", path, fullPath);
|
||||
NSDictionary *infoDict = [KMXFile keyboardInfoFromKmxFile:fullPath];
|
||||
if (!infoDict) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -876,10 +809,12 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
- (void) setSelectedKeyboard:(NSString*)keyboardName inMenuItem:(NSMenuItem*) menuItem {
|
||||
KVKFile *kvk = nil;
|
||||
|
||||
NSString *fullPath = [KMDataRepository.shared buildFullPath:keyboardName];
|
||||
os_log_debug([KMLogs dataLog], "setSelectedKeyboard, keyboardName = '%{public}@', full path = '%{public}@'", keyboardName, fullPath);
|
||||
[menuItem setState:NSOnState];
|
||||
KMXFile *kmx = [[KMXFile alloc] initWithFilePath:keyboardName];
|
||||
KMXFile *kmx = [[KMXFile alloc] initWithFilePath:fullPath];
|
||||
[self setKmx:kmx];
|
||||
NSDictionary *kmxInfo = [KMXFile keyboardInfoFromKmxFile:keyboardName];
|
||||
NSDictionary *kmxInfo = [KMXFile keyboardInfoFromKmxFile:fullPath];
|
||||
NSString *kvkFilename = [kmxInfo objectForKey:kKMVisualKeyboardKey];
|
||||
if (kvkFilename != nil) {
|
||||
NSString *kvkFilePath = [self kvkFilePathFromFilename:kvkFilename];
|
||||
|
|
@ -890,7 +825,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
[self setKvk:kvk];
|
||||
[self setKeyboardName:[kmxInfo objectForKey:kKMKeyboardNameKey]];
|
||||
[self setKeyboardIcon:[kmxInfo objectForKey:kKMKeyboardIconKey]];
|
||||
[self readPersistedOptions];
|
||||
[self applyPersistedOptions];
|
||||
}
|
||||
|
||||
// defaults to the whatever keyboard happens to be first in the list
|
||||
|
|
@ -931,10 +866,13 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
}
|
||||
|
||||
NSString *path = [self.activeKeyboards objectAtIndex:tag-KEYMAN_FIRST_KEYBOARD_MENUITEM_TAG];
|
||||
KMXFile *kmx = [[KMXFile alloc] initWithFilePath:path];
|
||||
NSString *fullPath = [KMDataRepository.shared buildFullPath:path];
|
||||
os_log_debug([KMLogs dataLog], "setSelectedKeyboard, keyboardName = '%{public}@', full path = '%{public}@'", path, fullPath);
|
||||
|
||||
KMXFile *kmx = [[KMXFile alloc] initWithFilePath:fullPath];
|
||||
[self setKmx:kmx];
|
||||
KVKFile *kvk = nil;
|
||||
NSDictionary *kmxInfo = [KMXFile keyboardInfoFromKmxFile:path];
|
||||
NSDictionary *kmxInfo = [KMXFile keyboardInfoFromKmxFile:fullPath];
|
||||
NSString *kvkFilename = [kmxInfo objectForKey:kKMVisualKeyboardKey];
|
||||
if (kvkFilename != nil) {
|
||||
NSString *kvkFilePath = [self kvkFilePathFromFilename:kvkFilename];
|
||||
|
|
@ -948,17 +886,17 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
[self setKeyboardIcon:[kmxInfo objectForKey:kKMKeyboardIconKey]];
|
||||
[self setContextBuffer:nil];
|
||||
[self setSelectedKeyboard:path];
|
||||
[self readPersistedOptions];
|
||||
[self applyPersistedOptions];
|
||||
if (kvk != nil && self.alwaysShowOSK)
|
||||
[self showOSK];
|
||||
}
|
||||
|
||||
- (NSArray *)KMXFiles {
|
||||
return [self KMXFilesAtPath:self.keyboardsPath];
|
||||
- (NSArray *)getKmxFilesInKeyboardsDirectory {
|
||||
return [self getKmxFilesAtPath:self.keyboardsPath];
|
||||
}
|
||||
|
||||
- (NSArray *)KMXFilesAtPath:(NSString *)path {
|
||||
os_log_debug([KMLogs dataLog], "Reading KMXFiles at path %{public}@", path);
|
||||
- (NSArray *)getKmxFilesAtPath:(NSString *)path {
|
||||
os_log_debug([KMLogs dataLog], "getKmxFilesAtPath, path: '%{public}@'", path);
|
||||
NSDirectoryEnumerator *dirEnum = [[NSFileManager defaultManager] enumeratorAtPath:path];
|
||||
NSMutableArray *kmxFiles = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
NSString *filePath;
|
||||
|
|
@ -973,23 +911,23 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
return kmxFiles;
|
||||
}
|
||||
|
||||
- (NSArray *)KVKFiles {
|
||||
- (NSArray *)getKvkFilesArray {
|
||||
NSDirectoryEnumerator *dirEnum = [[NSFileManager defaultManager] enumeratorAtPath:self.keyboardsPath];
|
||||
NSMutableArray *kvkFiles = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
NSMutableArray *kvkFilesArray = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
NSString *filePath;
|
||||
while (filePath = (NSString *)[dirEnum nextObject]) {
|
||||
NSString *extension = [[filePath pathExtension] lowercaseString];
|
||||
if ([extension isEqualToString:@"kvk"])
|
||||
[kvkFiles addObject:[self.keyboardsPath stringByAppendingPathComponent:filePath]];
|
||||
[kvkFilesArray addObject:[self.keyboardsPath stringByAppendingPathComponent:filePath]];
|
||||
}
|
||||
|
||||
return kvkFiles;
|
||||
return kvkFilesArray;
|
||||
}
|
||||
|
||||
- (NSString *)kvkFilePathFromFilename:(NSString *)kvkFilename {
|
||||
NSString *kvkFilePath = nil;
|
||||
NSArray *kvkFiles = [self KVKFiles];
|
||||
for (NSString *filePath in kvkFiles) {
|
||||
NSArray *kvkFilesArray = [self getKvkFilesArray];
|
||||
for (NSString *filePath in kvkFilesArray) {
|
||||
if ([[filePath lastPathComponent] isEqualToString:kvkFilename]) {
|
||||
kvkFilePath = filePath;
|
||||
break;
|
||||
|
|
@ -1338,7 +1276,8 @@ extern const CGKeyCode kProcessPendingBuffer;
|
|||
NSError *error = nil;
|
||||
NSString *fileName = filePath.lastPathComponent;
|
||||
NSString *folderName = [fileName stringByDeletingPathExtension];
|
||||
|
||||
os_log_debug([KMLogs keyboardLog], "unzipFile, folderName: %{public}@, fileName: %{public}@", folderName, fileName);
|
||||
|
||||
// First we unzip into a temp folder, and check kmp.json for the fileVersion
|
||||
// before we continue installation. We don't want to overwrite existing
|
||||
// package if it is there if the files are not compatible with the installed
|
||||
|
|
@ -1349,9 +1288,9 @@ extern const CGKeyCode kProcessPendingBuffer;
|
|||
|
||||
ZipArchive *za = [[ZipArchive alloc] init];
|
||||
if ([za UnzipOpenFile:filePath]) {
|
||||
os_log_debug([KMLogs keyboardLog], "Unzipping %{public}@ to %{public}@", filePath, tempDestFolder);
|
||||
os_log_debug([KMLogs keyboardLog], "unzipFile, Unzipping %{public}@ to %{public}@", filePath, tempDestFolder);
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:tempDestFolder]) {
|
||||
os_log_debug([KMLogs keyboardLog], "The temp destination folder already exists. Overwriting...");
|
||||
os_log_debug([KMLogs keyboardLog], "unzipFile, The temp destination folder already exists. Overwriting...");
|
||||
}
|
||||
|
||||
didUnzip = [za UnzipFileTo:tempDestFolder overWrite:YES];
|
||||
|
|
@ -1359,11 +1298,11 @@ extern const CGKeyCode kProcessPendingBuffer;
|
|||
}
|
||||
|
||||
if (!didUnzip) {
|
||||
os_log_error([KMLogs keyboardLog], "Failed to unzip file: %{public}@", filePath);
|
||||
os_log_error([KMLogs keyboardLog], "unzipFile, Failed to unzip file: %{public}@", filePath);
|
||||
return NO;
|
||||
}
|
||||
|
||||
os_log_debug([KMLogs keyboardLog], "Unzipped file: %{public}@", filePath);
|
||||
os_log_debug([KMLogs keyboardLog], "unzipFile, Unzipped file: %{public}@", filePath);
|
||||
|
||||
BOOL didInstall = [self verifyPackageVersionInTempFolder:tempDestFolder filePath:filePath];
|
||||
|
||||
|
|
@ -1371,10 +1310,10 @@ extern const CGKeyCode kProcessPendingBuffer;
|
|||
|
||||
// Remove existing package if it exists
|
||||
if (didInstall && [[NSFileManager defaultManager] fileExistsAtPath:destFolder]) {
|
||||
os_log_debug([KMLogs keyboardLog], "The destination folder already exists. Overwriting...");
|
||||
os_log_debug([KMLogs keyboardLog], "unzipFile, The destination folder already exists. Overwriting...");
|
||||
[[NSFileManager defaultManager] removeItemAtPath:destFolder error:&error];
|
||||
if (error != nil) {
|
||||
os_log_error([KMLogs keyboardLog], "Unable to remove destination folder %{public}@", destFolder);
|
||||
os_log_error([KMLogs keyboardLog], "unzipFile, Unable to remove destination folder %{public}@", destFolder);
|
||||
didInstall = NO;
|
||||
}
|
||||
}
|
||||
|
|
@ -1387,7 +1326,7 @@ extern const CGKeyCode kProcessPendingBuffer;
|
|||
if(didInstall) {
|
||||
[[NSFileManager defaultManager] moveItemAtPath:tempDestFolder toPath:destFolder error:&error];
|
||||
if (error != nil) {
|
||||
os_log_error([KMLogs keyboardLog], "Unable to move temp folder %{public}@ to dest folder %{public}@", tempDestFolder, destFolder);
|
||||
os_log_error([KMLogs keyboardLog], "unzipFile, Unable to move temp folder %{public}@ to dest folder %{public}@", tempDestFolder, destFolder);
|
||||
didInstall = NO;
|
||||
}
|
||||
}
|
||||
|
|
@ -1395,7 +1334,7 @@ extern const CGKeyCode kProcessPendingBuffer;
|
|||
if(!didInstall) {
|
||||
[[NSFileManager defaultManager] removeItemAtPath:tempDestFolder error:&error];
|
||||
if (error != nil) {
|
||||
os_log_error([KMLogs keyboardLog], "Unable to remove temp folder %{public}@", tempDestFolder);
|
||||
os_log_error([KMLogs keyboardLog], "unzipFile, Unable to remove temp folder %{public}@", tempDestFolder);
|
||||
}
|
||||
|
||||
return NO;
|
||||
|
|
@ -1404,11 +1343,12 @@ extern const CGKeyCode kProcessPendingBuffer;
|
|||
// Package has installed, now scan for keyboards and fonts
|
||||
// TODO: we need to be reading the kmp.json data to determine keyboards to install
|
||||
NSString * keyboardFolderPath = [self.keyboardsPath stringByAppendingPathComponent:folderName];
|
||||
os_log_debug([KMLogs keyboardLog], "unzipFile, folderName: %{public}@, keyboardFolderPath: %{public}@", folderName, keyboardFolderPath);
|
||||
[self installFontsAtPath:keyboardFolderPath];
|
||||
for (NSString *kmxFile in [self KMXFilesAtPath:keyboardFolderPath]) {
|
||||
os_log_debug([KMLogs keyboardLog], "Adding keyboard to list of active keyboards: %{public}@", kmxFile);
|
||||
if (![self.activeKeyboards containsObject:kmxFile])
|
||||
[self.activeKeyboards addObject:kmxFile];
|
||||
|
||||
for (NSString *kmxFile in [self getKmxFilesAtPath:keyboardFolderPath]) {
|
||||
NSString *partialPath = [KMDataRepository.shared buildPartialPathFrom:folderName keyboardFile:[kmxFile lastPathComponent]];
|
||||
[self addActiveKeyboard:partialPath];
|
||||
}
|
||||
[self saveActiveKeyboards];
|
||||
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ NSString* const kEasterEggKmxName = @"EnglishSpanish.kmx";
|
|||
NSString *value = [options objectForKey:key];
|
||||
if(key && value) {
|
||||
os_log_debug([KMLogs keyLog], "persistOptions, key: %{public}@, value: %{public}@", key, value);
|
||||
[self.appDelegate writePersistedOptions:key withValue:value];
|
||||
[[KMSettingsRepository shared] writeOptionForSelectedKeyboard:key withValue:value];
|
||||
}
|
||||
else {
|
||||
os_log_debug([KMLogs keyLog], "invalid values in persistOptions, not writing to UserDefaults, key: %{public}@, value: %{public}@", key, value);
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@interface KMPackageReader : NSObject
|
||||
|
||||
@property (assign, nonatomic) BOOL debugMode;
|
||||
|
||||
- (instancetype)init;
|
||||
- (KMPackageInfo *)loadPackageInfo:(NSString *)path;
|
||||
|
||||
|
|
|
|||
|
|
@ -44,9 +44,6 @@ typedef enum {
|
|||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_debugMode = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,17 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (BOOL)dataMigrationNeeded;
|
||||
- (void)convertSettingsForMigration;
|
||||
- (void)setDataModelVersionIfNecessary;
|
||||
- (NSString *)readSelectedKeyboard;
|
||||
- (void)writeSelectedKeyboard:(NSString *)selectedKeyboard;
|
||||
- (NSArray *)readActiveKeyboards;
|
||||
- (void)writeActiveKeyboards: (NSArray *) keyboards;
|
||||
- (void)clearActiveKeyboards;
|
||||
- (NSDictionary *)readOptionsForSelectedKeyboard;
|
||||
- (void)writeOptionForSelectedKeyboard:(NSString *)key withValue:(NSString*)value;
|
||||
- (BOOL)readAlwaysShowOsk;
|
||||
- (void)writeAlwaysShowOsk:(BOOL)alwaysShowOsk;
|
||||
- (BOOL)readUseVerboseLogging;
|
||||
- (void)writeUseVerboseLogging:(BOOL)verboseLogging;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
|||
|
|
@ -9,12 +9,24 @@
|
|||
|
||||
#import "KMSettingsRepository.h"
|
||||
#import "KMLogs.h"
|
||||
#import "KMDataRepository.h"
|
||||
|
||||
NSString *const kActiveKeyboardsKey = @"KMActiveKeyboardsKey";
|
||||
NSString *const kSelectedKeyboardKey = @"KMSelectedKeyboardKey";
|
||||
NSString *const kPersistedOptionsKey = @"KMPersistedOptionsKey";
|
||||
NSString *const kAlwaysShowOSKKey = @"KMAlwaysShowOSKKey";
|
||||
NSString *const kUseVerboseLogging = @"KMUseVerboseLogging";
|
||||
|
||||
NSString *const kObsoletePathComponent = @"/Documents/";
|
||||
/**
|
||||
* The following constant "KMSavedStoresKey" is left here for documentation
|
||||
* though we have abandoned stores written to UserDefaults with this key because
|
||||
* they used a less-reliable numeric key prior to integration with Keyman Core.
|
||||
* It is replaced by the renamed "KMPersistedOptionsKey" which directly
|
||||
* represents what it is saving.
|
||||
*/
|
||||
NSString *const kKMDeprecatedPersistedOptionsKey = @"KMSavedStoresKey";
|
||||
|
||||
NSString *const kObsoletePathComponent = @"/Documents/Keyman-Keyboards";
|
||||
NSString *const kNewPathComponent = @"/Library/Application Support/keyman.inputmethod.Keyman/";
|
||||
|
||||
/**
|
||||
|
|
@ -49,8 +61,46 @@ NSInteger const kCurrentDataModelVersionNumber = kVersionStoreDataInLibraryDirec
|
|||
* If this method is called after applicationDidFinishLaunching, then it will always return true.
|
||||
* If called from awakeFromNib, then it will return false when running for the first time.
|
||||
*/
|
||||
- (BOOL)settingsExist {
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:kSelectedKeyboardKey] != nil;
|
||||
- (BOOL)settingsExist
|
||||
{
|
||||
return ([[NSUserDefaults standardUserDefaults] objectForKey:kSelectedKeyboardKey] != nil);
|
||||
}
|
||||
|
||||
- (void)writeOptionForSelectedKeyboard:(NSString *)key withValue:(NSString*)value {
|
||||
NSDictionary *optionsMap = [self readOptionsForSelectedKeyboard];
|
||||
NSDictionary *newOptionsMap = nil;
|
||||
|
||||
// if we can read an existing options map, then add the specified key-value pair
|
||||
if (optionsMap != nil) {
|
||||
NSMutableDictionary *mutableOptionsMap = [optionsMap mutableCopy];
|
||||
[mutableOptionsMap setObject:value forKey:key];
|
||||
newOptionsMap = mutableOptionsMap;
|
||||
} else {
|
||||
// if no options map exists, create a new one add the specified key-value pair
|
||||
newOptionsMap = [[NSDictionary alloc] initWithObjectsAndKeys:value, key, nil];
|
||||
}
|
||||
|
||||
// write the options map for the selected keyboard to the dictionary of options
|
||||
NSString *selectedKeyboard = [self readSelectedKeyboard];
|
||||
os_log_info([KMLogs dataLog], "writeOptionForSelectedKeyboard, adding options map: %{public}@, to keyboard %{public}@", newOptionsMap, selectedKeyboard);
|
||||
[self writeKeyboardOptionsMap: selectedKeyboard withOptions:newOptionsMap];
|
||||
}
|
||||
|
||||
- (void)writeKeyboardOptionsMap:(NSString *)keyboardName withOptions:(NSDictionary*) optionsMap {
|
||||
NSMutableDictionary *newFullOptionsMap = nil;
|
||||
os_log_debug([KMLogs dataLog], "writeKeyboardOptionsMap, adding options map: %{public}@, to keyboard %{public}@", optionsMap, keyboardName);
|
||||
|
||||
NSDictionary *fullOptionsMap = [self readFullOptionsMap];
|
||||
// if we can read the existing full options map, then add for the specified keyboard
|
||||
if (fullOptionsMap != nil) {
|
||||
newFullOptionsMap = [fullOptionsMap mutableCopy];
|
||||
[newFullOptionsMap setObject:optionsMap forKey:keyboardName];
|
||||
} else {
|
||||
// otherwise, create the full options map and add for the specified keyboard
|
||||
newFullOptionsMap = [[NSMutableDictionary alloc] initWithObjectsAndKeys:optionsMap, keyboardName, nil];
|
||||
}
|
||||
|
||||
[self writeFullOptionsMap:newFullOptionsMap];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -83,11 +133,11 @@ NSInteger const kCurrentDataModelVersionNumber = kVersionStoreDataInLibraryDirec
|
|||
return migrationNeeded;
|
||||
}
|
||||
|
||||
- (NSString *)selectedKeyboard {
|
||||
- (NSString *)readSelectedKeyboard {
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:kSelectedKeyboardKey];
|
||||
}
|
||||
|
||||
- (void)saveSelectedKeyboard:(NSString *)selectedKeyboard {
|
||||
- (void)writeSelectedKeyboard:(NSString *)selectedKeyboard {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setObject:selectedKeyboard forKey:kSelectedKeyboardKey];
|
||||
}
|
||||
|
|
@ -101,63 +151,116 @@ NSInteger const kCurrentDataModelVersionNumber = kVersionStoreDataInLibraryDirec
|
|||
return activeKeyboards;
|
||||
}
|
||||
|
||||
- (NSDictionary *)persistedOptions {
|
||||
- (NSArray *)readActiveKeyboards {
|
||||
os_log_debug([KMLogs dataLog], "KMSettingsRepository readActiveKeyboards");
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
NSArray *keyboardsArray = [userData arrayForKey:kActiveKeyboardsKey];
|
||||
|
||||
// if the kActiveKeyboardsKey does not exist, then create an empty array
|
||||
if (!keyboardsArray) {
|
||||
os_log_debug([KMLogs dataLog], "KMActiveKeyboardsKey key not found in NSUserDefualts");
|
||||
keyboardsArray = [[NSArray alloc] init];
|
||||
}
|
||||
return keyboardsArray;
|
||||
}
|
||||
|
||||
- (void)writeActiveKeyboards: (NSArray *) keyboards {
|
||||
os_log_debug([KMLogs dataLog], "KMSettingsRepository writeActiveKeyboards");
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setObject:keyboards forKey:kActiveKeyboardsKey];
|
||||
}
|
||||
|
||||
- (void)clearActiveKeyboards {
|
||||
os_log_debug([KMLogs dataLog], "KMSettingsRepository clearActiveKeyboards");
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setObject:nil forKey:kActiveKeyboardsKey];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns dictionary of persisted options for the single selected keyboard
|
||||
*/
|
||||
- (NSDictionary *)readOptionsForSelectedKeyboard {
|
||||
NSDictionary *optionsMap = [self readFullOptionsMap];
|
||||
NSString *selectedKeyboard = [self readSelectedKeyboard];
|
||||
NSDictionary *selectedOptionsMap = [optionsMap objectForKey: selectedKeyboard];
|
||||
if (selectedOptionsMap == nil) {
|
||||
os_log_info([KMLogs dataLog], "no persisted options found in UserDefaults for keyboard %{public}@ ", selectedKeyboard);
|
||||
} else {
|
||||
for (NSString *key in selectedOptionsMap) {
|
||||
NSString *value = [selectedOptionsMap objectForKey:key];
|
||||
os_log_info([KMLogs dataLog], "option for keyboard %{public}@ key: %{public}@, value %{public}@", selectedKeyboard, key, value);
|
||||
}
|
||||
}
|
||||
return selectedOptionsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns dictionary of all persisted options for all keyboards
|
||||
* (options are stored in UserDefaults as a map of maps)
|
||||
*/
|
||||
- (NSDictionary *)readFullOptionsMap {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
return [userData dictionaryForKey:kPersistedOptionsKey];
|
||||
}
|
||||
|
||||
- (void)savePersistedOptions:(NSDictionary *) optionsDictionary {
|
||||
- (void)writeFullOptionsMap:(NSDictionary *) fullOptionsMap {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setObject:optionsDictionary forKey:kPersistedOptionsKey];
|
||||
[userData setObject:fullOptionsMap forKey:kPersistedOptionsKey];
|
||||
}
|
||||
|
||||
- (void)removePersistedOptions {
|
||||
- (void)removeAllOptions {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
return [userData removeObjectForKey:kPersistedOptionsKey];
|
||||
}
|
||||
|
||||
- (void)convertSettingsForMigration {
|
||||
os_log_debug([KMLogs dataLog], "converting settings in UserDefaults for migration");
|
||||
[self convertSelectedKeyboardPathForMigration];
|
||||
[self convertActiveKeyboardArrayForMigration];
|
||||
[self convertPersistedOptionsPathsForMigration];
|
||||
[self convertOptionsPathsForMigration];
|
||||
}
|
||||
|
||||
- (void)convertSelectedKeyboardPathForMigration {
|
||||
NSString *selectedKeyboardPath = [self selectedKeyboard];
|
||||
|
||||
NSString *selectedKeyboardPath = [self readSelectedKeyboard];
|
||||
if (selectedKeyboardPath != nil) {
|
||||
NSString *newPathString = [self convertOldKeyboardPath:selectedKeyboardPath];
|
||||
NSString *newPathString = [self trimObsoleteKeyboardPath:selectedKeyboardPath];
|
||||
|
||||
if ([selectedKeyboardPath isNotEqualTo:newPathString]) {
|
||||
[self saveSelectedKeyboard:newPathString];
|
||||
os_log([KMLogs dataLog], "converted selected keyboard setting from '%{public}@' to '%{public}@'", selectedKeyboardPath, newPathString);
|
||||
[self writeSelectedKeyboard:newPathString];
|
||||
os_log_debug([KMLogs dataLog], "converted selected keyboard setting from '%{public}@' to '%{public}@'", selectedKeyboardPath, newPathString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the path of the keyboard designating the Documents folder to its new location
|
||||
* in the Application Support folder
|
||||
* To convert the keyboard path for the new location, just trim the parent directory from the path
|
||||
* No need to repeatedly store the parent directory with the path of each keyboard
|
||||
* If the old directory is not found in the string, then return the string unchanged
|
||||
*/
|
||||
- (NSString *)convertOldKeyboardPath:(NSString *)oldPath {
|
||||
NSString *newPathString = @"";
|
||||
- (NSString *)trimObsoleteKeyboardPath:(NSString *)oldPath {
|
||||
NSString *newPath = oldPath;
|
||||
if(oldPath != nil) {
|
||||
newPathString = [oldPath stringByReplacingOccurrencesOfString:kObsoletePathComponent withString:kNewPathComponent];
|
||||
NSRange range = [oldPath rangeOfString:kObsoletePathComponent];
|
||||
if (range.length > 0) {
|
||||
newPath = [oldPath substringFromIndex:range.location + range.length];
|
||||
os_log_debug([KMLogs dataLog], "trimmed keyboard path from '%{public}@' to '%{public}@'", oldPath, newPath);
|
||||
}
|
||||
}
|
||||
return newPathString;
|
||||
return newPath;
|
||||
}
|
||||
|
||||
- (void)convertActiveKeyboardArrayForMigration {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableArray *activeKeyboards = [self activeKeyboards];
|
||||
NSMutableArray *keyboards = [self activeKeyboards];
|
||||
NSMutableArray *convertedActiveKeyboards = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
BOOL didConvert = NO;
|
||||
|
||||
for (NSString *oldPath in activeKeyboards) {
|
||||
NSString *newPath = [self convertOldKeyboardPath:oldPath];
|
||||
for (NSString *oldPath in keyboards) {
|
||||
NSString *newPath = [self trimObsoleteKeyboardPath:oldPath];
|
||||
if ([oldPath isNotEqualTo:newPath]) {
|
||||
[convertedActiveKeyboards addObject:newPath];
|
||||
os_log([KMLogs dataLog], "converted active keyboard from old path '%{public}@' to '%{public}@'", oldPath, newPath);
|
||||
os_log_debug([KMLogs dataLog], "converted active keyboard from old path '%{public}@' to '%{public}@'", oldPath, newPath);
|
||||
// if we have adjusted at least one path, set flag
|
||||
didConvert = YES;
|
||||
} else {
|
||||
|
|
@ -172,8 +275,8 @@ NSInteger const kCurrentDataModelVersionNumber = kVersionStoreDataInLibraryDirec
|
|||
}
|
||||
}
|
||||
|
||||
- (void)convertPersistedOptionsPathsForMigration {
|
||||
NSDictionary * optionsMap = [self persistedOptions];
|
||||
- (void)convertOptionsPathsForMigration {
|
||||
NSDictionary * optionsMap = [self readFullOptionsMap];
|
||||
NSMutableDictionary *mutableOptionsMap = nil;
|
||||
BOOL optionsChanged = NO;
|
||||
|
||||
|
|
@ -184,7 +287,7 @@ NSInteger const kCurrentDataModelVersionNumber = kVersionStoreDataInLibraryDirec
|
|||
os_log_info([KMLogs configLog], "persisted options found in UserDefaults with key = %{public}@", key);
|
||||
}
|
||||
for (NSString *key in optionsMap) {
|
||||
NSString *newPathString = [self convertOldKeyboardPath:key];
|
||||
NSString *newPathString = [self trimObsoleteKeyboardPath:key];
|
||||
NSDictionary *optionsValue = [optionsMap objectForKey:key];
|
||||
|
||||
if ([key isNotEqualTo:newPathString]) {
|
||||
|
|
@ -192,16 +295,36 @@ NSInteger const kCurrentDataModelVersionNumber = kVersionStoreDataInLibraryDirec
|
|||
|
||||
// insert options into new map with newly converted path as key
|
||||
[mutableOptionsMap setObject:optionsValue forKey:newPathString];
|
||||
os_log([KMLogs dataLog], "converted option key from '%{public}@' to '%{public}@'", key, newPathString);
|
||||
os_log_debug([KMLogs dataLog], "converted option key from '%{public}@' to '%{public}@'", key, newPathString);
|
||||
} else {
|
||||
// retain options that did not need converting
|
||||
[mutableOptionsMap setObject:optionsValue forKey:key];
|
||||
}
|
||||
}
|
||||
if (optionsChanged) {
|
||||
[self savePersistedOptions:mutableOptionsMap];
|
||||
[self writeFullOptionsMap:mutableOptionsMap];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)readAlwaysShowOsk {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
return [userData boolForKey:kAlwaysShowOSKKey];
|
||||
}
|
||||
|
||||
- (void)writeAlwaysShowOsk:(BOOL)alwaysShowOsk {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setBool:alwaysShowOsk forKey:kAlwaysShowOSKKey];
|
||||
}
|
||||
|
||||
- (BOOL)readUseVerboseLogging {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
return [userData boolForKey:kUseVerboseLogging];
|
||||
}
|
||||
|
||||
- (void)writeUseVerboseLogging:(BOOL)verboseLogging {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setBool:verboseLogging forKey:kUseVerboseLogging];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue