diff --git a/CHANGES.rst b/CHANGES.rst index 65744cf74f..2dd3d4f43f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,8 @@ Changes to be released in next version * 🙌 Improvements - * Room Norification Settings: Ability to change between "All Messages", "Mentions and Keywords" and "None". Not yet exposed in Element UI. (#4458). + * Room Notification Settings: Ability to change between "All Messages", "Mentions and Keywords" and "None". Not yet exposed in Element UI. (#4458). + * Add support for sending slow motion videos (#4483). 🐛 Bugfix * VoIP: Do not present ended calls. diff --git a/Riot/Modules/MediaPicker/MediaPickerCoordinator.swift b/Riot/Modules/MediaPicker/MediaPickerCoordinator.swift index d3b9c2c0d7..61586be8dc 100644 --- a/Riot/Modules/MediaPicker/MediaPickerCoordinator.swift +++ b/Riot/Modules/MediaPicker/MediaPickerCoordinator.swift @@ -83,8 +83,8 @@ extension MediaPickerCoordinator: MediaPickerViewControllerDelegate { self.delegate?.mediaPickerCoordinator(self, didSelectImageData: imageData, withUTI: uti) } - func mediaPickerController(_ mediaPickerController: MediaPickerViewController!, didSelectVideo videoURL: URL!) { - self.delegate?.mediaPickerCoordinator(self, didSelectVideoAt: videoURL) + func mediaPickerController(_ mediaPickerController: MediaPickerViewController!, didSelectVideo videoAsset: AVAsset!) { + self.delegate?.mediaPickerCoordinator(self, didSelectVideo: videoAsset) } func mediaPickerController(_ mediaPickerController: MediaPickerViewController!, didSelect assets: [PHAsset]!) { diff --git a/Riot/Modules/MediaPicker/MediaPickerCoordinatorBridgePresenter.swift b/Riot/Modules/MediaPicker/MediaPickerCoordinatorBridgePresenter.swift index 0ba21d8934..782662ea99 100644 --- a/Riot/Modules/MediaPicker/MediaPickerCoordinatorBridgePresenter.swift +++ b/Riot/Modules/MediaPicker/MediaPickerCoordinatorBridgePresenter.swift @@ -20,7 +20,7 @@ import Foundation @objc protocol MediaPickerCoordinatorBridgePresenterDelegate { func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectImageData imageData: Data, withUTI uti: MXKUTI?) - func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideoAt url: URL) + func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideo videoAsset: AVAsset) func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectAssets assets: [PHAsset]) func mediaPickerCoordinatorBridgePresenterDidCancel(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter) } @@ -110,8 +110,8 @@ extension MediaPickerCoordinatorBridgePresenter: MediaPickerCoordinatorDelegate self.delegate?.mediaPickerCoordinatorBridgePresenter(self, didSelectImageData: imageData, withUTI: uti) } - func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideoAt url: URL) { - self.delegate?.mediaPickerCoordinatorBridgePresenter(self, didSelectVideoAt: url) + func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideo videoAsset: AVAsset) { + self.delegate?.mediaPickerCoordinatorBridgePresenter(self, didSelectVideo: videoAsset) } func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectAssets assets: [PHAsset]) { diff --git a/Riot/Modules/MediaPicker/MediaPickerCoordinatorType.swift b/Riot/Modules/MediaPicker/MediaPickerCoordinatorType.swift index 53f154536a..9d91bdadc0 100644 --- a/Riot/Modules/MediaPicker/MediaPickerCoordinatorType.swift +++ b/Riot/Modules/MediaPicker/MediaPickerCoordinatorType.swift @@ -20,7 +20,7 @@ import Foundation protocol MediaPickerCoordinatorDelegate: class { func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectImageData imageData: Data, withUTI uti: MXKUTI?) - func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideoAt url: URL) + func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideo videoAsset: AVAsset) func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectAssets assets: [PHAsset]) func mediaPickerCoordinatorDidCancel(_ coordinator: MediaPickerCoordinatorType) } diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.h b/Riot/Modules/MediaPicker/MediaPickerViewController.h index 99e9365fe9..71487e1ea2 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.h +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.h @@ -39,9 +39,9 @@ Tells the delegate that the user select a video. @param mediaPickerController the `MediaPickerViewController` instance. - @param videoURL the local url of the video to send. + @param videoAsset an `AVAsset` that represents the video to send. */ -- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectVideo:(NSURL*)videoURL; +- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectVideo:(AVAsset*)videoAsset; /** Tells the delegate that the user wants to cancel media picking. diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index d08e6ab172..e34617241e 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -608,28 +608,19 @@ - (void)didSelectAsset:(PHAsset *)asset if (asset) { - if ([asset isKindOfClass:[AVURLAsset class]]) - { - MXLogDebug(@"[MediaPickerVC] didSelectAsset: Got AVAsset for video"); - AVURLAsset *avURLAsset = (AVURLAsset*)asset; + MXLogDebug(@"[MediaPickerVC] didSelectAsset: Got AVAsset for video"); + + // Validate first the selected video + [self validateSelectedVideo:asset responseHandler:^(BOOL isValidated) { + + if (isValidated) + { + [self.delegate mediaPickerController:self didSelectVideo:asset]; + } - // Validate first the selected video - [self validateSelectedVideo:[avURLAsset URL] responseHandler:^(BOOL isValidated) { - - if (isValidated) - { - [self.delegate mediaPickerController:self didSelectVideo:[avURLAsset URL]]; - } - - self->isValidationInProgress = NO; - - }]; - } - else - { - MXLogDebug(@"[MediaPickerVC] Selected video asset is not initialized from an URL!"); self->isValidationInProgress = NO; - } + + }]; } else { @@ -693,7 +684,7 @@ - (void)validateSelectedImage:(UIImage*)selectedImage responseHandler:(void (^)( [self setNeedsStatusBarAppearanceUpdate]; } -- (void)validateSelectedVideo:(NSURL*)selectedVideoURL responseHandler:(void (^)(BOOL isValidated))handler +- (void)validateSelectedVideo:(AVAsset*)selectedVideo responseHandler:(void (^)(BOOL isValidated))handler { [self dismissImageValidationView]; @@ -727,15 +718,15 @@ - (void)validateSelectedVideo:(NSURL*)selectedVideoURL responseHandler:(void (^) videoPlayer = [[AVPlayerViewController alloc] init]; if (videoPlayer) { + AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:selectedVideo]; videoPlayer.allowsPictureInPicturePlayback = NO; videoPlayer.updatesNowPlayingInfoCenter = NO; - videoPlayer.player = [AVPlayer playerWithURL:selectedVideoURL]; + videoPlayer.player = [AVPlayer playerWithPlayerItem:item]; videoPlayer.videoGravity = AVLayerVideoGravityResizeAspect; videoPlayer.showsPlaybackControls = NO; // create a thumbnail for the first frame - AVAsset *asset = [AVAsset assetWithURL:selectedVideoURL]; - AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset]; + AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:selectedVideo]; generator.appliesPreferredTrackTransform = YES; CGImageRef thumbnailRef = [generator copyCGImageAtTime:kCMTimeZero actualTime:nil error:nil]; diff --git a/Riot/Modules/MediaPicker/SingleImagePickerPresenter.swift b/Riot/Modules/MediaPicker/SingleImagePickerPresenter.swift index f8bc066ee9..56f501fdd1 100644 --- a/Riot/Modules/MediaPicker/SingleImagePickerPresenter.swift +++ b/Riot/Modules/MediaPicker/SingleImagePickerPresenter.swift @@ -135,7 +135,7 @@ extension SingleImagePickerPresenter: MediaPickerCoordinatorBridgePresenterDeleg self.delegate?.singleImagePickerPresenter(self, didSelectImageData: imageData, withUTI: uti) } - func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideoAt url: URL) { + func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideo videoAsset: AVAsset) { self.delegate?.singleImagePickerPresenterDidCancel(self) } diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 831f96634f..230d313cee 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -887,8 +887,10 @@ - (void)sendVideo:(NSURL*)videoLocalURL success:(void (^)(NSString *eventId))success failure:(void (^)(NSError *error))failure { + AVURLAsset *videoAsset = [AVURLAsset assetWithURL:videoLocalURL]; UIImage *videoThumbnail = [MXKVideoThumbnailGenerator.shared generateThumbnailFrom:videoLocalURL]; - [self sendVideo:videoLocalURL withThumbnail:videoThumbnail success:success failure:failure]; + + [self sendVideoAsset:videoAsset withThumbnail:videoThumbnail success:success failure:failure]; } - (void)acceptVerificationRequestForEventId:(NSString*)eventId success:(void(^)(void))success failure:(void(^)(NSError*))failure diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index fb4b7db8f9..fbd8a25f09 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -6056,7 +6056,8 @@ - (void)cameraPresenter:(CameraPresenter *)cameraPresenter didSelectVideoAt:(NSU RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView]; if (roomInputToolbarView) { - [roomInputToolbarView sendSelectedVideo:url isPhotoLibraryAsset:NO]; + AVURLAsset *selectedVideo = [AVURLAsset assetWithURL:url]; + [roomInputToolbarView sendSelectedVideoAsset:selectedVideo isPhotoLibraryAsset:NO]; } } @@ -6080,7 +6081,7 @@ - (void)mediaPickerCoordinatorBridgePresenter:(MediaPickerCoordinatorBridgePrese } } -- (void)mediaPickerCoordinatorBridgePresenter:(MediaPickerCoordinatorBridgePresenter *)coordinatorBridgePresenter didSelectVideoAt:(NSURL *)url +- (void)mediaPickerCoordinatorBridgePresenter:(MediaPickerCoordinatorBridgePresenter *)coordinatorBridgePresenter didSelectVideo:(AVAsset *)videoAsset { [coordinatorBridgePresenter dismissWithAnimated:YES completion:nil]; self.mediaPickerPresenter = nil; @@ -6088,7 +6089,7 @@ - (void)mediaPickerCoordinatorBridgePresenter:(MediaPickerCoordinatorBridgePrese RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView]; if (roomInputToolbarView) { - [roomInputToolbarView sendSelectedVideo:url isPhotoLibraryAsset:YES]; + [roomInputToolbarView sendSelectedVideoAsset:videoAsset isPhotoLibraryAsset:YES]; } } diff --git a/RiotShareExtension/Managers/ShareExtensionManager.m b/RiotShareExtension/Managers/ShareExtensionManager.m index 47dfb03c48..5b69743be8 100644 --- a/RiotShareExtension/Managers/ShareExtensionManager.m +++ b/RiotShareExtension/Managers/ShareExtensionManager.m @@ -1165,8 +1165,8 @@ - (void)sendVideo:(NSURL *)videoLocalUrl toRoom:(MXRoom *)room successBlock:(dis } // Retrieve the video frame at 1 sec to define the video thumbnail - AVURLAsset *urlAsset = [[AVURLAsset alloc] initWithURL:videoLocalUrl options:nil]; - AVAssetImageGenerator *assetImageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:urlAsset]; + AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoLocalUrl options:nil]; + AVAssetImageGenerator *assetImageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:videoAsset]; assetImageGenerator.appliesPreferredTrackTransform = YES; CMTime time = CMTimeMake(1, 1); CGImageRef imageRef = [assetImageGenerator copyCGImageAtTime:time actualTime:NULL error:nil]; @@ -1174,7 +1174,7 @@ - (void)sendVideo:(NSURL *)videoLocalUrl toRoom:(MXRoom *)room successBlock:(dis UIImage *videoThumbnail = [[UIImage alloc] initWithCGImage:imageRef]; CFRelease(imageRef); - [room sendVideo:videoLocalUrl withThumbnail:videoThumbnail localEcho:nil success:^(NSString *eventId) { + [room sendVideoAsset:videoAsset withThumbnail:videoThumbnail localEcho:nil success:^(NSString *eventId) { if (successBlock) { successBlock();