添加皮肤
This commit is contained in:
@@ -339,16 +339,18 @@
|
||||
|
||||
#if __has_include(<SSZipArchive/SSZipArchive.h>)
|
||||
// 若本地尚未缓存该皮肤资源且提供了 zip_url,则下载并解压 Zip 包。
|
||||
// 支持两种来源:
|
||||
// 1) 线上 URL(http/https):通过 KBNetworkManager 下载;
|
||||
// 2) 本地测试:zip_url 以 "bundle://" 前缀开头,例如 "bundle://001.zip"。
|
||||
if (!hasCachedAssets && zipURL.length > 0) {
|
||||
dispatch_group_enter(group);
|
||||
[[KBNetworkManager shared] GET:zipURL parameters:nil headers:nil completion:^(id jsonOrData, NSURLResponse *response, NSError *error) {
|
||||
NSData *data = ([jsonOrData isKindOfClass:NSData.class] ? (NSData *)jsonOrData : nil);
|
||||
if (error || data.length == 0) {
|
||||
|
||||
void (^handleZipData)(NSData *) = ^(NSData *data) {
|
||||
if (data.length == 0) {
|
||||
zipOK = NO;
|
||||
dispatch_group_leave(group);
|
||||
return;
|
||||
}
|
||||
|
||||
// 将 Zip 写入临时路径再解压
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:skinRoot
|
||||
withIntermediateDirectories:YES
|
||||
@@ -370,9 +372,81 @@
|
||||
[fm removeItemAtPath:zipPath error:nil];
|
||||
if (!ok || unzipError) {
|
||||
zipOK = NO;
|
||||
dispatch_group_leave(group);
|
||||
return;
|
||||
}
|
||||
|
||||
// 兼容“额外包一层目录”的压缩结构:
|
||||
// 若 Skins/<skinId>/icons 为空,但存在 Skins/<skinId>/<子目录>/icons,
|
||||
// 则将实际 icons 与 background.png 上移到预期位置。
|
||||
BOOL isDir2 = NO;
|
||||
NSArray *iconsContent = [fm contentsOfDirectoryAtPath:iconsDir error:NULL];
|
||||
BOOL iconsValid = ([fm fileExistsAtPath:iconsDir isDirectory:&isDir2] && isDir2 && iconsContent.count > 0);
|
||||
if (!iconsValid) {
|
||||
NSArray<NSString *> *subItems = [fm contentsOfDirectoryAtPath:skinRoot error:NULL];
|
||||
for (NSString *name in subItems) {
|
||||
if ([name isEqualToString:@"icons"] || [name isEqualToString:@"__MACOSX"]) continue;
|
||||
NSString *nestedRoot = [skinRoot stringByAppendingPathComponent:name];
|
||||
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) {
|
||||
// 确保目标 icons 目录存在
|
||||
[fm createDirectoryAtPath:iconsDir
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:NULL];
|
||||
// 将 icons 下所有文件上移一层
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理 background.png:若在子目录下存在,则上移到 skinRoot
|
||||
NSString *nestedBg = [nestedRoot stringByAppendingPathComponent:@"background.png"];
|
||||
if ([fm fileExistsAtPath:nestedBg]) {
|
||||
[fm removeItemAtPath:bgPath error:nil];
|
||||
[fm moveItemAtPath:nestedBg toPath:bgPath error:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
dispatch_group_leave(group);
|
||||
}];
|
||||
};
|
||||
|
||||
// 本地 bundle 测试:zip_url 形如 "bundle://001.zip"
|
||||
if ([zipURL hasPrefix:@"bundle://"]) {
|
||||
NSString *name = [zipURL substringFromIndex:@"bundle://".length];
|
||||
NSString *fileName = name ?: @"";
|
||||
NSString *ext = fileName.pathExtension;
|
||||
NSString *base = fileName;
|
||||
if (ext.length == 0) {
|
||||
ext = @"zip";
|
||||
} else {
|
||||
base = [fileName stringByDeletingPathExtension];
|
||||
}
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:base ofType:ext];
|
||||
NSData *data = (path.length > 0) ? [NSData dataWithContentsOfFile:path] : nil;
|
||||
handleZipData(data);
|
||||
} else {
|
||||
// 正常远程下载
|
||||
[[KBNetworkManager shared] GET:zipURL parameters:nil headers:nil completion:^(id jsonOrData, NSURLResponse *response, NSError *error) {
|
||||
NSData *data = ([jsonOrData isKindOfClass:NSData.class] ? (NSData *)jsonOrData : nil);
|
||||
if (error || data.length == 0) {
|
||||
zipOK = NO;
|
||||
dispatch_group_leave(group);
|
||||
return;
|
||||
}
|
||||
handleZipData(data);
|
||||
}];
|
||||
}
|
||||
}
|
||||
#else
|
||||
zipOK = NO;
|
||||
|
||||
Reference in New Issue
Block a user