1
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#import "KBKeyboardSubscriptionView.h"
|
||||
#import "KBLocalizationManager.h"
|
||||
#import "KBSkinManager.h"
|
||||
#import "KBSkinInstallBridge.h"
|
||||
#import "KBSuggestionEngine.h"
|
||||
#import "KBKeyboardLayoutResolver.h"
|
||||
#import <SDWebImage/SDWebImage.h>
|
||||
@@ -254,10 +255,9 @@ static NSString *KBFormatMB(uint64_t bytes) {
|
||||
- (void)kb_checkAndApplyLayoutIfNeeded {
|
||||
NSString *currentProfileId = [[KBKeyboardLayoutResolver sharedResolver] currentProfileId];
|
||||
if (currentProfileId.length == 0) {
|
||||
currentProfileId = @"en_US_qwerty"; // 默认回退
|
||||
currentProfileId = @"en_US_qwerty";
|
||||
}
|
||||
|
||||
// 如果 profileId 没有变化,不需要重新加载
|
||||
if ([currentProfileId isEqualToString:_kb_lastLoadedProfileId]) {
|
||||
return;
|
||||
}
|
||||
@@ -265,16 +265,20 @@ static NSString *KBFormatMB(uint64_t bytes) {
|
||||
NSLog(@"[KeyboardViewController] Detected profileId change: %@ -> %@", _kb_lastLoadedProfileId, currentProfileId);
|
||||
_kb_lastLoadedProfileId = currentProfileId;
|
||||
|
||||
// 通知 KBKeyBoardMainView 切换布局
|
||||
if (self.keyBoardMainView && [self.keyBoardMainView respondsToSelector:@selector(reloadLayoutWithProfileId:)]) {
|
||||
[self.keyBoardMainView performSelector:@selector(reloadLayoutWithProfileId:) withObject:currentProfileId];
|
||||
}
|
||||
|
||||
// 更新联想引擎类型
|
||||
NSString *suggestionEngine = [[KBKeyboardLayoutResolver sharedResolver] suggestionEngineForProfileId:currentProfileId];
|
||||
if (suggestionEngine.length > 0) {
|
||||
[self kb_updateSuggestionEngineType:suggestionEngine];
|
||||
}
|
||||
|
||||
NSString *languageCode = [[KBKeyboardLayoutResolver sharedResolver] currentLanguageCode];
|
||||
if (languageCode.length > 0) {
|
||||
NSLog(@"[KeyboardViewController] Reloading skin icon map for language: %@", languageCode);
|
||||
[KBSkinInstallBridge reloadCurrentSkinIconMapForLanguageCode:languageCode];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)kb_updateSuggestionEngineType:(NSString *)engineType {
|
||||
|
||||
@@ -97,9 +97,11 @@
|
||||
"letter_l_upper" = "key_l_up";
|
||||
|
||||
/* 字母 ñ(小写)- 西班牙语专用 */
|
||||
"letter_ñ_lower" = "key_n_tilde";
|
||||
"letter_ñ_lower" = "key_ñ";
|
||||
/* 字母 Ñ(大写)- 西班牙语专用 */
|
||||
"letter_ñ_upper" = "key_n_tilde_up";
|
||||
"letter_ñ_upper" = "key_ñ_up";
|
||||
/* 字母 ñ(基础映射) */
|
||||
"letter_ñ" = "key_ñ";
|
||||
|
||||
/* 字母 z(小写) */
|
||||
"letter_z_lower" = "key_z";
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
@{
|
||||
@"code": @"es",
|
||||
@"name": @"Español",
|
||||
@"defaultSkinZip": @"",
|
||||
@"defaultSkinZip": @"西班牙初始皮肤.zip",
|
||||
@"layouts": @[
|
||||
@{@"variant": @"qwerty", @"title": @"QWERTY", @"profileId": @"es_ES_qwerty", @"layoutJsonId": @"letters", @"suggestionEngine": @"latin"},
|
||||
@{@"variant": @"azerty", @"title": @"AZERTY", @"profileId": @"es_ES_azerty", @"layoutJsonId": @"letters_azerty", @"suggestionEngine": @"latin"},
|
||||
|
||||
@@ -89,6 +89,11 @@ typedef void (^KBSkinInstallConsumeCompletion)(BOOL success, NSError * _Nullable
|
||||
+ (BOOL)applyInstalledSkinWithId:(NSString *)skinId
|
||||
error:(NSError * _Nullable __autoreleasing *)error;
|
||||
|
||||
/// 重新应用当前皮肤的图标映射(用于语言切换时更新图标)。
|
||||
/// @param languageCode 新的语言代码
|
||||
/// @return 是否成功重新应用
|
||||
+ (BOOL)reloadCurrentSkinIconMapForLanguageCode:(NSString *)languageCode;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -947,4 +947,88 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
return applyOK;
|
||||
}
|
||||
|
||||
+ (BOOL)reloadCurrentSkinIconMapForLanguageCode:(NSString *)languageCode {
|
||||
if (languageCode.length == 0) {
|
||||
NSLog(@"[SkinBridge] reloadCurrentSkinIconMap: empty language code");
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *targetSkinId = [NSString stringWithFormat:@"bundle_skin_default_%@", languageCode];
|
||||
NSString *currentSkinId = [KBSkinManager shared].current.skinId ?: @"";
|
||||
|
||||
NSLog(@"[SkinBridge] reloadCurrentSkinIconMap: currentSkin=%@ targetSkin=%@ lang=%@",
|
||||
currentSkinId, targetSkinId, languageCode);
|
||||
|
||||
if ([targetSkinId isEqualToString:currentSkinId]) {
|
||||
NSLog(@"[SkinBridge] reloadCurrentSkinIconMap: already on target skin, just refresh icon map");
|
||||
} else {
|
||||
BOOL hasTargetSkin = [KBSkinManager kb_hasAssetsForSkinId:targetSkinId];
|
||||
NSLog(@"[SkinBridge] reloadCurrentSkinIconMap: hasTargetSkin=%d", hasTargetSkin);
|
||||
|
||||
if (hasTargetSkin) {
|
||||
NSError *applyError = nil;
|
||||
BOOL applied = [self applyInstalledSkinWithId:targetSkinId error:&applyError];
|
||||
NSLog(@"[SkinBridge] reloadCurrentSkinIconMap: switched to %@ applied=%d error=%@",
|
||||
targetSkinId, applied, applyError);
|
||||
return applied;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentSkinId.length == 0 || [currentSkinId isEqualToString:@"default"]) {
|
||||
NSLog(@"[SkinBridge] reloadCurrentSkinIconMap: no custom skin applied, skip");
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSDictionary<NSString *, NSString *> *iconShortNames = [self iconShortNamesForLanguageCode:languageCode];
|
||||
if (iconShortNames.count == 0) {
|
||||
NSLog(@"[SkinBridge] reloadCurrentSkinIconMap: no icon mapping found for language: %@", languageCode);
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSString *skinRoot = [[self kb_skinsRootPath] stringByAppendingPathComponent:currentSkinId];
|
||||
NSString *iconsDir = [skinRoot stringByAppendingPathComponent:@"icons"];
|
||||
|
||||
NSMutableDictionary<NSString *, NSString *> *iconPathMap = [NSMutableDictionary dictionary];
|
||||
[iconShortNames enumerateKeysAndObjectsUsingBlock:^(NSString *identifier, NSString *shortName, BOOL *stop) {
|
||||
if (![shortName isKindOfClass:NSString.class] || shortName.length == 0) return;
|
||||
NSString *fileName = shortName;
|
||||
if (fileName.pathExtension.length == 0) {
|
||||
fileName = [fileName stringByAppendingPathExtension:@"png"];
|
||||
}
|
||||
NSString *fullPath = [iconsDir stringByAppendingPathComponent:fileName];
|
||||
if ([fm fileExistsAtPath:fullPath]) {
|
||||
NSString *relative = [NSString stringWithFormat:@"Skins/%@/icons/%@", currentSkinId, fileName];
|
||||
iconPathMap[identifier] = relative;
|
||||
}
|
||||
}];
|
||||
|
||||
NSLog(@"[SkinBridge] reloadCurrentSkinIconMap: skin=%@ lang=%@ iconCount=%lu",
|
||||
currentSkinId, languageCode, (unsigned long)iconPathMap.count);
|
||||
|
||||
if (iconPathMap.count == 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSDictionary *meta = [self kb_metadataForSkinId:currentSkinId];
|
||||
NSMutableDictionary *themeJSON = [NSMutableDictionary dictionary];
|
||||
themeJSON[@"id"] = currentSkinId;
|
||||
NSString *name = [meta[kKBSkinMetadataNameKey] isKindOfClass:NSString.class] ? meta[kKBSkinMetadataNameKey] : currentSkinId;
|
||||
themeJSON[@"name"] = name;
|
||||
if (iconPathMap.count > 0) {
|
||||
themeJSON[@"key_icons"] = iconPathMap.copy;
|
||||
}
|
||||
|
||||
NSString *bgPath = [skinRoot stringByAppendingPathComponent:@"background.png"];
|
||||
NSData *bgData = [NSData dataWithContentsOfFile:bgPath];
|
||||
|
||||
BOOL themeOK = [[KBSkinManager shared] applyThemeFromJSON:themeJSON];
|
||||
if (bgData.length > 0) {
|
||||
[[KBSkinManager shared] applyImageSkinWithData:bgData skinId:currentSkinId name:name];
|
||||
}
|
||||
|
||||
NSLog(@"[SkinBridge] reloadCurrentSkinIconMap: applied themeOK=%d", themeOK);
|
||||
return themeOK;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -77,6 +77,9 @@ extern NSString * const KBDarwinSkinChanged; // cross-process
|
||||
/// Parse a hex color string like "#RRGGBB"/"#RRGGBBAA"
|
||||
+ (UIColor *)colorFromHexString:(NSString *)hex defaultColor:(UIColor *)fallback;
|
||||
|
||||
/// 判断指定 skinId 是否有可用资源目录
|
||||
+ (BOOL)kb_hasAssetsForSkinId:(NSString *)skinId;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -387,6 +387,20 @@ static void KBSkinDarwinCallback(CFNotificationCenterRef center, void *observer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 调试日志:打印未找到映射的按键 ID
|
||||
if (value.length == 0 && identifier.length > 0) {
|
||||
static NSMutableSet<NSString *> *kb_loggedMissingIds = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
kb_loggedMissingIds = [NSMutableSet set];
|
||||
});
|
||||
if (![kb_loggedMissingIds containsObject:identifier]) {
|
||||
[kb_loggedMissingIds addObject:identifier];
|
||||
NSLog(@"[SkinManager] ⚠️ Missing icon mapping: id='%@' skin='%@' mapCount=%lu",
|
||||
identifier, self.current.skinId ?: @"default", (unsigned long)map.count);
|
||||
}
|
||||
}
|
||||
|
||||
// 若在 keyIconMap 中找到了 value,按约定加载
|
||||
if (value.length > 0) {
|
||||
|
||||
@@ -13,22 +13,21 @@
|
||||
"layoutJsonId": "letters",
|
||||
"suggestionEngine": "latin"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "es",
|
||||
"name": "Español (Latinoamérica)",
|
||||
"defaultSkinZip": "",
|
||||
"layouts": [
|
||||
{
|
||||
"variant": "qwerty",
|
||||
"title": "QWERTY",
|
||||
"profileId": "es_419_qwerty",
|
||||
"layoutJsonId": "letters_es",
|
||||
"suggestionEngine": "spanish"
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
{
|
||||
"code": "es",
|
||||
"name": "Español (Latinoamérica)",
|
||||
"defaultSkinZip": "西班牙初始皮肤.zip",
|
||||
"layouts": [
|
||||
{
|
||||
"variant": "qwerty",
|
||||
"title": "QWERTY",
|
||||
"profileId": "es_419_qwerty",
|
||||
"layoutJsonId": "letters_es",
|
||||
"suggestionEngine": "spanish"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "pt",
|
||||
"name": "Português",
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
043213B02F556DF80065C888 /* KBSkinIconMap_id.strings in Resources */ = {isa = PBXBuildFile; fileRef = 043213AC2F556DF80065C888 /* KBSkinIconMap_id.strings */; };
|
||||
043213B12F556DF80065C888 /* KBSkinIconMap_es.strings in Resources */ = {isa = PBXBuildFile; fileRef = 043213AB2F556DF80065C888 /* KBSkinIconMap_es.strings */; };
|
||||
043213B22F556DF80065C888 /* KBSkinIconMap_zh_hant.strings in Resources */ = {isa = PBXBuildFile; fileRef = 043213AE2F556DF80065C888 /* KBSkinIconMap_zh_hant.strings */; };
|
||||
043213B42F557CC50065C888 /* 西班牙初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213B32F557CC50065C888 /* 西班牙初始皮肤.zip */; };
|
||||
043213B62F5582710065C888 /* spanish_words.json in Resources */ = {isa = PBXBuildFile; fileRef = 043213B52F5582710065C888 /* spanish_words.json */; };
|
||||
043213B82F558BC20065C888 /* 西班牙初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213B72F558BC20065C888 /* 西班牙初始皮肤.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 */; };
|
||||
@@ -402,8 +402,8 @@
|
||||
043213AC2F556DF80065C888 /* KBSkinIconMap_id.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = KBSkinIconMap_id.strings; sourceTree = "<group>"; };
|
||||
043213AD2F556DF80065C888 /* KBSkinIconMap_pt.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = KBSkinIconMap_pt.strings; sourceTree = "<group>"; };
|
||||
043213AE2F556DF80065C888 /* KBSkinIconMap_zh_hant.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = KBSkinIconMap_zh_hant.strings; sourceTree = "<group>"; };
|
||||
043213B32F557CC50065C888 /* 西班牙初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "西班牙初始皮肤.zip"; sourceTree = "<group>"; };
|
||||
043213B52F5582710065C888 /* spanish_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = spanish_words.json; sourceTree = "<group>"; };
|
||||
043213B72F558BC20065C888 /* 西班牙初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "西班牙初始皮肤.zip"; sourceTree = "<group>"; };
|
||||
0450AA722EF013D000B6AF06 /* KBEmojiCollectionCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBEmojiCollectionCell.h; sourceTree = "<group>"; };
|
||||
0450AA732EF013D000B6AF06 /* KBEmojiCollectionCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBEmojiCollectionCell.m; sourceTree = "<group>"; };
|
||||
0450AAE02EF03D5100B6AF06 /* keyBoard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "keyBoard-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
@@ -1298,7 +1298,7 @@
|
||||
047C652C2EBCAAAC0035E841 /* Resource */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
043213B32F557CC50065C888 /* 西班牙初始皮肤.zip */,
|
||||
043213B72F558BC20065C888 /* 西班牙初始皮肤.zip */,
|
||||
0479200A2ED87CEE004E8522 /* permiss_video.mp4 */,
|
||||
047920102ED98E7D004E8522 /* permiss_video_2.mp4 */,
|
||||
047920062ED86ABC004E8522 /* kb_guide_keyboard.gif */,
|
||||
@@ -1613,11 +1613,11 @@
|
||||
04E2277C2F516EBD001A8F14 /* PrivacyInfo.xcprivacy */,
|
||||
04FC95F52EB33B52007BD342 /* keyBoard.entitlements */,
|
||||
04FC95BF2EB1E3B1007BD342 /* Class */,
|
||||
04C6EAE32EAF942E0089C901 /* VC */,
|
||||
04C6EAAC2EAF86530089C901 /* AppDelegate.h */,
|
||||
04C6EAAD2EAF86530089C901 /* AppDelegate.m */,
|
||||
04C6EAAE2EAF86530089C901 /* Assets.xcassets */,
|
||||
04C6EAAF2EAF86530089C901 /* Info.plist */,
|
||||
04C6EAE32EAF942E0089C901 /* VC */,
|
||||
04C6EAB12EAF86530089C901 /* LaunchScreen.storyboard */,
|
||||
04C6EAB22EAF86530089C901 /* main.m */,
|
||||
04C6EAB42EAF86530089C901 /* Main.storyboard */,
|
||||
@@ -2336,7 +2336,7 @@
|
||||
04C6EABC2EAF86530089C901 /* LaunchScreen.storyboard in Resources */,
|
||||
04E0394F2F236E75002CA5A0 /* KBChatTableView_Usage.md in Resources */,
|
||||
04286A132ECDEBF900CE730C /* KBSkinIconMap.strings in Resources */,
|
||||
043213B42F557CC50065C888 /* 西班牙初始皮肤.zip in Resources */,
|
||||
043213B82F558BC20065C888 /* 西班牙初始皮肤.zip in Resources */,
|
||||
04C6EABD2EAF86530089C901 /* Main.storyboard in Resources */,
|
||||
046086CB2F1A092500757C95 /* comments_mock.json in Resources */,
|
||||
04E038E32F20E500002CA5A0 /* deepgramAPI.md in Resources */,
|
||||
|
||||
@@ -647,10 +647,13 @@ typedef void(^KBInputProfileSelectHandler)(NSString *languageCode, NSString *lay
|
||||
}
|
||||
|
||||
NSString *skinId = [NSString stringWithFormat:@"bundle_skin_default_%@", languageCode];
|
||||
NSDictionary<NSString *, NSString *> *iconShortNames = [KBSkinInstallBridge iconShortNamesForLanguageCode:languageCode];
|
||||
NSLog(@"[KBPersonInfoVC] Installing skin %@ with %lu icon mappings for language %@", skinId, (unsigned long)iconShortNames.count, languageCode);
|
||||
|
||||
[KBSkinInstallBridge publishBundleSkinRequestWithId:skinId
|
||||
name:skinId
|
||||
zipName:zipName
|
||||
iconShortNames:nil];
|
||||
iconShortNames:iconShortNames];
|
||||
[KBSkinInstallBridge consumePendingRequestFromBundle:NSBundle.mainBundle
|
||||
completion:^(BOOL success, NSError * _Nullable error) {
|
||||
if (!success && error) {
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user