From 4752cb94f598b83359c1e8dbd63df3b979ef97a7 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 14 Dec 2018 15:01:02 -0500 Subject: [PATCH] Add ImageEditorView. --- Signal.xcodeproj/project.pbxproj | 4 +++ .../AttachmentApprovalViewController.swift | 33 +++++++++++++++++++ .../Views/ImageEditor/ImageEditor.swift | 3 +- .../Views/ImageEditor/ImageEditorView.swift | 22 +++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 SignalMessaging/Views/ImageEditor/ImageEditorView.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 5f3c2779d..f6a6b10c8 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -237,6 +237,7 @@ 34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BECE2F1F7ABCF800D7438D /* GifPickerLayout.swift */; }; 34BEDB0E21C405B0007B0EAE /* ImageEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BEDB0D21C405B0007B0EAE /* ImageEditor.swift */; }; 34BEDB1121C41E71007B0EAE /* ImageEditorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BEDB1021C41E71007B0EAE /* ImageEditorTest.swift */; }; + 34BEDB1321C43F6A007B0EAE /* ImageEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BEDB1221C43F69007B0EAE /* ImageEditorView.swift */; }; 34C3C78D20409F320000134C /* Opening.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34C3C78C20409F320000134C /* Opening.m4r */; }; 34C3C78F2040A4F70000134C /* sonarping.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 34C3C78E2040A4F70000134C /* sonarping.mp3 */; }; 34C3C7922040B0DD0000134C /* OWSAudioPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 34C3C7902040B0DC0000134C /* OWSAudioPlayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -910,6 +911,7 @@ 34BECE2F1F7ABCF800D7438D /* GifPickerLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GifPickerLayout.swift; sourceTree = ""; }; 34BEDB0D21C405B0007B0EAE /* ImageEditor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditor.swift; sourceTree = ""; }; 34BEDB1021C41E71007B0EAE /* ImageEditorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditorTest.swift; sourceTree = ""; }; + 34BEDB1221C43F69007B0EAE /* ImageEditorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditorView.swift; sourceTree = ""; }; 34C3C78C20409F320000134C /* Opening.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Opening.m4r; sourceTree = ""; }; 34C3C78E2040A4F70000134C /* sonarping.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = sonarping.mp3; path = Signal/AudioFiles/sonarping.mp3; sourceTree = SOURCE_ROOT; }; 34C3C7902040B0DC0000134C /* OWSAudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAudioPlayer.h; sourceTree = ""; }; @@ -1867,6 +1869,7 @@ isa = PBXGroup; children = ( 34BEDB0D21C405B0007B0EAE /* ImageEditor.swift */, + 34BEDB1221C43F69007B0EAE /* ImageEditorView.swift */, ); path = ImageEditor; sourceTree = ""; @@ -3286,6 +3289,7 @@ 34AC09EF211B39B100997B47 /* ViewControllerUtils.m in Sources */, 346941A2215D2EE400B5BFAD /* OWSConversationColor.m in Sources */, 34AC0A17211B39EA00997B47 /* VideoPlayerView.swift in Sources */, + 34BEDB1321C43F6A007B0EAE /* ImageEditorView.swift in Sources */, 34AC09EE211B39B100997B47 /* EditContactShareNameViewController.swift in Sources */, 346129F71FD5F31400532771 /* OWS105AttachmentFilePaths.m in Sources */, 45194F931FD7215C00333B2C /* OWSContactOffersInteraction.m in Sources */, diff --git a/SignalMessaging/ViewControllers/AttachmentApprovalViewController.swift b/SignalMessaging/ViewControllers/AttachmentApprovalViewController.swift index aedddd26f..67a0d7270 100644 --- a/SignalMessaging/ViewControllers/AttachmentApprovalViewController.swift +++ b/SignalMessaging/ViewControllers/AttachmentApprovalViewController.swift @@ -15,6 +15,8 @@ public protocol AttachmentApprovalViewControllerDelegate: class { @objc optional func attachmentApproval(_ attachmentApproval: AttachmentApprovalViewController, changedCaptionOfAttachment attachment: SignalAttachment) } +// MARK: - + class AttachmentItemCollection { private (set) var attachmentItems: [SignalAttachmentItem] init(attachmentItems: [SignalAttachmentItem]) { @@ -48,6 +50,8 @@ class AttachmentItemCollection { } } +// MARK: - + class SignalAttachmentItem: Hashable { enum SignalAttachmentItemError: Error { @@ -56,8 +60,23 @@ class SignalAttachmentItem: Hashable { let attachment: SignalAttachment + var imageEditorModel: ImageEditorModel? + init(attachment: SignalAttachment) { self.attachment = attachment + + // Try and make a ImageEditorModel. + // This will only apply for valid images. + if let dataUrl: URL = attachment.dataUrl, + dataUrl.isFileURL { + let path = dataUrl.path + do { + imageEditorModel = try ImageEditorModel(srcImagePath: path) + } catch { + // Usually not an error. + Logger.warn("Could not create image editor: \(error)") + } + } } // MARK: @@ -97,12 +116,16 @@ class SignalAttachmentItem: Hashable { } } +// MARK: - + @objc public enum AttachmentApprovalViewControllerMode: UInt { case modal case sharedNavigation } +// MARK: - + @objc public class AttachmentApprovalViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate { @@ -777,6 +800,8 @@ public class AttachmentPrepViewController: OWSViewController, PlayerProgressBarD private(set) var contentContainer: UIView! private(set) var playVideoButton: UIView? + private var imageEditorView: ImageEditorView? + // MARK: - Initializers init(attachmentItem: SignalAttachmentItem) { @@ -865,6 +890,14 @@ public class AttachmentPrepViewController: OWSViewController, PlayerProgressBarD containerView.addSubview(mediaMessageView) mediaMessageView.autoPinEdgesToSuperviewEdges() + if let imageEditorModel = attachmentItem.imageEditorModel, + let imageMediaView = self.mediaMessageView.contentView { + let imageEditorView = ImageEditorView(model: imageEditorModel) + imageMediaView.addSubview(imageEditorView) + imageEditorView.autoPinEdgesToSuperviewEdges() + self.imageEditorView = imageEditorView + } + if isZoomable { // Add top and bottom gradients to ensure toolbar controls are legible // when placed over image/video preview which may be a clashing color. diff --git a/SignalMessaging/Views/ImageEditor/ImageEditor.swift b/SignalMessaging/Views/ImageEditor/ImageEditor.swift index 97954896a..95ac3936b 100644 --- a/SignalMessaging/Views/ImageEditor/ImageEditor.swift +++ b/SignalMessaging/Views/ImageEditor/ImageEditor.swift @@ -246,7 +246,8 @@ public class ImageEditorModel: NSObject { Logger.error("Couldn't determine MIME type for file.") throw ImageEditorError.invalidInput } - guard MIMETypeUtil.isImage(mimeType) else { + guard MIMETypeUtil.isImage(mimeType), + !MIMETypeUtil.isAnimated(mimeType) else { Logger.error("Invalid MIME type: \(mimeType).") throw ImageEditorError.invalidInput } diff --git a/SignalMessaging/Views/ImageEditor/ImageEditorView.swift b/SignalMessaging/Views/ImageEditor/ImageEditorView.swift new file mode 100644 index 000000000..eead0f8a1 --- /dev/null +++ b/SignalMessaging/Views/ImageEditor/ImageEditorView.swift @@ -0,0 +1,22 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +import UIKit + +@objc +public class ImageEditorView: UIView { + private let model: ImageEditorModel + + @objc + public required init(model: ImageEditorModel) { + self.model = model + + super.init(frame: .zero) + } + + @available(*, unavailable, message: "use other init() instead.") + required public init?(coder aDecoder: NSCoder) { + notImplemented() + } +}