2025-11-20 14:27:57 +08:00
|
|
|
|
//
|
|
|
|
|
|
// KBSkinInstallBridge.h
|
|
|
|
|
|
// 主 App 与键盘扩展共享的皮肤安装桥接工具。
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
|
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
|
|
|
|
|
|
|
/// 跨进程通知:主 App 请求键盘扩展安装皮肤。
|
|
|
|
|
|
extern NSString * const KBDarwinSkinInstallRequestNotification;
|
|
|
|
|
|
|
2025-11-25 18:54:53 +08:00
|
|
|
|
/// 皮肤安装桥接错误域。
|
|
|
|
|
|
extern NSErrorDomain const KBSkinBridgeErrorDomain;
|
|
|
|
|
|
|
|
|
|
|
|
/// 皮肤安装桥接错误码。
|
|
|
|
|
|
typedef NS_ENUM(NSUInteger, KBSkinBridgeErrorCode) {
|
|
|
|
|
|
KBSkinBridgeErrorInvalidPayload = 1,
|
|
|
|
|
|
KBSkinBridgeErrorContainerUnavailable,
|
|
|
|
|
|
KBSkinBridgeErrorZipMissing,
|
|
|
|
|
|
KBSkinBridgeErrorUnzipFailed,
|
|
|
|
|
|
KBSkinBridgeErrorApplyFailed,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-11-20 14:27:57 +08:00
|
|
|
|
typedef void (^KBSkinInstallConsumeCompletion)(BOOL success, NSError * _Nullable error);
|
|
|
|
|
|
|
2025-12-11 19:43:55 +08:00
|
|
|
|
/// 已安装的皮肤记录,用于“我的皮肤”列表展示。
|
|
|
|
|
|
@interface KBSkinDownloadRecord : NSObject
|
|
|
|
|
|
@property (nonatomic, copy) NSString *skinId;
|
|
|
|
|
|
@property (nonatomic, copy) NSString *name;
|
|
|
|
|
|
@property (nonatomic, copy, nullable) NSString *previewImage;
|
|
|
|
|
|
@property (nonatomic, copy, nullable) NSString *zipURL;
|
|
|
|
|
|
@property (nonatomic, assign) NSTimeInterval installedAt;
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
2025-11-20 14:27:57 +08:00
|
|
|
|
@interface KBSkinInstallBridge : NSObject
|
|
|
|
|
|
|
|
|
|
|
|
/// 默认图标短文件名映射(从 KBSkinIconMap.strings 读取)。
|
|
|
|
|
|
+ (NSDictionary<NSString *, NSString *> *)defaultIconShortNames;
|
|
|
|
|
|
|
2025-11-25 18:54:53 +08:00
|
|
|
|
/// 主 App / 键盘扩展:通过远程 zip_url 下载并安装一套皮肤。
|
|
|
|
|
|
/// - skinJSON 结构与后端约定一致,至少包含:
|
|
|
|
|
|
/// * id: 皮肤唯一标识
|
|
|
|
|
|
/// * name: 展示名称(可选,缺省为 id)
|
|
|
|
|
|
/// * zip_url: 远程 Zip 地址(http/https)
|
|
|
|
|
|
/// * key_icons: 按键 -> 图标“短文件名”映射(可选,不传则使用 defaultIconShortNames)
|
|
|
|
|
|
/// - 内部会将 Zip 解压到 App Group/Skins/<id>/...,并使用 KBSkinManager 应用主题与背景图。
|
|
|
|
|
|
/// - 应用成功后,KBSkinManager 会广播皮肤变更通知,键盘扩展可立即感知。
|
|
|
|
|
|
+ (void)installRemoteSkinWithJSON:(NSDictionary *)skinJSON
|
|
|
|
|
|
completion:(nullable KBSkinInstallConsumeCompletion)completion;
|
|
|
|
|
|
|
2025-11-20 14:27:57 +08:00
|
|
|
|
/// 主 App 侧:记录一个“从 bundle 解压皮肤”的请求,写入 App Group 并广播 Darwin 通知。
|
|
|
|
|
|
+ (void)publishBundleSkinRequestWithId:(NSString *)skinId
|
|
|
|
|
|
name:(NSString *)name
|
|
|
|
|
|
zipName:(NSString *)zipName
|
|
|
|
|
|
iconShortNames:(nullable NSDictionary<NSString *, NSString *> *)iconShortNames;
|
|
|
|
|
|
|
|
|
|
|
|
/// 读取当前 App Group 中待处理的请求。
|
|
|
|
|
|
+ (nullable NSDictionary *)pendingRequestPayload;
|
|
|
|
|
|
|
|
|
|
|
|
/// 清理 App Group 中的请求记录。
|
|
|
|
|
|
+ (void)clearPendingRequest;
|
|
|
|
|
|
|
|
|
|
|
|
/// 键盘扩展侧:如有请求则解压/应用皮肤。completion 中 success==YES 表示已处理并应用。
|
|
|
|
|
|
+ (void)consumePendingRequestFromBundle:(NSBundle *)bundle
|
|
|
|
|
|
completion:(nullable KBSkinInstallConsumeCompletion)completion;
|
|
|
|
|
|
|
2025-12-11 19:43:55 +08:00
|
|
|
|
/// 枚举当前 App Group 中所有已解压的皮肤信息。
|
|
|
|
|
|
+ (NSArray<KBSkinDownloadRecord *> *)installedSkinRecords;
|
|
|
|
|
|
|
|
|
|
|
|
/// 删除指定皮肤的本地资源目录(用于“我的皮肤 - 删除”)。
|
|
|
|
|
|
+ (BOOL)removeInstalledSkinWithId:(NSString *)skinId
|
|
|
|
|
|
error:(NSError * _Nullable __autoreleasing *)error;
|
|
|
|
|
|
|
|
|
|
|
|
/// 记录皮肤元数据(下载完成后调用,方便“我的皮肤”读取)。
|
|
|
|
|
|
+ (void)recordInstalledSkinWithId:(NSString *)skinId
|
|
|
|
|
|
name:(NSString *)name
|
|
|
|
|
|
preview:(nullable NSString *)preview
|
|
|
|
|
|
zipURL:(nullable NSString *)zipURL;
|
|
|
|
|
|
|
2025-11-20 14:27:57 +08:00
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_END
|