Implement preview for file-rooms

Use NCChatFileStatus instead NCMessageFileParameter to store download-related information
Correctly set creation date on downloaded files for caching

Signed-off-by: Marcel Müller <marcel-mueller@gmx.de>
This commit is contained in:
Marcel Müller 2020-12-12 21:13:08 +01:00
Родитель ef6f29fa0b
Коммит e5627c52c8
14 изменённых файлов: 348 добавлений и 71 удалений

Просмотреть файл

@ -13,6 +13,9 @@
1F4DD3EB2571C688007DC98E /* EmojiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4DD3EA2571C688007DC98E /* EmojiUtils.swift */; };
1F4DD3EC2571C688007DC98E /* EmojiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4DD3EA2571C688007DC98E /* EmojiUtils.swift */; };
1F4DD3ED2571C688007DC98E /* EmojiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4DD3EA2571C688007DC98E /* EmojiUtils.swift */; };
1F5CDF642584E78900B0026E /* NCChatFileStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F5CDF632584E78900B0026E /* NCChatFileStatus.m */; };
1F5CDF652584E78900B0026E /* NCChatFileStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F5CDF632584E78900B0026E /* NCChatFileStatus.m */; };
1F5CDF662584E78900B0026E /* NCChatFileStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F5CDF632584E78900B0026E /* NCChatFileStatus.m */; };
1FEDE3C6257D439500853F79 /* NCChatFileController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FEDE3C4257D439500853F79 /* NCChatFileController.m */; };
1FEDE3C7257D439500853F79 /* NCChatFileController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FEDE3C4257D439500853F79 /* NCChatFileController.m */; };
1FEDE3C8257D439500853F79 /* NCChatFileController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FEDE3C4257D439500853F79 /* NCChatFileController.m */; };
@ -470,6 +473,8 @@
1F3D3B20255F109E00230DAE /* BarButtonItemWithActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BarButtonItemWithActivity.m; sourceTree = "<group>"; };
1F3D3B21255F109E00230DAE /* BarButtonItemWithActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BarButtonItemWithActivity.h; sourceTree = "<group>"; };
1F4DD3EA2571C688007DC98E /* EmojiUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiUtils.swift; sourceTree = "<group>"; };
1F5CDF622584E78900B0026E /* NCChatFileStatus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCChatFileStatus.h; sourceTree = "<group>"; };
1F5CDF632584E78900B0026E /* NCChatFileStatus.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCChatFileStatus.m; sourceTree = "<group>"; };
1FEDE3C4257D439500853F79 /* NCChatFileController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NCChatFileController.m; sourceTree = "<group>"; };
1FEDE3C5257D439500853F79 /* NCChatFileController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCChatFileController.h; sourceTree = "<group>"; };
1FEDE3CC257D43AB00853F79 /* NCMessageFileParameter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NCMessageFileParameter.m; sourceTree = "<group>"; };
@ -1556,6 +1561,8 @@
2C42ADB320B58E6300296DEA /* NCChatController.m */,
1FEDE3C5257D439500853F79 /* NCChatFileController.h */,
1FEDE3C4257D439500853F79 /* NCChatFileController.m */,
1F5CDF622584E78900B0026E /* NCChatFileStatus.h */,
1F5CDF632584E78900B0026E /* NCChatFileStatus.m */,
2CA15543208E41B500CE8EF0 /* NCChatViewController.h */,
2CA15544208E41B500CE8EF0 /* NCChatViewController.m */,
2C43BA7421309A1000B3068A /* NCMessageParameter.h */,
@ -2036,6 +2043,7 @@
2CBF82B61FD0939600636459 /* NCAPISessionManager.m in Sources */,
2CA155562099E07700CE8EF0 /* GroupedChatMessageTableViewCell.m in Sources */,
2CA15548208EA1EA00CE8EF0 /* ChatMessageTableViewCell.m in Sources */,
1F5CDF642584E78900B0026E /* NCChatFileStatus.m in Sources */,
2CBF82C11FD5AE3F00636459 /* NCPushProxySessionManager.m in Sources */,
2C961E152216BF4B00F5C23F /* OCSharedDto.m in Sources */,
2C78EF951F7E70EB008AFA74 /* NCPeerConnection.m in Sources */,
@ -2148,6 +2156,7 @@
2C78E9E52512136100E3D4CA /* NCUserStatus.m in Sources */,
2C62B00D24C1BDC1007E460A /* NCPushNotification.m in Sources */,
2C62AFCD24C1BD78007E460A /* OCNotifications.m in Sources */,
1F5CDF662584E78900B0026E /* NCChatFileStatus.m in Sources */,
2C62B01C24C1BDC9007E460A /* CCCertificate.m in Sources */,
2C62B01424C1BDC5007E460A /* RoomCreationTableViewController.m in Sources */,
2C62AFCB24C1BD78007E460A /* OCExternalSites.m in Sources */,
@ -2305,6 +2314,7 @@
2CC001E224A37AD400A20167 /* VideoSettingsViewController.m in Sources */,
2CC001AA24A37A8F00A20167 /* ChatMessageTableViewCell.m in Sources */,
2C78E9E42512136000E3D4CA /* NCUserStatus.m in Sources */,
1F5CDF652584E78900B0026E /* NCChatFileStatus.m in Sources */,
2CC001BA24A37A9A00A20167 /* ResultMultiSelectionTableViewController.m in Sources */,
2CC001B824A37A9A00A20167 /* SearchTableViewController.m in Sources */,
2CC001D324A37ACA00A20167 /* RoomCreation2TableViewController.m in Sources */,

Просмотреть файл

@ -160,7 +160,7 @@
TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount];
[self.avatarView setImageWithURLRequest:[[NCAPIController sharedInstance] createAvatarRequestForUser:message.actorId andSize:96 usingAccount:activeAccount]
placeholderImage:nil success:nil failure:nil];
NSString *imageName = [[NCUtils previewImageForFileMIMEType:message.file.mimetype] stringByAppendingString:@"-chat-preview"];
UIImage *filePreviewImage = [UIImage imageNamed:imageName];
__weak FilePreviewImageView *weakPreviewImageView = self.previewImageView;
@ -177,8 +177,10 @@
[self.statusView addSubview:errorView];
} else if (message.isTemporary) {
[self addActivityIndicator:0];
} else if (message.file.isDownloading && message.file.downloadProgress < 1) {
[self addActivityIndicator:message.file.downloadProgress];
} else if (message.file.fileStatus) {
if (message.file.fileStatus.isDownloading && message.file.fileStatus.downloadProgress < 1) {
[self addActivityIndicator:message.file.fileStatus.downloadProgress];
}
}
self.fileParameter = message.file;
@ -187,9 +189,9 @@
- (void)didChangeIsDownloading:(NSNotification *)notification
{
dispatch_async(dispatch_get_main_queue(), ^{
NCMessageFileParameter *receivedParameter = [notification.userInfo objectForKey:@"fileParameter"];
NCChatFileStatus *receivedStatus = [notification.userInfo objectForKey:@"fileStatus"];
if (receivedParameter.parameterId != self->_fileParameter.parameterId || ![receivedParameter.path isEqualToString:self->_fileParameter.path]) {
if (![receivedStatus.fileId isEqualToString:self->_fileParameter.parameterId] || ![receivedStatus.filePath isEqualToString:self->_fileParameter.path]) {
// Received a notification for a different cell
return;
}
@ -207,9 +209,9 @@
- (void)didChangeDownloadProgress:(NSNotification *)notification
{
dispatch_async(dispatch_get_main_queue(), ^{
NCMessageFileParameter *receivedParameter = [notification.userInfo objectForKey:@"fileParameter"];
NCChatFileStatus *receivedStatus = [notification.userInfo objectForKey:@"fileStatus"];
if (receivedParameter.parameterId != self->_fileParameter.parameterId || ![receivedParameter.path isEqualToString:self->_fileParameter.path]) {
if (![receivedStatus.fileId isEqualToString:self->_fileParameter.parameterId] || ![receivedStatus.filePath isEqualToString:self->_fileParameter.path]) {
// Received a notification for a different cell
return;
}

Просмотреть файл

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "preview-file-settings@1x.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "preview-file-settings@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "preview-file-settings@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Двоичные данные
NextcloudTalk/Images.xcassets/preview-file-settings.imageset/preview-file-settings@1x.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 731 B

Двоичные данные
NextcloudTalk/Images.xcassets/preview-file-settings.imageset/preview-file-settings@2x.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
NextcloudTalk/Images.xcassets/preview-file-settings.imageset/preview-file-settings@3x.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.1 KiB

Просмотреть файл

@ -23,6 +23,7 @@
#import "NCDatabaseManager.h"
#import "NCMessageFileParameter.h"
#import "NCChatFileStatus.h"
NS_ASSUME_NONNULL_BEGIN
@ -33,7 +34,7 @@ extern NSString * const NCChatFileControllerDidChangeDownloadProgressNotificatio
@protocol NCChatFileControllerDelegate<NSObject>
- (void)fileControllerDidLoadFile:(NCChatFileController *)fileController withFileParameter:(NCMessageFileParameter *)parameter withFilePath:(NSString *)path;
- (void)fileControllerDidLoadFile:(NCChatFileController *)fileController withFileStatus:(NCChatFileStatus *)fileStatus;
@end
@ -42,6 +43,7 @@ extern NSString * const NCChatFileControllerDidChangeDownloadProgressNotificatio
@property (nonatomic, weak) id<NCChatFileControllerDelegate> delegate;
- (void)downloadFileFromMessage:(NCMessageFileParameter *)fileParameter;
- (void)downloadFileWithFileId:(NSString *)fileId;
- (void)deleteDownloadDirectoryForAccount:(TalkAccount *)account;
@end

Просмотреть файл

@ -32,10 +32,8 @@ int const kNCChatFileControllerDeleteFilesOlderThanDays = 7;
@interface NCChatFileController ()
@property (nonatomic, strong) TalkAccount *account;
@property (nonatomic, strong) NCMessageFileParameter *fileParameter;
@property (nonatomic, strong) NCChatFileStatus *fileStatus;
@property (nonatomic, strong) NSString *tempDirectoryPath;
@property (nonatomic, strong) NSString *fileLocalPath;
@end
@ -44,8 +42,6 @@ int const kNCChatFileControllerDeleteFilesOlderThanDays = 7;
- (void)initDownloadDirectoryForAccount:(TalkAccount *)account
{
_account = account;
NSString *encodedAccountId = [account.accountId stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLHostAllowedCharacterSet];
NSFileManager *fileManager = [NSFileManager defaultManager];
_tempDirectoryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"/download/"];
@ -113,13 +109,21 @@ int const kNCChatFileControllerDeleteFilesOlderThanDays = 7;
return YES;
}
// At this point there's a file in our cache but there's a newer one available
// At this point there's a file in our cache but there's a different one on the server
NSLog(@"Deleting file from cache: %@", filePath);
[fileManager removeItemAtPath:filePath error:nil];
return NO;
}
- (void)setCreationDateOnFile:(NSString *)filePath withCreationDate:(NSDate *)date
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *creationDateAttr = [NSDictionary dictionaryWithObjectsAndKeys:date, NSFileCreationDate, nil];
[fileManager setAttributes:creationDateAttr ofItemAtPath:filePath error:nil];
}
- (void)setModificationDateOnFile:(NSString *)filePath withModificationDate:(NSDate *)date
{
NSFileManager *fileManager = [NSFileManager defaultManager];
@ -129,6 +133,33 @@ int const kNCChatFileControllerDeleteFilesOlderThanDays = 7;
}
- (void)downloadFileFromMessage:(NCMessageFileParameter *)fileParameter
{
_fileStatus = [NCChatFileStatus initWithFileName:fileParameter.name withFilePath:fileParameter.path withFileId:fileParameter.parameterId];
fileParameter.fileStatus = _fileStatus;
[self startDownload];
}
- (void)downloadFileWithFileId:(NSString *)fileId
{
TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount];
[[NCAPIController sharedInstance] getFileByFileId:activeAccount fileId:fileId withCompletionBlock:^(NCCommunicationFile *file, NSInteger error, NSString *errorDescription) {
if (file) {
NSString *remoteDavPrefix = [NSString stringWithFormat:@"/remote.php/dav/files/%@/", activeAccount.userId];
NSString *directoryPath = [file.path componentsSeparatedByString:remoteDavPrefix].lastObject;
NSString *filePath = [NSString stringWithFormat:@"%@%@", directoryPath, file.fileName];
self->_fileStatus = [NCChatFileStatus initWithFileName:file.fileName withFilePath:filePath withFileId:file.fileId];
[self startDownload];
} else {
NSLog(@"An error occurred while getting file with fileId %@: %@", fileId, errorDescription);
}
}];
}
- (void)startDownload
{
TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount];
ServerCapabilities *serverCapabilities = [[NCDatabaseManager sharedInstance] serverCapabilitiesForAccountId:activeAccount.accountId];
@ -136,10 +167,8 @@ int const kNCChatFileControllerDeleteFilesOlderThanDays = 7;
[[NCAPIController sharedInstance] setupNCCommunicationForAccount:activeAccount];
[self initDownloadDirectoryForAccount:activeAccount];
NSString *serverUrlFileName = [NSString stringWithFormat:@"%@/%@/%@", activeAccount.server, serverCapabilities.webDAVRoot, fileParameter.path];
_account = activeAccount;
_fileParameter = fileParameter;
_fileLocalPath = [_tempDirectoryPath stringByAppendingPathComponent:fileParameter.name];
NSString *serverUrlFileName = [NSString stringWithFormat:@"%@/%@/%@", activeAccount.server, serverCapabilities.webDAVRoot, _fileStatus.filePath];
_fileStatus.fileLocalPath = [_tempDirectoryPath stringByAppendingPathComponent:_fileStatus.fileName];
// Setting just isDownloading without a concrete progress will show an indeterminate activity indicator
[self didChangeIsDownloadingNotification:YES];
@ -149,22 +178,27 @@ int const kNCChatFileControllerDeleteFilesOlderThanDays = 7;
if (errorCode == 0 && files.count == 1) {
// File exists on server -> check our cache
NCCommunicationFile *file = files.firstObject;
if ([self isFileInCache:self->_fileLocalPath withModificationDate:file.date withSize:file.size]) {
NSLog(@"Found file in cache: %@", self->_fileLocalPath);
if ([self isFileInCache:self->_fileStatus.fileLocalPath withModificationDate:file.date withSize:file.size]) {
NSLog(@"Found file in cache: %@", self->_fileStatus.fileLocalPath);
[self.delegate fileControllerDidLoadFile:self withFileStatus:self->_fileStatus];
[self didChangeIsDownloadingNotification:NO];
[self.delegate fileControllerDidLoadFile:self withFileParameter:self->_fileParameter withFilePath:self->_fileLocalPath];
return;
}
[[NCCommunication shared] downloadWithServerUrlFileName:serverUrlFileName fileNameLocalPath:self->_fileLocalPath customUserAgent:nil addCustomHeaders:nil progressHandler:^(NSProgress *progress) {
[[NCCommunication shared] downloadWithServerUrlFileName:serverUrlFileName fileNameLocalPath:self->_fileStatus.fileLocalPath customUserAgent:nil addCustomHeaders:nil progressHandler:^(NSProgress *progress) {
[self didChangeDownloadProgressNotification:progress.fractionCompleted];
} completionHandler:^(NSString *account, NSString *etag, NSDate *date, double length, NSDictionary *allHeaderFields, NSInteger errorCode, NSString * errorDescription) {
[self setModificationDateOnFile:self->_fileLocalPath withModificationDate:file.date];
// Set modification date to invalidate our cache
[self setModificationDateOnFile:self->_fileStatus.fileLocalPath withModificationDate:file.date];
// Set creation date to delete older files from cache
[self setCreationDateOnFile:self->_fileStatus.fileLocalPath withCreationDate:[NSDate date]];
[self.delegate fileControllerDidLoadFile:self withFileStatus:self->_fileStatus];
[self didChangeIsDownloadingNotification:NO];
[self.delegate fileControllerDidLoadFile:self withFileParameter:self->_fileParameter withFilePath:self->_fileLocalPath];
}];
} else {
[self didChangeIsDownloadingNotification:NO];
@ -175,13 +209,11 @@ int const kNCChatFileControllerDeleteFilesOlderThanDays = 7;
- (void)didChangeIsDownloadingNotification:(BOOL)isDownloading
{
_fileParameter.isDownloading = isDownloading;
_fileStatus.isDownloading = isDownloading;
NSMutableDictionary *userInfo = [NSMutableDictionary new];
[userInfo setObject:_account forKey:@"account"];
[userInfo setObject:_fileParameter forKey:@"fileParameter"];
[userInfo setObject:_fileStatus forKey:@"fileStatus"];
[userInfo setObject:@(isDownloading) forKey:@"isDownloading"];
[[NSNotificationCenter defaultCenter] postNotificationName:NCChatFileControllerDidChangeIsDownloadingNotification
object:self
userInfo:userInfo];
@ -189,11 +221,10 @@ int const kNCChatFileControllerDeleteFilesOlderThanDays = 7;
- (void)didChangeDownloadProgressNotification:(double)progress
{
_fileParameter.downloadProgress = progress;
_fileStatus.downloadProgress = progress;
NSMutableDictionary *userInfo = [NSMutableDictionary new];
[userInfo setObject:_account forKey:@"account"];
[userInfo setObject:_fileParameter forKey:@"fileParameter"];
[userInfo setObject:_fileStatus forKey:@"fileStatus"];
[userInfo setObject:@(progress) forKey:@"progress"];
[[NSNotificationCenter defaultCenter] postNotificationName:NCChatFileControllerDidChangeDownloadProgressNotification
object:self

Просмотреть файл

@ -0,0 +1,41 @@
/**
* @copyright Copyright (c) 2020 Marcel Müller <marcel-mueller@gmx.de>
*
* @author Marcel Müller <marcel-mueller@gmx.de>
*
* @license GNU GPL version 3 or any later version
*
* 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 <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NCChatFileStatus : NSObject
@property (nonatomic, strong) NSString *fileId;
@property (nonatomic, strong) NSString *fileName;
@property (nonatomic, strong) NSString *filePath;
@property (nonatomic, strong) NSString *fileLocalPath;
@property (nonatomic, assign) BOOL isDownloading;
@property (nonatomic, assign) CGFloat downloadProgress;
+ (instancetype)initWithFileName:(NSString *)fileName withFilePath:(NSString *)filePath withFileId:(NSString *)fileId;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -0,0 +1,37 @@
/**
* @copyright Copyright (c) 2020 Marcel Müller <marcel-mueller@gmx.de>
*
* @author Marcel Müller <marcel-mueller@gmx.de>
*
* @license GNU GPL version 3 or any later version
*
* 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 "NCChatFileStatus.h"
@implementation NCChatFileStatus
+ (instancetype)initWithFileName:(NSString *)fileName withFilePath:(NSString *)filePath withFileId:(NSString *)fileId
{
NCChatFileStatus *fileStatus = [[NCChatFileStatus alloc] init];
fileStatus.fileName = fileName;
fileStatus.filePath = filePath;
fileStatus.fileId = fileId;
return fileStatus;
}
@end

Просмотреть файл

@ -2244,7 +2244,7 @@ NSString * const NCChatViewControllerReplyPrivatelyNotification = @"NCChatViewCo
- (void)cellWantsToDownloadFile:(NCMessageFileParameter *)fileParameter
{
if (fileParameter.isDownloading) {
if (fileParameter.fileStatus && fileParameter.fileStatus.isDownloading) {
NSLog(@"File already downloading -> skipping new download");
return;
}
@ -2256,7 +2256,7 @@ NSString * const NCChatViewControllerReplyPrivatelyNotification = @"NCChatViewCo
#pragma mark - NCChatFileControllerDelegate
- (void)fileControllerDidLoadFile:(NCChatFileController *)fileController withFileParameter:(NCMessageFileParameter *)parameter withFilePath:(NSString *)path
- (void)fileControllerDidLoadFile:(NCChatFileController *)fileController withFileStatus:(NCChatFileStatus *)fileStatus
{
if (_isPreviewControllerShown) {
// We are showing a file already, no need to open another one
@ -2269,7 +2269,7 @@ NSString * const NCChatViewControllerReplyPrivatelyNotification = @"NCChatViewCo
NSDate *sectionDate = [_dateSections objectAtIndex:indexPath.section];
NCChatMessage *message = [[_messages objectForKey:sectionDate] objectAtIndex:indexPath.row];
if (message.file && message.file.parameterId == parameter.parameterId && [message.file.path isEqualToString:parameter.path]) {
if (message.file && [message.file.parameterId isEqualToString:fileStatus.fileId] && [message.file.path isEqualToString:fileStatus.filePath]) {
isFileCellStillVisible = YES;
break;
}
@ -2282,7 +2282,7 @@ NSString * const NCChatViewControllerReplyPrivatelyNotification = @"NCChatViewCo
dispatch_async(dispatch_get_main_queue(), ^{
self->_isPreviewControllerShown = YES;
self->_previewControllerFilePath = path;
self->_previewControllerFilePath = fileStatus.fileLocalPath;
QLPreviewController * preview = [[QLPreviewController alloc] init];
UIColor *themeColor = [NCAppBranding themeColor];
@ -2304,7 +2304,7 @@ NSString * const NCChatViewControllerReplyPrivatelyNotification = @"NCChatViewCo
preview.navigationItem.scrollEdgeAppearance = appearance;
}
[self presentViewController:preview animated:YES completion:nil];
[self.navigationController pushViewController:preview animated:YES];
});
}

Просмотреть файл

@ -24,6 +24,7 @@
#import <UIKit/UIKit.h>
#import "NCMessageParameter.h"
#import "NCChatFileStatus.h"
NS_ASSUME_NONNULL_BEGIN
@ -32,8 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong) NSString *path;
@property (nonatomic, strong) NSString *mimetype;
@property (nonatomic, assign) BOOL previewAvailable;
@property (nonatomic, assign) BOOL isDownloading;
@property (nonatomic, assign) CGFloat downloadProgress;
@property (nonatomic, strong) NCChatFileStatus *fileStatus;
@end

Просмотреть файл

@ -31,8 +31,6 @@
self.path = [parameterDict objectForKey:@"path"];
self.mimetype = [parameterDict objectForKey:@"mimetype"];
self.previewAvailable = [[parameterDict objectForKey:@"preview-available"] boolValue];
self.isDownloading = NO;
self.downloadProgress = 0;
}
return self;

Просмотреть файл

@ -22,6 +22,7 @@
#import "RoomInfoTableViewController.h"
#import <QuickLook/QuickLook.h>
#import "AddParticipantsTableViewController.h"
#import "ContactsTableViewCell.h"
@ -38,6 +39,7 @@
#import "NCUtils.h"
#import "UIImageView+Letters.h"
#import "UIImageView+AFNetworking.h"
#import "NCChatFileController.h"
typedef enum RoomInfoSection {
kRoomInfoSectionName = 0,
@ -45,14 +47,14 @@ typedef enum RoomInfoSection {
kRoomInfoSectionPublic,
kRoomInfoSectionWebinar,
kRoomInfoSectionParticipants,
kRoomInfoSectionDestructive
kRoomInfoSectionDestructive,
kRoomInfoSectionFile
} RoomInfoSection;
typedef enum RoomAction {
kRoomActionFavorite = 0,
kRoomActionNotifications,
kRoomActionSendLink,
kRoomActionGotoFile
kRoomActionSendLink
} RoomAction;
typedef enum PublicAction {
@ -84,9 +86,14 @@ typedef enum ModificationError {
kModificationErrorDelete
} ModificationError;
typedef enum FileAction {
kFileActionPreview = 0,
kFileActionOpenInFilesApp
} FileAction;
#define k_set_password_textfield_tag 98
@interface RoomInfoTableViewController () <UITextFieldDelegate, UIGestureRecognizerDelegate, AddParticipantsTableViewControllerDelegate>
@interface RoomInfoTableViewController () <UITextFieldDelegate, UIGestureRecognizerDelegate, AddParticipantsTableViewControllerDelegate, NCChatFileControllerDelegate, QLPreviewControllerDelegate, QLPreviewControllerDataSource>
@property (nonatomic, strong) NCRoom *room;
@property (nonatomic, strong) NCChatViewController *chatViewController;
@ -100,6 +107,8 @@ typedef enum ModificationError {
@property (nonatomic, strong) UIActivityIndicatorView *modifyingRoomView;
@property (nonatomic, strong) HeaderWithButton *headerView;
@property (nonatomic, strong) UIAlertAction *setPasswordAction;
@property (nonatomic, strong) UIActivityIndicatorView *fileDownloadIndicator;
@property (nonatomic, strong) NSString *previewControllerFilePath;
@end
@ -228,6 +237,10 @@ typedef enum ModificationError {
[sections addObject:[NSNumber numberWithInt:kRoomInfoSectionName]];
// Room actions section
[sections addObject:[NSNumber numberWithInt:kRoomInfoSectionActions]];
// File actions section
if ([_room.objectType isEqualToString:NCRoomObjectTypeFile]) {
[sections addObject:[NSNumber numberWithInt:kRoomInfoSectionFile]];
}
// Moderator sections
if (_room.canModerate) {
// Public room section
@ -267,11 +280,6 @@ typedef enum ModificationError {
[actions addObject:[NSNumber numberWithInt:kRoomActionSendLink]];
}
// Action for file-rooms
if ([_room.objectType isEqualToString:NCRoomObjectTypeFile]) {
[actions addObject:[NSNumber numberWithInt:kRoomActionGotoFile]];
}
return [NSArray arrayWithArray:actions];
}
@ -285,6 +293,17 @@ typedef enum ModificationError {
return actionIndexPath;
}
- (NSArray *)getFileActions
{
NSMutableArray *actions = [[NSMutableArray alloc] init];
// File preview
[actions addObject:[NSNumber numberWithInt:kFileActionPreview]];
// Open file in nextcloud app
[actions addObject:[NSNumber numberWithInt:kFileActionOpenInFilesApp]];
return [NSArray arrayWithArray:actions];
}
- (NSArray *)getPublicActions
{
NSMutableArray *actions = [[NSMutableArray alloc] init];
@ -680,7 +699,25 @@ typedef enum ModificationError {
};
}
- (void)gotoRoomFileFromIndexPath:(NSIndexPath *)indexPath
- (void)previewRoomFile:(NSIndexPath *)indexPath
{
if (_fileDownloadIndicator) {
// Already downloading a file
return;
}
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
_fileDownloadIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
[_fileDownloadIndicator startAnimating];
[cell setAccessoryView:_fileDownloadIndicator];
NCChatFileController *downloader = [[NCChatFileController alloc] init];
downloader.delegate = self;
[downloader downloadFileWithFileId:_room.objectId];
}
- (void)openRoomFileInFilesApp:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
@ -725,8 +762,6 @@ typedef enum ModificationError {
[[NCUserInterfaceController sharedInstance] presentAlertViewController:alert];
}
}];
}
- (void)leaveRoom
@ -1035,6 +1070,10 @@ typedef enum ModificationError {
return [self getRoomActions].count;
break;
case kRoomInfoSectionFile:
return [self getFileActions].count;
break;
case kRoomInfoSectionPublic:
return [self getPublicActions].count;
break;
@ -1079,6 +1118,9 @@ typedef enum ModificationError {
NSArray *sections = [self getRoomInfoSections];
RoomInfoSection infoSection = [[sections objectAtIndex:section] intValue];
switch (infoSection) {
case kRoomInfoSectionFile:
return NSLocalizedString(@"Linked file", nil);
break;
case kRoomInfoSectionPublic:
return NSLocalizedString(@"Guests", nil);
break;
@ -1121,6 +1163,7 @@ typedef enum ModificationError {
case kRoomInfoSectionActions:
return 10;
break;
case kRoomInfoSectionFile:
case kRoomInfoSectionPublic:
case kRoomInfoSectionWebinar:
return 36;
@ -1140,7 +1183,8 @@ typedef enum ModificationError {
static NSString *shareLinkCellIdentifier = @"ShareLinkCellIdentifier";
static NSString *passwordCellIdentifier = @"PasswordCellIdentifier";
static NSString *sendLinkCellIdentifier = @"SendLinkCellIdentifier";
static NSString *gotoFileCellIdentifier = @"GotoFileCellIdentifier";
static NSString *previewFileCellIdentifier = @"PreviewFileCellIdentifier";
static NSString *openFileCellIdentifier = @"OpenFileCellIdentifier";
static NSString *lobbyCellIdentifier = @"LobbyCellIdentifier";
static NSString *lobbyTimerCellIdentifier = @"LobbyTimerCellIdentifier";
static NSString *leaveRoomCellIdentifier = @"LeaveRoomCellIdentifier";
@ -1257,28 +1301,46 @@ typedef enum ModificationError {
return cell;
}
break;
case kRoomActionGotoFile:
}
}
break;
case kRoomInfoSectionFile:
{
NSArray *actions = [self getFileActions];
FileAction action = [[actions objectAtIndex:indexPath.row] intValue];
switch (action) {
case kFileActionPreview:
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:gotoFileCellIdentifier];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:previewFileCellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:gotoFileCellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:previewFileCellIdentifier];
}
cell.textLabel.text = NSLocalizedString(@"Go to file", nil);
NSString *fileName = _room.name;
NSString *fileExt = [fileName pathExtension];
cell.textLabel.text = NSLocalizedString(@"Preview", nil);
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
[cell.imageView setImage:[UIImage imageNamed:@"preview-file-settings"]];
[cell.imageView setImage:[UIImage imageNamed:[NCUtils previewImageForFileExtension:fileExt]]];
if (_fileDownloadIndicator) {
// Set download indicator in case we're already downloading a file
[cell setAccessoryView:_fileDownloadIndicator];
}
// Make sure the file icon has the same size as all other cell-images
// https://stackoverflow.com/questions/2788028/
CGSize itemSize = CGSizeMake(24, 24);
UIGraphicsBeginImageContextWithOptions(itemSize, NO, UIScreen.mainScreen.scale);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[cell.imageView.image drawInRect:imageRect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return cell;
}
break;
case kFileActionOpenInFilesApp:
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:openFileCellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:openFileCellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:NSLocalizedString(@"Open in %@", nil), filesAppName];
UIImage *nextcloudActionImage = [[UIImage imageNamed:@"logo-action"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[cell.imageView setImage:nextcloudActionImage];
cell.imageView.tintColor = [UIColor colorWithRed:0.43 green:0.43 blue:0.45 alpha:1];
return cell;
}
break;
@ -1477,8 +1539,19 @@ typedef enum ModificationError {
case kRoomActionSendLink:
[self shareRoomLinkFromIndexPath:indexPath];
break;
case kRoomActionGotoFile:
[self gotoRoomFileFromIndexPath:indexPath];
}
}
break;
case kRoomInfoSectionFile:
{
NSArray *actions = [self getFileActions];
FileAction action = [[actions objectAtIndex:indexPath.row] intValue];
switch (action) {
case kFileActionPreview:
[self previewRoomFile:indexPath];
break;
case kFileActionOpenInFilesApp:
[self openRoomFileInFilesApp:indexPath];
break;
}
}
@ -1517,4 +1590,64 @@ typedef enum ModificationError {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - NCChatFileControllerDelegate
- (void)fileControllerDidLoadFile:(NCChatFileController *)fileController withFileStatus:(NCChatFileStatus *)fileStatus
{
if (_fileDownloadIndicator) {
[_fileDownloadIndicator stopAnimating];
[_fileDownloadIndicator removeFromSuperview];
_fileDownloadIndicator = nil;
}
NSInteger fileSection = [[self getRoomInfoSections] indexOfObject:@(kRoomInfoSectionFile)];
NSInteger previewRow = [[self getFileActions] indexOfObject:@(kFileActionPreview)];
NSIndexPath *previewActionIndexPath = [NSIndexPath indexPathForRow:previewRow inSection:fileSection];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:previewActionIndexPath];
if (cell) {
// Make sure disclosure indicator is visible again (otherwise accessoryView is empty)
cell.accessoryView = nil;
// Only show preview controller if cell is still visible
dispatch_async(dispatch_get_main_queue(), ^{
self->_previewControllerFilePath = fileStatus.fileLocalPath;
QLPreviewController * preview = [[QLPreviewController alloc] init];
UIColor *themeColor = [NCAppBranding themeColor];
preview.dataSource = self;
preview.delegate = self;
preview.navigationController.navigationBar.tintColor = [NCAppBranding themeTextColor];
preview.navigationController.navigationBar.barTintColor = themeColor;
preview.tabBarController.tabBar.tintColor = themeColor;
if (@available(iOS 13.0, *)) {
UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
[appearance configureWithOpaqueBackground];
appearance.backgroundColor = themeColor;
appearance.titleTextAttributes = @{NSForegroundColorAttributeName:[NCAppBranding themeTextColor]};
preview.navigationItem.standardAppearance = appearance;
preview.navigationItem.compactAppearance = appearance;
preview.navigationItem.scrollEdgeAppearance = appearance;
}
[self.navigationController pushViewController:preview animated:YES];
});
}
}
#pragma mark - QLPreviewControllerDelegate/DataSource
- (NSInteger)numberOfPreviewItemsInPreviewController:(nonnull QLPreviewController *)controller {
return 1;
}
- (nonnull id<QLPreviewItem>)previewController:(nonnull QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
return [NSURL fileURLWithPath:_previewControllerFilePath];
}
@end