1
This commit is contained in:
@@ -5,12 +5,12 @@
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "切图 270@2x.png",
|
||||
"filename" : "切图 271@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "切图 270@3x.png",
|
||||
"filename" : "切图 271@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_key_icon.imageset/切图 271@2x.png
vendored
Normal file
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_key_icon.imageset/切图 271@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_key_icon.imageset/切图 271@3x.png
vendored
Normal file
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_key_icon.imageset/切图 271@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
@@ -22,6 +22,7 @@
|
||||
#import "KBBackspaceUndoManager.h"
|
||||
#import "KBInputBufferManager.h"
|
||||
#import "KBSuggestionEngine.h"
|
||||
//#import "KBLog.h"
|
||||
|
||||
// 提前声明一个类别,使编译器在 static 回调中识别 kb_consumePendingShopSkin 方法。
|
||||
@interface KeyboardViewController (KBSkinShopBridge)
|
||||
@@ -729,6 +730,7 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
KBSkinTheme *t = [KBSkinManager shared].current;
|
||||
UIImage *img = [[KBSkinManager shared] currentBackgroundImage];
|
||||
NSLog(@"⌨️[Keyboard] apply theme id=%@ hasBg=%d", t.skinId, (img != nil));
|
||||
[self kb_logSkinDiagnosticsWithTheme:t backgroundImage:img];
|
||||
self.bgImageView.image = img;
|
||||
BOOL hasImg = (img != nil);
|
||||
self.view.backgroundColor = hasImg ? [UIColor clearColor] : t.keyboardBackground;
|
||||
@@ -750,6 +752,46 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
}
|
||||
}
|
||||
|
||||
- (void)kb_logSkinDiagnosticsWithTheme:(KBSkinTheme *)theme
|
||||
backgroundImage:(UIImage *)image {
|
||||
#if DEBUG
|
||||
NSString *skinId = theme.skinId ?: @"";
|
||||
NSString *name = theme.name ?: @"";
|
||||
NSMutableArray<NSString *> *roots = [NSMutableArray array];
|
||||
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:AppGroup];
|
||||
if (containerURL.path.length > 0) {
|
||||
[roots addObject:containerURL.path];
|
||||
}
|
||||
NSString *cacheRoot = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
|
||||
if (cacheRoot.length > 0) {
|
||||
[roots addObject:cacheRoot];
|
||||
}
|
||||
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSMutableArray<NSString *> *lines = [NSMutableArray array];
|
||||
for (NSString *root in roots) {
|
||||
NSString *iconsDir = [[root stringByAppendingPathComponent:@"Skins"]
|
||||
stringByAppendingPathComponent:skinId];
|
||||
iconsDir = [iconsDir stringByAppendingPathComponent:@"icons"];
|
||||
BOOL isDir = NO;
|
||||
BOOL exists = [fm fileExistsAtPath:iconsDir isDirectory:&isDir] && isDir;
|
||||
NSArray *contents = exists ? [fm contentsOfDirectoryAtPath:iconsDir error:nil] : nil;
|
||||
NSUInteger count = contents.count;
|
||||
BOOL hasQ = exists && [fm fileExistsAtPath:[iconsDir stringByAppendingPathComponent:@"key_q.png"]];
|
||||
BOOL hasQUp = exists && [fm fileExistsAtPath:[iconsDir stringByAppendingPathComponent:@"key_q_up.png"]];
|
||||
BOOL hasDel = exists && [fm fileExistsAtPath:[iconsDir stringByAppendingPathComponent:@"key_del.png"]];
|
||||
BOOL hasShift = exists && [fm fileExistsAtPath:[iconsDir stringByAppendingPathComponent:@"key_up.png"]];
|
||||
BOOL hasShiftUpper = exists && [fm fileExistsAtPath:[iconsDir stringByAppendingPathComponent:@"key_up_upper.png"]];
|
||||
NSString *line = [NSString stringWithFormat:@"root=%@ icons=%@ exist=%d count=%tu key_q=%d key_q_up=%d key_del=%d key_up=%d key_up_upper=%d",
|
||||
root, iconsDir, exists, count, hasQ, hasQUp, hasDel, hasShift, hasShiftUpper];
|
||||
[lines addObject:line];
|
||||
}
|
||||
|
||||
NSLog(@"[Keyboard] theme id=%@ name=%@ hasBg=%d\n%@",
|
||||
skinId, name, (image != nil), [lines componentsJoinedByString:@"\n"]);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)kb_consumePendingShopSkin {
|
||||
KBWeakSelf
|
||||
[KBSkinInstallBridge consumePendingRequestFromBundle:NSBundle.mainBundle
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
/* 字母 g(小写) */
|
||||
"letter_g_lower" = "key_g";
|
||||
/* 字母 G(大写) */
|
||||
"letter_g_upper" = "key_f_up";
|
||||
"letter_g_upper" = "key_g_up";
|
||||
|
||||
/* 字母 h(小写) */
|
||||
"letter_h_lower" = "key_h";
|
||||
@@ -246,4 +246,3 @@
|
||||
"emoji_panel" = "key_emoji";
|
||||
/* 发送/换行键 */
|
||||
"return" = "key_send";
|
||||
|
||||
|
||||
Binary file not shown.
@@ -845,7 +845,6 @@ edgeSpacerMultiplier:(CGFloat)edgeSpacerMultiplier {
|
||||
}
|
||||
|
||||
[btn applyThemeForCurrentKey];
|
||||
[self kb_applySymbolIfNeededForButton:btn keyDef:def fontSize:fontSize];
|
||||
[btn addTarget:self action:@selector(onKeyTapped:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
if (key.type == KBKeyTypeBackspace) {
|
||||
@@ -854,6 +853,7 @@ edgeSpacerMultiplier:(CGFloat)edgeSpacerMultiplier {
|
||||
if (key.type == KBKeyTypeShift) {
|
||||
btn.selected = self.shiftOn;
|
||||
}
|
||||
[self kb_applySymbolIfNeededForButton:btn keyDef:def fontSize:fontSize];
|
||||
return btn;
|
||||
}
|
||||
|
||||
@@ -1052,7 +1052,11 @@ edgeSpacerMultiplier:(CGFloat)edgeSpacerMultiplier {
|
||||
}
|
||||
|
||||
KBKey *k = [KBKey keyWithIdentifier:finalId title:title output:output type:type];
|
||||
k.caseVariant = KBKeyCaseVariantNone;
|
||||
if (type == KBKeyTypeShift) {
|
||||
k.caseVariant = self.shiftOn ? KBKeyCaseVariantUpper : KBKeyCaseVariantLower;
|
||||
} else {
|
||||
k.caseVariant = KBKeyCaseVariantNone;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
@@ -226,6 +226,12 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
if ([forceValue respondsToSelector:@selector(boolValue)]) {
|
||||
forceDownload = [forceValue boolValue];
|
||||
}
|
||||
id serverIcons = skinJSON[@"key_icons"];
|
||||
NSUInteger serverIconCount = [serverIcons isKindOfClass:NSDictionary.class] ? ((NSDictionary *)serverIcons).count : 0;
|
||||
NSLog(@"[SkinBridge] request id=%@ zip=%@ force=%d key_icons_class=%@ count=%tu",
|
||||
skinId, zipURL, forceDownload,
|
||||
serverIcons ? NSStringFromClass([serverIcons class]) : @"nil",
|
||||
serverIconCount);
|
||||
|
||||
// key_icons 可选:
|
||||
// - 若后端提供 key_icons,则优先使用服务端映射;
|
||||
@@ -236,6 +242,9 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
} else {
|
||||
iconShortNames = [self defaultIconShortNames];
|
||||
}
|
||||
NSLog(@"[SkinBridge] iconShortNames source=%@ count=%tu",
|
||||
[skinJSON[@"key_icons"] isKindOfClass:NSDictionary.class] ? @"server" : @"default",
|
||||
iconShortNames.count);
|
||||
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSURL *containerURL = [fm containerURLForSecurityApplicationGroupIdentifier:AppGroup];
|
||||
@@ -262,6 +271,7 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
NSArray *contents = hasIconsDir ? [fm contentsOfDirectoryAtPath:iconsDir error:NULL] : nil;
|
||||
// 标记在本次请求发起前是否已经有缓存资源(用于“有缓存但本次下载失败”时仍允许切换皮肤)。
|
||||
BOOL hasCachedAssets = (contents.count > 0);
|
||||
NSLog(@"[SkinBridge] assets cache id=%@ cached=%d iconsDir=%@", skinId, hasCachedAssets, iconsDir);
|
||||
|
||||
NSString *bgPath = [skinRoot stringByAppendingPathComponent:@"background.png"];
|
||||
BOOL useTempRoot = forceDownload;
|
||||
@@ -482,6 +492,8 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
// 若既没有预先存在的缓存资源,也没有在本次流程中成功解压出资源,
|
||||
// 说明当前皮肤 B 的资源完全不可用,此时不应覆盖现有皮肤主题。
|
||||
BOOL hasAssets = (didUnzip || (!forceDownload && hasCachedAssets));
|
||||
NSLog(@"[SkinBridge] apply check id=%@ hasAssets=%d didUnzip=%d cached=%d",
|
||||
skinId, hasAssets, didUnzip, hasCachedAssets);
|
||||
if (!hasAssets) {
|
||||
NSError *finalError = innerError ?: [NSError errorWithDomain:KBSkinBridgeErrorDomain
|
||||
code:KBSkinBridgeErrorZipMissing
|
||||
@@ -491,7 +503,9 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
return;
|
||||
}
|
||||
|
||||
// 构造 key_icons -> App Group 相对路径 映射
|
||||
// 构造 key_icons -> App Group 相对路径 映射(仅保留实际存在的图标)
|
||||
NSString *iconsDirFinal = [skinRoot stringByAppendingPathComponent:@"icons"];
|
||||
__block NSUInteger missingCount = 0;
|
||||
NSMutableDictionary<NSString *, NSString *> *iconPathMap = [NSMutableDictionary dictionary];
|
||||
[iconShortNames enumerateKeysAndObjectsUsingBlock:^(NSString *identifier, NSString *shortName, BOOL *stop) {
|
||||
if (![shortName isKindOfClass:NSString.class] || shortName.length == 0) return;
|
||||
@@ -500,9 +514,27 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
if (fileName.pathExtension.length == 0) {
|
||||
fileName = [fileName stringByAppendingPathExtension:@"png"];
|
||||
}
|
||||
NSString *fullPath = [iconsDirFinal stringByAppendingPathComponent:fileName];
|
||||
if (![fm fileExistsAtPath:fullPath]) {
|
||||
missingCount += 1;
|
||||
if (missingCount <= 5) {
|
||||
NSLog(@"[SkinBridge] icon missing id=%@ short=%@", identifier, fileName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
NSString *relative = [NSString stringWithFormat:@"Skins/%@/icons/%@", skinId, fileName];
|
||||
iconPathMap[identifier] = relative;
|
||||
}];
|
||||
if (missingCount > 0) {
|
||||
NSLog(@"[SkinBridge] icon missing count=%tu total=%tu", missingCount, iconShortNames.count);
|
||||
}
|
||||
NSLog(@"[SkinBridge] iconPathMap count=%tu shift=%@ shift_upper=%@ backspace=%@ mode_123=%@ return=%@",
|
||||
iconPathMap.count,
|
||||
iconPathMap[@"shift"],
|
||||
iconPathMap[@"shift_upper"],
|
||||
iconPathMap[@"backspace"],
|
||||
iconPathMap[@"mode_123"],
|
||||
iconPathMap[@"return"]);
|
||||
|
||||
NSMutableDictionary *themeJSON = [skinJSON mutableCopy];
|
||||
themeJSON[@"id"] = skinId;
|
||||
@@ -515,6 +547,8 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
// 背景图优先从 Zip 解压出的 background.png 读取
|
||||
NSData *bgData = [NSData dataWithContentsOfFile:bgPath];
|
||||
BOOL ok = themeOK;
|
||||
NSLog(@"[SkinBridge] theme apply id=%@ themeOK=%d bg=%d",
|
||||
skinId, themeOK, (bgData.length > 0));
|
||||
if (bgData.length > 0) {
|
||||
ok = [[KBSkinManager shared] applyImageSkinWithData:bgData skinId:skinId name:name];
|
||||
}
|
||||
@@ -748,6 +782,8 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
shortNames = [self defaultIconShortNames];
|
||||
}
|
||||
|
||||
NSString *iconsDirFinal = iconsDir;
|
||||
__block NSUInteger missingCount = 0;
|
||||
NSMutableDictionary<NSString *, NSString *> *iconPathMap = [NSMutableDictionary dictionary];
|
||||
[shortNames enumerateKeysAndObjectsUsingBlock:^(NSString *identifier, NSString *shortName, BOOL *stop) {
|
||||
if (identifier.length == 0 || ![shortName isKindOfClass:NSString.class] || shortName.length == 0) return;
|
||||
@@ -755,9 +791,20 @@ static NSString * const kKBSkinMetadataThemeKey = @"theme_json";
|
||||
if (fileName.pathExtension.length == 0) {
|
||||
fileName = [fileName stringByAppendingPathExtension:@"png"];
|
||||
}
|
||||
NSString *fullPath = [iconsDirFinal stringByAppendingPathComponent:fileName];
|
||||
if (![fm fileExistsAtPath:fullPath]) {
|
||||
missingCount += 1;
|
||||
if (missingCount <= 5) {
|
||||
NSLog(@"[SkinBridge] icon missing(bundle) id=%@ short=%@", identifier, fileName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
NSString *relative = [NSString stringWithFormat:@"Skins/%@/icons/%@", skinId, fileName];
|
||||
iconPathMap[identifier] = relative;
|
||||
}];
|
||||
if (missingCount > 0) {
|
||||
NSLog(@"[SkinBridge] icon missing(bundle) count=%tu total=%tu", missingCount, shortNames.count);
|
||||
}
|
||||
|
||||
NSMutableDictionary *themeJSON = [NSMutableDictionary dictionary];
|
||||
themeJSON[@"id"] = skinId;
|
||||
|
||||
@@ -152,6 +152,18 @@ static void KBSkinDarwinCallback(CFNotificationCenterRef center, void *observer,
|
||||
if ([icons isKindOfClass:NSDictionary.class]) {
|
||||
t.keyIconMap = icons;
|
||||
}
|
||||
NSUInteger iconCount = [t.keyIconMap isKindOfClass:NSDictionary.class] ? t.keyIconMap.count : 0;
|
||||
NSUInteger hiddenCount = t.hiddenKeyTextIdentifiers.count;
|
||||
NSLog(@"[SkinManager] applyThemeFromJSON id=%@ name=%@ iconMap=%tu hiddenKeys=%tu",
|
||||
t.skinId, t.name, iconCount, hiddenCount);
|
||||
if (iconCount > 0) {
|
||||
NSLog(@"[SkinManager] iconMap sample shift=%@ shift_upper=%@ backspace=%@ mode_123=%@ return=%@",
|
||||
t.keyIconMap[@"shift"],
|
||||
t.keyIconMap[@"shift_upper"],
|
||||
t.keyIconMap[@"backspace"],
|
||||
t.keyIconMap[@"mode_123"],
|
||||
t.keyIconMap[@"return"]);
|
||||
}
|
||||
return [self applyTheme:t];
|
||||
}
|
||||
|
||||
@@ -249,6 +261,19 @@ static void KBSkinDarwinCallback(CFNotificationCenterRef center, void *observer,
|
||||
}
|
||||
|
||||
- (UIImage *)iconImageForKeyIdentifier:(NSString *)identifier caseVariant:(NSInteger)caseVariant {
|
||||
#if DEBUG
|
||||
static NSSet<NSString *> *kb_debugIconIds;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
kb_debugIconIds = [NSSet setWithObjects:
|
||||
@"shift", @"backspace", @"mode_123", @"mode_abc",
|
||||
@"symbols_toggle_more", @"symbols_toggle_123",
|
||||
@"return", @"space", @"emoji_panel", @"letter_q",
|
||||
nil];
|
||||
});
|
||||
BOOL shouldLog = [kb_debugIconIds containsObject:identifier];
|
||||
#endif
|
||||
|
||||
NSDictionary<NSString *, NSString *> *map = self.current.keyIconMap;
|
||||
NSString *value = nil;
|
||||
|
||||
@@ -292,10 +317,23 @@ static void KBSkinDarwinCallback(CFNotificationCenterRef center, void *observer,
|
||||
UIImage *img = [UIImage imageWithContentsOfFile:fullPath];
|
||||
if (img) return img;
|
||||
}
|
||||
#if DEBUG
|
||||
if (shouldLog) {
|
||||
NSLog(@"[SkinManager] icon file missing id=%@ value=%@ skin=%@",
|
||||
identifier, value, self.current.skinId ?: @"");
|
||||
}
|
||||
#endif
|
||||
return nil;
|
||||
}
|
||||
// 否则按本地 Assets 名称加载(兼容旧实现)
|
||||
return [UIImage imageNamed:value];
|
||||
UIImage *img = [UIImage imageNamed:value];
|
||||
#if DEBUG
|
||||
if (!img && shouldLog) {
|
||||
NSLog(@"[SkinManager] icon asset missing id=%@ value=%@ skin=%@",
|
||||
identifier, value, self.current.skinId ?: @"");
|
||||
}
|
||||
#endif
|
||||
return img;
|
||||
}
|
||||
|
||||
// 兜底:若 keyIconMap 中没有该键,则按照约定的命名规则直接从 App Group 读取:
|
||||
@@ -329,6 +367,12 @@ static void KBSkinDarwinCallback(CFNotificationCenterRef center, void *observer,
|
||||
if (img) return img;
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
if (shouldLog) {
|
||||
NSLog(@"[SkinManager] icon fallback missing id=%@ variant=%ld skin=%@",
|
||||
identifier, (long)caseVariant, self.current.skinId ?: @"");
|
||||
}
|
||||
#endif
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
04286A062ECC81B200CE730C /* KBSkinService.m in Sources */ = {isa = PBXBuildFile; fileRef = 04286A052ECC81B200CE730C /* KBSkinService.m */; };
|
||||
04286A0B2ECD88B400CE730C /* KeyboardAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 04286A0A2ECD88B400CE730C /* KeyboardAssets.xcassets */; };
|
||||
04286A0F2ECDA71B00CE730C /* 001.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04286A0E2ECDA71B00CE730C /* 001.zip */; };
|
||||
04286A132ECDEBF900CE730C /* KBSkinIconMap.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04286A122ECDEBF900CE730C /* KBSkinIconMap.strings */; };
|
||||
04286A132ECDEBF900CE730C /* KBSkinIconMap.strings in Resources */ = {isa = PBXBuildFile; fileRef = 041007D12ECE012000D203BB /* KBSkinIconMap.strings */; };
|
||||
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 */; };
|
||||
@@ -172,7 +172,7 @@
|
||||
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C6EADC2EAF8CEB0089C901 /* KBToolBar.m */; };
|
||||
04D1F6B22EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 04D1F6B12EDFF10A00B12345 /* KBSkinInstallBridge.m */; };
|
||||
04D1F6B32EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 04D1F6B12EDFF10A00B12345 /* KBSkinInstallBridge.m */; };
|
||||
04E161782F0FA7BD0022C23B /* normal_them.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04E161772F0FA7BD0022C23B /* normal_them.zip */; };
|
||||
04E1617A2F0FB1320022C23B /* normal_them.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04E161792F0FB1320022C23B /* normal_them.zip */; };
|
||||
04FC95672EB0546C007BD342 /* KBKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95652EB0546C007BD342 /* KBKey.m */; };
|
||||
04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95692EB05497007BD342 /* KBKeyButton.m */; };
|
||||
04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */; };
|
||||
@@ -299,7 +299,6 @@
|
||||
04286A052ECC81B200CE730C /* KBSkinService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinService.m; sourceTree = "<group>"; };
|
||||
04286A0A2ECD88B400CE730C /* KeyboardAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = KeyboardAssets.xcassets; sourceTree = "<group>"; };
|
||||
04286A0E2ECDA71B00CE730C /* 001.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = 001.zip; sourceTree = "<group>"; };
|
||||
04286A122ECDEBF900CE730C /* KBSkinIconMap.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = KBSkinIconMap.strings; 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>"; };
|
||||
@@ -541,7 +540,7 @@
|
||||
04C6EAE12EAF940F0089C901 /* KBPermissionViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPermissionViewController.m; sourceTree = "<group>"; };
|
||||
04D1F6B02EDFF10A00B12345 /* KBSkinInstallBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinInstallBridge.h; sourceTree = "<group>"; };
|
||||
04D1F6B12EDFF10A00B12345 /* KBSkinInstallBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinInstallBridge.m; sourceTree = "<group>"; };
|
||||
04E161772F0FA7BD0022C23B /* normal_them.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = normal_them.zip; sourceTree = "<group>"; };
|
||||
04E161792F0FB1320022C23B /* normal_them.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = normal_them.zip; sourceTree = "<group>"; };
|
||||
04FC953A2EAFAE56007BD342 /* KeyBoardPrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyBoardPrefixHeader.pch; sourceTree = "<group>"; };
|
||||
04FC95642EB0546C007BD342 /* KBKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKey.h; sourceTree = "<group>"; };
|
||||
04FC95652EB0546C007BD342 /* KBKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKey.m; sourceTree = "<group>"; };
|
||||
@@ -692,7 +691,7 @@
|
||||
041007D02ECE010100D203BB /* Resource */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
04E161772F0FA7BD0022C23B /* normal_them.zip */,
|
||||
04E161792F0FB1320022C23B /* normal_them.zip */,
|
||||
A1B2C3EC2F20000000000001 /* kb_words.txt */,
|
||||
A1B2C3F02F20000000000002 /* kb_keyboard_layout_config.json */,
|
||||
0498BDF42EEC50EE006CC1D5 /* emoji_categories.json */,
|
||||
@@ -899,7 +898,6 @@
|
||||
0479200A2ED87CEE004E8522 /* permiss_video.mp4 */,
|
||||
047920102ED98E7D004E8522 /* permiss_video_2.mp4 */,
|
||||
047920062ED86ABC004E8522 /* kb_guide_keyboard.gif */,
|
||||
04286A122ECDEBF900CE730C /* KBSkinIconMap.strings */,
|
||||
04286A0E2ECDA71B00CE730C /* 001.zip */,
|
||||
);
|
||||
path = Resource;
|
||||
@@ -1828,7 +1826,7 @@
|
||||
files = (
|
||||
04A9FE202EB893F10020DB6D /* Localizable.strings in Resources */,
|
||||
041007D42ECE012500D203BB /* 002.zip in Resources */,
|
||||
04E161782F0FA7BD0022C23B /* normal_them.zip in Resources */,
|
||||
04E1617A2F0FB1320022C23B /* normal_them.zip in Resources */,
|
||||
041007D22ECE012000D203BB /* KBSkinIconMap.strings in Resources */,
|
||||
A1B2C3ED2F20000000000001 /* kb_words.txt in Resources */,
|
||||
A1B2C3F12F20000000000002 /* kb_keyboard_layout_config.json in Resources */,
|
||||
|
||||
@@ -47,6 +47,15 @@
|
||||
if ([forceValue respondsToSelector:@selector(boolValue)]) {
|
||||
forceDownload = [forceValue boolValue];
|
||||
}
|
||||
id keyIcons = skinJSON[@"key_icons"];
|
||||
NSUInteger iconCount = [keyIcons isKindOfClass:NSDictionary.class] ? ((NSDictionary *)keyIcons).count : 0;
|
||||
KBLOG(@"[SkinService] apply mode=%lu id=%@ zip=%@ force=%d key_icons=%@ count=%tu",
|
||||
(unsigned long)mode,
|
||||
skinJSON[@"id"],
|
||||
skinJSON[@"zip_url"],
|
||||
forceDownload,
|
||||
keyIcons ? NSStringFromClass([keyIcons class]) : @"nil",
|
||||
iconCount);
|
||||
NSLog(@"🧩[SkinService] apply mode=%lu id=%@ force=%d",
|
||||
(unsigned long)mode, skinJSON[@"id"], forceDownload);
|
||||
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
/* 字母 q(小写) */
|
||||
"letter_q_lower" = "key_q";
|
||||
/* 字母 Q(大写) */
|
||||
"letter_q_upper" = "key_q";
|
||||
|
||||
/* 字母 w(小写) */
|
||||
"letter_w_lower" = "key_w";
|
||||
/* 字母 W(大写) */
|
||||
"letter_w_upper" = "key_w";
|
||||
|
||||
/* 字母 e(小写) */
|
||||
"letter_e_lower" = "key_e";
|
||||
/* 字母 E(大写) */
|
||||
"letter_e_upper" = "key_e";
|
||||
|
||||
/* 字母 r(小写) */
|
||||
"letter_r_lower" = "key_r";
|
||||
/* 字母 R(大写) */
|
||||
"letter_r_upper" = "key_r";
|
||||
|
||||
/* 字母 t(小写) */
|
||||
"letter_t_lower" = "key_t";
|
||||
/* 字母 T(大写) */
|
||||
"letter_t_upper" = "key_t";
|
||||
|
||||
/* 字母 y(小写) */
|
||||
"letter_y_lower" = "key_y";
|
||||
/* 字母 Y(大写) */
|
||||
"letter_y_upper" = "key_y";
|
||||
|
||||
/* 字母 u(小写) */
|
||||
"letter_u_lower" = "key_u";
|
||||
/* 字母 U(大写) */
|
||||
"letter_u_upper" = "key_u";
|
||||
|
||||
/* 字母 i(小写) */
|
||||
"letter_i_lower" = "key_i";
|
||||
/* 字母 I(大写) */
|
||||
"letter_i_upper" = "key_i";
|
||||
|
||||
/* 字母 o(小写) */
|
||||
"letter_o_lower" = "key_o";
|
||||
/* 字母 O(大写) */
|
||||
"letter_o_upper" = "key_o";
|
||||
|
||||
/* 字母 p(小写) */
|
||||
"letter_p_lower" = "key_p";
|
||||
/* 字母 P(大写) */
|
||||
"letter_p_upper" = "key_p";
|
||||
|
||||
/* 字母 a(小写) */
|
||||
"letter_a_lower" = "key_a";
|
||||
/* 字母 A(大写) */
|
||||
"letter_a_upper" = "key_a";
|
||||
|
||||
/* 字母 s(小写) */
|
||||
"letter_s_lower" = "key_s";
|
||||
/* 字母 S(大写) */
|
||||
"letter_s_upper" = "key_s";
|
||||
|
||||
/* 字母 d(小写) */
|
||||
"letter_d_lower" = "key_d";
|
||||
/* 字母 D(大写) */
|
||||
"letter_d_upper" = "key_d";
|
||||
|
||||
/* 字母 f(小写) */
|
||||
"letter_f_lower" = "key_f";
|
||||
/* 字母 F(大写) */
|
||||
"letter_f_upper" = "key_f";
|
||||
|
||||
/* 字母 g(小写) */
|
||||
"letter_g_lower" = "key_g";
|
||||
/* 字母 G(大写) */
|
||||
"letter_g_upper" = "key_g";
|
||||
|
||||
/* 字母 h(小写) */
|
||||
"letter_h_lower" = "key_h";
|
||||
/* 字母 H(大写) */
|
||||
"letter_h_upper" = "key_h";
|
||||
|
||||
/* 字母 j(小写) */
|
||||
"letter_j_lower" = "key_j";
|
||||
/* 字母 J(大写) */
|
||||
"letter_j_upper" = "key_j";
|
||||
|
||||
/* 字母 k(小写) */
|
||||
"letter_k_lower" = "key_k";
|
||||
/* 字母 K(大写) */
|
||||
"letter_k_upper" = "key_k";
|
||||
|
||||
/* 字母 l(小写) */
|
||||
"letter_l_lower" = "key_l";
|
||||
/* 字母 L(大写) */
|
||||
"letter_l_upper" = "key_l";
|
||||
|
||||
/* 字母 z(小写) */
|
||||
"letter_z_lower" = "key_z";
|
||||
/* 字母 Z(大写) */
|
||||
"letter_z_upper" = "key_z";
|
||||
|
||||
/* 字母 x(小写) */
|
||||
"letter_x_lower" = "key_x";
|
||||
/* 字母 X(大写) */
|
||||
"letter_x_upper" = "key_x";
|
||||
|
||||
/* 字母 c(小写) */
|
||||
"letter_c_lower" = "key_c";
|
||||
/* 字母 C(大写) */
|
||||
"letter_c_upper" = "key_c";
|
||||
|
||||
/* 字母 v(小写) */
|
||||
"letter_v_lower" = "key_v";
|
||||
/* 字母 V(大写) */
|
||||
"letter_v_upper" = "key_v";
|
||||
|
||||
/* 字母 b(小写) */
|
||||
"letter_b_lower" = "key_b";
|
||||
/* 字母 B(大写) */
|
||||
"letter_b_upper" = "key_b";
|
||||
|
||||
/* 字母 n(小写) */
|
||||
"letter_n_lower" = "key_n";
|
||||
/* 字母 N(大写) */
|
||||
"letter_n_upper" = "key_n";
|
||||
|
||||
/* 字母 m(小写) */
|
||||
"letter_m_lower" = "key_m";
|
||||
/* 字母 M(大写) */
|
||||
"letter_m_upper" = "key_m";
|
||||
|
||||
/* 数字 1 */
|
||||
"digit_1" = "key_1";
|
||||
/* 数字 2 */
|
||||
"digit_2" = "key_2";
|
||||
/* 数字 3 */
|
||||
"digit_3" = "key_3";
|
||||
/* 数字 4 */
|
||||
"digit_4" = "key_4";
|
||||
/* 数字 5 */
|
||||
"digit_5" = "key_5";
|
||||
/* 数字 6 */
|
||||
"digit_6" = "key_6";
|
||||
/* 数字 7 */
|
||||
"digit_7" = "key_7";
|
||||
/* 数字 8 */
|
||||
"digit_8" = "key_8";
|
||||
/* 数字 9 */
|
||||
"digit_9" = "key_9";
|
||||
/* 数字 0 */
|
||||
"digit_0" = "key_0";
|
||||
|
||||
/* '-' */
|
||||
"sym_minus" = "key_minus";
|
||||
/* '/' */
|
||||
"sym_slash" = "key_slash";
|
||||
/* ':' */
|
||||
"sym_colon" = "key_colon";
|
||||
/* ';' */
|
||||
"sym_semicolon" = "key_semicolon";
|
||||
/* '(' */
|
||||
"sym_paren_l" = "key_paren_l";
|
||||
/* ')' */
|
||||
"sym_paren_r" = "key_paren_r";
|
||||
/* '$' */
|
||||
"sym_dollar" = "key_dollar";
|
||||
/* '&' */
|
||||
"sym_amp" = "key_amp";
|
||||
/* '@' */
|
||||
"sym_at" = "key_at";
|
||||
/* 双引号 " */
|
||||
"sym_quote_double" = "key_quote_d";
|
||||
|
||||
/* ',' */
|
||||
"sym_comma" = "key_comma";
|
||||
/* '.' */
|
||||
"sym_dot" = "key_dot";
|
||||
/* '?' */
|
||||
"sym_question" = "key_question";
|
||||
/* '!' */
|
||||
"sym_exclam" = "key_exclam";
|
||||
/* 单引号 ' */
|
||||
"sym_quote_single" = "key_quote";
|
||||
|
||||
/* '[' */
|
||||
"sym_bracket_l" = "key_bracket_l";
|
||||
/* ']' */
|
||||
"sym_bracket_r" = "key_bracket_r";
|
||||
/* '{' */
|
||||
"sym_brace_l" = "key_brace_l";
|
||||
/* '}' */
|
||||
"sym_brace_r" = "key_brace_r";
|
||||
/* '#' */
|
||||
"sym_hash" = "key_hash";
|
||||
/* '%' */
|
||||
"sym_percent" = "key_percent";
|
||||
/* '^' */
|
||||
"sym_caret" = "key_caret";
|
||||
/* '*' */
|
||||
"sym_asterisk" = "key_asterisk";
|
||||
/* '+' */
|
||||
"sym_plus" = "key_plus";
|
||||
/* '=' */
|
||||
"sym_equal" = "key_equal";
|
||||
|
||||
/* '_' */
|
||||
"sym_underscore" = "key_underscore";
|
||||
/* '\' */
|
||||
"sym_backslash" = "key_backslash";
|
||||
/* '|' */
|
||||
"sym_pipe" = "key_pipe";
|
||||
/* '~' */
|
||||
"sym_tilde" = "key_tilde";
|
||||
/* '<' */
|
||||
"sym_lt" = "key_lt";
|
||||
/* '>' */
|
||||
"sym_gt" = "key_gt";
|
||||
/* '¥' */
|
||||
"sym_money" = "key_money";
|
||||
/* '€' */
|
||||
"sym_euro" = "key_euro";
|
||||
/* '£' */
|
||||
"sym_pound" = "key_pound";
|
||||
/* '•' */
|
||||
"sym_bullet" = "key_bullet";
|
||||
|
||||
/* 空格键 */
|
||||
"space" = "key_space";
|
||||
/* 删除键(⌫) */
|
||||
"backspace" = "key_del";
|
||||
/* Shift(⇧) */
|
||||
"shift" = "key_up";
|
||||
/* 字母面板左下角 "123" */
|
||||
"mode_123" = "key_123";
|
||||
/* 数字面板左下角 "abc" */
|
||||
"mode_abc" = "key_abc";
|
||||
/* 数字面板内 "123 -> #+=" */
|
||||
"symbols_toggle_more" = "key_symbols_more";
|
||||
/* 数字面板内 "#+= -> 123" */
|
||||
"symbols_toggle_123" = "key_symbols_123";
|
||||
/* 自定义 AI 功能键 */
|
||||
"ai" = "key_ai";
|
||||
//"emoji" = "key_emoji";
|
||||
"emoji_panel" = "key_emoji";
|
||||
|
||||
/* 发送/换行键 */
|
||||
"return" = "key_send";
|
||||
|
||||
Reference in New Issue
Block a user