Fix issues in media gallery cells; Improve debug galleries.
This commit is contained in:
parent
88a1186e4e
commit
60c5a84dd2
|
@ -2287,28 +2287,28 @@
|
|||
B633C4FD1A1D190B0059AC12 /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34B6A90A218BA1D0007C4606 /* typing-animation.gif */,
|
||||
AD83FF461A73428300B5C81A /* audio_play_button_blue.png */,
|
||||
AD83FF381A73426500B5C81A /* audio_pause_button_blue.png */,
|
||||
AD83FF391A73426500B5C81A /* audio_pause_button_blue@2x.png */,
|
||||
AD83FF3D1A73426500B5C81A /* audio_pause_button.png */,
|
||||
AD83FF3E1A73426500B5C81A /* audio_pause_button@2x.png */,
|
||||
AD83FF461A73428300B5C81A /* audio_play_button_blue.png */,
|
||||
AD83FF3A1A73426500B5C81A /* audio_play_button_blue@2x.png */,
|
||||
AD83FF3B1A73426500B5C81A /* audio_play_button.png */,
|
||||
AD83FF3C1A73426500B5C81A /* audio_play_button@2x.png */,
|
||||
AD83FF3D1A73426500B5C81A /* audio_pause_button.png */,
|
||||
AD83FF3E1A73426500B5C81A /* audio_pause_button@2x.png */,
|
||||
B10C9B5B1A7049EC00ECA2BF /* pause_icon.png */,
|
||||
B10C9B5C1A7049EC00ECA2BF /* pause_icon@2x.png */,
|
||||
B10C9B5D1A7049EC00ECA2BF /* play_icon.png */,
|
||||
B10C9B5E1A7049EC00ECA2BF /* play_icon@2x.png */,
|
||||
B633C5041A1D190B0059AC12 /* call@2x.png */,
|
||||
B633C50B1A1D190B0059AC12 /* contact_default_feed.png */,
|
||||
B633C51B1A1D190B0059AC12 /* endcall@2x.png */,
|
||||
FC5CDF371A3393DD00B47253 /* error_white@2x.png */,
|
||||
B633C5411A1D190B0059AC12 /* mute_off@2x.png */,
|
||||
B633C5421A1D190B0059AC12 /* mute_on@2x.png */,
|
||||
B10C9B5B1A7049EC00ECA2BF /* pause_icon.png */,
|
||||
B10C9B5C1A7049EC00ECA2BF /* pause_icon@2x.png */,
|
||||
B10C9B5D1A7049EC00ECA2BF /* play_icon.png */,
|
||||
B10C9B5E1A7049EC00ECA2BF /* play_icon@2x.png */,
|
||||
FC91203F1A39EFB70074545C /* qr@2x.png */,
|
||||
B633C54C1A1D190B0059AC12 /* quit@2x.png */,
|
||||
B633C5501A1D190B0059AC12 /* savephoto@2x.png */,
|
||||
34B6A90A218BA1D0007C4606 /* typing-animation.gif */,
|
||||
FC5CDF381A3393DD00B47253 /* warning_white@2x.png */,
|
||||
);
|
||||
path = Images;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#import "OWSBackup.h"
|
||||
#import "OWSBackupIO.h"
|
||||
#import "OWSBezierPathView.h"
|
||||
#import "OWSBubbleShapeView.h"
|
||||
#import "OWSBubbleView.h"
|
||||
#import "OWSCallNotificationsAdaptee.h"
|
||||
#import "OWSDatabaseMigration.h"
|
||||
|
|
|
@ -51,6 +51,12 @@ public class ConversationMediaView: UIView {
|
|||
}
|
||||
}
|
||||
|
||||
private func addMediaSubview(_ subview: UIView) {
|
||||
addSubview(subview)
|
||||
subview.autoPinEdgesToSuperviewEdges()
|
||||
// TODO: Possibly add upload/download indicator here.
|
||||
}
|
||||
|
||||
private func configureForAnimatedImage(attachmentStream: TSAttachmentStream) {
|
||||
guard let cacheKey = attachmentStream.uniqueId else {
|
||||
owsFailDebug("Attachment stream missing unique ID.")
|
||||
|
@ -65,8 +71,7 @@ public class ConversationMediaView: UIView {
|
|||
animatedImageView.layer.minificationFilter = kCAFilterTrilinear
|
||||
animatedImageView.layer.magnificationFilter = kCAFilterTrilinear
|
||||
animatedImageView.backgroundColor = Theme.offBackgroundColor
|
||||
addSubview(animatedImageView)
|
||||
animatedImageView.autoPinEdgesToSuperviewEdges()
|
||||
addMediaSubview(animatedImageView)
|
||||
loadBlock = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
@ -112,8 +117,7 @@ public class ConversationMediaView: UIView {
|
|||
stillImageView.layer.minificationFilter = kCAFilterTrilinear
|
||||
stillImageView.layer.magnificationFilter = kCAFilterTrilinear
|
||||
stillImageView.backgroundColor = Theme.offBackgroundColor
|
||||
addSubview(stillImageView)
|
||||
stillImageView.autoPinEdgesToSuperviewEdges()
|
||||
addMediaSubview(stillImageView)
|
||||
loadBlock = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
@ -158,8 +162,7 @@ public class ConversationMediaView: UIView {
|
|||
stillImageView.layer.minificationFilter = kCAFilterTrilinear
|
||||
stillImageView.layer.magnificationFilter = kCAFilterTrilinear
|
||||
stillImageView.backgroundColor = Theme.offBackgroundColor
|
||||
addSubview(stillImageView)
|
||||
stillImageView.autoPinEdgesToSuperviewEdges()
|
||||
addMediaSubview(stillImageView)
|
||||
|
||||
// TODO: Hide during upload/download.
|
||||
let videoPlayIcon = UIImage(named: "play_button")
|
||||
|
|
|
@ -7,11 +7,18 @@ import Foundation
|
|||
@objc(OWSMediaGalleryCellView)
|
||||
public class MediaGalleryCellView: UIStackView {
|
||||
private let items: [ConversationMediaGalleryItem]
|
||||
private let itemViews: [ConversationMediaView]
|
||||
|
||||
@objc
|
||||
public let itemViews: [ConversationMediaView]
|
||||
|
||||
private static let kSpacingPts: CGFloat = 2
|
||||
private static let kMaxItems = 5
|
||||
|
||||
@available(*, unavailable, message: "use other init() instead.")
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
notImplemented()
|
||||
}
|
||||
|
||||
@objc
|
||||
public required init(mediaCache: NSCache<NSString, AnyObject>,
|
||||
items: [ConversationMediaGalleryItem],
|
||||
|
@ -24,7 +31,8 @@ public class MediaGalleryCellView: UIStackView {
|
|||
|
||||
super.init(frame: .zero)
|
||||
|
||||
backgroundColor = Theme.backgroundColor
|
||||
// UIStackView's backgroundColor property has no effect.
|
||||
addBackgroundView(withBackgroundColor: Theme.backgroundColor)
|
||||
|
||||
createContents(maxMessageWidth: maxMessageWidth)
|
||||
}
|
||||
|
@ -173,11 +181,6 @@ public class MediaGalleryCellView: UIStackView {
|
|||
}
|
||||
}
|
||||
|
||||
@available(*, unavailable, message: "use other init() instead.")
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
notImplemented()
|
||||
}
|
||||
|
||||
private class func itemsToDisplay(forItems items: [ConversationMediaGalleryItem]) -> [ConversationMediaGalleryItem] {
|
||||
// TODO: Unless design changes, we want to display
|
||||
// items which are still downloading and invalid
|
||||
|
|
|
@ -23,7 +23,8 @@ typedef NS_ENUM(NSUInteger, OWSBubbleShapeViewMode) {
|
|||
@property (nonatomic) CAShapeLayer *shapeLayer;
|
||||
@property (nonatomic) CAShapeLayer *maskLayer;
|
||||
|
||||
@property (nonatomic, weak) OWSBubbleView *bubbleView;
|
||||
@property (nonatomic, nullable, weak) OWSBubbleView *bubbleView;
|
||||
@property (nonatomic) BOOL isConfigured;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -33,7 +34,6 @@ typedef NS_ENUM(NSUInteger, OWSBubbleShapeViewMode) {
|
|||
|
||||
- (void)configure
|
||||
{
|
||||
self.mode = OWSBubbleShapeViewMode_Draw;
|
||||
self.opaque = NO;
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.layoutMargins = UIEdgeInsetsZero;
|
||||
|
@ -42,8 +42,11 @@ typedef NS_ENUM(NSUInteger, OWSBubbleShapeViewMode) {
|
|||
[self.layer addSublayer:self.shapeLayer];
|
||||
|
||||
self.maskLayer = [CAShapeLayer new];
|
||||
}
|
||||
|
||||
self.isConfigured = YES;
|
||||
|
||||
[self updateLayers];
|
||||
}
|
||||
|
||||
- (instancetype)initDraw
|
||||
{
|
||||
|
@ -100,7 +103,6 @@ typedef NS_ENUM(NSUInteger, OWSBubbleShapeViewMode) {
|
|||
_innerShadowOpacity = opacity;
|
||||
|
||||
[self configure];
|
||||
[self updateLayers];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -176,15 +178,24 @@ typedef NS_ENUM(NSUInteger, OWSBubbleShapeViewMode) {
|
|||
[self updateLayers];
|
||||
}
|
||||
|
||||
- (void)setBubbleView:(nullable OWSBubbleView *)bubbleView
|
||||
{
|
||||
_bubbleView = bubbleView;
|
||||
|
||||
[self updateLayers];
|
||||
}
|
||||
|
||||
- (void)updateLayers
|
||||
{
|
||||
if (!self.shapeLayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.bubbleView) {
|
||||
return;
|
||||
}
|
||||
if (!self.isConfigured) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent the layer from animating changes.
|
||||
[CATransaction begin];
|
||||
|
|
|
@ -21,7 +21,7 @@ typedef NS_OPTIONS(NSUInteger, OWSDirectionalRectCorner) {
|
|||
|
||||
- (void)updateLayers;
|
||||
|
||||
- (void)setBubbleView:(OWSBubbleView *)bubbleView;
|
||||
- (void)setBubbleView:(nullable OWSBubbleView *)bubbleView;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -351,15 +351,6 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
|
|||
|
||||
if (self.hasBodyMediaWithThumbnail) {
|
||||
[self.stackView addArrangedSubview:bodyMediaView];
|
||||
|
||||
OWSBubbleShapeView *innerShadowView = [[OWSBubbleShapeView alloc]
|
||||
initInnerShadowWithColor:(Theme.isDarkThemeEnabled ? UIColor.ows_whiteColor
|
||||
: UIColor.ows_blackColor)
|
||||
radius:0.5f
|
||||
opacity:0.15f];
|
||||
[bodyMediaView addSubview:innerShadowView];
|
||||
[self.bubbleView addPartnerView:innerShadowView];
|
||||
[self.viewConstraints addObjectsFromArray:[innerShadowView ows_autoPinToSuperviewEdges]];
|
||||
} else {
|
||||
OWSAssertDebug(self.cellType == OWSMessageCellType_ContactShare);
|
||||
|
||||
|
@ -620,7 +611,8 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
|
|||
|
||||
- (BOOL)hasFullWidthMediaView
|
||||
{
|
||||
return (self.hasBodyMediaWithThumbnail || self.cellType == OWSMessageCellType_ContactShare);
|
||||
return (self.hasBodyMediaWithThumbnail || self.cellType == OWSMessageCellType_ContactShare
|
||||
|| self.cellType == OWSMessageCellType_MediaGallery);
|
||||
}
|
||||
|
||||
- (BOOL)canFooterOverlayMedia
|
||||
|
@ -802,6 +794,14 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
|
|||
self.unloadCellContentBlock = ^{
|
||||
[galleryView unloadMedia];
|
||||
};
|
||||
for (UIView *itemView in galleryView.itemViews) {
|
||||
OWSBubbleShapeView *strokeView = [[OWSBubbleShapeView alloc] initDraw];
|
||||
strokeView.strokeColor = [UIColor colorWithWhite:0.5f alpha:0.4f];
|
||||
strokeView.strokeThickness = 1.f;
|
||||
[itemView addSubview:strokeView];
|
||||
[self.bubbleView addPartnerView:strokeView];
|
||||
[self.viewConstraints addObjectsFromArray:[strokeView ows_autoPinToSuperviewEdges]];
|
||||
}
|
||||
|
||||
return galleryView;
|
||||
}
|
||||
|
@ -821,6 +821,14 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
|
|||
};
|
||||
[self addAttachmentUploadViewIfNecessary];
|
||||
|
||||
OWSBubbleShapeView *innerShadowView = [[OWSBubbleShapeView alloc]
|
||||
initInnerShadowWithColor:(Theme.isDarkThemeEnabled ? UIColor.ows_whiteColor : UIColor.ows_blackColor)
|
||||
radius:0.5f
|
||||
opacity:0.15f];
|
||||
[mediaView addSubview:innerShadowView];
|
||||
[self.bubbleView addPartnerView:innerShadowView];
|
||||
[self.viewConstraints addObjectsFromArray:[innerShadowView ows_autoPinToSuperviewEdges]];
|
||||
|
||||
return mediaView;
|
||||
}
|
||||
|
||||
|
|
|
@ -4645,52 +4645,85 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
|
|||
const uint32_t kMinImageCount = 2;
|
||||
const uint32_t kMaxImageCount = 10;
|
||||
uint32_t imageCount = kMinImageCount + arc4random_uniform(kMaxImageCount - kMinImageCount);
|
||||
[self sendMediaGalleryInThread:thread imageCount:imageCount];
|
||||
NSString *_Nullable messageBody = (arc4random_uniform(2) > 0 ? @"This is the media gallery title..." : nil);
|
||||
[self sendMediaGalleryInThread:thread imageCount:imageCount messageBody:messageBody];
|
||||
}
|
||||
|
||||
+ (void)sendExemplaryMediaGalleriesInThread:(TSThread *)thread
|
||||
{
|
||||
OWSLogInfo(@"");
|
||||
|
||||
[self sendMediaGalleryInThread:thread imageCount:2];
|
||||
[self sendMediaGalleryInThread:thread imageCount:3];
|
||||
[self sendMediaGalleryInThread:thread imageCount:4];
|
||||
[self sendMediaGalleryInThread:thread imageCount:5];
|
||||
[self sendMediaGalleryInThread:thread imageCount:6];
|
||||
[self sendMediaGalleryInThread:thread imageCount:2 messageBody:nil];
|
||||
[self sendMediaGalleryInThread:thread imageCount:3 messageBody:nil];
|
||||
[self sendMediaGalleryInThread:thread imageCount:4 messageBody:nil];
|
||||
[self sendMediaGalleryInThread:thread imageCount:5 messageBody:nil];
|
||||
[self sendMediaGalleryInThread:thread imageCount:6 messageBody:nil];
|
||||
[self sendMediaGalleryInThread:thread imageCount:7 messageBody:nil];
|
||||
NSString *messageBody = @"This is the media gallery title...";
|
||||
[self sendMediaGalleryInThread:thread imageCount:2 messageBody:messageBody];
|
||||
[self sendMediaGalleryInThread:thread imageCount:3 messageBody:messageBody];
|
||||
[self sendMediaGalleryInThread:thread imageCount:4 messageBody:messageBody];
|
||||
[self sendMediaGalleryInThread:thread imageCount:5 messageBody:messageBody];
|
||||
[self sendMediaGalleryInThread:thread imageCount:6 messageBody:messageBody];
|
||||
[self sendMediaGalleryInThread:thread imageCount:7 messageBody:messageBody];
|
||||
}
|
||||
|
||||
+ (void)sendMediaGalleryInThread:(TSThread *)thread imageCount:(uint32_t)imageCount
|
||||
+ (void)sendMediaGalleryInThread:(TSThread *)thread
|
||||
imageCount:(uint32_t)imageCount
|
||||
messageBody:(nullable NSString *)messageBody
|
||||
fakeAssetLoaders:(NSArray<DebugUIMessagesAssetLoader *> *)fakeAssetLoaders
|
||||
{
|
||||
OWSAssertDebug(imageCount > 0);
|
||||
OWSLogInfo(@"");
|
||||
|
||||
NSMutableArray<SignalAttachment *> *attachments = [NSMutableArray new];
|
||||
for (uint32_t i = 0; i < imageCount; i++) {
|
||||
UIColor *imageColor = [UIColor colorWithRed:arc4random_uniform(256) / 255.f
|
||||
green:arc4random_uniform(256) / 255.f
|
||||
blue:arc4random_uniform(256) / 255.f
|
||||
alpha:1.f];
|
||||
UIImage *image = [UIImage imageWithColor:imageColor size:CGSizeMake(10.f, 10.f)];
|
||||
OWSAssertDebug(image);
|
||||
NSData *pngData = UIImagePNGRepresentation(image);
|
||||
OWSAssertDebug(pngData);
|
||||
NSString *filePath = [OWSFileSystem temporaryFilePathWithFileExtension:@"png"];
|
||||
[pngData writeToFile:filePath atomically:YES];
|
||||
OWSAssertDebug([NSFileManager.defaultManager fileExistsAtPath:filePath]);
|
||||
DataSource *dataSource = [DataSourcePath dataSourceWithFilePath:filePath shouldDeleteOnDeallocation:YES];
|
||||
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource
|
||||
dataUTI:(NSString *)kUTTypePNG
|
||||
imageQuality:TSImageQualityOriginal];
|
||||
DebugUIMessagesAssetLoader *fakeAssetLoader
|
||||
= fakeAssetLoaders[arc4random_uniform((uint32_t)fakeAssetLoaders.count)];
|
||||
OWSAssertDebug([NSFileManager.defaultManager fileExistsAtPath:fakeAssetLoader.filePath]);
|
||||
DataSource *dataSource =
|
||||
[DataSourcePath dataSourceWithFilePath:fakeAssetLoader.filePath shouldDeleteOnDeallocation:NO];
|
||||
SignalAttachment *attachment =
|
||||
[SignalAttachment attachmentWithDataSource:dataSource
|
||||
dataUTI:[MIMETypeUtil utiTypeForMIMEType:fakeAssetLoader.mimeType]
|
||||
imageQuality:TSImageQualityOriginal];
|
||||
[attachments addObject:attachment];
|
||||
}
|
||||
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
TSOutgoingMessage *message =
|
||||
[ThreadUtil enqueueMessageWithAttachments:attachments inThread:thread quotedReplyModel:nil];
|
||||
TSOutgoingMessage *message = [ThreadUtil enqueueMessageWithAttachments:attachments
|
||||
messageBody:messageBody
|
||||
inThread:thread
|
||||
quotedReplyModel:nil];
|
||||
OWSLogError(@"timestamp: %llu.", message.timestamp);
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)sendMediaGalleryInThread:(TSThread *)thread
|
||||
imageCount:(uint32_t)imageCount
|
||||
messageBody:(nullable NSString *)messageBody
|
||||
{
|
||||
OWSAssertDebug(thread);
|
||||
|
||||
NSArray<DebugUIMessagesAssetLoader *> *fakeAssetLoaders = @[
|
||||
[DebugUIMessagesAssetLoader jpegInstance],
|
||||
[DebugUIMessagesAssetLoader largePngInstance],
|
||||
[DebugUIMessagesAssetLoader tinyPngInstance],
|
||||
[DebugUIMessagesAssetLoader gifInstance],
|
||||
[DebugUIMessagesAssetLoader mp4Instance],
|
||||
];
|
||||
[DebugUIMessagesAssetLoader prepareAssetLoaders:fakeAssetLoaders
|
||||
success:^{
|
||||
[self sendMediaGalleryInThread:thread
|
||||
imageCount:imageCount
|
||||
messageBody:messageBody
|
||||
fakeAssetLoaders:fakeAssetLoaders];
|
||||
}
|
||||
failure:^{
|
||||
OWSLogError(@"Could not prepare fake asset loaders.");
|
||||
}];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
|
|
@ -41,6 +41,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
+ (instancetype)oversizeTextInstance;
|
||||
+ (instancetype)oversizeTextInstanceWithText:(NSString *)text;
|
||||
|
||||
#pragma mark -
|
||||
|
||||
+ (void)prepareAssetLoaders:(NSArray<DebugUIMessagesAssetLoader *> *)assetLoaders
|
||||
success:(dispatch_block_t)success
|
||||
failure:(dispatch_block_t)failure;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
#import "DebugUIMessagesAssetLoader.h"
|
||||
#import <AFNetworking/AFHTTPSessionManager.h>
|
||||
#import <AFNetworking/AFNetworking.h>
|
||||
#import <PromiseKit/AnyPromise.h>
|
||||
#import <SignalCoreKit/Randomness.h>
|
||||
#import <SignalServiceKit/MIMETypeUtil.h>
|
||||
#import <SignalServiceKit/OWSFileSystem.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <SignalServiceKit/TSAttachment.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
@ -151,6 +153,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
OWSAssertDebug(label.length > 0);
|
||||
|
||||
@autoreleasepool {
|
||||
imageSize.width /= UIScreen.mainScreen.scale;
|
||||
imageSize.height /= UIScreen.mainScreen.scale;
|
||||
|
||||
CGRect frame = CGRectZero;
|
||||
frame.size = imageSize;
|
||||
CGFloat smallDimension = MIN(imageSize.width, imageSize.height);
|
||||
|
@ -575,6 +580,49 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return instance;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
+ (void)prepareAssetLoaders:(NSArray<DebugUIMessagesAssetLoader *> *)assetLoaders
|
||||
success:(dispatch_block_t)success
|
||||
failure:(dispatch_block_t)failure
|
||||
{
|
||||
|
||||
NSMutableArray<AnyPromise *> *promises = [NSMutableArray array];
|
||||
NSMutableArray<NSError *> *errors = [NSMutableArray array];
|
||||
|
||||
for (DebugUIMessagesAssetLoader *assetLoader in assetLoaders) {
|
||||
// Use chained promises to make the code more readable.
|
||||
AnyPromise *promise = [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
|
||||
assetLoader.prepareBlock(
|
||||
^{
|
||||
// The value doesn't matter, we just need any non-NSError value.
|
||||
resolve(@(1));
|
||||
},
|
||||
^{
|
||||
NSError *error =
|
||||
[NSError errorWithDomain:@"DebugUI"
|
||||
code:0
|
||||
userInfo:@{ NSLocalizedDescriptionKey : @"Could not prepare fake assets." }];
|
||||
@synchronized(errors) {
|
||||
[errors addObject:error];
|
||||
}
|
||||
resolve(error);
|
||||
});
|
||||
}];
|
||||
[promises addObject:promise];
|
||||
}
|
||||
|
||||
// We could use PMKJoin() or PMKWhen().
|
||||
[PMKJoin(promises)
|
||||
.then(^(id value) {
|
||||
success();
|
||||
})
|
||||
.catch(^(id error) {
|
||||
OWSLogError(@"Could not prepare fake asset loaders: %@.", error);
|
||||
failure();
|
||||
}) retainUntilComplete];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -54,6 +54,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel;
|
||||
|
||||
+ (TSOutgoingMessage *)enqueueMessageWithAttachments:(NSArray<SignalAttachment *> *)attachments
|
||||
messageBody:(nullable NSString *)messageBody
|
||||
inThread:(TSThread *)thread
|
||||
quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel;
|
||||
|
||||
|
|
|
@ -96,11 +96,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return [self enqueueMessageWithAttachments:@[
|
||||
attachment,
|
||||
]
|
||||
messageBody:attachment.captionText
|
||||
inThread:thread
|
||||
quotedReplyModel:quotedReplyModel];
|
||||
}
|
||||
|
||||
+ (TSOutgoingMessage *)enqueueMessageWithAttachments:(NSArray<SignalAttachment *> *)attachments
|
||||
messageBody:(nullable NSString *)messageBody
|
||||
inThread:(TSThread *)thread
|
||||
quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel
|
||||
{
|
||||
|
@ -117,8 +119,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
uint32_t expiresInSeconds = (configuration.isEnabled ? configuration.durationSeconds : 0);
|
||||
BOOL isVoiceMessage = (attachments.count == 1 && attachments.lastObject.isVoiceMessage);
|
||||
// TODO: Support multi-image captions.
|
||||
NSString *_Nullable messageBody = attachments.lastObject.captionText;
|
||||
TSOutgoingMessage *message =
|
||||
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
|
|
Loading…
Reference in New Issue