This commit is contained in:
2025-11-19 19:15:28 +08:00
parent 4108aed4e0
commit 0196128008
2 changed files with 14 additions and 121 deletions

View File

@@ -38,7 +38,7 @@
if (!self.iconView) {
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectZero];
//
iv.contentMode = UIViewContentModeScaleAspectFill;
iv.contentMode = UIViewContentModeScaleAspectFit;
iv.clipsToBounds = YES;
iv.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:iv];

View File

@@ -163,133 +163,26 @@
return;
}
// 1. & 访
KBKeyboardPermissionManager *perm = [KBKeyboardPermissionManager shared];
BOOL enabled = [perm isKeyboardEnabled];
KBFARecord fa = [perm lastKnownFullAccess];
BOOL hasFullAccess = (fa == KBFARecordGranted);
if (!enabled || !hasFullAccess) {
//
[perm presentPermissionIfNeededFrom:presenting];
// 访 App Group
[KBHUD showInfo:KBLocalized(@"皮肤已应用,键盘需开启“允许完全访问”后才能显示图片")];
}
// // 1. & 访
// KBKeyboardPermissionManager *perm = [KBKeyboardPermissionManager shared];
// BOOL enabled = [perm isKeyboardEnabled];
// KBFARecord fa = [perm lastKnownFullAccess];
// BOOL hasFullAccess = (fa == KBFARecordGranted);
//
// if (!enabled || !hasFullAccess) {
// //
// [perm presentPermissionIfNeededFrom:presenting];
//
// // 访 App Group
// [KBHUD showInfo:KBLocalized(@"皮肤已应用,键盘需开启“允许完全访问”后才能显示图片")];
// }
#if KB_SKIN_ICON_USE_REMOTE
[self kb_applySkinUsingRemoteIcons:skinJSON completion:completion];
#else
[self kb_applySkinUsingLocalIcons:skinJSON completion:completion];
#endif
}
#pragma mark - Internal helpers
/// key_icons value Assets App bundle App Group
- (void)kb_applySkinUsingLocalIcons:(NSDictionary *)skin completion:(KBSkinApplyCompletion)completion {
NSString *skinId = skin[@"id"] ?: @"local";
NSString *name = skin[@"name"] ?: skinId;
NSDictionary *iconNames = [skin[@"key_icons"] isKindOfClass:NSDictionary.class] ? skin[@"key_icons"] : @{};
NSMutableDictionary<NSString *, NSString *> *iconPathMap = [NSMutableDictionary dictionary];
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:AppGroup];
if (containerURL && iconNames.count > 0) {
NSString *skinsRoot = [containerURL.path stringByAppendingPathComponent:@"Skins"];
NSString *skinRoot = [skinsRoot stringByAppendingPathComponent:skinId];
NSString *iconsDir = [skinRoot stringByAppendingPathComponent:@"icons"];
[[NSFileManager defaultManager] createDirectoryAtPath:iconsDir
withIntermediateDirectories:YES
attributes:nil
error:NULL];
[iconNames enumerateKeysAndObjectsUsingBlock:^(NSString *identifier, NSString *imageName, BOOL *stop) {
if (![imageName isKindOfClass:NSString.class] || imageName.length == 0) return;
UIImage *img = [UIImage imageNamed:imageName];
if (!img) return;
NSData *data = UIImagePNGRepresentation(img);
if (data.length == 0) return;
NSString *fileName = [NSString stringWithFormat:@"%@.png", identifier];
NSString *fullPath = [iconsDir stringByAppendingPathComponent:fileName];
if ([data writeToFile:fullPath atomically:YES]) {
NSString *relative = [NSString stringWithFormat:@"Skins/%@/icons/%@", skinId, fileName];
iconPathMap[identifier] = relative;
}
}];
}
NSMutableDictionary *themeJSON = [skin mutableCopy];
if (iconPathMap.count > 0) {
themeJSON[@"key_icons"] = iconPathMap.copy; // value App Group
}
// / hidden_keys / key_icons App Group
BOOL themeOK = [[KBSkinManager shared] applyThemeFromJSON:themeJSON];
// background_image
NSString *bgURL = skin[@"background_image"] ?: @"";
if (bgURL.length == 0) {
if (completion) completion(themeOK);
if (themeOK) {
[KBHUD showInfo:KBLocalized(@"已应用皮肤(无背景图)")];
} else {
[KBHUD showInfo:KBLocalized(@"应用皮肤失败")];
}
return;
}
[[KBNetworkManager shared] GET:bgURL parameters:nil headers:nil completion:^(id jsonOrData, NSURLResponse *response, NSError *error) {
NSData *data = ([jsonOrData isKindOfClass:NSData.class] ? (NSData *)jsonOrData : nil);
// Keychain
if (data && data.length > 0) {
UIImage *img = [UIImage imageWithData:data];
if (img) {
CGFloat maxW = 1500.0;
if (img.size.width > maxW) {
CGFloat scale = maxW / img.size.width;
CGSize newSize = CGSizeMake(maxW, floor(img.size.height * scale));
UIGraphicsBeginImageContextWithOptions(newSize, YES, 1.0);
[img drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *resized = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
img = resized ?: img;
}
data = UIImageJPEGRepresentation(img, 0.85) ?: data;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
NSData *payload = data;
if (payload.length == 0) {
//
CGSize size = CGSizeMake(1200, 600);
UIGraphicsBeginImageContextWithOptions(size, YES, 1.0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
UIColor *c1 = [UIColor colorWithRed:0.76 green:0.91 blue:0.86 alpha:1];
UIColor *c2 = [UIColor colorWithRed:0.93 green:0.97 blue:0.91 alpha:1];
if ([skin[@"id"] hasPrefix:@"dark"]) {
c1 = [UIColor colorWithRed:0.1 green:0.12 blue:0.16 alpha:1];
c2 = [UIColor colorWithRed:0.22 green:0.24 blue:0.28 alpha:1];
}
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
NSArray *colors = @[(__bridge id)c1.CGColor, (__bridge id)c2.CGColor];
CGFloat locs[] = {0,1};
CGGradientRef grad = CGGradientCreateWithColors(space, (__bridge CFArrayRef)colors, locs);
CGContextDrawLinearGradient(ctx, grad, CGPointZero, CGPointMake(size.width, size.height), 0);
CGGradientRelease(grad); CGColorSpaceRelease(space);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
payload = UIImageJPEGRepresentation(img, 0.9);
}
BOOL ok = (payload.length > 0)
? [[KBSkinManager shared] applyImageSkinWithData:payload skinId:skinId name:name]
: themeOK;
if (completion) completion(ok);
[KBHUD showInfo:(ok ? KBLocalized(@"已应用,切到键盘查看") : KBLocalized(@"应用皮肤失败"))];
});
}];
}
/// Zip skinJSON zip_url
/// - Zip AppGroup/Skins/<skinId>/...
/// * icons/<shortName>.png icons/key_a.png