forked from mirrors/linphone-iphone
enable multipart send and recv
This commit is contained in:
parent
c9e189e0ae
commit
6ef77ebdaa
15 changed files with 614 additions and 125 deletions
|
|
@ -25,10 +25,22 @@
|
|||
|
||||
#import "UICheckBoxTableView.h"
|
||||
|
||||
@interface FileContext : NSObject
|
||||
@property NSMutableArray <NSString *> *typesArray;
|
||||
@property NSMutableArray <NSData *> *datasArray;
|
||||
@property NSMutableArray <UIImage *> *previewsArray;
|
||||
@property NSMutableArray <NSString *> *namesArray;
|
||||
@property NSMutableArray <NSUUID *> *uuidsArray;
|
||||
|
||||
- (void)clear;
|
||||
- (NSUInteger)count;
|
||||
- (void)addObject:(NSData *)data name:(NSString *)name type:(NSString *)type;
|
||||
@end
|
||||
|
||||
@protocol ChatConversationDelegate <NSObject>
|
||||
|
||||
- (BOOL)resendMultiFiles:(FileContext *)newFileContext message:(NSString *)message;
|
||||
- (BOOL)resendFile:(NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message;
|
||||
- (BOOL)startImageUpload:(UIImage *)image withQuality:(float)quality andMessage:(NSString *)message;
|
||||
- (BOOL)startFileUpload:(NSData *)data withName:(NSString *)name;
|
||||
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url;
|
||||
- (void)tableViewIsScrolling;
|
||||
|
|
@ -45,6 +57,7 @@
|
|||
@property(nonatomic) NSInteger currentIndex;
|
||||
@property(nonatomic, strong) id<ChatConversationDelegate> chatRoomDelegate;
|
||||
@property NSMutableDictionary<NSString *, UIImage *> *imagesInChatroom;
|
||||
@property(nonatomic) BOOL vfsEnabled;
|
||||
|
||||
- (void)addEventEntry:(LinphoneEventLog *)event;
|
||||
- (void)scrollToBottom:(BOOL)animated;
|
||||
|
|
|
|||
|
|
@ -183,6 +183,10 @@
|
|||
#pragma mark - Property Functions
|
||||
|
||||
- (void)setChatRoom:(LinphoneChatRoom *)room {
|
||||
if (room) {
|
||||
_vfsEnabled = [[LinphoneManager instance] lpConfigBoolForKey:@"vfs_enabled_preference"] && (linphone_chat_room_get_capabilities(room) & LinphoneChatRoomCapabilitiesEncrypted);
|
||||
}
|
||||
|
||||
_chatRoom = room;
|
||||
[self reloadData];
|
||||
}
|
||||
|
|
@ -246,6 +250,12 @@ static const int BASIC_EVENT_LIST=15;
|
|||
return eventList.count;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath {
|
||||
if ([[cell reuseIdentifier] isEqualToString:@"UIChatBubblePhotoCell"]) {
|
||||
[(UIChatBubbleTextCell *)cell clearEncryptedFiles];
|
||||
}
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSString *kCellId = nil;
|
||||
LinphoneEventLog *event = [[eventList objectAtIndex:indexPath.row] pointerValue];
|
||||
|
|
@ -260,7 +270,7 @@ static const int BASIC_EVENT_LIST=15;
|
|||
UIChatBubbleTextCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
|
||||
cell = [[NSClassFromString(kCellId) alloc] initWithIdentifier:kCellId];
|
||||
|
||||
[cell setEvent:event];
|
||||
[cell setEvent:event vfsEnabled:_vfsEnabled];
|
||||
if (chat) {
|
||||
cell.isFirst = [self isFirstIndexInTableView:indexPath chat:chat];
|
||||
cell.isLast = [self isLastIndexInTableView:indexPath chat:chat];
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "linphone/linphonecore.h"
|
||||
|
||||
|
||||
//Quicklook Preview Item
|
||||
@interface PreviewItem : NSObject <QLPreviewItem>
|
||||
@property(readonly, nonatomic) NSURL *previewItemURL;
|
||||
|
|
@ -43,7 +44,7 @@
|
|||
|
||||
//QuickLook Datasource for rending PDF docs
|
||||
@interface FileDataSource : NSObject <QLPreviewControllerDataSource>
|
||||
@property (strong, nonatomic) PreviewItem *item;
|
||||
@property NSMutableArray<NSURL*> *files;
|
||||
@end
|
||||
|
||||
@interface ChatConversationView
|
||||
|
|
@ -81,14 +82,12 @@
|
|||
@property(weak, nonatomic) IBOutlet UIBackToCallButton *backToCallButton;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *infoButton;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *particpantsLabel;
|
||||
//@property (nonatomic, strong) UIDocumentInteractionController *documentInteractionController;
|
||||
@property NSMutableArray <UIImage *> *imagesArray;
|
||||
@property NSMutableArray <NSString *> *assetIdsArray;
|
||||
@property NSMutableArray <NSNumber *> *qualitySettingsArray;
|
||||
@property (weak, nonatomic) IBOutlet UICollectionView *imagesCollectionView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *imagesView;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *encryptedButton;
|
||||
@property (weak, nonatomic) IBOutlet UIInterfaceStyleButton *toggleSelectionButton;
|
||||
@property FileContext *fileContext;
|
||||
|
||||
+ (void)markAsRead:(LinphoneChatRoom *)chatRoom;
|
||||
+ (void)autoDownload:(LinphoneChatMessage *)message;
|
||||
|
|
@ -97,6 +96,8 @@
|
|||
+ (void)writeFileInCache:(NSData *)data name:(NSString *)name;
|
||||
+ (NSData *)getCacheFileData:(NSString *)name;
|
||||
+ (void)writeMediaToGallery:(NSString *)name fileType:(NSString *)fileType;
|
||||
+(UIImage *)getBasicImage;
|
||||
+(UIImage*)drawText:(NSString*)text image:(UIImage *)image textSize:(CGFloat)textSize;
|
||||
|
||||
- (void)configureForRoom:(BOOL)editing;
|
||||
- (IBAction)onBackClick:(id)event;
|
||||
|
|
@ -111,6 +112,7 @@
|
|||
- (IBAction)onEncryptedDevicesClick:(id)sender;
|
||||
- (void)update;
|
||||
- (void)openFileWithURL:(NSURL *)url;
|
||||
- (void)openFileWithURLs:(NSMutableArray<NSURL *>*)urls index:(NSInteger)currentIndex;
|
||||
- (void)clearMessageView;
|
||||
- (void)configureMessageField;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,50 @@
|
|||
#import "DevicesListView.h"
|
||||
#import "SVProgressHUD.h"
|
||||
|
||||
@implementation FileContext
|
||||
|
||||
- (void)addObject:(UIImage *)image withQuality:(float)quality {
|
||||
NSString *name = [NSString stringWithFormat:@"%li-%f.jpg", (long)image.hash, [NSDate timeIntervalSinceReferenceDate]];
|
||||
NSData *data = UIImageJPEGRepresentation(image, quality);
|
||||
|
||||
[self addObject:data name:name type:@"image" image:image];
|
||||
}
|
||||
|
||||
- (void)addObject:(NSData *)data name:(NSString *)name type:(NSString *)type image:(UIImage *)image {
|
||||
[_previewsArray addObject:image];
|
||||
[_uuidsArray addObject:[NSUUID UUID]];
|
||||
[self addObject:data name:name type:type];
|
||||
}
|
||||
|
||||
- (void)addObject:(NSData *)data name:(NSString *)name type:(NSString *)type {
|
||||
[_namesArray addObject:name];
|
||||
[_typesArray addObject:type];
|
||||
[_datasArray addObject:data];
|
||||
}
|
||||
|
||||
- (void)deleteContentWithUuid:(NSUUID *)uuid {
|
||||
NSUInteger key = [_uuidsArray indexOfObject:uuid];
|
||||
[_previewsArray removeObjectAtIndex:key];
|
||||
[_uuidsArray removeObjectAtIndex:key];
|
||||
[_namesArray removeObjectAtIndex:key];
|
||||
[_typesArray removeObjectAtIndex:key];
|
||||
[_datasArray removeObjectAtIndex:key];
|
||||
}
|
||||
|
||||
- (void)clear {
|
||||
_previewsArray = [NSMutableArray array];
|
||||
_uuidsArray = [NSMutableArray array];
|
||||
_namesArray = [NSMutableArray array];
|
||||
_typesArray = [NSMutableArray array];
|
||||
_datasArray = [NSMutableArray array];
|
||||
}
|
||||
|
||||
- (NSUInteger)count {
|
||||
return [_datasArray count];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation PreviewItem
|
||||
- (instancetype)initPreviewURL:(NSURL *)docURL
|
||||
|
|
@ -41,18 +85,19 @@
|
|||
@end
|
||||
|
||||
@implementation FileDataSource
|
||||
- (instancetype)initWithPreviewItem:(PreviewItem *)item {
|
||||
- (instancetype)initWithFiles:(NSMutableArray<NSURL*>*)files {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_item = item;
|
||||
_files = files;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller {
|
||||
return 1;
|
||||
return _files.count;
|
||||
}
|
||||
- (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
|
||||
return self.item;
|
||||
NSURL *url = [_files objectAtIndex:index];
|
||||
return [[PreviewItem alloc] initPreviewURL:url WithTitle:[url lastPathComponent]];
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
@ -175,7 +220,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
selector:@selector(onLinphoneCoreReady:)
|
||||
name:kLinphoneGlobalStateUpdate
|
||||
object:nil];
|
||||
if ([_imagesArray count] > 0) {
|
||||
if ([_fileContext count] > 0) {
|
||||
[UIView animateWithDuration:0
|
||||
delay:0
|
||||
options:UIViewAnimationOptionBeginFromCurrentState
|
||||
|
|
@ -419,11 +464,9 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
|
||||
- (void)saveAndSend:(UIImage *)image assetId:(NSString *)phAssetId withQuality:(float)quality{
|
||||
|
||||
[_imagesArray addObject:image];
|
||||
[_assetIdsArray addObject:phAssetId];
|
||||
[_qualitySettingsArray addObject:@(quality)];
|
||||
[self refreshImageDrawer];
|
||||
[_fileContext addObject:image withQuality:quality];
|
||||
[_qualitySettingsArray addObject:@(quality)];
|
||||
[self refreshImageDrawer];
|
||||
}
|
||||
|
||||
- (void)chooseImageQuality:(UIImage *)image assetId:(NSString *)phAssetId {
|
||||
|
|
@ -583,7 +626,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
messageRect.size.height += diff;
|
||||
[_messageView setFrame:messageRect];
|
||||
|
||||
if ([_imagesArray count] > 0) {
|
||||
if ([_fileContext count] > 0) {
|
||||
CGRect _imagesRect = [_imagesView frame];
|
||||
_imagesRect.origin.y -= diff;
|
||||
[_imagesView setFrame:_imagesRect];
|
||||
|
|
@ -626,24 +669,28 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
|
||||
- (IBAction)onSendClick:(id)event {
|
||||
if ([_imagesArray count] > 0) {
|
||||
int i = 0;
|
||||
for (i = 0; i < [_imagesArray count] - 1; ++i) {
|
||||
[self startImageUpload:[_imagesArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:NULL];
|
||||
}
|
||||
if (isOneToOne) {
|
||||
[self startImageUpload:[_imagesArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:NULL];
|
||||
if (![[self.messageField text] isEqualToString:@""]) {
|
||||
[self sendMessage:[_messageField text] withExterlBodyUrl:nil];
|
||||
}
|
||||
} else {
|
||||
[self startImageUpload:[_imagesArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:[self.messageField text]];
|
||||
}
|
||||
|
||||
[self clearMessageView];
|
||||
return;
|
||||
}
|
||||
[self sendMessageInMessageField];
|
||||
if ([_fileContext count] > 0) {
|
||||
if (linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesConference) {
|
||||
[self startMultiFilesUpload];
|
||||
} else {
|
||||
int i = 0;
|
||||
for (i = 0; i < [_fileContext count]-1; ++i) {
|
||||
[self startUploadData:[_fileContext.datasArray objectAtIndex:i] withType:[_fileContext.typesArray objectAtIndex:i] withName:[_fileContext.namesArray objectAtIndex:i] andMessage:NULL];
|
||||
}
|
||||
if (isOneToOne) {
|
||||
[self startUploadData:[_fileContext.datasArray objectAtIndex:i] withType:[_fileContext.typesArray objectAtIndex:i] withName:[_fileContext.namesArray objectAtIndex:i] andMessage:NULL];
|
||||
if (![[self.messageField text] isEqualToString:@""]) {
|
||||
[self sendMessage:[_messageField text] withExterlBodyUrl:nil];
|
||||
}
|
||||
} else {
|
||||
[self startUploadData:[_fileContext.datasArray objectAtIndex:i] withType:[_fileContext.typesArray objectAtIndex:i] withName:[_fileContext.namesArray objectAtIndex:i] andMessage:[self.messageField text]];
|
||||
}
|
||||
}
|
||||
|
||||
[self clearMessageView];
|
||||
return;
|
||||
}
|
||||
[self sendMessageInMessageField];
|
||||
}
|
||||
|
||||
- (IBAction)onListTap:(id)sender {
|
||||
|
|
@ -739,11 +786,25 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
|
||||
#pragma mark ChatRoomDelegate
|
||||
|
||||
- (BOOL)startImageUpload:(UIImage *)image withQuality:(float)quality andMessage:(NSString *)message {
|
||||
- (BOOL)startMultiFilesUpload {
|
||||
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
[fileTransfer setText:[self.messageField text]];
|
||||
[fileTransfer uploadFileContent:_fileContext forChatRoom:_chatRoom];
|
||||
[_tableController scrollToBottom:true];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL)startUploadData:(NSData *)data withType:(NSString*)type withName:(NSString *)name andMessage:(NSString *)message {
|
||||
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
if (message)
|
||||
[fileTransfer setText:message];
|
||||
[fileTransfer uploadImage:image forChatRoom:_chatRoom withQuality:quality];
|
||||
NSString *key = @"localfile";
|
||||
if ([type isEqualToString:@"video"]) {
|
||||
key = @"localvideo";
|
||||
} else if ([type isEqualToString:@"image"]) {
|
||||
key = @"localimage";
|
||||
}
|
||||
[fileTransfer uploadData:data forChatRoom:_chatRoom type:type subtype:type name:name key:key];
|
||||
[_tableController scrollToBottom:true];
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -755,6 +816,15 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL)resendMultiFiles:(FileContext *)newFileContext message:(NSString *)message {
|
||||
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
if (message)
|
||||
[fileTransfer setText:message];
|
||||
[fileTransfer uploadFileContent:newFileContext forChatRoom:_chatRoom];
|
||||
[_tableController scrollToBottom:true];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL)resendFile: (NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message {
|
||||
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
if (message)
|
||||
|
|
@ -805,7 +875,9 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
[exportSession exportAsynchronouslyWithCompletionHandler:^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[SVProgressHUD dismiss];
|
||||
[self startFileUpload:[NSData dataWithContentsOfURL:compressedVideoUrl] withName:localname];
|
||||
UIImage* image = [UIChatBubbleTextCell getImageFromVideoUrl:compressedVideoUrl];
|
||||
[_fileContext addObject:[NSData dataWithContentsOfURL:compressedVideoUrl] name:localname type:@"video" image:image];
|
||||
[self refreshImageDrawer];
|
||||
});
|
||||
}];
|
||||
|
||||
|
|
@ -1005,7 +1077,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
|
||||
|
||||
if ([_imagesArray count] > 0){
|
||||
if ([_fileContext count] > 0){
|
||||
// resizing imagesView
|
||||
CGRect imagesFrame = [_imagesView frame];
|
||||
imagesFrame.origin.y = [_messageView frame].origin.y - heightDiff;
|
||||
|
|
@ -1074,7 +1146,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
[_tableController.view setFrame:tableFrame];
|
||||
}
|
||||
|
||||
if ([_imagesArray count] > 0){
|
||||
if ([_fileContext count] > 0){
|
||||
// resizing imagesView
|
||||
CGRect imagesFrame = [_imagesView frame];
|
||||
imagesFrame.origin.y = [_messageView frame].origin.y - heightDiff;
|
||||
|
|
@ -1213,21 +1285,24 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
|||
[view.encryptedButton setImage:image forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)openFileWithURL:(NSURL *)url
|
||||
- (void)openFileWithURLs:(NSMutableArray<NSURL *>*)urls index:(NSInteger)currentIndex
|
||||
{
|
||||
//create the Quicklook controller.
|
||||
QLPreviewController *qlController = [[QLPreviewController alloc] init];
|
||||
|
||||
PreviewItem *item = [[PreviewItem alloc] initPreviewURL:url WithTitle:[url lastPathComponent]];
|
||||
self.FileDataSource = [[FileDataSource alloc] initWithPreviewItem:item];
|
||||
self.FileDataSource = [[FileDataSource alloc] initWithFiles:urls];
|
||||
|
||||
qlController.dataSource = self.FileDataSource;
|
||||
qlController.currentPreviewItemIndex = currentIndex;
|
||||
qlController.delegate = self;
|
||||
|
||||
//present the document.
|
||||
[self presentViewController:qlController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)openFileWithURL:(NSURL *)url
|
||||
{
|
||||
[self openFileWithURLs:[NSMutableArray arrayWithObject:url] index:0];
|
||||
}
|
||||
|
||||
- (void)previewControllerDidDismiss:(QLPreviewController *)controller
|
||||
{
|
||||
|
|
@ -1307,23 +1382,21 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
|||
}
|
||||
}
|
||||
|
||||
- (void)deleteImageWithAssetId:(NSString *)assetId {
|
||||
NSUInteger key = [_assetIdsArray indexOfObject:assetId];
|
||||
[_imagesArray removeObjectAtIndex:key];
|
||||
[_assetIdsArray removeObjectAtIndex:key];
|
||||
[self refreshImageDrawer];
|
||||
- (void)deleteFileWithUuid:(NSUUID *)uuid {
|
||||
[_fileContext deleteContentWithUuid:uuid];
|
||||
[self refreshImageDrawer];
|
||||
}
|
||||
|
||||
- (void)clearMessageView {
|
||||
[_messageField setText:@""];
|
||||
_imagesArray = [NSMutableArray array];
|
||||
_assetIdsArray = [NSMutableArray array];
|
||||
if (!_fileContext) _fileContext = [[FileContext alloc] init];
|
||||
[_fileContext clear];
|
||||
|
||||
[self refreshImageDrawer];
|
||||
}
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
||||
return [_imagesArray count];
|
||||
return [_fileContext count];
|
||||
}
|
||||
|
||||
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
|
@ -1336,8 +1409,8 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
|||
imgFrame.size.height = 100;
|
||||
}
|
||||
|
||||
[imgView.image setImage:[UIImage resizeImage:[_imagesArray objectAtIndex:[indexPath item]] withMaxWidth:imgFrame.size.width andMaxHeight:imgFrame.size.height]];
|
||||
[imgView setAssetId:[_assetIdsArray objectAtIndex:[indexPath item]]];
|
||||
[imgView.image setImage:[UIImage resizeImage:[_fileContext.previewsArray objectAtIndex:[indexPath item]] withMaxWidth:imgFrame.size.width andMaxHeight:imgFrame.size.height]];
|
||||
[imgView setUuid:[_fileContext.uuidsArray objectAtIndex:[indexPath item]]];
|
||||
[imgView setDeleteDelegate:self];
|
||||
[imgView setFrame:imgFrame];
|
||||
[_sendButton setEnabled:TRUE];
|
||||
|
|
@ -1347,7 +1420,7 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
|||
- (void)refreshImageDrawer {
|
||||
int heightDiff = UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? 55 : 105;
|
||||
|
||||
if ([_imagesArray count] == 0) {
|
||||
if ([_fileContext count] == 0) {
|
||||
[UIView animateWithDuration:0
|
||||
delay:0
|
||||
options:UIViewAnimationOptionBeginFromCurrentState
|
||||
|
|
@ -1433,10 +1506,38 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
|||
NSFileCoordinator *co =[[NSFileCoordinator alloc] init];
|
||||
NSError *error = nil;
|
||||
[co coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL * _Nonnull newURL) {
|
||||
[self startFileUpload:[NSData dataWithContentsOfURL:newURL] withName:[newURL lastPathComponent]];
|
||||
UIImage *image = [ChatConversationView drawText:[newURL lastPathComponent] image:[ChatConversationView getBasicImage] textSize:10];
|
||||
[_fileContext addObject:[NSData dataWithContentsOfURL:newURL] name:[newURL lastPathComponent] type:@"file" image:image];
|
||||
[self refreshImageDrawer];
|
||||
}];
|
||||
[url stopAccessingSecurityScopedResource];
|
||||
}
|
||||
|
||||
+(UIImage *)getBasicImage {
|
||||
UIColor *color=[UIColor grayColor];
|
||||
CGRect frame = CGRectMake(0, 0, 200, 200);
|
||||
UIGraphicsBeginImageContext(frame.size);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextSetFillColorWithColor(context, [color CGColor]);
|
||||
CGContextFillRect(context, frame);
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
return image;
|
||||
}
|
||||
|
||||
+(UIImage*)drawText:(NSString*)text image:(UIImage *)image textSize:(CGFloat)textSize
|
||||
{
|
||||
UIFont *font = [UIFont boldSystemFontOfSize:textSize];
|
||||
UIGraphicsBeginImageContext(image.size);
|
||||
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
|
||||
CGRect rect = CGRectMake(0, 30, image.size.width, image.size.height);
|
||||
[[UIColor whiteColor] set];
|
||||
[text drawInRect:CGRectIntegral(rect) withFont:font];
|
||||
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return newImage;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#import "FileTransferDelegate.h"
|
||||
#import "ChatConversationTableView.h"
|
||||
#import "UIChatBubbleTextCell.h"
|
||||
#import "UIChatContentView.h"
|
||||
|
||||
@interface UIChatBubblePhotoCell : UIChatBubbleTextCell
|
||||
|
||||
|
|
@ -41,8 +42,10 @@
|
|||
@property (weak, nonatomic) IBOutlet UIButton *fileButton;
|
||||
@property (weak, nonatomic) IBOutlet UIView *fileView;
|
||||
@property (strong, nonatomic) IBOutlet UILongPressGestureRecognizer *plusLongGestureRecognizer;
|
||||
@property(strong, nonatomic) NSMutableArray<UIChatContentView *> *contentViews;
|
||||
|
||||
- (void)setEvent:(LinphoneEventLog *)event;
|
||||
|
||||
- (void)setEvent:(LinphoneEventLog *)event vfsEnabled:(BOOL)enabled;
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)message;
|
||||
- (void)connectToFileDelegate:(FileTransferDelegate *)ftd;
|
||||
- (IBAction)onDownloadClick:(id)event;
|
||||
|
|
|
|||
|
|
@ -53,29 +53,21 @@
|
|||
videoDefaultSize = CGSizeMake(320, 240);
|
||||
assetIsLoaded = FALSE;
|
||||
self.contentView.userInteractionEnabled = NO;
|
||||
_contentViews = [[NSMutableArray alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
NSString *filePath = [LinphoneManager getMessageAppDataForKey:@"encryptedfile" inMessage:self.message];
|
||||
if (filePath) {
|
||||
[[NSFileManager defaultManager] removeItemAtPath:filePath error:NULL];
|
||||
[LinphoneManager setValueInMessageAppData:NULL forKey:@"encryptedfile" inMessage:self.message];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)onDelete {
|
||||
[super onDelete];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
- (void)setEvent:(LinphoneEventLog *)event {
|
||||
- (void)setEvent:(LinphoneEventLog *)event vfsEnabled:(BOOL)enabled {
|
||||
if (!event || !(linphone_event_log_get_type(event) == LinphoneEventLogTypeConferenceChatMessage))
|
||||
return;
|
||||
|
||||
super.event = event;
|
||||
[super setEvent:event vfsEnabled:enabled];
|
||||
[self setChatMessage:linphone_event_log_get_chat_message(event)];
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +93,6 @@
|
|||
}
|
||||
|
||||
[super setChatMessageForCbs:amessage];
|
||||
[LinphoneManager setValueInMessageAppData:NULL forKey:@"encryptedfile" inMessage:self.message];
|
||||
}
|
||||
|
||||
- (void) loadImageAsset:(PHAsset*) asset image:(UIImage *)image {
|
||||
|
|
@ -117,8 +108,6 @@
|
|||
});
|
||||
}
|
||||
|
||||
static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
||||
|
||||
- (void) loadAsset:(PHAsset *) asset {
|
||||
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
|
||||
options.synchronous = TRUE;
|
||||
|
|
@ -165,6 +154,59 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
return;
|
||||
}
|
||||
[super update];
|
||||
|
||||
const bctbx_list_t *contents = linphone_chat_message_get_contents(self.message);
|
||||
BOOL multiParts = ((linphone_chat_message_get_text_content(self.message) != NULL) ? bctbx_list_size(contents) > 2 : bctbx_list_size(contents) > 1);
|
||||
if (multiParts) {
|
||||
if (!assetIsLoaded) {
|
||||
NSMutableDictionary<NSString *, NSString *> *encrptedFilePaths = NULL;
|
||||
if (self.vfsEnabled) {
|
||||
encrptedFilePaths = [LinphoneManager getMessageAppDataForKey:@"encryptedfiles" inMessage:self.message];
|
||||
if (!encrptedFilePaths) {
|
||||
encrptedFilePaths = [NSMutableDictionary dictionary];
|
||||
}
|
||||
}
|
||||
|
||||
_imageGestureRecognizer.enabled = NO;
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = _playButton.hidden = _fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
|
||||
|
||||
const bctbx_list_t *it = contents;
|
||||
int i;
|
||||
for (it = contents, i=0; it != NULL; it=bctbx_list_next(it)){
|
||||
LinphoneContent *content = (LinphoneContent *)it->data;
|
||||
if (linphone_content_is_file_transfer(content) || linphone_content_is_file(content)){
|
||||
UIChatContentView *contentView = [[UIChatContentView alloc] initWithFrame: CGRectMake(0,0,0,0)];
|
||||
if(self.vfsEnabled && (linphone_chat_message_is_outgoing(self.message) || linphone_content_is_file(content))) {
|
||||
// downloaded or ougoing message
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
NSString *filePath = [encrptedFilePaths valueForKey:name];
|
||||
if (filePath == NULL) {
|
||||
char *cPath = linphone_content_get_plain_file_path(content);
|
||||
if (cPath) {
|
||||
NSString *filePath = [NSString stringWithUTF8String:cPath];
|
||||
ms_free(cPath);
|
||||
[encrptedFilePaths setValue:filePath forKey:name];
|
||||
}
|
||||
}
|
||||
contentView.filePath = filePath;
|
||||
}
|
||||
[contentView setContent:content message:self.message];
|
||||
contentView.position = i;
|
||||
[_contentViews addObject:contentView];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (self.vfsEnabled) {
|
||||
[LinphoneManager setValueInMessageAppData:encrptedFilePaths forKey:@"encryptedfiles" inMessage:self.message];
|
||||
}
|
||||
assetIsLoaded = TRUE;
|
||||
[self layoutSubviews];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *url = linphone_chat_message_get_external_body_url(self.message);
|
||||
BOOL is_external =
|
||||
(url && (strstr(url, "http") == url)) || linphone_chat_message_get_file_transfer_information(self.message);
|
||||
|
|
@ -203,11 +245,13 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
NSString *fileName = [NSString stringWithUTF8String:linphone_content_get_name(fileContent)];
|
||||
|
||||
if (!filePath) {
|
||||
char *cPath = [[LinphoneManager instance] lpConfigBoolForKey:@"vfs_enabled_preference"] ? linphone_content_get_plain_file_path(fileContent) : NULL;
|
||||
if (cPath) {
|
||||
filePath = [NSString stringWithUTF8String:cPath];
|
||||
ms_free(cPath);
|
||||
[LinphoneManager setValueInMessageAppData:filePath forKey:@"encryptedfile" inMessage:self.message];
|
||||
if (self.vfsEnabled) {
|
||||
char *cPath = self.vfsEnabled ? linphone_content_get_plain_file_path(fileContent) : NULL;
|
||||
if (cPath) {
|
||||
filePath = [NSString stringWithUTF8String:cPath];
|
||||
ms_free(cPath);
|
||||
[LinphoneManager setValueInMessageAppData:filePath forKey:@"encryptedfile" inMessage:self.message];
|
||||
}
|
||||
} else {
|
||||
filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:fileName];
|
||||
}
|
||||
|
|
@ -638,20 +682,60 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
bubbleFrame.origin.x = origin_x;
|
||||
|
||||
super.bubbleView.frame = bubbleFrame;
|
||||
|
||||
// Resizing Image view
|
||||
if (_finalImage.image) {
|
||||
CGRect imgFrame = self.finalAssetView.frame;
|
||||
imgFrame.size = [UIChatBubbleTextCell getMediaMessageSizefromOriginalSize:[_finalImage.image size] withWidth:chatTableView.tableView.frame.size.width - CELL_IMAGE_X_MARGIN];
|
||||
imgFrame.origin.x = (self.innerView.frame.size.width - imgFrame.size.width-17)/2;
|
||||
self.finalAssetView.frame = imgFrame;
|
||||
}
|
||||
|
||||
if (_contentViews.count > 0) {
|
||||
// Positioning contentViews
|
||||
CGFloat imagesw=0;
|
||||
CGFloat max_imagesh=0;
|
||||
CGFloat max_imagesw=0;
|
||||
CGFloat originy=0;
|
||||
CGFloat originx=0;
|
||||
CGFloat availableWidth = chatTableView.tableView.frame.size.width-CELL_IMAGE_X_MARGIN;
|
||||
|
||||
NSMutableArray<NSURL *> *fileUrls = [[NSMutableArray alloc] init];
|
||||
for (UIChatContentView *contentView in _contentViews) {
|
||||
if (contentView.filePath) {
|
||||
[fileUrls addObject:[NSURL fileURLWithPath:contentView.filePath]];
|
||||
}
|
||||
}
|
||||
for (UIChatContentView *contentView in _contentViews) {
|
||||
UIImage *image = contentView.image;
|
||||
CGSize sSize = [UIChatBubbleTextCell getMediaMessageSizefromOriginalSize:image.size withWidth:IMAGE_DEFAULT_WIDTH];
|
||||
imagesw += sSize.width;
|
||||
if (imagesw > availableWidth) {
|
||||
imagesw = sSize.width;
|
||||
max_imagesw = MAX(max_imagesw, imagesw);
|
||||
originy = max_imagesh+IMAGE_DEFAULT_MARGIN;
|
||||
max_imagesh = sSize.height;
|
||||
originx = sSize.width;
|
||||
} else {
|
||||
max_imagesw = MAX(max_imagesw, imagesw);
|
||||
max_imagesh = MAX(max_imagesh, sSize.height);
|
||||
originx += (sSize.width+IMAGE_DEFAULT_MARGIN);
|
||||
}
|
||||
|
||||
[contentView setFrame:CGRectMake(originx-sSize.width, originy, sSize.width, sSize.height)];
|
||||
contentView.fileUrls = fileUrls;
|
||||
[_finalAssetView addSubview:contentView];
|
||||
}
|
||||
_finalImage.hidden = YES;
|
||||
} else {
|
||||
// Resizing Image view
|
||||
if (_finalImage.image) {
|
||||
CGRect imgFrame = self.finalAssetView.frame;
|
||||
imgFrame.size = [UIChatBubbleTextCell getMediaMessageSizefromOriginalSize:[_finalImage.image size] withWidth:chatTableView.tableView.frame.size.width - CELL_IMAGE_X_MARGIN];
|
||||
imgFrame.origin.x = (self.innerView.frame.size.width - imgFrame.size.width-17)/2;
|
||||
self.finalAssetView.frame = imgFrame;
|
||||
}
|
||||
}
|
||||
|
||||
// Positioning text message
|
||||
const char *utf8Text = linphone_chat_message_get_text_content(self.message);
|
||||
|
||||
CGRect textFrame = self.messageText.frame;
|
||||
if (_finalImage.image)
|
||||
if (_contentViews.count > 0)
|
||||
textFrame.origin = CGPointMake(textFrame.origin.x, self.finalAssetView.frame.origin.y + self.finalAssetView.frame.size.height-10);
|
||||
else if (_finalImage.image)
|
||||
textFrame.origin = CGPointMake(textFrame.origin.x, self.finalAssetView.frame.origin.y + self.finalAssetView.frame.size.height);
|
||||
else
|
||||
// When image hasn't be download
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
#import "ChatConversationTableView.h"
|
||||
#import "UIRoundedImageView.h"
|
||||
|
||||
#define CELL_IMAGE_X_MARGIN 100
|
||||
#define IMAGE_DEFAULT_WIDTH 120
|
||||
#define IMAGE_DEFAULT_MARGIN 5
|
||||
|
||||
@interface UIChatBubbleTextCell : UITableViewCell <UIDocumentPickerDelegate>
|
||||
|
||||
@property(readonly, nonatomic) LinphoneEventLog *event;
|
||||
|
|
@ -42,17 +46,20 @@
|
|||
@property (nonatomic, strong) UIDocumentPickerViewController *documentPicker;
|
||||
@property (weak, nonatomic) IBOutlet UIView *innerView;
|
||||
|
||||
@property(nonatomic) Boolean isFirst;
|
||||
@property(nonatomic) Boolean isLast;
|
||||
@property(nonatomic) Boolean notDelivered;
|
||||
@property(nonatomic) BOOL isFirst;
|
||||
@property(nonatomic) BOOL isLast;
|
||||
@property(nonatomic) BOOL notDelivered;
|
||||
@property(nonatomic) BOOL vfsEnabled;
|
||||
|
||||
+ (CGSize)ViewSizeForMessage:(LinphoneChatMessage *)chat withWidth:(int)width;
|
||||
+ (CGSize)ViewHeightForMessageText:(LinphoneChatMessage *)chat withWidth:(int)width textForImdn:(NSString *)imdnText;
|
||||
+ (CGSize)getMediaMessageSizefromOriginalSize:(CGSize)originalSize withWidth:(int)width;
|
||||
+ (UIImage *)getImageFromVideoUrl:(NSURL *)url;
|
||||
+ (UIImage *)getImageFromContent:(LinphoneContent *)content filePath:(NSString *)filePath;
|
||||
|
||||
- (void)setEvent:(LinphoneEventLog *)event;
|
||||
- (void)setEvent:(LinphoneEventLog *)event vfsEnabled:(BOOL)enabled;
|
||||
- (void)setChatMessageForCbs:(LinphoneChatMessage *)message;
|
||||
- (void)clearEncryptedFiles;
|
||||
|
||||
- (void)onDelete;
|
||||
- (void)onResend;
|
||||
|
|
|
|||
|
|
@ -62,17 +62,38 @@
|
|||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self setEvent:NULL];
|
||||
[self setEvent:NULL vfsEnabled:_vfsEnabled];
|
||||
[self setChatMessageForCbs:NULL];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)setEvent:(LinphoneEventLog *)event {
|
||||
- (void)clearEncryptedFiles {
|
||||
if (_vfsEnabled) {
|
||||
NSMutableDictionary<NSString *, NSString *> *encrptedFilePaths = [LinphoneManager getMessageAppDataForKey:@"encryptedfiles" inMessage:_message];
|
||||
if ([encrptedFilePaths count] > 0) {
|
||||
for(NSString *path in [encrptedFilePaths allValues]) {
|
||||
[[NSFileManager defaultManager] removeItemAtPath:path error:NULL];
|
||||
}
|
||||
[LinphoneManager setValueInMessageAppData:NULL forKey:@"encryptedfiles" inMessage:_message];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *filePath = [LinphoneManager getMessageAppDataForKey:@"encryptedfile" inMessage:_message];
|
||||
if (filePath) {
|
||||
if (![filePath isEqualToString:@""])
|
||||
[[NSFileManager defaultManager] removeItemAtPath:filePath error:NULL];
|
||||
[LinphoneManager setValueInMessageAppData:NULL forKey:@"encryptedfile" inMessage:_message];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setEvent:(LinphoneEventLog *)event vfsEnabled:(BOOL)enabled {
|
||||
if(!event)
|
||||
return;
|
||||
|
||||
_event = event;
|
||||
_vfsEnabled = enabled;
|
||||
if (!(linphone_event_log_get_type(event) == LinphoneEventLogTypeConferenceChatMessage)) {
|
||||
LOGE(@"Impossible to create a ChatBubbleText whit a non message event");
|
||||
return;
|
||||
|
|
@ -274,33 +295,52 @@
|
|||
if (state != LinphoneChatMessageStateNotDelivered && state != LinphoneChatMessageStateFileTransferError)
|
||||
return;
|
||||
|
||||
const bctbx_list_t *contents = linphone_chat_message_get_contents(_message);
|
||||
BOOL multiParts = ((linphone_chat_message_get_text_content(self.message) != NULL) ? bctbx_list_size(contents) > 2 : bctbx_list_size(contents) > 1);
|
||||
if (multiParts) {
|
||||
FileContext *newfileContext = [[FileContext alloc] init];
|
||||
[newfileContext clear];
|
||||
NSMutableDictionary<NSString *, NSString *> *encrptedFilePaths = encrptedFilePaths = [LinphoneManager getMessageAppDataForKey:@"encryptedfiles" inMessage:_message];
|
||||
int i;
|
||||
const bctbx_list_t *it;
|
||||
for (it = contents, i=0; it != NULL; it=bctbx_list_next(it)){
|
||||
LinphoneContent *content = (LinphoneContent *)it->data;
|
||||
if (linphone_content_is_file_transfer(content) || linphone_content_is_file(content)){
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
NSString *filePath = [encrptedFilePaths valueForKey:name];
|
||||
if (filePath == NULL) {
|
||||
filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
}
|
||||
[newfileContext addObject:[NSData dataWithContentsOfFile:filePath] name:name type:[NSString stringWithUTF8String:linphone_content_get_type(content)]];
|
||||
}
|
||||
}
|
||||
[self onDelete];
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
const char *text = linphone_chat_message_get_text_content(_message);
|
||||
[_chatRoomDelegate resendMultiFiles:newfileContext message: text? [NSString stringWithUTF8String:text]: NULL];
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (linphone_chat_message_get_file_transfer_information(_message) != NULL) {
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:_message];
|
||||
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:_message];
|
||||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:_message];
|
||||
|
||||
/*FileTransferDelegate *thiz = [FileTransferDelegate messageDelegate:_message];
|
||||
if (thiz) {
|
||||
[thiz stop]
|
||||
}*/
|
||||
NSString *filePath = [LinphoneManager getMessageAppDataForKey:@"encryptedfile" inMessage:self.message];
|
||||
|
||||
[self onDelete];
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
LinphoneContent *fileContent = linphone_chat_message_get_file_transfer_information(_message);
|
||||
NSData *data = NULL;
|
||||
char *cPath = [[LinphoneManager instance] lpConfigBoolForKey:@"vfs_enabled_preference"] ? linphone_content_get_plain_file_path(fileContent) : NULL;
|
||||
if (cPath) {
|
||||
NSString *filePath = [NSString stringWithUTF8String:cPath];
|
||||
if (filePath) {
|
||||
data = [NSData dataWithContentsOfFile:filePath];
|
||||
ms_free(cPath);
|
||||
[[NSFileManager defaultManager] removeItemAtPath:filePath error:NULL];
|
||||
}
|
||||
|
||||
const char *text = linphone_chat_message_get_text_content(_message);
|
||||
NSString *str = text ? [NSString stringWithUTF8String:text] : NULL;
|
||||
if (localImage) {
|
||||
[_chatRoomDelegate resendFile: (data?:[ChatConversationView getCacheFileData:localImage]) withName:localImage type:@"image" key:@"localimage" message:self.textMessage];
|
||||
[_chatRoomDelegate resendFile: (data?:[ChatConversationView getCacheFileData:localImage]) withName:localImage type:@"image" key:@"localimage" message:str];
|
||||
} else if (localVideo) {
|
||||
[_chatRoomDelegate resendFile:(data?:[ChatConversationView getCacheFileData:localVideo]) withName:localVideo type:@"video" key:@"localvideo" message:self.textMessage];
|
||||
[_chatRoomDelegate resendFile:(data?:[ChatConversationView getCacheFileData:localVideo]) withName:localVideo type:@"video" key:@"localvideo" message:str];
|
||||
} else {
|
||||
[_chatRoomDelegate resendFile:(data?:[ChatConversationView getCacheFileData:localFile]) withName:localFile type:@"image" key:@"localfile" message:self.textMessage];
|
||||
[_chatRoomDelegate resendFile:(data?:[ChatConversationView getCacheFileData:localFile]) withName:localFile type:@"image" key:@"localfile" message:str];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
|
@ -364,7 +404,6 @@ static const CGFloat CELL_MIN_HEIGHT = 65.0f;
|
|||
static const CGFloat CELL_MIN_WIDTH = 190.0f;
|
||||
static const CGFloat CELL_MESSAGE_X_MARGIN = 68 + 10.0f;
|
||||
static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
|
||||
static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
||||
|
||||
+ (CGSize)ViewHeightForMessage:(LinphoneChatMessage *)chat withWidth:(int)width {
|
||||
return [self ViewHeightForMessageText:chat withWidth:width textForImdn:nil];
|
||||
|
|
@ -378,7 +417,28 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
return size;
|
||||
}
|
||||
|
||||
+ (CGSize)ViewHeightForMessageText:(LinphoneChatMessage *)chat withWidth:(int)width textForImdn:(NSString *)imdnText{
|
||||
+ (UIImage *)getImageFromContent:(LinphoneContent *)content filePath:(NSString *)filePath; {
|
||||
NSString *type = [NSString stringWithUTF8String:linphone_content_get_type(content)];
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
if (!filePath) {
|
||||
filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
}
|
||||
|
||||
UIImage *image = nil;
|
||||
if ([type isEqualToString:@"video"]) {
|
||||
image = [UIChatBubbleTextCell getImageFromVideoUrl:[NSURL fileURLWithPath:filePath]];
|
||||
} else if ([type isEqualToString:@"image"]) {
|
||||
NSData* data = [NSData dataWithContentsOfFile:filePath];
|
||||
image = [[UIImage alloc] initWithData:data];
|
||||
}
|
||||
if (image) return image;
|
||||
UIImage *basicImage = [ChatConversationView getBasicImage];
|
||||
image = [ChatConversationView drawText:[NSString stringWithFormat:@"📎 %@",name] image:basicImage textSize:25];
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
+ (CGSize)ViewHeightForMessageText:(LinphoneChatMessage *)chat withWidth:(int)width textForImdn:(NSString *)imdnText {
|
||||
NSString *messageText = [UIChatBubbleTextCell TextMessageForChat:chat];
|
||||
static UIFont *messageFont = nil;
|
||||
|
||||
|
|
@ -399,7 +459,68 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN + 50, CELL_MIN_HEIGHT);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
CGFloat imagesw=0;
|
||||
CGFloat imagesh=0;
|
||||
CGFloat max_imagesw=0;
|
||||
CGFloat max_imagesh=0;
|
||||
const bctbx_list_t *contents = linphone_chat_message_get_contents(chat);
|
||||
BOOL multiParts = ((linphone_chat_message_get_text_content(chat) != NULL) ? bctbx_list_size(contents) > 2 : bctbx_list_size(contents) > 1);
|
||||
if (multiParts) {
|
||||
const bctbx_list_t *it = contents;
|
||||
NSMutableDictionary<NSString *, NSString *> *encrptedFilePaths = [LinphoneManager getMessageAppDataForKey:@"encryptedfiles" inMessage:chat];
|
||||
|
||||
for (it = contents; it != NULL; it=bctbx_list_next(it)){
|
||||
LinphoneContent *content = (LinphoneContent *)it->data;
|
||||
UIImage *image;
|
||||
if(!linphone_chat_message_is_outgoing(chat) && linphone_content_is_file_transfer(content)) {
|
||||
// not yet downloaded
|
||||
UIImage *basicImage = [ChatConversationView getBasicImage];
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)] ;
|
||||
image = [ChatConversationView drawText:name image:basicImage textSize:25];
|
||||
} else if (linphone_content_is_file_transfer(content) || linphone_content_is_file(content)) {
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
NSString *filePath=[encrptedFilePaths valueForKey:name];
|
||||
if (filePath == NULL) {
|
||||
filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
}
|
||||
|
||||
image = [UIChatBubbleTextCell getImageFromContent:content filePath:filePath];
|
||||
}
|
||||
if (image) {
|
||||
CGSize sSize = [self getMediaMessageSizefromOriginalSize:image.size withWidth:IMAGE_DEFAULT_WIDTH];
|
||||
imagesw += sSize.width;
|
||||
if (imagesw > width) {
|
||||
imagesw = sSize.width;
|
||||
max_imagesw = MAX(max_imagesw, imagesw);
|
||||
max_imagesh = imagesh;
|
||||
imagesh = sSize.height;
|
||||
} else {
|
||||
max_imagesw = MAX(max_imagesw, imagesw);
|
||||
imagesh = MAX(imagesh, sSize.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
max_imagesh += imagesh;
|
||||
size = CGSizeMake(max_imagesw, max_imagesh);
|
||||
CGSize textSize = CGSizeMake(0, 0);
|
||||
if (![messageText isEqualToString:@"🗻"]) {
|
||||
textSize = [self computeBoundingBox:messageText
|
||||
size:CGSizeMake(width - CELL_MESSAGE_X_MARGIN - 4, CGFLOAT_MAX)
|
||||
font:messageFont];
|
||||
size.height += textSize.height;
|
||||
}
|
||||
|
||||
// add size for message text
|
||||
size.height += textSize.height;
|
||||
size.width = MAX(textSize.width, size.width);
|
||||
size.width = MAX(size.width + CELL_MESSAGE_X_MARGIN, CELL_MIN_WIDTH);
|
||||
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN, CELL_MIN_HEIGHT);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
LinphoneContent *fileContent = linphone_chat_message_get_file_transfer_information(chat);
|
||||
if (url == nil && fileContent == NULL) {
|
||||
size = [self computeBoundingBox:messageText
|
||||
|
|
@ -410,6 +531,7 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:chat];
|
||||
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:chat];
|
||||
NSString *filePath = [LinphoneManager getMessageAppDataForKey:@"encryptedfile" inMessage:chat];
|
||||
NSString *fileName = [NSString stringWithUTF8String:linphone_content_get_name(fileContent)];
|
||||
|
||||
CGSize textSize = CGSizeMake(0, 0);
|
||||
if (![messageText isEqualToString:@"🗻"]) {
|
||||
|
|
@ -420,12 +542,13 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
}
|
||||
|
||||
CGSize originalImageSize = CGSizeMake(230, 50);
|
||||
if (!filePath) {
|
||||
filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:fileName];
|
||||
}
|
||||
if (localFile) {
|
||||
UIImage *image = nil;
|
||||
NSString *type = [NSString stringWithUTF8String:linphone_content_get_type(fileContent)];
|
||||
if (!filePath) {
|
||||
filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localFile];
|
||||
}
|
||||
|
||||
if ([type isEqualToString:@"video"]) {
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]) {
|
||||
image = [self getImageFromVideoUrl:[NSURL fileURLWithPath:filePath]];
|
||||
|
|
@ -451,13 +574,6 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
return CGSizeMake(CELL_MIN_WIDTH + CELL_MESSAGE_X_MARGIN, CELL_MIN_HEIGHT + CELL_MESSAGE_Y_MARGIN + textSize.height + 20);
|
||||
}
|
||||
|
||||
if (!filePath) {
|
||||
if (localImage) {
|
||||
filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localImage];
|
||||
} else {
|
||||
filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localVideo];
|
||||
}
|
||||
}
|
||||
if (localImage && [[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
||||
NSData* data = [NSData dataWithContentsOfFile:filePath];
|
||||
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||
|
|
|
|||
34
Classes/LinphoneUI/UIChatContentView.h
Normal file
34
Classes/LinphoneUI/UIChatContentView.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
|
||||
@interface UIChatContentView : UIImageView
|
||||
|
||||
@property(strong, nonatomic) NSMutableArray<NSURL*> *fileUrls;
|
||||
@property(nonatomic) NSInteger position;
|
||||
@property(readonly, nonatomic) LinphoneContent *content;
|
||||
@property(readonly, nonatomic) LinphoneChatMessage *message;
|
||||
@property(nonatomic) UIButton *downloadButton;
|
||||
@property(nonatomic) NSString *filePath;
|
||||
|
||||
- (void)setContent:(LinphoneContent *)content message:(LinphoneChatMessage *)message;
|
||||
|
||||
@end
|
||||
75
Classes/LinphoneUI/UIChatContentView.m
Normal file
75
Classes/LinphoneUI/UIChatContentView.m
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIChatContentView.h"
|
||||
#import "ChatConversationView.h"
|
||||
#import "PhoneMainView.h"
|
||||
|
||||
@implementation UIChatContentView
|
||||
|
||||
- (void)setContent:(LinphoneContent *)content message:(LinphoneChatMessage *)message {
|
||||
_content = content;
|
||||
_message = message;
|
||||
self.userInteractionEnabled = YES;
|
||||
|
||||
if(!linphone_chat_message_is_outgoing(_message) && linphone_content_is_file_transfer(_content)) {
|
||||
// has not yet downloaded
|
||||
UIImage *basicImage = [ChatConversationView getBasicImage];
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)] ;
|
||||
UIImage *image = [ChatConversationView drawText:name image:basicImage textSize:25];
|
||||
[self setImage:image];
|
||||
_downloadButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_downloadButton addTarget:self
|
||||
action:@selector(onDownloadClick:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
_downloadButton.backgroundColor = [UIColor orangeColor];
|
||||
UIFont *boldFont = [UIFont systemFontOfSize:10];
|
||||
NSMutableAttributedString *boldText = [[NSMutableAttributedString alloc] initWithString:@"Download" attributes:@{ NSFontAttributeName : boldFont }];
|
||||
[_downloadButton setAttributedTitle:boldText forState:UIControlStateNormal];
|
||||
_downloadButton.frame = CGRectMake(3, 3, 60, 30);
|
||||
[self addSubview:_downloadButton];
|
||||
} else {
|
||||
if (_filePath == NULL) {
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
_filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
}
|
||||
UIImage *image = [UIChatBubbleTextCell getImageFromContent:content filePath:_filePath];
|
||||
[self setImage:image];
|
||||
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onMultiPartClick:)];
|
||||
tapGestureRecognizer.numberOfTapsRequired = 1;
|
||||
tapGestureRecognizer.enabled = YES;
|
||||
[self addGestureRecognizer:tapGestureRecognizer];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-(IBAction)onMultiPartClick:(id)sender {
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
[view openFileWithURLs:_fileUrls index:_position];
|
||||
}
|
||||
|
||||
-(IBAction)onDownloadClick:(id)sender {
|
||||
_downloadButton.enabled = NO;
|
||||
linphone_content_set_file_path(_content, [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:[NSString stringWithUTF8String:linphone_content_get_name(_content)]].UTF8String);
|
||||
linphone_chat_message_download_content(_message, _content);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
@ -23,13 +23,13 @@
|
|||
|
||||
@required
|
||||
|
||||
- (void)deleteImageWithAssetId:(NSString *)assetId;
|
||||
- (void)deleteFileWithUuid:(NSUUID *)uuid;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIImageViewDeletable : UICollectionViewCell
|
||||
|
||||
@property NSString *assetId;
|
||||
@property NSUUID *uuid;
|
||||
@property(nonatomic, strong) id<UIImageViewDeletableDelegate> deleteDelegate;
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *image;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
}
|
||||
|
||||
- (IBAction)onDeletePressed {
|
||||
[_deleteDelegate deleteImageWithAssetId:_assetId];
|
||||
[_deleteDelegate deleteFileWithUuid:_uuid];
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -20,9 +20,11 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "LinphoneManager.h"
|
||||
#import "ChatConversationView.h"
|
||||
|
||||
@interface FileTransferDelegate : NSObject
|
||||
|
||||
- (void)uploadFileContent: (FileContext *)context forChatRoom:(LinphoneChatRoom *)chatRoom;
|
||||
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key;
|
||||
- (void)uploadImage:(UIImage *)image forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality;
|
||||
- (void)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name;
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message,
|
|||
return;
|
||||
}
|
||||
[LinphoneManager.instance.fileTransferDelegates addObject:self];
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
|
||||
LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_core(chatRoom));
|
||||
linphone_content_set_type(content, [type UTF8String]);
|
||||
|
|
@ -128,21 +129,56 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message,
|
|||
linphone_chat_message_send(_message);
|
||||
}
|
||||
|
||||
- (void)uploadFileContent: (FileContext *)context forChatRoom:(LinphoneChatRoom *)chatRoom {
|
||||
[LinphoneManager.instance.fileTransferDelegates addObject:self];
|
||||
|
||||
_message = linphone_chat_room_create_empty_message(chatRoom);
|
||||
NSMutableArray<NSString *> *names = [[NSMutableArray alloc] init];
|
||||
NSMutableArray<NSString *> *types = [[NSMutableArray alloc] init];
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < [context count]; ++i) {
|
||||
LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_core(chatRoom));
|
||||
NSString *type = [context.typesArray objectAtIndex:i];
|
||||
NSString *name = [context.namesArray objectAtIndex:i];
|
||||
NSData *data = [context.datasArray objectAtIndex:i];
|
||||
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
|
||||
linphone_content_set_type(content, [type UTF8String]);
|
||||
|
||||
linphone_content_set_subtype(content, [name.pathExtension UTF8String]);
|
||||
linphone_content_set_name(content, [name UTF8String]);
|
||||
linphone_content_set_file_path(content, [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name].UTF8String);
|
||||
[names addObject:name];
|
||||
[types addObject:type];
|
||||
linphone_chat_message_add_file_content(_message, content);
|
||||
linphone_content_unref(content);
|
||||
}
|
||||
|
||||
if (_text!=nil && ![_text isEqualToString:@""])
|
||||
linphone_chat_message_add_text_content(_message, [_text UTF8String]);
|
||||
|
||||
// todo indication progress
|
||||
[LinphoneManager setValueInMessageAppData:names forKey:@"multiparts" inMessage:_message];
|
||||
[LinphoneManager setValueInMessageAppData:types forKey:@"multipartstypes" inMessage:_message];
|
||||
LOGI(@"%p Uploading content from message %p", self, _message);
|
||||
linphone_chat_message_send(_message);
|
||||
}
|
||||
|
||||
|
||||
- (void)uploadImage:(UIImage *)image forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality {
|
||||
NSString *name = [NSString stringWithFormat:@"%li-%f.jpg", (long)image.hash, [NSDate timeIntervalSinceReferenceDate]];
|
||||
NSData *data = UIImageJPEGRepresentation(image, quality);
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
[self uploadData:data forChatRoom:chatRoom type:@"image" subtype:@"jpg" name:name key:@"localimage"];
|
||||
}
|
||||
|
||||
- (void)uploadVideo:(NSData *)data withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom {
|
||||
NSString *name = [NSString stringWithFormat:@"IMG-%f.MOV", [NSDate timeIntervalSinceReferenceDate]];
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:@"mov" name:name key:@"localvideo"];
|
||||
}
|
||||
|
||||
- (void)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name {
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
NSURL *url = [ChatConversationView getCacheFileUrl:name];
|
||||
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
|
||||
NSString *fileType = [[asset tracksWithMediaType:AVMediaTypeVideo] count] > 0 ? @"video" : @"file";
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@
|
|||
615A28422180C0870060F920 /* recording.png in Resources */ = {isa = PBXBuildFile; fileRef = 615A28412180C0820060F920 /* recording.png */; };
|
||||
615A28442180C0900060F920 /* recording@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 615A28432180C08F0060F920 /* recording@2x.png */; };
|
||||
617B4A60260A2B7800A87337 /* RecordingsListView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 617B4A62260A2B7800A87337 /* RecordingsListView.xib */; };
|
||||
617C242A263022690042FB4A /* UIChatContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 617C2429263022690042FB4A /* UIChatContentView.m */; };
|
||||
6180D6FE21EE41A800AD9CB6 /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6180D6FD21EE41A800AD9CB6 /* QuickLook.framework */; };
|
||||
61AE364F20C00B370089D9D3 /* ShareViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61AE364E20C00B370089D9D3 /* ShareViewController.m */; };
|
||||
61AE365220C00B370089D9D3 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61AE365020C00B370089D9D3 /* MainInterface.storyboard */; };
|
||||
|
|
@ -962,6 +963,8 @@
|
|||
617B4A61260A2B7800A87337 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/RecordingsListView.xib; sourceTree = "<group>"; };
|
||||
617B4A64260A2B8500A87337 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/RecordingsListView.strings; sourceTree = "<group>"; };
|
||||
617B4A75260A3F5500A87337 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/RecordingsListView.strings; sourceTree = "<group>"; };
|
||||
617C2428263022430042FB4A /* UIChatContentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIChatContentView.h; sourceTree = "<group>"; };
|
||||
617C2429263022690042FB4A /* UIChatContentView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIChatContentView.m; sourceTree = "<group>"; };
|
||||
6180D6FD21EE41A800AD9CB6 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = System/Library/Frameworks/QuickLook.framework; sourceTree = SDKROOT; };
|
||||
6187B1B524B3271500D580FB /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/AboutView.strings; sourceTree = "<group>"; };
|
||||
6187B1B624B3271500D580FB /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/AssistantLinkView.strings; sourceTree = "<group>"; };
|
||||
|
|
@ -2178,6 +2181,8 @@
|
|||
D3A8BB6E15A6C7D500F96BE5 /* UIChatBubbleTextCell.h */,
|
||||
D3A8BB6F15A6C7D500F96BE5 /* UIChatBubbleTextCell.m */,
|
||||
639E9CA51C0DB7EA00019A75 /* UIChatBubbleTextCell.xib */,
|
||||
617C2428263022430042FB4A /* UIChatContentView.h */,
|
||||
617C2429263022690042FB4A /* UIChatContentView.m */,
|
||||
D3EA540F159853750037DC6B /* UIChatCell.h */,
|
||||
D3EA5410159853750037DC6B /* UIChatCell.m */,
|
||||
639CEB0B1A1DF4FA004DE38F /* UIChatCell.xib */,
|
||||
|
|
@ -4207,6 +4212,7 @@
|
|||
6377AC801BDE4069007F7625 /* UIBackToCallButton.m in Sources */,
|
||||
6308F9C51BF0DD6600D1234B /* XMLRPCHelper.m in Sources */,
|
||||
D3ED3E871586291E006C0DE4 /* TabBarView.m in Sources */,
|
||||
617C242A263022690042FB4A /* UIChatContentView.m in Sources */,
|
||||
D3ED3EA71587334E006C0DE4 /* HistoryListTableView.m in Sources */,
|
||||
61AEBEBD2191990A00F35E7F /* DevicesListView.m in Sources */,
|
||||
D3ED3EB81587392C006C0DE4 /* HistoryListView.m in Sources */,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue