// _____ _
// |_ _| |_ _ _ ___ ___ _ __ __ _
// | | | ' \| '_/ -_) -_) ' \/ _` |_
// |_| |_||_|_| \___\___|_|_|_\__,_(_)
//
// Threema iOS Client
// Copyright (c) 2015-2020 Threema GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#import "MessageActivityItem.h"
#import "TextMessage.h"
#import "ImageMessage.h"
#import "VideoMessage.h"
#import "AudioMessage.h"
#import "FileMessage.h"
#import "UTIConverter.h"
#ifdef DEBUG
static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
#else
static const DDLogLevel ddLogLevel = DDLogLevelWarning;
#endif
@interface MessageActivityItem ()
@property BaseMessage *message;
@property NSURL *url;
@property BOOL didExportData;
@end
@implementation MessageActivityItem
+ (instancetype)activityItemFor:(BaseMessage *)message {
return [[MessageActivityItem alloc] initWith: message];
}
- (instancetype)initWith:(BaseMessage *)message
{
self = [super init];
if (self) {
self.message = message;
self.didExportData = NO;
}
return self;
}
- (NSURL *)dataUrl {
if ([_message isKindOfClass:[AudioMessage class]]) {
return [self audioUrl];
} else if ([_message isKindOfClass:[ImageMessage class]]) {
return [self imageUrl];
} else if ([_message isKindOfClass:[VideoMessage class]]) {
return [self videoUrl];
} else if ([_message isKindOfClass:[FileMessage class]]) {
NSString *filename = [FileUtility getTemporaryFileName];
return [((FileMessage *)_message) tmpURL:filename];
}
return nil;
}
- (NSURL *)tmpShareDirUrl {
NSURL *tmpDirUrl = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
return [tmpDirUrl URLByAppendingPathComponent:SHARE_FILE_PREFIX];
}
- (NSURL *)audioUrl {
return [[self tmpShareDirUrl] URLByAppendingPathExtension: MEDIA_EXTENSION_AUDIO];
}
- (NSURL *)imageUrl {
return [[self tmpShareDirUrl] URLByAppendingPathExtension:MEDIA_EXTENSION_IMAGE];
}
- (NSURL *)videoUrl {
return [[self tmpShareDirUrl] URLByAppendingPathExtension: MEDIA_EXTENSION_VIDEO];
}
- (void)exportDataToUrl {
if (_didExportData) {
return;
}
_didExportData = YES;
if ([_message isKindOfClass:[AudioMessage class]]) {
AudioMessage *audioMessage = (AudioMessage*)self.message;
[audioMessage.audio.data writeToURL:_url atomically:NO];
} else if ([_message isKindOfClass:[ImageMessage class]]) {
ImageMessage *imageMessage = (ImageMessage*)self.message;
// strip image metadata
UIImage *image = imageMessage.image.uiImage;
NSData *imageData = UIImageJPEGRepresentation(image, kJPEGCompressionQuality);
[imageData writeToURL:_url atomically:NO];
} else if ([_message isKindOfClass:[VideoMessage class]]) {
VideoMessage *videoMessage = (VideoMessage*)self.message;
[videoMessage.video.data writeToURL:_url atomically:NO];
} else if ([_message isKindOfClass:[FileMessage class]]) {
FileMessage *fileMessage = (FileMessage *)self.message;
[fileMessage exportDataToURL:_url];
}
}
- (NSURL *)getURL {
if (_url == nil) {
_url = [self dataUrl];
}
return _url;
}
#pragma mark - UIActivityItemSource
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType {
if ([_message isKindOfClass:[TextMessage class]]) {
return ((TextMessage *)_message).text;
}
if (_url) {
[self exportDataToUrl];
if ([_message isKindOfClass:[FileMessage class]] && [activityType isEqualToString:@"ch.threema.iapp.forwardMsg"]) {
NSNumber *type = ((FileMessage *)_message).type;
if (type == nil) {
type = @0;
}
return @{@"url": _url, @"renderType": type};
} else {
return _url;
}
}
// unsupported message type
DDLogInfo(@"MessageActivityItem: unsupported message type");
return nil;
}
- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController {
if ([_message isKindOfClass:[TextMessage class]]) {
return ((TextMessage *)_message).text;
}
// don't try to return thumbnail image, it won't work
_url = [self dataUrl];
// some activities only appear in menu if file is exported at this point in time
// that's ok since files will be deleted after activity controller finishes (ActivityUtil)
[self exportDataToUrl];
return _url;
}
- (NSString *)activityViewController:(UIActivityViewController *)activityViewController dataTypeIdentifierForActivityType:(NSString *)activityType {
if ([_message isKindOfClass:[TextMessage class]]) {
return UTTYPE_PLAIN_TEXT;
} else if ([_message respondsToSelector:@selector(blobGetUTI)]) {
return [((id)self.message) blobGetUTI];
}
return nil;
}
@end