diff --git a/NextcloudTalk.xcodeproj/project.pbxproj b/NextcloudTalk.xcodeproj/project.pbxproj index abf17545..25290bf1 100644 --- a/NextcloudTalk.xcodeproj/project.pbxproj +++ b/NextcloudTalk.xcodeproj/project.pbxproj @@ -253,6 +253,7 @@ 1FBC3BE92B61BD09003909E0 /* TestBaseRealm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FBC3BE82B61BD09003909E0 /* TestBaseRealm.swift */; }; 1FC940B92A5F21FC00FFFADE /* SwiftMarkdownObjCBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0A1D432A5F1FA800A25433 /* SwiftMarkdownObjCBridge.swift */; }; 1FC940BA2A5F21FD00FFFADE /* SwiftMarkdownObjCBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0A1D432A5F1FA800A25433 /* SwiftMarkdownObjCBridge.swift */; }; + 1FCE3D532C9B5918009C68A9 /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = 1FCE3D522C9B5918009C68A9 /* SwiftyGif */; }; 1FD6F83C2B825069004048AB /* NCRoomsManagerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD6F83B2B825069004048AB /* NCRoomsManagerExtensions.swift */; }; 1FD6F83E2B87B712004048AB /* NCUserStatusExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD6F83D2B87B712004048AB /* NCUserStatusExtensions.swift */; }; 1FD8AE6B2A3A216300787C16 /* UIRoomTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8AD8C2A3A162100787C16 /* UIRoomTest.swift */; }; @@ -1233,6 +1234,7 @@ files = ( 2CA1CCCA1F17C503002FE6A2 /* AudioToolbox.framework in Frameworks */, 2CCCD21D2835088F00F076CE /* OpenSSL in Frameworks */, + 1FCE3D532C9B5918009C68A9 /* SwiftyGif in Frameworks */, 1F90EFC725FE4BE700F3FA55 /* IntentsUI.framework in Frameworks */, 2CA1CC971F016117002FE6A2 /* Security.framework in Frameworks */, 1F45A1212A01D8BA005FE87D /* SDWebImageSVGKitPlugin in Frameworks */, @@ -2236,6 +2238,7 @@ 1FAB2E872ACD44D0001214EB /* WebRTC */, 80CDF8C32A8E098900CB57AE /* SwiftUIIntrospect */, 1F759C2B2B63CB93000534AB /* Realm */, + 1FCE3D522C9B5918009C68A9 /* SwiftyGif */, ); productName = NextcloudTalk; productReference = 2C05747D1EDD9E8E00D9E7F2 /* NextcloudTalk.app */; @@ -2393,6 +2396,7 @@ 1FAB2E862ACD44CF001214EB /* XCRemoteSwiftPackageReference "talk-clients-webrtc" */, 80CDF8C22A8E098900CB57AE /* XCRemoteSwiftPackageReference "swiftui-introspect" */, 1F759C2A2B63CB93000534AB /* XCRemoteSwiftPackageReference "realm-swift-binary" */, + 1FCE3D512C9B5918009C68A9 /* XCRemoteSwiftPackageReference "SwiftyGif" */, ); productRefGroup = 2C05747E1EDD9E8E00D9E7F2 /* Products */; projectDirPath = ""; @@ -4240,6 +4244,14 @@ revision = 5f15c82f4b02072c1595980580eade9325e1819f; }; }; + 1FCE3D512C9B5918009C68A9 /* XCRemoteSwiftPackageReference "SwiftyGif" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/alexiscreuzot/SwiftyGif"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.4.5; + }; + }; 2CCCD21B2835088F00F076CE /* XCRemoteSwiftPackageReference "OpenSSL" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/krzyzanowskim/OpenSSL"; @@ -4449,6 +4461,11 @@ package = 1FAB2E862ACD44CF001214EB /* XCRemoteSwiftPackageReference "talk-clients-webrtc" */; productName = WebRTC; }; + 1FCE3D522C9B5918009C68A9 /* SwiftyGif */ = { + isa = XCSwiftPackageProductDependency; + package = 1FCE3D512C9B5918009C68A9 /* XCRemoteSwiftPackageReference "SwiftyGif" */; + productName = SwiftyGif; + }; 1FF136192BFBC841006A6101 /* SwiftyAttributes */ = { isa = XCSwiftPackageProductDependency; package = 1F66B72D29FABD01003FB168 /* XCRemoteSwiftPackageReference "SwiftyAttributes" */; diff --git a/NextcloudTalk/NCChatMessage.swift b/NextcloudTalk/NCChatMessage.swift index 23ce23b2..135c0d93 100644 --- a/NextcloudTalk/NCChatMessage.swift +++ b/NextcloudTalk/NCChatMessage.swift @@ -257,4 +257,15 @@ import SwiftyAttributes return nil } + + public var isAnimatableGif: Bool { + guard let accountId, let file = self.file() else { return false } + + let capabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: accountId) + + guard NCUtils.isGif(fileType: file.mimetype), let maxGifSize = capabilities?.maxGifSize, maxGifSize > 0 else { return false } + + return file.size <= maxGifSize + } + } diff --git a/NextcloudTalk/NCDatabaseManager.m b/NextcloudTalk/NCDatabaseManager.m index bddb1ee4..867ccebe 100644 --- a/NextcloudTalk/NCDatabaseManager.m +++ b/NextcloudTalk/NCDatabaseManager.m @@ -16,7 +16,7 @@ NSString *const kTalkDatabaseFolder = @"Library/Application Support/Talk"; NSString *const kTalkDatabaseFileName = @"talk.realm"; -uint64_t const kTalkDatabaseSchemaVersion = 67; +uint64_t const kTalkDatabaseSchemaVersion = 68; NSString * const kCapabilitySystemMessages = @"system-messages"; NSString * const kCapabilityNotificationLevels = @"notification-levels"; @@ -454,6 +454,13 @@ NSString * const NCDatabaseManagerRoomCapabilitiesChangedNotification = @"NCData } else { capabilities.federationOnlyTrustedServers = NO; } + + NSDictionary *previewConfig = [talkConfig objectForKey:@"previews"]; + NSArray *previewConfigKeys = [previewConfig allKeys]; + + if ([previewConfigKeys containsObject:@"max-gif-size"]) { + capabilities.maxGifSize = [[previewConfig objectForKey:@"max-gif-size"] intValue]; + } } #pragma mark - Federated capabilities diff --git a/NextcloudTalk/NCMediaViewerPageViewController.swift b/NextcloudTalk/NCMediaViewerPageViewController.swift index 22130cad..81a0c4f8 100644 --- a/NextcloudTalk/NCMediaViewerPageViewController.swift +++ b/NextcloudTalk/NCMediaViewerPageViewController.swift @@ -5,6 +5,7 @@ import Foundation import UIKit +import SwiftyGif @objc protocol NCMediaViewerPageViewControllerDelegate { @objc func mediaViewerPageZoomDidChange(_ controller: NCMediaViewerPageViewController, _ scale: Double) @@ -119,6 +120,7 @@ import UIKit } func showErrorView() { + self.imageView.image = nil self.view.addSubview(self.errorView) NSLayoutConstraint.activate([ @@ -130,25 +132,28 @@ import UIKit } // MARK: - NCChatFileController delegate - func fileControllerDidLoadFile(_ fileController: NCChatFileController, with fileStatus: NCChatFileStatus) { self.activityIndicator.stopAnimating() self.activityIndicator.isHidden = true - if let localPath = fileStatus.fileLocalPath, let image = UIImage(contentsOfFile: localPath) { - self.imageView.image = image - - // Adjust the view to the new image - self.zoomableView.contentViewSize = image.size - self.zoomableView.resizeContentView() - - self.delegate?.mediaViewerPageImageDidLoad(self) - } else { - self.imageView.image = nil + guard let localPath = fileStatus.fileLocalPath, let image = UIImage(contentsOfFile: localPath) else { self.showErrorView() - - print("Error in fileControllerDidLoadFile getting UIImage") + return } + + if let file = message.file(), message.isAnimatableGif, + let data = try? Data(contentsOf: URL(fileURLWithPath: localPath)), let gifImage = try? UIImage(gifData: data) { + + self.imageView.setGifImage(gifImage) + } else { + self.imageView.image = image + } + + // Adjust the view to the new image (use the non-gif version here for correct dimensions) + self.zoomableView.contentViewSize = image.size + self.zoomableView.resizeContentView() + + self.delegate?.mediaViewerPageImageDidLoad(self) } func fileControllerDidFailLoadingFile(_ fileController: NCChatFileController, withErrorDescription errorDescription: String) { diff --git a/NextcloudTalk/NCUtils.swift b/NextcloudTalk/NCUtils.swift index 3664a01d..9de3f4d2 100644 --- a/NextcloudTalk/NCUtils.swift +++ b/NextcloudTalk/NCUtils.swift @@ -84,6 +84,10 @@ import AVFoundation return self.previewImage(forMimeType: fileType) == "file-vcard" } + public static func isGif(fileType: String) -> Bool { + return UTType(mimeType: fileType)?.conforms(to: .gif) ?? false + } + public static func isNextcloudAppInstalled() -> Bool { var isInstalled = false diff --git a/NextcloudTalk/TalkCapabilities.h b/NextcloudTalk/TalkCapabilities.h index aab36ee6..792bdabf 100644 --- a/NextcloudTalk/TalkCapabilities.h +++ b/NextcloudTalk/TalkCapabilities.h @@ -27,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN @property BOOL federationIncomingEnabled; @property BOOL federationOutgoingEnabled; @property BOOL federationOnlyTrustedServers; +@property NSInteger maxGifSize; @end