Files
keyboard/Pods/LookinServer/Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.m
2025-10-28 10:18:10 +08:00

256 lines
10 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifdef SHOULD_COMPILE_LOOKIN_SERVER
//
// LKS_InbuiltAttrModificationHandler.m
// LookinServer
//
// Created by Li Kai on 2019/6/12.
// https://lookin.work
//
#import "LKS_InbuiltAttrModificationHandler.h"
#import "UIColor+LookinServer.h"
#import "LookinAttributeModification.h"
#import "LKS_AttrGroupsMaker.h"
#import "LookinDisplayItemDetail.h"
#import "LookinStaticAsyncUpdateTask.h"
#import "LookinServerDefines.h"
#import "LKS_CustomAttrGroupsMaker.h"
@implementation LKS_InbuiltAttrModificationHandler
+ (void)handleModification:(LookinAttributeModification *)modification completion:(void (^)(LookinDisplayItemDetail *data, NSError *error))completion {
if (!completion) {
NSAssert(NO, @"");
return;
}
if (!modification || ![modification isKindOfClass:[LookinAttributeModification class]]) {
completion(nil, LookinErr_Inner);
return;
}
NSObject *receiver = [NSObject lks_objectWithOid:modification.targetOid];
if (!receiver) {
completion(nil, LookinErr_ObjNotFound);
return;
}
NSMethodSignature *setterSignature = [receiver methodSignatureForSelector:modification.setterSelector];
NSInvocation *setterInvocation = [NSInvocation invocationWithMethodSignature:setterSignature];
setterInvocation.target = receiver;
setterInvocation.selector = modification.setterSelector;
if (setterSignature.numberOfArguments != 3 || ![receiver respondsToSelector:modification.setterSelector]) {
completion(nil, LookinErr_Inner);
return;
}
switch (modification.attrType) {
case LookinAttrTypeNone:
case LookinAttrTypeVoid: {
completion(nil, LookinErr_Inner);
return;
}
case LookinAttrTypeChar: {
char expectedValue = [(NSNumber *)modification.value charValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeInt:
case LookinAttrTypeEnumInt: {
int expectedValue = [(NSNumber *)modification.value intValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeShort: {
short expectedValue = [(NSNumber *)modification.value shortValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeLong:
case LookinAttrTypeEnumLong: {
long expectedValue = [(NSNumber *)modification.value longValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeLongLong: {
long long expectedValue = [(NSNumber *)modification.value longLongValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeUnsignedChar: {
unsigned char expectedValue = [(NSNumber *)modification.value unsignedCharValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeUnsignedInt: {
unsigned int expectedValue = [(NSNumber *)modification.value unsignedIntValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeUnsignedShort: {
unsigned short expectedValue = [(NSNumber *)modification.value unsignedShortValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeUnsignedLong: {
unsigned long expectedValue = [(NSNumber *)modification.value unsignedLongValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeUnsignedLongLong: {
unsigned long long expectedValue = [(NSNumber *)modification.value unsignedLongLongValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeFloat: {
float expectedValue = [(NSNumber *)modification.value floatValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeDouble: {
double expectedValue = [(NSNumber *)modification.value doubleValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeBOOL: {
BOOL expectedValue = [(NSNumber *)modification.value boolValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeSel: {
SEL expectedValue = NSSelectorFromString(modification.value);
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeClass: {
Class expectedValue = NSClassFromString(modification.value);
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeCGPoint: {
CGPoint expectedValue = [(NSValue *)modification.value CGPointValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeCGVector: {
CGVector expectedValue = [(NSValue *)modification.value CGVectorValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeCGSize: {
CGSize expectedValue = [(NSValue *)modification.value CGSizeValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeCGRect: {
CGRect expectedValue = [(NSValue *)modification.value CGRectValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeCGAffineTransform: {
CGAffineTransform expectedValue = [(NSValue *)modification.value CGAffineTransformValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeUIEdgeInsets: {
UIEdgeInsets expectedValue = [(NSValue *)modification.value UIEdgeInsetsValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeUIOffset: {
UIOffset expectedValue = [(NSValue *)modification.value UIOffsetValue];
[setterInvocation setArgument:&expectedValue atIndex:2];
break;
}
case LookinAttrTypeCustomObj:
case LookinAttrTypeNSString: {
NSObject *expectedValue = modification.value;
[setterInvocation setArgument:&expectedValue atIndex:2];
[setterInvocation retainArguments];
break;
}
case LookinAttrTypeUIColor: {
NSArray<NSNumber *> *rgba = modification.value;
UIColor *expectedValue = [UIColor lks_colorFromRGBAComponents:rgba];
[setterInvocation setArgument:&expectedValue atIndex:2];
[setterInvocation retainArguments];
break;
}
default: {
completion(nil, LookinErr_Inner);
return;
}
}
NSError *error = nil;
@try {
[setterInvocation invoke];
} @catch (NSException *exception) {
NSString *errorMsg = [NSString stringWithFormat:LKS_Localized(@"<%@: %p>: an exception was raised when invoking %@. (%@)"), NSStringFromClass(receiver.class), receiver, NSStringFromSelector(modification.setterSelector), exception.reason];
error = [NSError errorWithDomain:LookinErrorDomain code:LookinErrCode_Exception userInfo:@{NSLocalizedDescriptionKey:LKS_Localized(@"The modification may failed."), NSLocalizedRecoverySuggestionErrorKey:errorMsg}];
} @finally {
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CALayer *layer = nil;
if ([receiver isKindOfClass:[CALayer class]]) {
layer = (CALayer *)receiver;
} else if ([receiver isKindOfClass:[UIView class]]) {
layer = ((UIView *)receiver).layer;
} else {
completion(nil, LookinErr_ObjNotFound);
return;
}
// 比如试图更改 frame 时,这个改动很有可能触发用户业务的 relayout因此这时 dispatch 一下以确保拿到的 attrGroups 数据是最新的
LookinDisplayItemDetail *detail = [LookinDisplayItemDetail new];
detail.displayItemOid = modification.targetOid;
detail.attributesGroupList = [LKS_AttrGroupsMaker attrGroupsForLayer:layer];
NSString *version = modification.clientReadableVersion;
if (version.length > 0 && [version lookin_numbericOSVersion] >= 10004) {
LKS_CustomAttrGroupsMaker *maker = [[LKS_CustomAttrGroupsMaker alloc] initWithLayer:layer];
[maker execute];
detail.customAttrGroupList = [maker getGroups];
}
detail.frameValue = [NSValue valueWithCGRect:layer.frame];
detail.boundsValue = [NSValue valueWithCGRect:layer.bounds];
detail.hiddenValue = [NSNumber numberWithBool:layer.isHidden];
detail.alphaValue = @(layer.opacity);
completion(detail, error);
});
}
+ (void)handlePatchWithTasks:(NSArray<LookinStaticAsyncUpdateTask *> *)tasks block:(void (^)(LookinDisplayItemDetail *data))block {
if (!block) {
NSAssert(NO, @"");
return;
}
[tasks enumerateObjectsUsingBlock:^(LookinStaticAsyncUpdateTask * _Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
LookinDisplayItemDetail *itemDetail = [LookinDisplayItemDetail new];
itemDetail.displayItemOid = task.oid;
id object = [NSObject lks_objectWithOid:task.oid];
if (!object || ![object isKindOfClass:[CALayer class]]) {
block(itemDetail);
return;
}
CALayer *layer = object;
if (task.taskType == LookinStaticAsyncUpdateTaskTypeSoloScreenshot) {
UIImage *image = [layer lks_soloScreenshotWithLowQuality:NO];
itemDetail.soloScreenshot = image;
} else if (task.taskType == LookinStaticAsyncUpdateTaskTypeGroupScreenshot) {
UIImage *image = [layer lks_groupScreenshotWithLowQuality:NO];
itemDetail.groupScreenshot = image;
}
block(itemDetail);
}];
}
@end
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */