From 07c9282f8b02bf8c3be37e7c5875e4605e295b9c Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Mon, 28 Mar 2022 22:33:17 +0800 Subject: [PATCH] mgrLM // Allow specifying user data folder, etc. mgrLM // +checkIfSpecifiedUserDataFolderValid. mgrLM // Allow dataFolderPath to be specified, etc. - Also add a parameter to dataFolderPath in case that only the default value is requested. mgrLM // Avoid implicit Enum conversion. mgrLM // Auto-remove invalid userDataPath preferences. mgrLM // Ensure stringByExpandingTildeInPath. --- .../Modules/LangModelRelated/mgrLangModel.h | 4 +- .../Modules/LangModelRelated/mgrLangModel.mm | 40 ++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/Source/Modules/LangModelRelated/mgrLangModel.h b/Source/Modules/LangModelRelated/mgrLangModel.h index eba1d6b3..0a3d3332 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel.h +++ b/Source/Modules/LangModelRelated/mgrLangModel.h @@ -30,6 +30,8 @@ NS_ASSUME_NONNULL_BEGIN + (void)loadUserPhraseReplacement; + (BOOL)checkIfUserLanguageModelFilesExist; + (BOOL)checkIfUserDataFolderExists; ++ (BOOL)checkIfSpecifiedUserDataFolderValid:(NSString *)folderPath; ++ (NSString *)dataFolderPath:(bool)isDefaultFolder NS_SWIFT_NAME(dataFolderPath(isDefaultFolder:)); + (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase inputMode:(InputMode)mode key:(NSString *)key NS_SWIFT_NAME(checkIfUserPhraseExist(userPhrase:mode:key:)); + (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode areWeDuplicating:(BOOL)areWeDuplicating areWeDeleting:(BOOL)areWeDeleting; @@ -44,8 +46,6 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *)excludedPhrasesDataPath:(InputMode)mode; + (NSString *)phraseReplacementDataPath:(InputMode)mode; -@property (class, readonly, nonatomic) NSString *dataFolderPath; - @end /// The following methods are merely for testing. diff --git a/Source/Modules/LangModelRelated/mgrLangModel.mm b/Source/Modules/LangModelRelated/mgrLangModel.mm index c98a740a..9d5e411d 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel.mm +++ b/Source/Modules/LangModelRelated/mgrLangModel.mm @@ -136,7 +136,7 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing + (BOOL)checkIfUserDataFolderExists { - NSString *folderPath = [self dataFolderPath]; + NSString *folderPath = [self dataFolderPath:false]; BOOL isFolder = NO; BOOL folderExist = [[NSFileManager defaultManager] fileExistsAtPath:folderPath isDirectory:&isFolder]; if (folderExist && !isFolder) { @@ -159,6 +159,16 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing return YES; } ++ (BOOL)checkIfSpecifiedUserDataFolderValid:(NSString *)folderPath +{ + BOOL isFolder = NO; + BOOL folderExist = [[NSFileManager defaultManager] fileExistsAtPath:folderPath isDirectory:&isFolder]; + if ((folderExist && !isFolder) || (!folderExist)) { + return NO; + } + return YES; +} + + (BOOL)ensureFileExists:(NSString *)filePath populateWithTemplate:(NSString *)templateBasename extension:(NSString *)ext { if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) { @@ -250,42 +260,52 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing return YES; } -+ (NSString *)dataFolderPath ++ (NSString *)dataFolderPath:(bool)isDefaultFolder { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDirectory, YES); - NSString *appSupportPath = paths[0]; - NSString *userDictPath = [appSupportPath stringByAppendingPathComponent:@"vChewing"]; + // 此處不能用「~」來取代當前使用者目錄名稱。不然的話,一旦輸入法被系統的沙箱干預的話,則反而會定位到沙箱目錄內。 + NSString *appSupportPath = [NSFileManager.defaultManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask][0].path; + NSString *userDictPath = [appSupportPath stringByAppendingPathComponent:@"vChewing"].stringByExpandingTildeInPath; + if (mgrPrefs.userDataFolderSpecified.stringByExpandingTildeInPath == userDictPath || isDefaultFolder) { + return userDictPath; + } + if ([mgrPrefs ifSpecifiedUserDataPathExistsInPlist]) { + if ([self checkIfSpecifiedUserDataFolderValid:mgrPrefs.userDataFolderSpecified.stringByExpandingTildeInPath]) { + return mgrPrefs.userDataFolderSpecified.stringByExpandingTildeInPath; + } else { + [NSUserDefaults.standardUserDefaults removeObjectForKey:@"UserDataFolderSpecified"]; + } + } return userDictPath; } + (NSString *)userPhrasesDataPath:(InputMode)mode; { NSString *fileName = [mode isEqualToString:imeModeCHT] ? @"userdata-cht.txt" : @"userdata-chs.txt"; - return [[self dataFolderPath] stringByAppendingPathComponent:fileName]; + return [[self dataFolderPath:false] stringByAppendingPathComponent:fileName]; } + (NSString *)userSymbolDataPath:(InputMode)mode; { NSString *fileName = [mode isEqualToString:imeModeCHT] ? @"usersymbolphrases-cht.txt" : @"usersymbolphrases-chs.txt"; - return [[self dataFolderPath] stringByAppendingPathComponent:fileName]; + return [[self dataFolderPath:false] stringByAppendingPathComponent:fileName]; } + (NSString *)userAssociatedPhrasesDataPath:(InputMode)mode; { NSString *fileName = [mode isEqualToString:imeModeCHT] ? @"associatedPhrases-cht.txt" : @"associatedPhrases-chs.txt"; - return [[self dataFolderPath] stringByAppendingPathComponent:fileName]; + return [[self dataFolderPath:false] stringByAppendingPathComponent:fileName]; } + (NSString *)excludedPhrasesDataPath:(InputMode)mode; { NSString *fileName = [mode isEqualToString:imeModeCHT] ? @"exclude-phrases-cht.txt" : @"exclude-phrases-chs.txt"; - return [[self dataFolderPath] stringByAppendingPathComponent:fileName]; + return [[self dataFolderPath:false] stringByAppendingPathComponent:fileName]; } + (NSString *)phraseReplacementDataPath:(InputMode)mode; { NSString *fileName = [mode isEqualToString:imeModeCHT] ? @"phrases-replacement-cht.txt" : @"phrases-replacement-chs.txt"; - return [[self dataFolderPath] stringByAppendingPathComponent:fileName]; + return [[self dataFolderPath:false] stringByAppendingPathComponent:fileName]; } + (vChewing::LMInstantiator *)lmCHT