diff --git a/CustomKeyboard/Resource/kb_keyboard_layouts_i18n.json b/CustomKeyboard/Resource/kb_keyboard_layouts_i18n.json index 2a8ebc8..6309e3e 100644 --- a/CustomKeyboard/Resource/kb_keyboard_layouts_i18n.json +++ b/CustomKeyboard/Resource/kb_keyboard_layouts_i18n.json @@ -452,7 +452,7 @@ "insetLeft": 4, "insetRight": 4, "gap": 5, - "items": ["sym:-", "sym:/", "sym::", "sym:;", "sym:(", "sym:)", "sym:Rp", "sym:&", "sym:@", "sym:\""] + "items": ["sym:-", "sym:/", "sym::", "sym:;", "sym:(", "sym:)", "sym:¥", "sym:&", "sym:@", "sym:\""] }, { "align": "center", @@ -496,7 +496,7 @@ "insetLeft": 4, "insetRight": 4, "gap": 5, - "items": ["sym:_", "sym:\\", "sym:|", "sym:~", "sym:<", "sym:>", "sym:Rp", "sym:$", "sym:€", "sym:·"] + "items": ["sym:_", "sym:\\", "sym:|", "sym:~", "sym:<", "sym:>", "sym:$", "sym:€", "sym:£", "sym:·"] }, { "align": "center", diff --git a/Shared/KBSkinInstallBridge.m b/Shared/KBSkinInstallBridge.m index 39a7532..a44fb63 100644 --- a/Shared/KBSkinInstallBridge.m +++ b/Shared/KBSkinInstallBridge.m @@ -742,99 +742,99 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json"; NSString *skinsRoot = [baseRoot stringByAppendingPathComponent:@"Skins"]; NSString *skinRoot = [skinsRoot stringByAppendingPathComponent:skinId]; NSString *iconsDir = [skinRoot stringByAppendingPathComponent:@"icons"]; + + // 每次切换语言都强制重新解压,确保获取最新的皮肤资源 + NSLog(@"[SkinBridge] Force reinstall skin: %@", skinId); + [fm removeItemAtPath:skinRoot error:nil]; [fm createDirectoryAtPath:iconsDir withIntermediateDirectories:YES attributes:nil error:NULL]; - BOOL isDir = NO; - BOOL hasIconsDir = [fm fileExistsAtPath:iconsDir isDirectory:&isDir] && isDir; - NSArray *contents = hasIconsDir ? [fm contentsOfDirectoryAtPath:iconsDir error:NULL] : nil; - BOOL hasCachedAssets = (contents.count > 0); - NSString *bgPath = [skinRoot stringByAppendingPathComponent:@"background.png"]; + + NSString *fileName = zipName; + if ([fileName hasPrefix:@"bundle://"]) { + fileName = [fileName substringFromIndex:[@"bundle://" length]]; + } + NSString *dir = [fileName stringByDeletingLastPathComponent]; + NSString *last = fileName.lastPathComponent; + NSString *ext = last.pathExtension; + NSString *base = last; + if (ext.length == 0) { + ext = @"zip"; + } else { + base = [last stringByDeletingPathExtension]; + } - if (!hasCachedAssets) { - NSString *fileName = zipName; - if ([fileName hasPrefix:@"bundle://"]) { - fileName = [fileName substringFromIndex:[@"bundle://" length]]; - } - NSString *dir = [fileName stringByDeletingLastPathComponent]; - NSString *last = fileName.lastPathComponent; - NSString *ext = last.pathExtension; - NSString *base = last; - if (ext.length == 0) { - ext = @"zip"; - } else { - base = [last stringByDeletingPathExtension]; + NSString *zipPath = nil; + if (dir.length > 0) { + zipPath = [bundle pathForResource:base ofType:ext inDirectory:dir]; + } else { + zipPath = [bundle pathForResource:base ofType:ext]; + } + + if (zipPath.length == 0) { + if (error) { + *error = [NSError errorWithDomain:KBSkinBridgeErrorDomain + code:KBSkinBridgeErrorZipMissing + userInfo:@{NSLocalizedDescriptionKey: @"Zip resource not found"}]; } + return NO; + } - NSString *zipPath = nil; - if (dir.length > 0) { - zipPath = [bundle pathForResource:base ofType:ext inDirectory:dir]; - } else { - zipPath = [bundle pathForResource:base ofType:ext]; - } - if (zipPath.length == 0) { - if (error) { - *error = [NSError errorWithDomain:KBSkinBridgeErrorDomain - code:KBSkinBridgeErrorZipMissing - userInfo:@{NSLocalizedDescriptionKey: @"Zip resource not found"}]; - } - return NO; + NSError *unzipError = nil; + BOOL unzipOK = [SSZipArchive unzipFileAtPath:zipPath + toDestination:skinRoot + overwrite:YES + password:nil + error:&unzipError]; + if (!unzipOK || unzipError) { + if (error) { + *error = unzipError ?: [NSError errorWithDomain:KBSkinBridgeErrorDomain + code:KBSkinBridgeErrorUnzipFailed + userInfo:nil]; } + return NO; + } - NSError *unzipError = nil; - BOOL ok = [SSZipArchive unzipFileAtPath:zipPath - toDestination:skinRoot - overwrite:YES - password:nil - error:&unzipError]; - if (!ok || unzipError) { - if (error) { - *error = unzipError ?: [NSError errorWithDomain:KBSkinBridgeErrorDomain - code:KBSkinBridgeErrorUnzipFailed - userInfo:nil]; - } - return NO; - } + BOOL isDir2 = NO; + NSArray *iconsContent = [fm contentsOfDirectoryAtPath:iconsDir error:NULL]; + BOOL iconsValid = ([fm fileExistsAtPath:iconsDir isDirectory:&isDir2] && isDir2 && iconsContent.count > 0); + if (!iconsValid) { + NSArray *subItems = [fm contentsOfDirectoryAtPath:skinRoot error:NULL]; + for (NSString *subName in subItems) { + if ([subName isEqualToString:@"icons"] || [subName isEqualToString:@"__MACOSX"]) continue; + NSString *nestedRoot = [skinRoot stringByAppendingPathComponent:subName]; + BOOL isDirNested = NO; + if (![fm fileExistsAtPath:nestedRoot isDirectory:&isDirNested] || !isDirNested) continue; - BOOL isDir2 = NO; - NSArray *iconsContent = [fm contentsOfDirectoryAtPath:iconsDir error:NULL]; - BOOL iconsValid = ([fm fileExistsAtPath:iconsDir isDirectory:&isDir2] && isDir2 && iconsContent.count > 0); - if (!iconsValid) { - NSArray *subItems = [fm contentsOfDirectoryAtPath:skinRoot error:NULL]; - for (NSString *subName in subItems) { - if ([subName isEqualToString:@"icons"] || [subName isEqualToString:@"__MACOSX"]) continue; - NSString *nestedRoot = [skinRoot stringByAppendingPathComponent:subName]; - BOOL isDirNested = NO; - if (![fm fileExistsAtPath:nestedRoot isDirectory:&isDirNested] || !isDirNested) continue; - - NSString *nestedIcons = [nestedRoot stringByAppendingPathComponent:@"icons"]; - BOOL isDirNestedIcons = NO; - if ([fm fileExistsAtPath:nestedIcons isDirectory:&isDirNestedIcons] && isDirNestedIcons) { - NSArray *nestedFiles = [fm contentsOfDirectoryAtPath:nestedIcons error:NULL]; - if (nestedFiles.count > 0) { - [fm createDirectoryAtPath:iconsDir - withIntermediateDirectories:YES - attributes:nil - error:NULL]; - for (NSString *fn in nestedFiles) { - NSString *from = [nestedIcons stringByAppendingPathComponent:fn]; - NSString *to = [iconsDir stringByAppendingPathComponent:fn]; - [fm removeItemAtPath:to error:nil]; - [fm moveItemAtPath:from toPath:to error:nil]; - } + NSString *nestedIcons = [nestedRoot stringByAppendingPathComponent:@"icons"]; + BOOL isDirNestedIcons = NO; + if ([fm fileExistsAtPath:nestedIcons isDirectory:&isDirNestedIcons] && isDirNestedIcons) { + NSArray *nestedFiles = [fm contentsOfDirectoryAtPath:nestedIcons error:NULL]; + if (nestedFiles.count > 0) { + [fm createDirectoryAtPath:iconsDir + withIntermediateDirectories:YES + attributes:nil + error:NULL]; + for (NSString *fn in nestedFiles) { + NSString *from = [nestedIcons stringByAppendingPathComponent:fn]; + NSString *to = [iconsDir stringByAppendingPathComponent:fn]; + [fm removeItemAtPath:to error:nil]; + [fm moveItemAtPath:from toPath:to error:nil]; } } + } - NSString *nestedBg = [nestedRoot stringByAppendingPathComponent:@"background.png"]; - if ([fm fileExistsAtPath:nestedBg]) { - [fm removeItemAtPath:bgPath error:nil]; - [fm moveItemAtPath:nestedBg toPath:bgPath error:nil]; - } + NSString *nestedBg = [nestedRoot stringByAppendingPathComponent:@"background.png"]; + if ([fm fileExistsAtPath:nestedBg]) { + NSString *bgPath = [skinRoot stringByAppendingPathComponent:@"background.png"]; + [fm removeItemAtPath:bgPath error:nil]; + [fm moveItemAtPath:nestedBg toPath:bgPath error:nil]; } } } + NSString *bgPath = [skinRoot stringByAppendingPathComponent:@"background.png"]; NSDictionary *shortNames = payload[kKBSkinPendingIconShortKey]; if (![shortNames isKindOfClass:NSDictionary.class] || shortNames.count == 0) { NSString *currentLanguageCode = [[NSUserDefaults standardUserDefaults] diff --git a/Shared/Resource/kb_input_profiles.json b/Shared/Resource/kb_input_profiles.json index 4df0528..7005b5c 100644 --- a/Shared/Resource/kb_input_profiles.json +++ b/Shared/Resource/kb_input_profiles.json @@ -74,7 +74,7 @@ { "code": "id", "name": "Bahasa Indonesia", - "defaultSkinZip": "", + "defaultSkinZip": "印度尼西亚初始皮肤.zip", "layouts": [ { "variant": "qwerty", diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index ee1a08e..a1d654e 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 043213B62F5582710065C888 /* spanish_words.json in Resources */ = {isa = PBXBuildFile; fileRef = 043213B52F5582710065C888 /* spanish_words.json */; }; 043213BD2F56A3920065C888 /* 西班牙初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213BC2F56A3920065C888 /* 西班牙初始皮肤.zip */; }; 043213BE2F56A3920065C888 /* 葡萄牙初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213BB2F56A3920065C888 /* 葡萄牙初始皮肤.zip */; }; + 043213C02F56C9330065C888 /* 印度尼西亚初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213BF2F56C9330065C888 /* 印度尼西亚初始皮肤.zip */; }; 043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C6EAE12EAF940F0089C901 /* KBPermissionViewController.m */; }; 0450AA742EF013D000B6AF06 /* KBEmojiCollectionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0450AA732EF013D000B6AF06 /* KBEmojiCollectionCell.m */; }; 0450AAE22EF03D5100B6AF06 /* KBPerson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0450AAE12EF03D5100B6AF06 /* KBPerson.swift */; }; @@ -406,6 +407,7 @@ 043213B52F5582710065C888 /* spanish_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = spanish_words.json; sourceTree = ""; }; 043213BB2F56A3920065C888 /* 葡萄牙初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "葡萄牙初始皮肤.zip"; sourceTree = ""; }; 043213BC2F56A3920065C888 /* 西班牙初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "西班牙初始皮肤.zip"; sourceTree = ""; }; + 043213BF2F56C9330065C888 /* 印度尼西亚初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "印度尼西亚初始皮肤.zip"; sourceTree = ""; }; 0450AA722EF013D000B6AF06 /* KBEmojiCollectionCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBEmojiCollectionCell.h; sourceTree = ""; }; 0450AA732EF013D000B6AF06 /* KBEmojiCollectionCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBEmojiCollectionCell.m; sourceTree = ""; }; 0450AAE02EF03D5100B6AF06 /* keyBoard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "keyBoard-Bridging-Header.h"; sourceTree = ""; }; @@ -1307,6 +1309,7 @@ 045ED52A2F540FBE00131114 /* normal_them.zip */, 043213BB2F56A3920065C888 /* 葡萄牙初始皮肤.zip */, 043213BC2F56A3920065C888 /* 西班牙初始皮肤.zip */, + 043213BF2F56C9330065C888 /* 印度尼西亚初始皮肤.zip */, ); path = Resource; sourceTree = ""; @@ -2345,6 +2348,7 @@ 046086CB2F1A092500757C95 /* comments_mock.json in Resources */, 04E038E32F20E500002CA5A0 /* deepgramAPI.md in Resources */, 043213A92F5566EF0065C888 /* kb_input_profiles.json in Resources */, + 043213C02F56C9330065C888 /* 印度尼西亚初始皮肤.zip in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/keyBoard/Class/Resource/印度尼西亚初始皮肤.zip b/keyBoard/Class/Resource/印度尼西亚初始皮肤.zip new file mode 100644 index 0000000..6072191 Binary files /dev/null and b/keyBoard/Class/Resource/印度尼西亚初始皮肤.zip differ