From 27fa793959ba07978f2afc6a3baacffc9edd6d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=92=BB?= Date: Mon, 9 Mar 2026 16:26:45 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E7=9C=9F=E5=AE=9E=E4=BA=BA=E6=95=B0=E4=B8=8E=E8=AF=84?= =?UTF-8?q?=E8=AE=BA=E7=B2=BE=E7=A1=AE=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + AwemeHeaders.h | 4 ++ DYYY.xm | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ DYYYSettings.xm | 13 ++++++ 4 files changed, 129 insertions(+) diff --git a/.gitignore b/.gitignore index 82bb8a085..673a85142 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ packages .DS_Store Aweme Makefile.local +.vscode/ \ No newline at end of file diff --git a/AwemeHeaders.h b/AwemeHeaders.h index 540124b54..4c09205f0 100644 --- a/AwemeHeaders.h +++ b/AwemeHeaders.h @@ -323,6 +323,10 @@ typedef NS_ENUM(NSUInteger, DYEdgeMode) { - (void)buttonTouchUp:(id)sender; @end +@interface HTSLiveRoomStatsMessage : NSObject +- (NSInteger)displayValue; +@end + @interface AWEFeedVideoButton : UIButton @end diff --git a/DYYY.xm b/DYYY.xm index f4b8a1c80..74e81427f 100644 --- a/DYYY.xm +++ b/DYYY.xm @@ -10,6 +10,7 @@ #import #import #import +#import #import "AwemeHeaders.h" #import "CityManager.h" @@ -362,6 +363,104 @@ static BOOL DYYYShouldHandleSpeedFeatures(void) { %end +// 直播间真实人数 + +static NSString *(*orig_displayShort)(id, SEL); +static NSString *my_displayShort(id self, SEL _cmd) { + if (!DYYYGetBool(@"DYYYEnableLiveRealCount")) return orig_displayShort(self, _cmd); + if ([self respondsToSelector:@selector(displayValue)]) { + NSInteger count = (NSInteger)[self performSelector:@selector(displayValue)]; + if (count > 0) return [NSString stringWithFormat:@"%ld", (long)count]; + } + return orig_displayShort(self, _cmd); +} + +static NSString *(*orig_displayMiddle)(id, SEL); +static NSString *my_displayMiddle(id self, SEL _cmd) { + if (!DYYYGetBool(@"DYYYEnableLiveRealCount")) return orig_displayMiddle(self, _cmd); + if ([self respondsToSelector:@selector(displayValue)]) { + NSInteger count = (NSInteger)[self performSelector:@selector(displayValue)]; + if (count > 0) return [NSString stringWithFormat:@"%ld", (long)count]; + } + return orig_displayMiddle(self, _cmd); +} + +static NSString *(*orig_displayLong)(id, SEL); +static NSString *my_displayLong(id self, SEL _cmd) { + if (!DYYYGetBool(@"DYYYEnableLiveRealCount")) return orig_displayLong(self, _cmd); + if ([self respondsToSelector:@selector(displayValue)]) { + NSInteger count = (NSInteger)[self performSelector:@selector(displayValue)]; + if (count > 0) return [NSString stringWithFormat:@"%ld在线观众", (long)count]; + } + return orig_displayLong(self, _cmd); +} + +// 评论具体时间 +%hook AWEDateTimeFormatter + ++ (id)formattedDateForTimestamp:(double)timestamp { + if (!DYYYGetBool(@"DYYYCommentExactTime")) return %orig(timestamp); + return [NSString stringWithFormat:@"%.0f ", timestamp]; +} + +%end + +%hook AWERLVirtualLabel + +- (void)setText:(NSString *)text { + if (!DYYYGetBool(@"DYYYCommentExactTime") || !text || text.length == 0) { + %orig(text); + return; + } + + NSError *error = nil; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^(\\d{10,13})([\\s\\S]*)" options:0 error:&error]; + + NSTextCheckingResult *match = [regex firstMatchInString:text options:0 range:NSMakeRange(0, text.length)]; + + if (match) { + NSString *rawTs = [text substringWithRange:[match rangeAtIndex:1]]; + NSString *suffix = [text substringWithRange:[match rangeAtIndex:2]]; + + long long ts = [rawTs longLongValue]; + + if (ts > 100000000000) { + ts = ts / 1000; + } + + NSDate *date = [NSDate dateWithTimeIntervalSince1970:ts]; + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; + NSString *formattedDate = [formatter stringFromDate:date]; + + NSString *newText = [NSString stringWithFormat:@"%@%@", formattedDate, suffix]; + %orig(newText); + } else { + %orig(text); + } +} + +%end + +%group DYYYCommentExactTimeGroup +%hook AWECommentSwiftBizUI_CommentInteractionBaseLabel + +- (void)setFrame:(CGRect)frame { + if (!DYYYGetBool(@"DYYYCommentExactTime")) { + %orig(frame); + return; + } + frame.size.width = 800.0; + + UIView *labelView = (UIView *)self; + labelView.clipsToBounds = NO; + + %orig(frame); +} + +%end +%end + // 禁用自动进入直播间 %hook AWELiveGuideElement @@ -8508,6 +8607,18 @@ static void findTargetViewInView(UIView *view) { } %ctor { + Class interactionBaseLabelClass = objc_getClass("AWECommentSwiftBizUI.CommentInteractionBaseLabel"); + if (interactionBaseLabelClass) { + %init(DYYYCommentExactTimeGroup, AWECommentSwiftBizUI_CommentInteractionBaseLabel = interactionBaseLabelClass); + } + + Class statsMessageClass = objc_getClass("HTSLiveRoomStatsMessage"); + if (statsMessageClass) { + MSHookMessageEx(statsMessageClass, @selector(displayShort), (IMP)&my_displayShort, (IMP *)&orig_displayShort); + MSHookMessageEx(statsMessageClass, @selector(displayMiddle), (IMP)&my_displayMiddle, (IMP *)&orig_displayMiddle); + MSHookMessageEx(statsMessageClass, @selector(displayLong), (IMP)&my_displayLong, (IMP *)&orig_displayLong); + } + Class imMenuComponentClass = objc_getClass("AWEIMCustomMenuComponent"); if (imMenuComponentClass) { SEL legacySelector = NSSelectorFromString(@"msg_showMenuForBubbleFrameInScreen:tapLocationInScreen:menuItemList:moreEmoticon:onCell:extra:"); diff --git a/DYYYSettings.xm b/DYYYSettings.xm index d19b5dcd4..ec2afbe34 100644 --- a/DYYYSettings.xm +++ b/DYYYSettings.xm @@ -496,6 +496,19 @@ void showDYYYSettingsVC(UIViewController *rootVC, BOOL hasAgreed) { @"detail" : @"自动", @"cellType" : @26, @"imageName" : @"ic_video_outlined_20"}, + @{@"identifier" : @"DYYYEnableLiveRealCount", + @"title" : @"直播真实人数", + @"subTitle" : @"直播显示具体的在线人数", + @"detail" : @"", + @"cellType" : @37, + @"imageName" : @"ic_video_outlined_20"}, + + @{@"identifier" : @"DYYYCommentExactTime", + @"title" : @"评论具体时间", + @"subTitle" : @"开启后评论区将显示具体的发布时间而非相对时间", + @"detail" : @"", + @"cellType" : @37, + @"imageName" : @"ic_clock_outlined_20"}, @{@"identifier" : @"DYYYEnableVideoHighestQuality", @"title" : @"提高视频画质", @"detail" : @"", From a6324ca9ea0fc8efc76d3d4a6359c2a7f117ec6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=92=BB?= Date: Mon, 9 Mar 2026 17:10:02 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AF=84=E8=AE=BA?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=98=BE=E7=A4=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DYYY.xm | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/DYYY.xm b/DYYY.xm index 74e81427f..557e64ce9 100644 --- a/DYYY.xm +++ b/DYYY.xm @@ -413,6 +413,11 @@ static NSString *my_displayLong(id self, SEL _cmd) { return; } + if ([text isEqualToString:@"回复"]) { + %orig(@""); + return; + } + NSError *error = nil; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^(\\d{10,13})([\\s\\S]*)" options:0 error:&error]; @@ -446,14 +451,18 @@ static NSString *my_displayLong(id self, SEL _cmd) { %hook AWECommentSwiftBizUI_CommentInteractionBaseLabel - (void)setFrame:(CGRect)frame { - if (!DYYYGetBool(@"DYYYCommentExactTime")) { + if (!DYYYGetBool(@"DYYYCommentExactTime") || ![self respondsToSelector:@selector(text)]) { %orig(frame); return; } - frame.size.width = 800.0; - - UIView *labelView = (UIView *)self; - labelView.clipsToBounds = NO; + + if (ABS(frame.size.width - 115.0) <= 5.0 && ABS(frame.size.height - 16.0) <= 1) { + + frame.size.width = 800.0; + + UIView *labelView = (UIView *)self; + labelView.clipsToBounds = NO; + } %orig(frame); } From ea5483fd49238ae8e47ed676acfd43a53203e494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=92=BB?= Date: Mon, 9 Mar 2026 21:49:10 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=84=E8=AE=BA?= =?UTF-8?q?=E5=8C=BA=E6=97=B6=E9=97=B4=E5=BC=95=E8=B5=B7=E7=9A=84=E4=B8=80?= =?UTF-8?q?=E4=BA=9Bbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DYYY.xm | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 6 deletions(-) diff --git a/DYYY.xm b/DYYY.xm index 557e64ce9..ad15dc306 100644 --- a/DYYY.xm +++ b/DYYY.xm @@ -450,18 +450,67 @@ static NSString *my_displayLong(id self, SEL _cmd) { %group DYYYCommentExactTimeGroup %hook AWECommentSwiftBizUI_CommentInteractionBaseLabel +- (void)setText:(NSString *)text { + %orig(text); // 先让系统把文本赋上去 + + if (!DYYYGetBool(@"DYYYCommentExactTime")) { + return; + } + + UILabel *label = (UILabel *)self; + if (!text || text.length == 0) return; + + // --- 1. 拦截翻译文本,将其绝对定位在屏幕右侧 100 像素 --- + if ([text isEqualToString:@"翻译"] || [text isEqualToString:@"隐藏翻译"]) { + CGRect currentFrame = label.frame; + CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; + // 重新计算 X 坐标:屏幕宽度 - 100 - 标签自身宽度 + currentFrame.origin.x = screenWidth - 100.0 - currentFrame.size.width; + label.frame = currentFrame; + return; + } + + // --- 2. 拦截时间文本,如果不够宽则扩充宽度 --- + UIFont *font = label.font; + if (font) { + CGFloat expectedWidth = ceilf([text sizeWithAttributes:@{NSFontAttributeName: font}].width); + CGRect currentFrame = label.frame; + + // 如果当前宽度不够,并且不是尚未初始化的状态(>0),则强行修改并重新赋值 + if (currentFrame.size.width < expectedWidth && currentFrame.size.width > 0) { + currentFrame.size.width = expectedWidth; + label.frame = currentFrame; + label.clipsToBounds = NO; + } + } +} + - (void)setFrame:(CGRect)frame { if (!DYYYGetBool(@"DYYYCommentExactTime") || ![self respondsToSelector:@selector(text)]) { %orig(frame); return; } - if (ABS(frame.size.width - 115.0) <= 5.0 && ABS(frame.size.height - 16.0) <= 1) { - - frame.size.width = 800.0; - - UIView *labelView = (UIView *)self; - labelView.clipsToBounds = NO; + UILabel *label = (UILabel *)self; + NSString *text = label.text; + + if (text && text.length > 0) { + // --- 1. 拦截翻译文本,将其绝对定位在屏幕右侧 100 像素 --- + if ([text isEqualToString:@"翻译"] || [text isEqualToString:@"隐藏翻译"]) { + CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; + frame.origin.x = screenWidth - 100.0 - frame.size.width; + } + // --- 2. 拦截时间文本,如果不够宽则扩充宽度 --- + else if ([self respondsToSelector:@selector(font)]) { + UIFont *font = label.font; + if (font) { + CGFloat expectedWidth = ceilf([text sizeWithAttributes:@{NSFontAttributeName: font}].width); + if (frame.size.width < expectedWidth && frame.size.width > 0) { + frame.size.width = expectedWidth; + label.clipsToBounds = NO; + } + } + } } %orig(frame); @@ -470,6 +519,46 @@ static NSString *my_displayLong(id self, SEL _cmd) { %end %end +// 前面的AWEDateTimeFormatter会导致图文视频展开时间文本变成时间戳,这里处理下 +%hook YYLabel + +// 1. Hook 富文本赋值方法 (核心) +- (void)setAttributedText:(NSAttributedString *)attributedText { + if (!DYYYGetBool(@"DYYYCommentExactTime") || !attributedText || attributedText.length == 0) { + %orig(attributedText); + return; + } + + NSString *plainText = [attributedText string]; + + NSError *error = nil; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^(\\d{10,13})" options:0 error:&error]; + NSTextCheckingResult *match = [regex firstMatchInString:plainText options:0 range:NSMakeRange(0, plainText.length)]; + + if (match) { + NSString *rawTs = [plainText substringWithRange:[match rangeAtIndex:1]]; + long long ts = [rawTs longLongValue]; + + if (ts > 100000000000) { + ts = ts / 1000; + } + + NSDate *date = [NSDate dateWithTimeIntervalSince1970:ts]; + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; + NSString *formattedDate = [formatter stringFromDate:date]; + + NSMutableAttributedString *newAttrStr = [attributedText mutableCopy]; + [newAttrStr replaceCharactersInRange:[match rangeAtIndex:1] withString:formattedDate]; + + %orig(newAttrStr); + } else { + %orig(attributedText); + } +} + +%end + // 禁用自动进入直播间 %hook AWELiveGuideElement