Skip to content

Commit

Permalink
added video support in media view
Browse files Browse the repository at this point in the history
Fixes nextcloud#1702

Signed-off-by: Daniel Standfest <[email protected]>
  • Loading branch information
Daniel Standfest committed Oct 18, 2024
1 parent ca4522b commit fb169a9
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 22 deletions.
92 changes: 79 additions & 13 deletions NextcloudTalk/NCMediaViewerPageViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//

import AVKit
import AVFoundation
import Foundation
import UIKit
import SwiftyGif

@objc protocol NCMediaViewerPageViewControllerDelegate {
@objc func mediaViewerPageZoomDidChange(_ controller: NCMediaViewerPageViewController, _ scale: Double)
@objc func mediaViewerPageImageDidLoad(_ controller: NCMediaViewerPageViewController)
@objc func mediaViewerPageMediaDidLoad(_ controller: NCMediaViewerPageViewController)
}

@objcMembers class NCMediaViewerPageViewController: UIViewController, NCChatFileControllerDelegate, NCZoomableViewDelegate {
Expand Down Expand Up @@ -72,6 +74,10 @@ import SwiftyGif
return self.imageView.image
}

public var currentVideoURL: URL?

private var playerViewController: AVPlayerViewController?

private lazy var activityIndicator = {
let indicator = NCActivityIndicator(frame: .init(x: 0, y: 0, width: 100, height: 100))
indicator.translatesAutoresizingMaskIntoConstraints = false
Expand Down Expand Up @@ -121,6 +127,7 @@ import SwiftyGif

func showErrorView() {
self.imageView.image = nil
self.removePlayerViewControllerIfNeeded()
self.view.addSubview(self.errorView)

NSLayoutConstraint.activate([
Expand All @@ -136,24 +143,18 @@ import SwiftyGif
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true

guard let localPath = fileStatus.fileLocalPath, let image = UIImage(contentsOfFile: localPath) else {
guard let localPath = fileStatus.fileLocalPath else {
self.showErrorView()
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)
if NCUtils.isImage(fileType: message.file().mimetype) {
displayImage(from: localPath)
} else if NCUtils.isVideo(fileType: message.file().mimetype) {
playVideo(from: localPath)
} else {
self.imageView.image = image
self.showErrorView()
}

// 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) {
Expand Down Expand Up @@ -188,4 +189,69 @@ import SwiftyGif
func contentViewZoomDidChange(_ view: NCZoomableView, _ scale: Double) {
self.delegate?.mediaViewerPageZoomDidChange(self, scale)
}

private func displayImage(from localPath: String) {
guard let image = UIImage(contentsOfFile: localPath) else {
self.showErrorView()
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.zoomableView.isHidden = false
self.imageView.isHidden = false

removePlayerViewControllerIfNeeded()
self.delegate?.mediaViewerPageMediaDidLoad(self)
}

private func playVideo(from localPath: String) {
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback, options: [])
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Failed to set audio session category: \(error)")
}

let videoURL = URL(fileURLWithPath: localPath)
self.currentVideoURL = videoURL
let player = AVPlayer(url: videoURL)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.playerViewController = playerViewController

self.addChild(playerViewController)
self.view.addSubview(playerViewController.view)
playerViewController.view.frame = self.view.bounds
playerViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
playerViewController.didMove(toParent: self)

self.zoomableView.contentViewSize = playerViewController.view.bounds.size
self.zoomableView.resizeContentView()
self.zoomableView.isHidden = false
self.imageView.isHidden = true

self.delegate?.mediaViewerPageMediaDidLoad(self)
}

private func removePlayerViewControllerIfNeeded() {
if let playerVC = self.playerViewController {
playerVC.willMove(toParent: nil)
playerVC.view.removeFromSuperview()
playerVC.removeFromParent()
self.playerViewController = nil
self.currentVideoURL = nil
}
}
}
24 changes: 15 additions & 9 deletions NextcloudTalk/NCMediaViewerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,20 @@ import UIKit

private lazy var shareButton = {
let shareButton = UIBarButtonItem(title: nil, style: .plain, target: nil, action: nil)

shareButton.isEnabled = false
shareButton.primaryAction = UIAction(title: "", image: .init(systemName: "square.and.arrow.up"), handler: { [unowned self, unowned shareButton] _ in
guard let mediaPageViewController = self.getCurrentPageViewController(),
let image = mediaPageViewController.currentImage
else { return }
guard let mediaPageViewController = self.getCurrentPageViewController() else { return }

var itemsToShare: [Any] = []

let activityViewController = UIActivityViewController(activityItems: [image], applicationActivities: nil)
if let image = mediaPageViewController.currentImage {
itemsToShare.append(image)
} else if let videoURL = mediaPageViewController.currentVideoURL {
itemsToShare.append(videoURL)
} else {
return
}
let activityViewController = UIActivityViewController(activityItems: itemsToShare, applicationActivities: nil)
activityViewController.popoverPresentationController?.barButtonItem = shareButton

self.present(activityViewController, animated: true)
Expand Down Expand Up @@ -106,7 +112,7 @@ import UIKit
let messageObject = self.getAllFileMessages().objects(with: prevQuery).lastObject()

if let message = messageObject as? NCChatMessage {
if NCUtils.isImage(fileType: message.file().mimetype) {
if NCUtils.isImage(fileType: message.file().mimetype) || NCUtils.isVideo(fileType: message.file().mimetype) {
return message
}

Expand All @@ -122,7 +128,7 @@ import UIKit
let messageObject = self.getAllFileMessages().objects(with: prevQuery).firstObject()

if let message = messageObject as? NCChatMessage {
if NCUtils.isImage(fileType: message.file().mimetype) {
if NCUtils.isImage(fileType: message.file().mimetype) || NCUtils.isVideo(fileType: message.file().mimetype) {
return message
}

Expand Down Expand Up @@ -158,7 +164,7 @@ import UIKit
guard let mediaPageViewController = self.getCurrentPageViewController() else { return }
self.navigationItem.title = mediaPageViewController.navigationItem.title

self.shareButton.isEnabled = (mediaPageViewController.currentImage != nil)
self.shareButton.isEnabled = (mediaPageViewController.currentImage != nil) || (mediaPageViewController.currentVideoURL != nil)
}

// MARK: - NCMediaViewerPageViewController delegate
Expand All @@ -178,7 +184,7 @@ import UIKit
}
}

func mediaViewerPageImageDidLoad(_ controller: NCMediaViewerPageViewController) {
func mediaViewerPageMediaDidLoad(_ controller: NCMediaViewerPageViewController) {
if let mediaPageViewController = self.getCurrentPageViewController(), mediaPageViewController.isEqual(controller) {
self.shareButton.isEnabled = true
}
Expand Down

0 comments on commit fb169a9

Please sign in to comment.