change(mac): add class to encapsulate settings

This commit is contained in:
Shawn Schantz 2024-07-29 16:01:58 +07:00
parent f5f3c31548
commit 5488e32be2
5 changed files with 113 additions and 4 deletions

View file

@ -72,6 +72,7 @@
98FE10631B4DEE5600525F54 /* KMInfoWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 98FE10611B4DEE5600525F54 /* KMInfoWindowController.m */; };
9A3D6C5D221531B0008785A3 /* KMOSVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3D6C5C221531B0008785A3 /* KMOSVersion.m */; };
B90818AF7ED302187DE0E026 /* Pods_Keyman.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B644E63217FFE54B91C71C94 /* Pods_Keyman.framework */; };
D861B03F2C5747F70003675E /* KMSettingsRepository.m in Sources */ = {isa = PBXBuildFile; fileRef = D861B03E2C5747F70003675E /* KMSettingsRepository.m */; };
E211769D20E182DD00F8065D /* NoContextTestClient.m in Sources */ = {isa = PBXBuildFile; fileRef = E211769C20E182DD00F8065D /* NoContextTestClient.m */; };
E21176A020E18C5200F8065D /* AppleCompliantTestClient.m in Sources */ = {isa = PBXBuildFile; fileRef = E211769F20E18C5200F8065D /* AppleCompliantTestClient.m */; };
E211CCF620B600A500505C36 /* KeymanEngine4Mac.framework.dSYM in CopyFiles */ = {isa = PBXBuildFile; fileRef = E211CCF520B600A500505C36 /* KeymanEngine4Mac.framework.dSYM */; };
@ -350,6 +351,8 @@
CEFFECDB2A417FEC00D58C36 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/KMKeyboardHelpWindowController.strings; sourceTree = "<group>"; };
CEFFECDC2A417FEC00D58C36 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/MainMenu.strings; sourceTree = "<group>"; };
CEFFECDD2A4180FD00D58C36 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
D861B03D2C5747F70003675E /* KMSettingsRepository.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMSettingsRepository.h; sourceTree = "<group>"; };
D861B03E2C5747F70003675E /* KMSettingsRepository.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = KMSettingsRepository.m; sourceTree = "<group>"; tabWidth = 2; };
E211769B20E1826800F8065D /* NoContextTestClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NoContextTestClient.h; sourceTree = "<group>"; };
E211769C20E182DD00F8065D /* NoContextTestClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NoContextTestClient.m; sourceTree = "<group>"; };
E211769E20E18C0B00F8065D /* AppleCompliantTestClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleCompliantTestClient.h; sourceTree = "<group>"; };
@ -548,6 +551,8 @@
29B4A0D32BF7675A00682049 /* KMLogs.m */,
299ABD6F29ECE75B00AA5948 /* KeySender.m */,
299ABD7029ECE75B00AA5948 /* KeySender.h */,
D861B03D2C5747F70003675E /* KMSettingsRepository.h */,
D861B03E2C5747F70003675E /* KMSettingsRepository.m */,
297A501128DF4D360074EB1B /* Privacy */,
98FE105B1B4DE86300525F54 /* Categories */,
98D6DA791A799EE700B09822 /* Frameworks */,
@ -974,6 +979,7 @@
29B4A0D52BF7675A00682049 /* KMLogs.m in Sources */,
98BF924F1BF02DC20002126A /* KMBarView.m in Sources */,
E240F599202DED740000067D /* KMPackage.m in Sources */,
D861B03F2C5747F70003675E /* KMSettingsRepository.m in Sources */,
984B8F441AF1C3D900E096A8 /* OSKWindowController.m in Sources */,
9836B3711AE5F11D00780482 /* mztools.c in Sources */,
9836B3701AE5F11D00780482 /* ioapi.c in Sources */,

View file

@ -16,6 +16,7 @@
// 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 "KMConfigurationWindowController.h"
#import "KMDownloadKBWindowController.h"
#import "ZipArchive.h"
@ -509,7 +510,9 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
if(_keymanDataPath == nil) {
NSString *documentDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
_keymanDataPath = [documentDirPath stringByAppendingPathComponent:@"Keyman-Keyboards"];
os_log_debug([KMLogs dataLog], "creating keymanDataPath, %{public}@", _keymanDataPath);
NSFileManager *fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:_keymanDataPath]) {
[fm createDirectoryAtPath:_keymanDataPath withIntermediateDirectories:YES attributes:nil error:nil];
@ -531,6 +534,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
}
- (NSArray *)kmxFileList {
os_log_debug([KMLogs dataLog], "kmxFileList");
if (_kmxFileList == nil) {
NSArray *kmxFiles = [self KMXFiles];
_kmxFileList = [[NSMutableArray alloc] initWithCapacity:0];
@ -650,6 +654,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]) {
NSDictionary * infoDict = [KMXFile keyboardInfoFromKmxFile:kmxFile];
@ -756,6 +761,12 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
}
- (void)awakeFromNib {
if ([KMSettingsRepository.shared keyboardsMigrationNeeded]) {
os_log_info([KMLogs startupLog], "keyboards migration needed");
} else {
os_log_info([KMLogs startupLog], "keyboards migration not needed");
}
[self setDefaultKeymanMenuItems];
[self updateKeyboardMenuItems];
}
@ -928,13 +939,16 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
}
- (NSArray *)KMXFilesAtPath:(NSString *)path {
os_log_debug([KMLogs dataLog], "Reading KMXFiles at path %{public}@", path);
NSDirectoryEnumerator *dirEnum = [[NSFileManager defaultManager] enumeratorAtPath:path];
NSMutableArray *kmxFiles = [[NSMutableArray alloc] initWithCapacity:0];
NSString *filePath;
while (filePath = (NSString *)[dirEnum nextObject]) {
NSString *extension = [[filePath pathExtension] lowercaseString];
if ([extension isEqualToString:@"kmx"])
if ([extension isEqualToString:@"kmx"]) {
[kmxFiles addObject:[path stringByAppendingPathComponent:filePath]];
os_log_debug([KMLogs dataLog], "file = %{public}@", filePath);
}
}
return kmxFiles;

View file

@ -10,6 +10,7 @@
#import <Carbon/Carbon.h> /* For kVK_ constants. */
#import "KeySender.h"
#import "TextApiCompliance.h"
#import "KMSettingsRepository.h"
#import "KMLogs.h"
@import Sentry;
@ -238,6 +239,17 @@ NSString* const kEasterEggKmxName = @"EnglishSpanish.kmx";
// return NO to pass through to client app
return NO;
}
// TODO: remove test code
/*
if (event.keyCode == kVK_ANSI_Slash) {
if ([KMSettingsRepository.shared keyboardsMigrationNeeded]) {
os_log_info([KMLogs startupLog], "keyboards migration needed");
} else {
os_log_info([KMLogs startupLog], "keyboards migration not needed");
}
}
*/
}
if (event.type == NSEventTypeFlagsChanged) {
@ -412,11 +424,11 @@ NSString* const kEasterEggKmxName = @"EnglishSpanish.kmx";
for(NSString *key in options) {
NSString *value = [options objectForKey:key];
if(key && value) {
os_log_debug([KMLogs keyLog], "applyNonTextualOutput calling writePersistedOptions, key: %{public}@, value: %{public}@", key, value);
os_log_debug([KMLogs keyLog], "persistOptions, key: %{public}@, value: %{public}@", key, value);
[self.appDelegate writePersistedOptions:key withValue:value];
}
else {
os_log_debug([KMLogs keyLog], "applyNonTextualOutput, invalid values in optionsToPersist, not writing to UserDefaults, key: %{public}@, value: %{public}@", key, value);
os_log_debug([KMLogs keyLog], "invalid values in persistOptions, not writing to UserDefaults, key: %{public}@, value: %{public}@", key, value);
}
}
}

View file

@ -0,0 +1,20 @@
/**
* Keyman is copyright (C) SIL International. MIT License.
*
* KMSettingsRepository.h
* Keyman
*
* Created by Shawn Schantz on 2024-07-29.
*
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface KMSettingsRepository : NSObject
+ (KMSettingsRepository *)shared;
- (BOOL)keyboardsMigrationNeeded;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,57 @@
/**
* Keyman is copyright (C) SIL International. MIT License.
*
* KMSettingsRepository.h
* Keyman
*
* Created by Shawn Schantz on 2024-07-29.
*
* Singleton object for reading and writing Keyman application settings.
* Serves as an abstraction to StandardUserDefaults which is currently used to persist application settings.
*/
#import "KMSettingsRepository.h"
#import "KMLogs.h"
NSString *const kStoreKeyboardsInLibraryKey = @"KMStoreKeyboardsInLibraryKey";
NSString *const kActiveKeyboardsKey = @"KMActiveKeyboardsKey";
@implementation KMSettingsRepository
+ (KMSettingsRepository *)shared
{
static KMSettingsRepository *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[KMSettingsRepository alloc] init];
});
return shared;
}
- (BOOL)settingsExist
{
return [[NSUserDefaults standardUserDefaults] objectForKey:kActiveKeyboardsKey] != nil;
}
- (BOOL)keyboardsStoredInLibraryFolder
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kStoreKeyboardsInLibraryKey];
}
/**
* Determines whether the keyboards data needs to be moved from the old location in the Documents folder to the new location under /username/Library...
* This is true if
* 1) the UserDefaults exist (indicating that this is not a new installation of Keyman) and
* 2) the value for KMStoreKeyboardsInLibraryKey is not set to true
*/
- (BOOL)keyboardsMigrationNeeded {
BOOL keyboardSettingsExist = [self settingsExist];
os_log([KMLogs startupLog], " keyboard settings exist: %@", keyboardSettingsExist ? @"YES" : @"NO" );
BOOL keyboardsInLibrary = [self keyboardsStoredInLibraryFolder];
os_log([KMLogs startupLog], " keyboards stored in Library: %@", keyboardsInLibrary ? @"YES" : @"NO" );
return !(keyboardSettingsExist && keyboardsInLibrary);
}
@end