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

Stories: 16.8 Bug Fixes #102

Merged
merged 12 commits into from
Mar 5, 2021
6 changes: 2 additions & 4 deletions Classes/Camera/CameraController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1001,16 +1001,14 @@ open class CameraController: UIViewController, MediaClipsEditorDelegate, CameraP
analyticsProvider?.logPreviewDismissed()
}
if settings.features.multipleExports {
self.dismiss(animated: true, completion: {
self.dismiss(animated: false)
})
delegate?.editorDismissed(self)
showPreviewWithSegments([], selected: multiEditorViewController?.selected ?? 0)
} else {
performUIUpdate { [weak self] in
self?.dismiss(animated: true)
}
delegate?.editorDismissed(self)
}
delegate?.editorDismissed(self)
}

public func tagButtonPressed() {
Expand Down
8 changes: 7 additions & 1 deletion Classes/Editor/EditorViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public final class EditorViewController: UIViewController, MediaPlayerController
}()

private lazy var textController: EditorTextController = {
let textViewSettings = EditorTextView.Settings(fontSelectorUsesFont: settings.fontSelectorUsesFont)
let textViewSettings = EditorTextView.Settings(fontSelectorUsesFont: settings.fontSelectorUsesFont, resizesFonts: settings.features.resizesFonts)
let settings = EditorTextController.Settings(textViewSettings: textViewSettings)
let controller = EditorTextController(settings: settings)
controller.delegate = self
Expand Down Expand Up @@ -393,6 +393,12 @@ public final class EditorViewController: UIViewController, MediaPlayerController

startPlayerFromSegments()
}

public override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

player.pause()
}

override public func viewDidLoad() {
super.viewDidLoad()
Expand Down
47 changes: 36 additions & 11 deletions Classes/Editor/MultiEditor/MultiEditorViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ class MultiEditorViewController: UIViewController {
}
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
clipsController.select(index: selected ?? 0)
}

func loadEditor(for index: Int) {
let frame = frames[index]
if let editor = delegate?.editor(segment: frame.segment, edit: frame.edit) {
Expand Down Expand Up @@ -208,8 +213,11 @@ extension MultiEditorViewController: MediaClipsEditorDelegate {
frames.remove(at: index)
}

migratedIndex = shift(index: selected ?? 0, indices: [index], edits: frames)
selected = newIndex(indices: [index], selected: selected, edits: frames)
let newSelection = newIndex(indices: [index], selected: selected, edits: frames)
if newSelection == selected {
selected = nil
}
selected = newSelection
if selected == nil {
dismissButtonPressed()
}
Expand All @@ -224,12 +232,12 @@ extension MultiEditorViewController: MediaClipsEditorDelegate {

let sortedindices = indices.sorted()

if let selected = selected, sortedindices.contains(selected) {
if let index = indices.first, edits.indices.contains(index) {
if let selected = selected, sortedindices.contains(selected) { // If the selection is contained in the set
if let index = indices.first, edits.indices.contains(index) { // Keep the same selection if it still exists.
return index
} else if let firstIndex = indices.first, firstIndex > edits.startIndex {
} else if let firstIndex = indices.first, firstIndex > edits.startIndex { // Item before if it does not.
nextIndex = edits.index(before: firstIndex)
} else if let lastIndex = sortedindices.last, lastIndex < edits.endIndex {
} else if let lastIndex = sortedindices.last, lastIndex < edits.endIndex { // Item after if prior item doesn't exist.
nextIndex = edits.index(after: lastIndex)
}
} else {
Expand All @@ -248,23 +256,40 @@ extension MultiEditorViewController: MediaClipsEditorDelegate {
}
}

func shift(index: Int, moves: [(origin: Int, destination: Int)], edits: [Any]) -> Int {
let indexMoves: [Int] = moves.map { origin, destination -> Int in
if (index < origin && index < destination) || (index > origin && index > destination) {
return 0
} else {
if destination >= index && origin < index {
return -1
} else if destination <= index && origin > index {
return 1
} else {
return 0
}
}
}
return index + indexMoves.reduce(0, { $0 + $1 })
}

func mediaClipWasMoved(from originIndex: Int, to destinationIndex: Int) {
if let selected = selected {
archive(index: selected)
}
frames.move(from: originIndex, to: destinationIndex)

let newIndex: Int
let selectedIndex: Int
if selected == originIndex {
// When moving the selected frame just move it to the destination index
newIndex = destinationIndex
selectedIndex = destinationIndex
} else {
// Otherwise calculate the shifted index value
newIndex = shift(index: selected ?? 0, indices: [originIndex], edits: frames)
selectedIndex = shift(index: selected ?? 0, moves: [(originIndex, destinationIndex)], edits: frames)
}

migratedIndex = newIndex
selected = newIndex
migratedIndex = selectedIndex
selected = selectedIndex
}

func mediaClipWasSelected(at: Int) {
Expand Down
3 changes: 3 additions & 0 deletions Classes/Editor/Text/EditorTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ final class EditorTextView: UIView, MainTextViewDelegate {
struct Settings {
/// The Font Selector button uses the current selected font (`font`) for its label
let fontSelectorUsesFont: Bool
/// Enables/disables progressive font resizing
let resizesFonts: Bool
}

private let settings: Settings
Expand Down Expand Up @@ -251,6 +253,7 @@ final class EditorTextView: UIView, MainTextViewDelegate {
private func setUpMainTextView() {
mainTextView.accessibilityIdentifier = "Editor Text Main View"
mainTextView.translatesAutoresizingMaskIntoConstraints = false
mainTextView.resizesFont = settings.resizesFonts
addSubview(mainTextView)

let topMargin = Constants.topMargin + Constants.confirmButtonSize
Expand Down
4 changes: 3 additions & 1 deletion Classes/Editor/Text/MainTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ final class MainTextView: StylableTextView {
resizeFont()
centerContentVertically()
}

var resizesFont: Bool = true

override init() {
super.init()
Expand Down Expand Up @@ -88,7 +90,7 @@ final class MainTextView: StylableTextView {
}

func resizeFont() {
guard !bounds.size.equalTo(.zero), let currentFont = font else { return }
guard resizesFont && !bounds.size.equalTo(.zero), let currentFont = font else { return }
var bestFont = currentFont.withSize(Constants.fontSizes[0])

for fontSize in Constants.fontSizes {
Expand Down
1 change: 1 addition & 0 deletions Classes/MediaClips/MediaClipsCollectionCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ final class MediaClipsCollectionCell: UICollectionViewCell {
override func prepareForReuse() {
super.prepareForReuse()
clipImage.image = .none
clipView.layer.borderWidth = MediaClipsCollectionCellConstants.borderWidth
}

override var isSelected: Bool {
Expand Down
15 changes: 14 additions & 1 deletion Classes/MediaClips/MediaClipsCollectionController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,20 @@ final class MediaClipsCollectionController: UIViewController, UICollectionViewDe
}

func select(index: Int) {
mediaClipsCollectionView.collectionView.selectItem(at: IndexPath(item: index, section: 0), animated: false, scrollPosition: .left)
let selectedIndexPath = IndexPath(item: index, section: 0)
guard mediaClipsCollectionView.collectionView.indexPathsForSelectedItems?.contains(selectedIndexPath) == false else {
return
}
mediaClipsCollectionView.collectionView.indexPathsForSelectedItems?.forEach({ indexPath in
mediaClipsCollectionView.collectionView.deselectItem(at: indexPath, animated: false)
})
let scrollPosition: UICollectionView.ScrollPosition
if mediaClipsCollectionView.collectionView.indexPathsForVisibleItems.contains(selectedIndexPath) {
scrollPosition = []
} else {
scrollPosition = .left
}
mediaClipsCollectionView.collectionView.selectItem(at: selectedIndexPath, animated: false, scrollPosition: scrollPosition)
}

func removeAllClips() {
Expand Down
11 changes: 10 additions & 1 deletion Classes/MediaClips/MediaClipsCollectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ private func createCollectionView() -> UICollectionView {
let layout = UICollectionViewFlowLayout()
configureCollectionLayout(layout: layout)

let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
let collectionView = InteractiveMovementsCrashFixCollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.accessibilityIdentifier = "Media Clips Collection"
collectionView.backgroundColor = .clear
configureCollection(collectionView: collectionView)
Expand All @@ -99,3 +99,12 @@ private func configureCollection(collectionView: UICollectionView) {
collectionView.dragInteractionEnabled = true
collectionView.reorderingCadence = .immediate
}

// Fixes a crash in `_UIDragFeedbackGenerator`: https://github.com/tumblr/kanvas-ios/issues/98
private class InteractiveMovementsCrashFixCollectionView: UICollectionView {
// See https://stackoverflow.com/questions/51553223/handling-multiple-uicollectionview-interactivemovements-crash-uidragsnapping for more details
override func cancelInteractiveMovement() {
super.cancelInteractiveMovement()
super.endInteractiveMovement() // animation will be ended early here
}
}
4 changes: 4 additions & 0 deletions Classes/Settings/CameraSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ public struct CameraFeatures {
/// This scales the imported media to fill the screen by setting the `mediaContentMode` to `scaleAspectFill` on the pixel buffer views.
/// The buffer views will resize their contents during drawing to fill the screen.
public var scaleMediaToFill: Bool = false

/// Resizes Text View Fonts
/// Whether or not to resize the text view fonts progressively to fit withinthe editing area.
public var resizesFonts: Bool = true
}

// A class that defines the settings for the Kanvas Camera
Expand Down
2 changes: 1 addition & 1 deletion Kanvas.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = "Kanvas"
spec.version = "1.2.3"
spec.version = "1.2.4"
spec.summary = "A custom camera built for iOS."
spec.homepage = "https://github.com/tumblr/kanvas-ios"
spec.license = "MPLv2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,45 @@ class MultiEditorControllerTests: FBSnapshotTestCase {
_ = viewController.shouldExport()
wait(for: [expectation], timeout: 2)
}

func testDeletedIndex() {
let segments = getPhotoSegment() + getPhotoSegment() + getPhotoSegment()
let inFrames = frames(segments: segments)
let vc = newViewController(frames: inFrames)

let frameMovedAhead = vc.shift(index: 2, moves: [(1,0)], edits: inFrames)
XCTAssertEqual(frameMovedAhead, 2, "Selection shouldn't change")
let frameMovedBehind = vc.shift(index: 0, moves: [(1,2)], edits: inFrames)
XCTAssertEqual(frameMovedBehind, 0, "Selection shouldn't change")
let frameMovedInFront = vc.shift(index: 1, moves: [(0,2)], edits: inFrames)
XCTAssertEqual(frameMovedInFront, 0, "Selection should be moved back")
let frameMovedInBack = vc.shift(index: 1, moves: [(2,0)], edits: inFrames)
XCTAssertEqual(frameMovedInBack, 2, "Selection should be moved forward")
}

func testRemovedIndex() {
let segments = getPhotoSegment() + getPhotoSegment() + getPhotoSegment()
var inFrames = frames(segments: segments)
let vc = newViewController(frames: inFrames)

inFrames.removeLast(2)
let deletedLast = vc.newIndex(indices: [2], selected: 2, edits: inFrames)
XCTAssertEqual(deletedLast, 1, "Selection should move back")
inFrames = inFrames + frames(segments: getPhotoSegment())
inFrames.removeFirst(1)
let deletedFirst = vc.newIndex(indices: [0], selected: 0, edits: inFrames)
XCTAssertEqual(deletedFirst, 0, "Selection should not move")
inFrames = frames(segments: getPhotoSegment()) + inFrames

inFrames.removeFirst(1)
let deletedInFront = vc.newIndex(indices: [0], selected: 1, edits: inFrames)
XCTAssertEqual(deletedInFront, 0, "Selection should be moved back")
inFrames = frames(segments: getPhotoSegment()) + inFrames

inFrames.removeLast(2)
let deletedInBack = vc.newIndex(indices: [1], selected: 0, edits: inFrames)
XCTAssertEqual(deletedInBack, 0, "Selection shouldn't change")
}
}

final class MultiEditorControllerDelegateStub: MultiEditorComposerDelegate {
Expand Down Expand Up @@ -183,4 +222,5 @@ final class MultiEditorControllerDelegateStub: MultiEditorComposerDelegate {
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ final class EditorTextControllerTests: FBSnapshotTestCase {
}

func newViewController() -> EditorTextController {
let editorSettings = EditorTextController.Settings(textViewSettings: EditorTextView.Settings(fontSelectorUsesFont: false))
let editorSettings = EditorTextController.Settings(textViewSettings: EditorTextView.Settings(fontSelectorUsesFont: false, resizesFonts: true))
let controller = EditorTextController(settings: editorSettings)
controller.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
controller.view.setNeedsDisplay()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class EditorTextViewTests: FBSnapshotTestCase {
}

func newView() -> EditorTextView {
let textViewSettings = EditorTextView.Settings(fontSelectorUsesFont: false)
let textViewSettings = EditorTextView.Settings(fontSelectorUsesFont: false, resizesFonts: true)
let view = EditorTextView(settings: textViewSettings)
view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
return view
Expand Down
4 changes: 2 additions & 2 deletions KanvasExample/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ PODS:
- FBSnapshotTestCase/Core (2.1.4)
- FBSnapshotTestCase/SwiftSupport (2.1.4):
- FBSnapshotTestCase/Core
- Kanvas (1.2.2)
- Kanvas (1.2.3)

DEPENDENCIES:
- FBSnapshotTestCase (= 2.1.4)
Expand All @@ -20,7 +20,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a
Kanvas: 412d5b7502809153a6acac98f57923ad5d0251f8
Kanvas: 97860c54ea07119c533a80d951ee8c1b39d8f386

PODFILE CHECKSUM: 14b28dd726149c0d01dba9154d5bb095d9ba6a18

Expand Down