mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
tap-to-retry failed thumbnail downloads
// FREEBIE
This commit is contained in:
parent
8716d6b7a6
commit
64ff4cd660
8 changed files with 171 additions and 42 deletions
|
@ -5,10 +5,10 @@
|
|||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class ConversationViewItem;
|
||||
@class OWSQuotedReplyModel;
|
||||
@class TSAttachmentPointer;
|
||||
@class TSAttachmentStream;
|
||||
@class TSOutgoingMessage;
|
||||
@class TSQuotedMessage;
|
||||
|
||||
typedef NS_ENUM(NSUInteger, OWSMessageGestureLocation) {
|
||||
// Message text, etc.
|
||||
|
@ -37,7 +37,10 @@ typedef NS_ENUM(NSUInteger, OWSMessageGestureLocation) {
|
|||
|
||||
- (void)didTapFailedOutgoingMessage:(TSOutgoingMessage *)message;
|
||||
|
||||
- (void)didTapQuotedMessage:(ConversationViewItem *)viewItem quotedMessage:(TSQuotedMessage *)quotedMessage;
|
||||
- (void)didTapConversationItem:(ConversationViewItem *)viewItem quotedReply:(OWSQuotedReplyModel *)quotedReply;
|
||||
- (void)didTapConversationItem:(ConversationViewItem *)viewItem
|
||||
quotedReply:(OWSQuotedReplyModel *)quotedReply
|
||||
failedThumbnailDownloadAttachmentPointer:(TSAttachmentPointer *)attachmentPointer;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSMessageBubbleView ()
|
||||
@interface OWSMessageBubbleView () <OWSQuotedMessageViewDelegate>
|
||||
|
||||
@property (nonatomic) OWSBubbleView *bubbleView;
|
||||
|
||||
|
@ -272,6 +272,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[OWSQuotedMessageView quotedMessageViewForConversation:self.viewItem.quotedReply
|
||||
displayableQuotedText:displayableQuotedText
|
||||
isOutgoing:isOutgoing];
|
||||
quotedMessageView.delegate = self;
|
||||
|
||||
self.quotedMessageView = quotedMessageView;
|
||||
[quotedMessageView createContents];
|
||||
[self.bubbleView addSubview:quotedMessageView];
|
||||
|
@ -1101,8 +1103,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[self handleMediaTapGesture];
|
||||
break;
|
||||
case OWSMessageGestureLocation_QuotedReply:
|
||||
if (self.message.quotedMessage) {
|
||||
[self.delegate didTapQuotedMessage:self.viewItem quotedMessage:self.message.quotedMessage];
|
||||
if (self.viewItem.quotedReply) {
|
||||
[self.delegate didTapConversationItem:self.viewItem quotedReply:self.viewItem.quotedReply];
|
||||
} else {
|
||||
OWSFail(@"%@ Missing quoted message.", self.logTag);
|
||||
}
|
||||
|
@ -1198,6 +1200,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return OWSMessageGestureLocation_Default;
|
||||
}
|
||||
|
||||
- (void)didTapQuotedReply:(OWSQuotedReplyModel *)quotedReply
|
||||
failedThumbnailDownloadAttachmentPointer:(TSAttachmentPointer *)attachmentPointer
|
||||
{
|
||||
[self.delegate didTapConversationItem:self.viewItem
|
||||
quotedReply:quotedReply
|
||||
failedThumbnailDownloadAttachmentPointer:attachmentPointer];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -7,10 +7,20 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@class DisplayableText;
|
||||
@class OWSBubbleStrokeView;
|
||||
@class OWSQuotedReplyModel;
|
||||
@class TSAttachmentPointer;
|
||||
@class TSQuotedMessage;
|
||||
|
||||
@protocol OWSQuotedMessageViewDelegate
|
||||
|
||||
- (void)didTapQuotedReply:(OWSQuotedReplyModel *)quotedReply
|
||||
failedThumbnailDownloadAttachmentPointer:(TSAttachmentPointer *)attachmentPointer;
|
||||
|
||||
@end
|
||||
|
||||
@interface OWSQuotedMessageView : UIView
|
||||
|
||||
@property (nonatomic, nullable, readonly) OWSBubbleStrokeView *boundsStrokeView;
|
||||
@property (nonatomic, nullable, weak) id<OWSQuotedMessageViewDelegate> delegate;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
OWSAssert(!self.boundsStrokeView);
|
||||
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
self.userInteractionEnabled = NO;
|
||||
self.userInteractionEnabled = YES;
|
||||
self.layoutMargins = UIEdgeInsetsZero;
|
||||
self.clipsToBounds = YES;
|
||||
|
||||
|
@ -140,6 +140,27 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
quotedAttachmentView.layer.cornerRadius = 2.f;
|
||||
quotedAttachmentView.clipsToBounds = YES;
|
||||
quotedAttachmentView.backgroundColor = [UIColor whiteColor];
|
||||
} else if (self.quotedMessage.thumbnailDownloadFailed) {
|
||||
// TODO design review icon and color
|
||||
UIImage *contentIcon =
|
||||
[[UIImage imageNamed:@"btnRefresh--white"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
||||
UIImageView *contentImageView = [self imageViewForImage:contentIcon];
|
||||
contentImageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
contentImageView.userInteractionEnabled = YES;
|
||||
contentImageView.tintColor = UIColor.whiteColor;
|
||||
quotedAttachmentView = [UIView containerView];
|
||||
[quotedAttachmentView addSubview:contentImageView];
|
||||
quotedAttachmentView.backgroundColor = self.highlightColor;
|
||||
quotedAttachmentView.layer.cornerRadius = self.quotedAttachmentSize * 0.5f;
|
||||
[contentImageView autoCenterInSuperview];
|
||||
[contentImageView
|
||||
autoSetDimensionsToSize:CGSizeMake(self.quotedAttachmentSize * 0.5f, self.quotedAttachmentSize * 0.5f)];
|
||||
contentImageView.layer.minificationFilter = kCAFilterTrilinear;
|
||||
contentImageView.layer.magnificationFilter = kCAFilterTrilinear;
|
||||
|
||||
UITapGestureRecognizer *tapGesture =
|
||||
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapFailedThumbnailDownload:)];
|
||||
[quotedAttachmentView addGestureRecognizer:tapGesture];
|
||||
} else {
|
||||
// TODO: This asset is wrong.
|
||||
// TODO: There's a special asset for audio files.
|
||||
|
@ -154,7 +175,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
autoSetDimensionsToSize:CGSizeMake(self.quotedAttachmentSize * 0.5f, self.quotedAttachmentSize * 0.5f)];
|
||||
}
|
||||
|
||||
quotedAttachmentView.userInteractionEnabled = NO;
|
||||
quotedAttachmentView.userInteractionEnabled = YES;
|
||||
[self addSubview:quotedAttachmentView];
|
||||
[quotedAttachmentView autoPinTrailingToSuperviewMarginWithInset:self.quotedContentHInset];
|
||||
[quotedAttachmentView autoVCenterInSuperview];
|
||||
|
@ -224,6 +245,24 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
}
|
||||
|
||||
- (void)didTapFailedThumbnailDownload:(UITapGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
DDLogDebug(@"%@ in didTapFailedThumbnailDownload", self.logTag);
|
||||
|
||||
if (!self.quotedMessage.thumbnailDownloadFailed) {
|
||||
OWSFail(@"%@ in %s thumbnailDownloadFailed was unexpectedly false", self.logTag, __PRETTY_FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.quotedMessage.thumbnailAttachmentPointer) {
|
||||
OWSFail(@"%@ in %s thumbnailAttachmentPointer was unexpectedly nil", self.logTag, __PRETTY_FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
[self.delegate didTapQuotedReply:self.quotedMessage
|
||||
failedThumbnailDownloadAttachmentPointer:self.quotedMessage.thumbnailAttachmentPointer];
|
||||
}
|
||||
|
||||
- (nullable UIImage *)tryToLoadThumbnailImage
|
||||
{
|
||||
if (!self.hasQuotedAttachmentThumbnailImage) {
|
||||
|
|
|
@ -2125,13 +2125,51 @@ typedef enum : NSUInteger {
|
|||
[self handleUnsentMessageTap:message];
|
||||
}
|
||||
|
||||
- (void)didTapQuotedMessage:(ConversationViewItem *)viewItem quotedMessage:(TSQuotedMessage *)quotedMessage
|
||||
- (void)didTapConversationItem:(ConversationViewItem *)viewItem
|
||||
quotedReply:(OWSQuotedReplyModel *)quotedReply
|
||||
failedThumbnailDownloadAttachmentPointer:(TSAttachmentPointer *)attachmentPointer
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
OWSAssert(viewItem);
|
||||
OWSAssert(quotedMessage);
|
||||
OWSAssert(quotedMessage.timestamp > 0);
|
||||
OWSAssert(quotedMessage.authorId.length > 0);
|
||||
OWSAssert(attachmentPointer);
|
||||
|
||||
TSMessage *message = (TSMessage *)viewItem.interaction;
|
||||
if (![message isKindOfClass:[TSMessage class]]) {
|
||||
OWSFail(@"%@ in %s message had unexpected class: %@", self.logTag, __PRETTY_FUNCTION__, message.class);
|
||||
return;
|
||||
}
|
||||
|
||||
OWSAttachmentsProcessor *processor =
|
||||
[[OWSAttachmentsProcessor alloc] initWithAttachmentPointer:attachmentPointer
|
||||
networkManager:self.networkManager];
|
||||
|
||||
[self.editingDatabaseConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[processor fetchAttachmentsForMessage:nil
|
||||
transaction:transaction
|
||||
success:^(TSAttachmentStream *_Nonnull attachmentStream) {
|
||||
[self.editingDatabaseConnection
|
||||
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull postSuccessTransaction) {
|
||||
[message setQuotedMessageThumbnailAttachmentStream:attachmentStream];
|
||||
[message saveWithTransaction:postSuccessTransaction];
|
||||
}];
|
||||
}
|
||||
failure:^(NSError *_Nonnull error) {
|
||||
DDLogWarn(@"%@ Failed to redownload thumbnail with error: %@", self.logTag, error);
|
||||
[self.editingDatabaseConnection
|
||||
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull postSuccessTransaction) {
|
||||
[message touchWithTransaction:transaction];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)didTapConversationItem:(ConversationViewItem *)viewItem quotedMessage:(OWSQuotedReplyModel *)quotedReply
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
OWSAssert(viewItem);
|
||||
OWSAssert(quotedReply);
|
||||
OWSAssert(quotedReply.timestamp > 0);
|
||||
OWSAssert(quotedReply.authorId.length > 0);
|
||||
|
||||
// We try to find the index of the item within the current thread's
|
||||
// interactions that includes the "quoted interaction".
|
||||
|
@ -2154,8 +2192,8 @@ typedef enum : NSUInteger {
|
|||
__block NSNumber *_Nullable groupIndex = nil;
|
||||
|
||||
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
quotedInteraction = [ThreadUtil findInteractionInThreadByTimestamp:quotedMessage.timestamp
|
||||
authorId:quotedMessage.authorId
|
||||
quotedInteraction = [ThreadUtil findInteractionInThreadByTimestamp:quotedReply.timestamp
|
||||
authorId:quotedReply.authorId
|
||||
threadUniqueId:self.thread.uniqueId
|
||||
transaction:transaction];
|
||||
if (!quotedInteraction) {
|
||||
|
|
|
@ -655,7 +655,11 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
|
|||
// no - op
|
||||
}
|
||||
|
||||
func didTapQuotedMessage(_ viewItem: ConversationViewItem, quotedMessage: TSQuotedMessage) {
|
||||
func didTapConversationItem(_ viewItem: ConversationViewItem, quotedReply: OWSQuotedReplyModel) {
|
||||
// no - op
|
||||
}
|
||||
|
||||
func didTapConversationItem(_ viewItem: ConversationViewItem, quotedReply: OWSQuotedReplyModel, failedThumbnailDownloadAttachmentPointer attachmentPointer: TSAttachmentPointer) {
|
||||
// no - op
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
@class TSAttachmentPointer;
|
||||
@class TSAttachmentStream;
|
||||
@class TSMessage;
|
||||
@class TSQuotedMessage;
|
||||
|
@ -15,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, readonly) uint64_t timestamp;
|
||||
@property (nonatomic, readonly) NSString *authorId;
|
||||
@property (nonatomic, readonly, nullable) TSAttachmentStream *attachmentStream;
|
||||
@property (nonatomic, readonly, nullable) TSAttachmentPointer *thumbnailAttachmentPointer;
|
||||
@property (nonatomic, readonly) BOOL thumbnailDownloadFailed;
|
||||
|
||||
// This property should be set IFF we are quoting a text message
|
||||
// or attachment with caption.
|
||||
|
@ -29,11 +32,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, readonly, nullable) NSString *sourceFilename;
|
||||
@property (nonatomic, readonly, nullable) UIImage *thumbnailImage;
|
||||
|
||||
// Used for building an outgoing quoted reply preview, before it's sent
|
||||
- (instancetype)initWithTimestamp:(uint64_t)timestamp
|
||||
authorId:(NSString *)authorId
|
||||
body:(NSString *_Nullable)body
|
||||
attachmentStream:(nullable TSAttachmentStream *)attachment;
|
||||
|
||||
// Used for persisted quoted replies, both incoming and outgoing.
|
||||
- (instancetype)initWithQuotedMessage:(TSQuotedMessage *)quotedMessage
|
||||
transaction:(YapDatabaseReadTransaction *)transaction;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#import <SignalServiceKit/MIMETypeUtil.h>
|
||||
#import <SignalServiceKit/OWSMessageSender.h>
|
||||
#import <SignalServiceKit/TSAccountManager.h>
|
||||
#import <SignalServiceKit/TSAttachmentPointer.h>
|
||||
#import <SignalServiceKit/TSAttachmentStream.h>
|
||||
#import <SignalServiceKit/TSIncomingMessage.h>
|
||||
#import <SignalServiceKit/TSMessage.h>
|
||||
|
@ -27,9 +28,51 @@
|
|||
thumbnailImage:attachmentStream.thumbnailImage
|
||||
contentType:attachmentStream.contentType
|
||||
sourceFilename:attachmentStream.sourceFilename
|
||||
attachmentStream:attachmentStream];
|
||||
attachmentStream:attachmentStream
|
||||
thumbnailAttachmentPointer:nil
|
||||
thumbnailDownloadFailed:NO];
|
||||
}
|
||||
|
||||
- (instancetype)initWithQuotedMessage:(TSQuotedMessage *)quotedMessage
|
||||
transaction:(YapDatabaseReadTransaction *)transaction
|
||||
{
|
||||
OWSAssert(quotedMessage.quotedAttachments.count <= 1);
|
||||
OWSAttachmentInfo *attachmentInfo = quotedMessage.quotedAttachments.firstObject;
|
||||
|
||||
BOOL thumbnailDownloadFailed = NO;
|
||||
UIImage *_Nullable thumbnailImage;
|
||||
TSAttachmentPointer *attachmentPointer;
|
||||
if (attachmentInfo.thumbnailAttachmentStreamId) {
|
||||
TSAttachment *attachment =
|
||||
[TSAttachment fetchObjectWithUniqueID:attachmentInfo.thumbnailAttachmentStreamId transaction:transaction];
|
||||
|
||||
TSAttachmentStream *attachmentStream;
|
||||
if ([attachment isKindOfClass:[TSAttachmentStream class]]) {
|
||||
attachmentStream = (TSAttachmentStream *)attachment;
|
||||
thumbnailImage = attachmentStream.image;
|
||||
}
|
||||
} else if (attachmentInfo.thumbnailAttachmentPointerId) {
|
||||
// download failed, or hasn't completed yet.
|
||||
TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentInfo.thumbnailAttachmentPointerId transaction:transaction];
|
||||
|
||||
if ([attachment isKindOfClass:[TSAttachmentPointer class]]) {
|
||||
attachmentPointer = (TSAttachmentPointer *)attachment;
|
||||
if (attachmentPointer.state == TSAttachmentPointerStateFailed) {
|
||||
thumbnailDownloadFailed = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [self initWithTimestamp:quotedMessage.timestamp
|
||||
authorId:quotedMessage.authorId
|
||||
body:quotedMessage.body
|
||||
thumbnailImage:thumbnailImage
|
||||
contentType:attachmentInfo.contentType
|
||||
sourceFilename:attachmentInfo.sourceFilename
|
||||
attachmentStream:nil
|
||||
thumbnailAttachmentPointer:attachmentPointer
|
||||
thumbnailDownloadFailed:thumbnailDownloadFailed];
|
||||
}
|
||||
|
||||
- (instancetype)initWithTimestamp:(uint64_t)timestamp
|
||||
authorId:(NSString *)authorId
|
||||
|
@ -38,6 +81,8 @@
|
|||
contentType:(nullable NSString *)contentType
|
||||
sourceFilename:(nullable NSString *)sourceFilename
|
||||
attachmentStream:(nullable TSAttachmentStream *)attachmentStream
|
||||
thumbnailAttachmentPointer:(nullable TSAttachmentPointer *)thumbnailAttachmentPointer
|
||||
thumbnailDownloadFailed:(BOOL)thumbnailDownloadFailed
|
||||
{
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
|
@ -51,37 +96,12 @@
|
|||
_contentType = contentType;
|
||||
_sourceFilename = sourceFilename;
|
||||
_attachmentStream = attachmentStream;
|
||||
_thumbnailAttachmentPointer = thumbnailAttachmentPointer;
|
||||
_thumbnailDownloadFailed = thumbnailDownloadFailed;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithQuotedMessage:(TSQuotedMessage *)quotedMessage
|
||||
transaction:(YapDatabaseReadTransaction *)transaction
|
||||
{
|
||||
OWSAssert(quotedMessage.quotedAttachments.count <= 1);
|
||||
OWSAttachmentInfo *attachmentInfo = quotedMessage.quotedAttachments.firstObject;
|
||||
|
||||
UIImage *_Nullable thumbnailImage;
|
||||
if (attachmentInfo.thumbnailAttachmentStreamId) {
|
||||
TSAttachment *attachment =
|
||||
[TSAttachment fetchObjectWithUniqueID:attachmentInfo.thumbnailAttachmentStreamId transaction:transaction];
|
||||
|
||||
TSAttachmentStream *attachmentStream;
|
||||
if ([attachment isKindOfClass:[TSAttachmentStream class]]) {
|
||||
attachmentStream = (TSAttachmentStream *)attachment;
|
||||
thumbnailImage = attachmentStream.image;
|
||||
}
|
||||
}
|
||||
|
||||
return [self initWithTimestamp:quotedMessage.timestamp
|
||||
authorId:quotedMessage.authorId
|
||||
body:quotedMessage.body
|
||||
thumbnailImage:thumbnailImage
|
||||
contentType:attachmentInfo.contentType
|
||||
sourceFilename:attachmentInfo.sourceFilename
|
||||
attachmentStream:nil];
|
||||
}
|
||||
|
||||
- (TSQuotedMessage *)buildQuotedMessage
|
||||
{
|
||||
NSArray *attachments = self.attachmentStream ? @[ self.attachmentStream ] : @[];
|
||||
|
|
Loading…
Reference in a new issue