Skip to content

Commit a645fbf

Browse files
committed
2 parents 1479762 + 94f1e81 commit a645fbf

File tree

7 files changed

+243
-26
lines changed

7 files changed

+243
-26
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
packages
33
.DS_Store
44
Aweme
5+
Makefile.local

AwemeHeaders.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,15 @@ typedef NS_ENUM(NSUInteger, DYEdgeMode) {
525525
@property(nonatomic, copy) NSString *accessibilityLabel;
526526
@end
527527

528+
// 评论区实况照片模型
529+
@interface AWECommentLivePhotoModel : NSObject
530+
@property(nonatomic, copy) NSArray *videoUrl;
531+
@end
532+
528533
@interface AWECommentImageModel : NSObject
529-
@property(nonatomic, copy) NSString *originUrl;
534+
@property(nonatomic, strong) AWEURLModel *originUrl;
535+
@property(nonatomic, strong) AWEURLModel *mediumUrl;
536+
@property(nonatomic, strong) AWECommentLivePhotoModel *livePhotoModel;
530537
@end
531538

532539
@class AWECommentModel;
@@ -541,11 +548,13 @@ typedef NS_ENUM(NSUInteger, DYEdgeMode) {
541548

542549
@interface AWECommentLongPressPanelParam : NSObject
543550
- (AWECommentModel *)selectdComment;
551+
- (NSDictionary *)extraParams;
544552
@end
545553

546554
@interface AWECommentModel : NSObject
547555
- (AWEIMStickerModel *)sticker;
548556
- (NSString *)content;
557+
- (NSArray<AWECommentImageModel *> *)imageList;
549558
@end
550559

551560
@interface AWEIMStickerModel : NSObject

DYYY.xm

Lines changed: 88 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,35 +2126,98 @@ static BOOL dyyyShouldUseLastStickerURL = NO;
21262126
}
21272127

21282128
- (void)elementTapped {
2129-
if (!DYYYGetBool(@"DYYYForceDownloadEmotion")) {
2130-
%orig;
2131-
return;
2132-
}
21332129
AWECommentLongPressPanelContext *context = [self commentPageContext];
2134-
AWECommentModel *selected = [context selectdComment] ?: [[context params] selectdComment];
2135-
AWEIMStickerModel *sticker = [selected sticker];
2136-
NSArray *originURLList = sticker.staticURLModel.originURLList;
2137-
if (originURLList.count == 0) {
2138-
%orig;
2139-
return;
2130+
AWECommentLongPressPanelParam *params = [context params];
2131+
AWECommentModel *comment = [context selectdComment] ?: [params selectdComment];
2132+
2133+
// 判断是表情包还是图片
2134+
AWEIMStickerModel *sticker = [comment sticker];
2135+
NSArray *stickerURLList = sticker.staticURLModel.originURLList;
2136+
BOOL hasSticker = (stickerURLList.count > 0);
2137+
2138+
NSArray *imageList = nil;
2139+
if ([comment respondsToSelector:@selector(imageList)]) {
2140+
imageList = [comment imageList];
2141+
}
2142+
BOOL hasImages = (imageList && imageList.count > 0);
2143+
2144+
// 表情包保存逻辑
2145+
if (hasSticker && DYYYGetBool(@"DYYYForceDownloadEmotion")) {
2146+
NSString *urlString = dyyyShouldUseLastStickerURL ? stickerURLList.lastObject : stickerURLList.firstObject;
2147+
dyyyShouldUseLastStickerURL = NO;
2148+
NSURL *stickerURL = [NSURL URLWithString:urlString];
2149+
2150+
if (stickerURL) {
2151+
[DYYYManager downloadMedia:stickerURL
2152+
mediaType:MediaTypeHeic
2153+
audio:nil
2154+
completion:^(BOOL success) {
2155+
if (!success && stickerURLList.count > 1) {
2156+
dyyyShouldUseLastStickerURL = YES;
2157+
}
2158+
}];
2159+
return;
2160+
}
21402161
}
2141-
2142-
NSString *urlString = dyyyShouldUseLastStickerURL ? originURLList.lastObject : originURLList.firstObject;
2143-
dyyyShouldUseLastStickerURL = NO;
2144-
NSURL *heifURL = [NSURL URLWithString:urlString];
2145-
if (!heifURL) {
2146-
%orig;
2162+
2163+
// 图片保存逻辑
2164+
if (hasImages && DYYYGetBool(@"DYYYForceDownloadCommentImage")) {
2165+
// 检查 is_pic_inflow 判断是保存全部还是单张
2166+
// is_pic_inflow = 1: 点开具体图片后长按 -> 只保存当前图片
2167+
// is_pic_inflow = 0: 直接在评论区长按 -> 保存全部图片
2168+
NSDictionary *extraParams = [params extraParams];
2169+
BOOL isPicInflow = NO;
2170+
if (extraParams && [extraParams isKindOfClass:[NSDictionary class]]) {
2171+
id isPicInflowValue = extraParams[@"is_pic_inflow"];
2172+
if (isPicInflowValue) {
2173+
isPicInflow = [isPicInflowValue integerValue] == 1;
2174+
}
2175+
}
2176+
2177+
NSInteger currentIndex = -1; // -1 表示保存全部
2178+
2179+
if (isPicInflow) {
2180+
// 使用 DYYYUtils 封装的方法查找目标控制器
2181+
UIViewController *topVC = [DYYYUtils topView];
2182+
2183+
// 获取 Ivar 定义的类和目标控制器类
2184+
Class ivarClass = NSClassFromString(@"AWECommentMediaFeedSwfitImpl.CommentMediaFeedCellViewController");
2185+
Class targetClass = NSClassFromString(@"AWECommentMediaFeedSwfitImpl.CommentMediaFeedCommonImageCellViewController");
2186+
2187+
if (ivarClass && targetClass && topVC) {
2188+
Ivar multiIndexIvar = class_getInstanceVariable(ivarClass, "currentIndexInMultiImageList");
2189+
if (multiIndexIvar) {
2190+
UIViewController *cellVC = [DYYYUtils findViewControllerOfClass:targetClass inViewController:topVC];
2191+
if (cellVC) {
2192+
ptrdiff_t offset = ivar_getOffset(multiIndexIvar);
2193+
NSInteger *ptr = (NSInteger *)((char *)(__bridge void *)cellVC + offset);
2194+
currentIndex = *ptr;
2195+
}
2196+
}
2197+
}
2198+
}
2199+
2200+
NSString *hint = (currentIndex >= 0) ? @"正在保存当前图片..." :
2201+
[NSString stringWithFormat:@"正在保存 %lu 张图片...", (unsigned long)imageList.count];
2202+
[DYYYUtils showToast:hint];
2203+
2204+
[DYYYManager saveCommentImages:imageList
2205+
currentIndex:currentIndex
2206+
completion:^(NSInteger successCount, NSInteger livePhotoCount, NSInteger failedCount) {
2207+
NSMutableString *message = [NSMutableString stringWithFormat:@"成功保存 %ld 张", (long)successCount];
2208+
if (livePhotoCount > 0) {
2209+
[message appendFormat:@"\n(含 %ld 张实况照片)", (long)livePhotoCount];
2210+
}
2211+
if (failedCount > 0) {
2212+
[message appendFormat:@"\n失败 %ld 张", (long)failedCount];
2213+
}
2214+
[DYYYUtils showToast:message];
2215+
}];
21472216
return;
21482217
}
2149-
2150-
[DYYYManager downloadMedia:heifURL
2151-
mediaType:MediaTypeHeic
2152-
audio:nil
2153-
completion:^(BOOL success) {
2154-
if (!success && originURLList.count > 1) {
2155-
dyyyShouldUseLastStickerURL = YES;
2156-
}
2157-
}];
2218+
2219+
// 默认行为
2220+
%orig;
21582221
}
21592222

21602223
%end

DYYYManager.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@
8585
progress:(void (^)(NSInteger current, NSInteger total))progressBlock
8686
completion:(void (^)(NSInteger successCount, NSInteger totalCount))completion;
8787

88+
/**
89+
* 保存评论区图片(支持普通图片和实况照片)
90+
* @param imageModels 评论图片模型数组(AWECommentImageModel)
91+
* @param currentIndex 当前图片索引(-1 表示保存全部)
92+
* @param completion 完成回调
93+
*/
94+
+ (void)saveCommentImages:(NSArray *)imageModels
95+
currentIndex:(NSInteger)currentIndex
96+
completion:(void (^)(NSInteger successCount, NSInteger livePhotoCount, NSInteger failedCount))completion;
97+
8898
/**
8999
* 批量下载图片
90100
* @param imageURLs 图片URL数组

DYYYManager.m

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,6 +1806,130 @@ - (void)deleteFile:(NSString *)file {
18061806
}
18071807
}
18081808

1809+
#pragma mark - 评论区图片保存
1810+
1811+
+ (void)saveCommentImages:(NSArray *)imageModels
1812+
currentIndex:(NSInteger)currentIndex
1813+
completion:(void (^)(NSInteger successCount, NSInteger livePhotoCount, NSInteger failedCount))completion {
1814+
if (!imageModels || imageModels.count == 0) {
1815+
if (completion) completion(0, 0, 0);
1816+
return;
1817+
}
1818+
1819+
// 确定要保存的图片
1820+
NSArray *imagesToSave = nil;
1821+
if (currentIndex >= 0 && currentIndex < (NSInteger)imageModels.count) {
1822+
imagesToSave = @[imageModels[currentIndex]];
1823+
} else {
1824+
imagesToSave = imageModels;
1825+
}
1826+
1827+
// 分离普通图片和实况照片
1828+
NSMutableArray *normalImages = [NSMutableArray array];
1829+
NSMutableArray *livePhotos = [NSMutableArray array];
1830+
1831+
for (id imageModel in imagesToSave) {
1832+
@try {
1833+
// 获取图片 URL - originUrl 和 mediumUrl 都是 AWEURLModel 类型
1834+
NSString *imageUrlStr = nil;
1835+
1836+
// 首先尝试 originUrl
1837+
AWEURLModel *originUrlModel = [imageModel valueForKey:@"originUrl"];
1838+
if (originUrlModel) {
1839+
NSArray *urlList = [originUrlModel originURLList];
1840+
if (urlList && urlList.count > 0) {
1841+
imageUrlStr = urlList.firstObject;
1842+
}
1843+
}
1844+
1845+
// 如果 originUrl 没有获取到,尝试 mediumUrl
1846+
if (!imageUrlStr) {
1847+
AWEURLModel *mediumUrlModel = [imageModel valueForKey:@"mediumUrl"];
1848+
if (mediumUrlModel) {
1849+
NSArray *urlList = [mediumUrlModel originURLList];
1850+
if (urlList && urlList.count > 0) {
1851+
imageUrlStr = urlList.firstObject;
1852+
}
1853+
}
1854+
}
1855+
1856+
NSLog(@"[DYYY] 评论图片URL: %@", imageUrlStr);
1857+
1858+
if (!imageUrlStr || imageUrlStr.length == 0) {
1859+
NSLog(@"[DYYY] 无法获取图片URL,imageModel: %@", imageModel);
1860+
continue;
1861+
}
1862+
1863+
// 检查是否是实况照片
1864+
id livePhotoModel = [imageModel valueForKey:@"livePhotoModel"];
1865+
if (livePhotoModel) {
1866+
NSArray *videoUrls = [livePhotoModel valueForKey:@"videoUrl"];
1867+
if (videoUrls && videoUrls.count > 0) {
1868+
NSString *videoUrlStr = videoUrls.firstObject;
1869+
if (videoUrlStr && videoUrlStr.length > 0) {
1870+
// 传入字符串而不是 NSURL,与 downloadAllLivePhotosWithProgress 期望的格式一致
1871+
[livePhotos addObject:@{
1872+
@"imageURL": imageUrlStr,
1873+
@"videoURL": videoUrlStr
1874+
}];
1875+
continue;
1876+
}
1877+
}
1878+
}
1879+
1880+
// 普通图片 - 存储字符串而不是 NSURL
1881+
[normalImages addObject:imageUrlStr];
1882+
} @catch (NSException *e) {
1883+
NSLog(@"[DYYY] 解析评论图片失败: %@", e);
1884+
}
1885+
}
1886+
1887+
NSLog(@"[DYYY] 解析完成: 普通图片=%lu, 实况照片=%lu", (unsigned long)normalImages.count, (unsigned long)livePhotos.count);
1888+
1889+
// 如果都没有解析到有效URL,直接返回失败
1890+
if (normalImages.count == 0 && livePhotos.count == 0) {
1891+
if (completion) completion(0, 0, (NSInteger)imagesToSave.count);
1892+
return;
1893+
}
1894+
1895+
__block NSInteger successCount = 0;
1896+
__block NSInteger livePhotoCount = 0;
1897+
__block NSInteger failedCount = 0;
1898+
1899+
dispatch_group_t group = dispatch_group_create();
1900+
1901+
// 保存普通图片
1902+
if (normalImages.count > 0) {
1903+
dispatch_group_enter(group);
1904+
[self downloadAllImagesWithProgress:[normalImages mutableCopy]
1905+
progress:nil
1906+
completion:^(NSInteger imgSuccess, NSInteger imgTotal) {
1907+
successCount += imgSuccess;
1908+
failedCount += (imgTotal - imgSuccess);
1909+
dispatch_group_leave(group);
1910+
}];
1911+
}
1912+
1913+
// 保存实况照片
1914+
if (livePhotos.count > 0) {
1915+
dispatch_group_enter(group);
1916+
[self downloadAllLivePhotosWithProgress:livePhotos
1917+
progress:nil
1918+
completion:^(NSInteger lpSuccess, NSInteger lpTotal) {
1919+
successCount += lpSuccess;
1920+
livePhotoCount = lpSuccess;
1921+
failedCount += (lpTotal - lpSuccess);
1922+
dispatch_group_leave(group);
1923+
}];
1924+
}
1925+
1926+
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
1927+
if (completion) {
1928+
completion(successCount, livePhotoCount, failedCount);
1929+
}
1930+
});
1931+
}
1932+
18091933
+ (void)downloadAllLivePhotos:(NSArray<NSDictionary *> *)livePhotos {
18101934
if (livePhotos.count == 0) {
18111935
return;

DYYYSettings.xm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,14 @@ void showDYYYSettingsVC(UIViewController *rootVC, BOOL hasAgreed) {
19561956
@"detail" : @"",
19571957
@"cellType" : @6,
19581958
@"imageName" : @"ic_removeimage_outlined_20"},
1959+
@{
1960+
@"identifier" : @"DYYYForceDownloadCommentImage",
1961+
@"title" : @"保存评论区图片",
1962+
@"subTitle" : @"长按评论可保存所有实况和图片",
1963+
@"detail" : @"",
1964+
@"cellType" : @37,
1965+
@"imageName" : @"ic_image_outlined"
1966+
},
19591967
@{
19601968
@"identifier" : @"DYYYForceDownloadEmotion",
19611969
@"title" : @"保存评论区表情包",

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
# Channel: @huamidev
66
# Created on: 2024/10/04
77
#
8+
# 本地配置文件(可选)
9+
-include Makefile.local
810

911
TARGET = iphone:clang:latest:14.0
1012
ARCHS = arm64 arm64e

0 commit comments

Comments
 (0)