Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds iPad support to Kanvas #112

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Classes/Camera/CameraController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ open class CameraController: UIViewController, MediaClipsEditorDelegate, CameraP
return controller
}()
private lazy var clipsController: MediaClipsEditorViewController = {
let controller = MediaClipsEditorViewController(showsAddButton: false)
let viewSettings = MediaClipsCollectionView.Settings(showsFadeOutGradient: false)
let collectionSettings = MediaClipsCollectionController.Settings(clipsCollectionViewSettings: viewSettings)
let controller = MediaClipsEditorViewController(showsAddButton: false, collectionSettings: collectionSettings)
controller.delegate = self
return controller
}()
Expand Down Expand Up @@ -640,6 +642,10 @@ open class CameraController: UIViewController, MediaClipsEditorDelegate, CameraP
private func generateHapticFeedback() {
feedbackGenerator.notificationOccurred(.success)
}

public var confirmButton: UIView? {
return (presentedViewController as? MultiEditorViewController)?.currentEditor?.editorView.confirmOrPostButton()
}

// MARK: - CameraViewDelegate

Expand Down Expand Up @@ -1091,7 +1097,7 @@ open class CameraController: UIViewController, MediaClipsEditorDelegate, CameraP

func cameraPermissionsChanged(hasFullAccess: Bool) {
if hasFullAccess {
cameraInputController.setupCaptureSession()
cameraInputController.setupCaptureSession(frameSize: view.frame.size)
toggleMediaPicker(visible: true, animated: false)
}
}
Expand Down
43 changes: 40 additions & 3 deletions Classes/Camera/CameraInputController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ final class CameraInputController: UIViewController, CameraRecordingDelegate, AV
setupFlash(defaultOption: settings.preferredFlashOption)

setupPreviewBlur()

NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)
}

override func viewWillAppear(_ animated: Bool) {
Expand All @@ -197,7 +199,7 @@ final class CameraInputController: UIViewController, CameraRecordingDelegate, AV
return
}

setupCaptureSession()
setupCaptureSession(frameSize: view.frame.size)

setupNotifications()
}
Expand All @@ -214,8 +216,7 @@ final class CameraInputController: UIViewController, CameraRecordingDelegate, AV
teardownNotifications()
}

func setupCaptureSession() {
let frameSize = view.frame.size
func setupCaptureSession(frameSize: CGSize) {
previewBlurView.effect = CameraInputController.blurEffect()
let hasFullAccess = delegate?.cameraInputControllerHasFullAccess() ?? true
guard hasFullAccess else {
Expand Down Expand Up @@ -283,13 +284,49 @@ final class CameraInputController: UIViewController, CameraRecordingDelegate, AV
try configureAudioDataOutput()
try configureCurrentOutput()
captureSession?.commitConfiguration()
refreshOrientation()
} catch {
// this can happen if not all permissions were accepted, should not throw an exception
captureSession?.commitConfiguration()
return
}
}

@objc func orientationChanged() {
refreshOrientation()
}

private func refreshOrientation() {
captureSession?.connections.forEach({ connection in
connection.videoOrientation = orientation()
})
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)

refreshOrientation()

stopCaptureSession()
setupCaptureSession(frameSize: CGSize(width: size.width, height: size.height))
}


private func orientation() -> AVCaptureVideoOrientation {
switch UIDevice.current.orientation {
case .portrait:
return .portrait
case .portraitUpsideDown:
return .portraitUpsideDown
case .landscapeLeft:
return .landscapeRight
case .landscapeRight:
return .landscapeLeft
default:
return .portrait
}
}

private func setupGestures() {
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapped(gesture:))))
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
Expand Down
39 changes: 39 additions & 0 deletions Classes/Constants/KanvasEditorDesign.swift
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,43 @@ public struct KanvasEditorDesign {
}
)
}()

public static var storiesDesign: KanvasEditorDesign = {
return KanvasEditorDesign(
isVerticalMenu: false,
checkmarkImage: KanvasImages.shared.editorConfirmImage,
buttonBackgroundColor: .clear,
buttonInvertedBackgroundColor: .clear,
optionBackgroundColor: .clear,
topButtonSize: 49,
topSecondaryButtonSize: 36,
topButtonInterspace: 30,
fakeOptionCellCheckmarkImage: UIImage.imageFromCameraBundle(named: "confirm"),
closeGradientImage: UIImage.imageFromCameraBundle(named: "closeGradient"),
editorViewCloseImage: UIImage.imageFromCameraBundle(named: "whiteCloseIcon"),
editorViewBackImage: UIImage.imageFromCameraBundle(named: "back"),
editorViewButtonTopMargin: 24,
editorViewButtonBottomMargin: Device.belongsToIPhoneXGroup ? 14 : 19.5,
editorViewFakeOptionCellMinSize: 36,
editorViewFakeOptionCellMaxSize: 45,
editorViewCloseButtonSize: 26.5,
editorViewCloseButtonHorizontalMargin: 24,
drawingViewUndoImage: UIImage.imageFromCameraBundle(named: "undo"),
drawingViewEraserSelectedImage: UIImage.imageFromCameraBundle(named: "eraserSelected"),
drawingViewEraserUnselectedImage: UIImage.imageFromCameraBundle(named: "eraserUnselected"),
drawingViewMarkerImage: UIImage.imageFromCameraBundle(named: "marker"),
drawingViewSharpieImage: UIImage.imageFromCameraBundle(named: "sharpie"),
drawingViewPencilImage: UIImage.imageFromCameraBundle(named: "pencil"),
drawingViewEyeDropperImage: UIImage.imageFromCameraBundle(named: "eyeDropper"),
editorTextViewFontImage: UIImage.imageFromCameraBundle(named: "font"),
editorTextViewAlignmentImage: [
.left: UIImage.imageFromCameraBundle(named: "leftAlignment"),
.center: UIImage.imageFromCameraBundle(named: "centerAlignment"),
.right: UIImage.imageFromCameraBundle(named: "rightAlignment"),
],
editorTextViewHighlightImage: { selected in
return selected ? UIImage.imageFromCameraBundle(named: "highlightSelected") : UIImage.imageFromCameraBundle(named: "highlightUnselected")
}
)
}()
}
2 changes: 1 addition & 1 deletion Classes/Editor/EditorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ final class EditorView: UIView, MovableViewCanvasDelegate, MediaPlayerViewDelega

let bottomConstraint: NSLayoutConstraint
let topConstraint: NSLayoutConstraint
if Device.belongsToIPhoneXGroup {
if Device.belongsToIPhoneXGroup || Device.isIPad {
bottomConstraint = playerView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor)
topConstraint = playerView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor)
} else {
Expand Down
6 changes: 4 additions & 2 deletions Classes/Editor/MultiEditor/MultiEditorViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ protocol MultiEditorComposerDelegate: EditorControllerDelegate {

class MultiEditorViewController: UIViewController {
private lazy var clipsController: MediaClipsEditorViewController = {
let clipsEditor = MediaClipsEditorViewController(showsAddButton: true)
let collectionViewSettings = MediaClipsCollectionView.Settings(showsFadeOutGradient: false)
let collectionSettings = MediaClipsCollectionController.Settings(clipsCollectionViewSettings: collectionViewSettings)
let clipsEditor = MediaClipsEditorViewController(showsAddButton: true, collectionSettings: collectionSettings)
clipsEditor.delegate = self
clipsEditor.view.backgroundColor = UIColor.black.withAlphaComponent(0.4)
return clipsEditor
Expand Down Expand Up @@ -76,7 +78,7 @@ class MultiEditorViewController: UIViewController {

private var exportingEditors: [EditorViewController]?

private weak var currentEditor: EditorViewController?
private(set) weak var currentEditor: EditorViewController?

init(settings: CameraSettings,
frames: [Frame],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ final class ColorCollectionCell: UICollectionViewCell {
circleView.accessibilityIdentifier = "Color Cell View"

NSLayoutConstraint.activate([
circleView.centerXAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.centerXAnchor),
circleView.centerYAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.centerYAnchor),
circleView.centerXAnchor.constraint(equalTo: contentView.layoutMarginsGuide.centerXAnchor),
circleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
circleView.heightAnchor.constraint(equalToConstant: ColorCollectionCellConstants.circleDiameter),
circleView.widthAnchor.constraint(equalToConstant: ColorCollectionCellConstants.circleDiameter)
])
Expand Down
9 changes: 8 additions & 1 deletion Classes/Editor/Text/EditorTextController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ final class EditorTextController: UIViewController, EditorTextViewDelegate, Colo
// This method is called inside the keyboard animation,
// so any UI change made here will be animated.
@objc func keyboardWillHide(notification: NSNotification) {
if isHiding == false && textView.alpha != 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this one be if !isHiding ..... {

didConfirmText()
}
textView.moveToolsDown()
}

Expand Down Expand Up @@ -336,13 +339,17 @@ final class EditorTextController: UIViewController, EditorTextViewDelegate, Colo
self.textView.startWriting()
})
}


/// A flag to indicate whether we're in the process of hiding. This is used in `keyboardWillHide` to determine whether to confirm the text.
private var isHiding = false

/// Makes the view disappear
private func hide() {
textView.endWriting()
isHiding = true
UIView.animate(withDuration: Constants.animationDuration) {
self.textView.alpha = 0
self.isHiding = false
}
}

Expand Down
11 changes: 9 additions & 2 deletions Classes/MediaClips/MediaClipsCollectionController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,23 @@ private struct MediaClipsCollectionControllerConstants {

/// Controller for handling the media clips collection.
final class MediaClipsCollectionController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
private lazy var mediaClipsCollectionView = MediaClipsCollectionView()
private lazy var mediaClipsCollectionView = MediaClipsCollectionView(settings: settings.clipsCollectionViewSettings)

private var clips: [MediaClip]
private var draggingClipIndex: IndexPath?
private weak var draggingCell: MediaClipsCollectionCell?

weak var delegate: MediaClipsCollectionControllerDelegate?

init() {
struct Settings {
let clipsCollectionViewSettings: MediaClipsCollectionView.Settings
}

private let settings: Settings

init(settings: Settings) {
clips = []
self.settings = settings
super.init(nibName: .none, bundle: .none)
}

Expand Down
13 changes: 11 additions & 2 deletions Classes/MediaClips/MediaClipsCollectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@ final class MediaClipsCollectionView: UIView {
static let height = MediaClipsCollectionViewConstants.height
let collectionView: UICollectionView
let fadeOutGradient = CAGradientLayer()

struct Settings {
let showsFadeOutGradient: Bool
}

private let settings: Settings

init() {
init(settings: Settings) {
collectionView = createCollectionView()
self.settings = settings

super.init(frame: .zero)

Expand Down Expand Up @@ -49,7 +56,9 @@ extension MediaClipsCollectionView {
private func setUpViews() {
collectionView.add(into: self)
collectionView.clipsToBounds = false
setFadeOutGradient()
if settings.showsFadeOutGradient {
setFadeOutGradient()
}
}

private func setFadeOutGradient() {
Expand Down
4 changes: 2 additions & 2 deletions Classes/MediaClips/MediaClipsEditorViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ final class MediaClipsEditorViewController: UIViewController, MediaClipsCollecti
/// This needs to be dynamic because it will be observed
@objc private(set) dynamic var hasClips: Bool = false

init(showsAddButton: Bool = false) {
init(showsAddButton: Bool = false, collectionSettings: MediaClipsCollectionController.Settings) {
editorView = MediaClipsEditorView(showsAddButton: showsAddButton)
collectionController = MediaClipsCollectionController()
collectionController = MediaClipsCollectionController(settings: collectionSettings)
super.init(nibName: .none, bundle: .none)
collectionController.delegate = self
editorView.delegate = self
Expand Down
4 changes: 4 additions & 0 deletions Classes/Settings/CameraSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ public struct CameraFeatures {
/// Animate the movement of control in the editor
public var animateEditorControls: Bool = DefaultCameraSettings.animateEditorControls

/// Whether to show a shadow to the sides of the media clips
public var showShadowOverMediaClips: Bool = DefaultCameraSettings.showShadowOverMediaClips

/// The Font Selector button uses the currently selected font for its label
public var fontSelectorUsesFont: Bool = DefaultCameraSettings.fontFamilyUsesFont

Expand Down Expand Up @@ -377,4 +380,5 @@ private struct DefaultCameraSettings {
static let gifCameraShouldStartGIFMaker: Bool = false
static let fontFamilyUsesFont: Bool = false
static let animateEditorControls: Bool = true
static let showShadowOverMediaClips: Bool = true
}