| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- // Created by Tencent on 2023/06/09.
- // Copyright © 2023 Tencent. All rights reserved.
- #import "TUIImageCollectionCell.h"
- #import <TIMCommon/TIMDefine.h>
- #import <TUICore/TUITool.h>
- #import "TUICircleLodingView.h"
- @interface TUIImageCollectionCellScrollView : UIScrollView <UIScrollViewDelegate>
- @property(nonatomic, strong) UIView *containerView;
- @property(assign, nonatomic) CGFloat imageNormalWidth;
- @property(assign, nonatomic) CGFloat imageNormalHeight;
- - (void)pictureZoomWithScale:(CGFloat)zoomScale;
- @end
- @implementation TUIImageCollectionCellScrollView
- - (id)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- if (self) {
- self.delegate = self;
- self.minimumZoomScale = 0.1f;
- self.maximumZoomScale = 2.0f;
- _imageNormalHeight = frame.size.height;
- _imageNormalWidth = frame.size.width;
- self.containerView = [[UIView alloc] initWithFrame:frame];
- [self addSubview:self.containerView];
- if (@available(iOS 11.0, *)) {
- self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
- } else {
- // Fallback on earlier versions
- }
- }
- return self;
- }
- - (void)drawRect:(CGRect)rect {
- [super drawRect:rect];
- }
- #pragma mark-- Help Methods
- - (void)pictureZoomWithScale:(CGFloat)zoomScale {
- CGFloat imageScaleWidth = zoomScale * self.imageNormalWidth;
- CGFloat imageScaleHeight = zoomScale * self.imageNormalHeight;
- CGFloat imageX = 0;
- CGFloat imageY = 0;
- if (imageScaleWidth < self.frame.size.width) {
- imageX = floorf((self.frame.size.width - imageScaleWidth) / 2.0);
- }
- if (imageScaleHeight < self.frame.size.height) {
- imageY = floorf((self.frame.size.height - imageScaleHeight) / 2.0);
- }
- self.containerView.frame = CGRectMake(imageX, imageY, imageScaleWidth, imageScaleHeight);
- self.contentSize = CGSizeMake(imageScaleWidth, imageScaleHeight);
- }
- #pragma mark-- Setter
- - (void)setImageNormalWidth:(CGFloat)imageNormalWidth {
- _imageNormalWidth = imageNormalWidth;
- self.containerView.frame = CGRectMake(0, 0, _imageNormalWidth, _imageNormalHeight);
- self.containerView.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
- }
- - (void)setImageNormalHeight:(CGFloat)imageNormalHeight {
- _imageNormalHeight = imageNormalHeight;
- self.containerView.frame = CGRectMake(0, 0, _imageNormalWidth, _imageNormalHeight);
- self.containerView.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
- }
- #pragma mark-- UIScrollViewDelegate
- // Returns the view control that needs to be zoomed. During zooming
- - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
- return self.containerView;
- }
- // BeginZooming
- - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view {
- NSLog(@"BeginZooming");
- }
- // EndZooming
- - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
- NSLog(@"EndZooming");
- }
- // zoom
- - (void)scrollViewDidZoom:(UIScrollView *)scrollView {
- CGFloat imageScaleWidth = scrollView.zoomScale * self.imageNormalWidth;
- CGFloat imageScaleHeight = scrollView.zoomScale * self.imageNormalHeight;
- CGFloat imageX = 0;
- CGFloat imageY = 0;
- if (imageScaleWidth < self.frame.size.width) {
- imageX = floorf((self.frame.size.width - imageScaleWidth) / 2.0);
- }
- if (imageScaleHeight < self.frame.size.height) {
- imageY = floorf((self.frame.size.height - imageScaleHeight) / 2.0);
- }
- self.containerView.frame = CGRectMake(imageX, imageY, imageScaleWidth, imageScaleHeight);
- }
- @end
- @interface TUIImageCollectionCell ()
- @property(nonatomic, strong) TUIImageCollectionCellScrollView *scrollView;
- @property(nonatomic, strong) TUIImageMessageCellData *imgCellData;
- @property(nonatomic, strong) UIButton *mainDownloadBtn;
- @property(nonatomic, strong) TUICircleLodingView *animateCircleView;
- @end
- @implementation TUIImageCollectionCell
- - (id)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- if (self) {
- [self setupViews];
- [self setupRotaionNotifications];
- }
- return self;
- }
- - (void)setupViews {
- self.scrollView = [[TUIImageCollectionCellScrollView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)];
- [self addSubview:self.scrollView];
- self.imageView = [[UIImageView alloc] init];
- self.imageView.layer.cornerRadius = 5.0;
- [self.imageView.layer setMasksToBounds:YES];
- self.imageView.contentMode = UIViewContentModeScaleAspectFill;
- self.imageView.backgroundColor = [UIColor clearColor];
- [self.scrollView.containerView addSubview:self.imageView];
- self.imageView.mm_fill();
- self.imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- self.mainDownloadBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- self.mainDownloadBtn.contentMode = UIViewContentModeScaleToFill;
- [self.mainDownloadBtn setTitle:TIMCommonLocalizableString(TUIKitImageViewOrigin) forState:UIControlStateNormal];
- self.mainDownloadBtn.backgroundColor = [UIColor grayColor];
- [self.mainDownloadBtn.titleLabel setFont:[UIFont systemFontOfSize:14]];
- self.mainDownloadBtn.layer.borderColor = [UIColor whiteColor].CGColor;
- self.mainDownloadBtn.layer.cornerRadius = .16;
- self.mainDownloadBtn.hidden = YES;
- [self.mainDownloadBtn addTarget:self action:@selector(mainDownloadBtnClick) forControlEvents:UIControlEventTouchUpInside];
- [self addSubview:self.mainDownloadBtn];
- self.downloadBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- self.downloadBtn.contentMode = UIViewContentModeScaleToFill;
- [self.downloadBtn setImage:TUIChatCommonBundleImage(@"download") forState:UIControlStateNormal];
- [self.downloadBtn addTarget:self action:@selector(onSaveBtnClick) forControlEvents:UIControlEventTouchUpInside];
- [self addSubview:self.downloadBtn];
- self.animateCircleView = [[TUICircleLodingView alloc] initWithFrame:CGRectMake(0, 0, kScale390(40), kScale390(40))];
- self.animateCircleView.hidden = YES;
- self.animateCircleView.progress = 0;
- [self addSubview:_animateCircleView];
- self.backgroundColor = [UIColor clearColor];
- UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onSelectMedia)];
- [self addGestureRecognizer:tap];
- }
- - (void)setupRotaionNotifications {
- if (@available(iOS 16.0, *)) {
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(onDeviceOrientationChange:)
- name:TUIMessageMediaViewDeviceOrientationChangeNotification
- object:nil];
- } else {
- [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(onDeviceOrientationChange:)
- name:UIDeviceOrientationDidChangeNotification
- object:nil];
- }
- }
- - (void)mainDownloadBtnClick {
- if (self.imgCellData.originImage == nil) {
- [self.imgCellData downloadImage:TImage_Type_Origin];
- }
- }
- - (void)onSaveBtnClick {
- UIImage *image = self.imageView.image;
- [[PHPhotoLibrary sharedPhotoLibrary]
- performChanges:^{
- [PHAssetChangeRequest creationRequestForAssetFromImage:image];
- }
- completionHandler:^(BOOL success, NSError *_Nullable error) {
- dispatch_async(dispatch_get_main_queue(), ^{
- if (success) {
- [TUITool makeToast:TIMCommonLocalizableString(TUIKitPictureSavedSuccess)];
- } else {
- [TUITool makeToast:TIMCommonLocalizableString(TUIKitPictureSavedFailed)];
- }
- });
- }];
- }
- - (void)onSelectMedia {
- if (self.delegate && [self.delegate respondsToSelector:@selector(onCloseMedia:)]) {
- [self.delegate onCloseMedia:self];
- }
- }
- - (void)fillWithData:(TUIImageMessageCellData *)data;
- {
- [super fillWithData:data];
- self.imgCellData = data;
- self.imageView.image = nil;
-
- BOOL hasRiskContent = data.innerMessage.hasRiskContent;
- if (hasRiskContent ) {
- self.imageView.image = TIMCommonBundleThemeImage(@"", @"icon_security_strike");
- for (UIView *subview in self.subviews) {
- if (subview != self.scrollView ){
- subview.hidden = YES;
- }
- }
- return;
- }
-
- //1.Read from cache
- if ([self originImageFirst:data]) {
- return;
- }
-
- if ([self largeImageSecond:data]) {
- return;
- }
-
- //2. download image
- if (data.thumbImage == nil) {
- [data downloadImage:TImage_Type_Thumb];
- }
- if (data.thumbImage && data.largeImage == nil) {
- self.animateCircleView.hidden = NO;
- [data downloadImage:TImage_Type_Large];
- }
- [self fillThumbImageWithData:data];
- [self fillLargeImageWithData:data];
- [self fillOriginImageWithData:data];
- }
- - (BOOL)largeImageSecond:(TUIImageMessageCellData *)data {
- BOOL isExist = NO;
- NSString *path = [data getImagePath:TImage_Type_Large isExist:&isExist];
- if (isExist) {
- [data decodeImage:TImage_Type_Large];
- [self fillLargeImageWithData:data];
- }
- return isExist;
- }
- - (BOOL)originImageFirst:(TUIImageMessageCellData *)data {
- BOOL isExist = NO;
- NSString *path = [data getImagePath:TImage_Type_Origin isExist:&isExist];
- if (isExist) {
- [data decodeImage:TImage_Type_Origin];
- [self fillOriginImageWithData:data];
- }
- return isExist;
- }
- - (void)fillOriginImageWithData:(TUIImageMessageCellData *)data{
- @weakify(self);
- // originImage
- [[RACObserve(data, originImage) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(UIImage *originImage) {
- @strongify(self);
- if (originImage) {
- self.imageView.image = originImage;
- [self setNeedsLayout];
- }
- }];
- [[[RACObserve(data, originProgress) takeUntil:self.rac_prepareForReuseSignal] distinctUntilChanged] subscribeNext:^(NSNumber *x) {
- @strongify(self);
- int progress = [x intValue];
- if (progress == 100) {
- self.animateCircleView.progress = 99;
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- self.animateCircleView.progress = 100;
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- self.animateCircleView.progress = 0;
- self.mainDownloadBtn.hidden = YES;
- self.animateCircleView.hidden = YES;
- [self.mainDownloadBtn setTitle:TIMCommonLocalizableString(TUIKitImageViewOrigin) forState:UIControlStateNormal];
- });
- });
- } else if (progress > 1 && progress < 100) {
- self.animateCircleView.progress = progress;
- [self.mainDownloadBtn setTitle:[NSString stringWithFormat:@"%d%%", progress] forState:UIControlStateNormal];
- self.animateCircleView.hidden = YES;
- } else {
- self.animateCircleView.progress = progress;
- }
- }];
- }
- - (void)fillLargeImageWithData:(TUIImageMessageCellData *)data {
- @weakify(self);
- // largeImage
- [[RACObserve(data, largeImage) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(UIImage *largeImage) {
- @strongify(self);
- if (largeImage) {
- self.imageView.image = largeImage;
- [self setNeedsLayout];
- }
- }];
- [[[RACObserve(data, largeProgress) takeUntil:self.rac_prepareForReuseSignal] distinctUntilChanged] subscribeNext:^(NSNumber *x) {
- @strongify(self);
- int progress = [x intValue];
- if (progress == 100) {
- self.animateCircleView.progress = 99;
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- self.animateCircleView.progress = 100;
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- self.animateCircleView.progress = 0;
- self.mainDownloadBtn.hidden = NO;
- self.animateCircleView.hidden = YES;
- });
- });
- } else if (progress > 1 && progress < 100) {
- self.animateCircleView.progress = progress;
- self.mainDownloadBtn.hidden = YES;
- self.animateCircleView.hidden = NO;
- } else {
- self.animateCircleView.progress = progress;
- }
- }];
- }
- - (void)fillThumbImageWithData:(TUIImageMessageCellData *)data {
- @weakify(self);
- [[RACObserve(data, thumbImage) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(UIImage *thumbImage) {
- @strongify(self);
- if (thumbImage) {
- self.imageView.image = thumbImage;
- [self setNeedsLayout];
- }
- }];
- }
- - (void)layoutSubviews {
- [super layoutSubviews];
- [self.mainDownloadBtn sizeToFit];
- self.mainDownloadBtn.mm_width(self.mainDownloadBtn.mm_w + 10).mm_height(self.mainDownloadBtn.mm_h).mm__centerX(self.mm_w / 2).mm_bottom(48);
- self.mainDownloadBtn.layer.cornerRadius = (self.mainDownloadBtn.mm_h * 0.5);
- self.animateCircleView.tui_mm_center();
- self.downloadBtn.mm_width(31).mm_height(31).mm_right(16).mm_bottom(48);
- self.scrollView.mm_width(self.mm_w).mm_height(self.mm_h).mm__centerX(self.mm_w / 2).mm__centerY(self.mm_h / 2);
- self.scrollView.imageNormalWidth = self.imageView.image.size.width;
- self.scrollView.imageNormalHeight = self.imageView.image.size.height;
- self.imageView.frame = CGRectMake(self.scrollView.bounds.origin.x,
- self.scrollView.bounds.origin.y,
- self.imageView.image.size.width,
- self.imageView.image.size.height);
-
- [self.imageView layoutIfNeeded];
- [self adjustScale];
- }
- - (void)onDeviceOrientationChange:(NSNotification *)noti {
- [self reloadAllView];
- }
- - (void)reloadAllView {
- for (UIView *subview in self.subviews) {
- if (subview) {
- [UIView animateWithDuration:0.1 animations:^{
- [subview removeFromSuperview];
- }];
- }
- }
- [self setupViews];
- [self fillWithData:self.imgCellData];
- }
- #pragma mark - V2TIMAdvancedMsgListener
- - (void)onRecvMessageModified:(V2TIMMessage *)msg {
- V2TIMMessage *imMsg = msg;
- if (imMsg == nil || ![imMsg isKindOfClass:V2TIMMessage.class]) {
- return;
- }
- if ([self.imgCellData.innerMessage.msgID isEqualToString:imMsg.msgID]) {
- BOOL hasRiskContent = imMsg.hasRiskContent;
- if (hasRiskContent) {
- self.imgCellData.innerMessage = imMsg;
- [self showRiskAlert];
- }
- }
- }
- - (void)showRiskAlert {
- UIAlertController *ac = [UIAlertController alertControllerWithTitle:nil
- message:TIMCommonLocalizableString(TUIKitPictureCheckRisk)
- preferredStyle:UIAlertControllerStyleAlert];
- __weak typeof(self) weakSelf = self;
- [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(TUIKitVideoCheckRiskCancel)
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction *_Nonnull action) {
- __strong typeof(weakSelf) strongSelf = weakSelf;
- [strongSelf reloadAllView];
- }]];
- [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:ac animated:YES completion:nil];
- }
- - (void)adjustScale {
- CGFloat scale = 1;
- if (Screen_Width > self.imageView.image.size.width) {
- scale = 1;
- CGFloat scaleHeight = Screen_Height/ self.imageView.image.size.height;
- scale = MIN(scale, scaleHeight);
- }
- else {
- scale = Screen_Width/ self.imageView.image.size.width;
- CGFloat scaleHeight = Screen_Height/ self.imageView.image.size.height;
- scale = MIN(scale, scaleHeight);
- }
- self.scrollView.containerView.frame = CGRectMake(0, 0,MIN(Screen_Width,self.imageView.image.size.width), self.imageView.image.size.height);
- [self.scrollView pictureZoomWithScale:scale];
- }
- @end
|