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