Skip to content

Commit 9c73232

Browse files
authored
Merge pull request #102 from tumblr/stories/16-8-release-fixes
Stories: 16.8 Bug Fixes
2 parents f4d5428 + 22d2f13 commit 9c73232

14 files changed

+125
-24
lines changed

Classes/Camera/CameraController.swift

+2-4
Original file line numberDiff line numberDiff line change
@@ -1001,16 +1001,14 @@ open class CameraController: UIViewController, MediaClipsEditorDelegate, CameraP
10011001
analyticsProvider?.logPreviewDismissed()
10021002
}
10031003
if settings.features.multipleExports {
1004-
self.dismiss(animated: true, completion: {
1005-
self.dismiss(animated: false)
1006-
})
1004+
delegate?.editorDismissed(self)
10071005
showPreviewWithSegments([], selected: multiEditorViewController?.selected ?? 0)
10081006
} else {
10091007
performUIUpdate { [weak self] in
10101008
self?.dismiss(animated: true)
10111009
}
1010+
delegate?.editorDismissed(self)
10121011
}
1013-
delegate?.editorDismissed(self)
10141012
}
10151013

10161014
public func tagButtonPressed() {

Classes/Editor/EditorViewController.swift

+7-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public final class EditorViewController: UIViewController, MediaPlayerController
132132
}()
133133

134134
private lazy var textController: EditorTextController = {
135-
let textViewSettings = EditorTextView.Settings(fontSelectorUsesFont: settings.fontSelectorUsesFont)
135+
let textViewSettings = EditorTextView.Settings(fontSelectorUsesFont: settings.fontSelectorUsesFont, resizesFonts: settings.features.resizesFonts)
136136
let settings = EditorTextController.Settings(textViewSettings: textViewSettings)
137137
let controller = EditorTextController(settings: settings)
138138
controller.delegate = self
@@ -393,6 +393,12 @@ public final class EditorViewController: UIViewController, MediaPlayerController
393393

394394
startPlayerFromSegments()
395395
}
396+
397+
public override func viewWillDisappear(_ animated: Bool) {
398+
super.viewWillDisappear(animated)
399+
400+
player.pause()
401+
}
396402

397403
override public func viewDidLoad() {
398404
super.viewDidLoad()

Classes/Editor/MultiEditor/MultiEditorViewController.swift

+36-11
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ class MultiEditorViewController: UIViewController {
122122
}
123123
}
124124

125+
override func viewDidAppear(_ animated: Bool) {
126+
super.viewDidAppear(animated)
127+
clipsController.select(index: selected ?? 0)
128+
}
129+
125130
func loadEditor(for index: Int) {
126131
let frame = frames[index]
127132
if let editor = delegate?.editor(segment: frame.segment, edit: frame.edit) {
@@ -208,8 +213,11 @@ extension MultiEditorViewController: MediaClipsEditorDelegate {
208213
frames.remove(at: index)
209214
}
210215

211-
migratedIndex = shift(index: selected ?? 0, indices: [index], edits: frames)
212-
selected = newIndex(indices: [index], selected: selected, edits: frames)
216+
let newSelection = newIndex(indices: [index], selected: selected, edits: frames)
217+
if newSelection == selected {
218+
selected = nil
219+
}
220+
selected = newSelection
213221
if selected == nil {
214222
dismissButtonPressed()
215223
}
@@ -224,12 +232,12 @@ extension MultiEditorViewController: MediaClipsEditorDelegate {
224232

225233
let sortedindices = indices.sorted()
226234

227-
if let selected = selected, sortedindices.contains(selected) {
228-
if let index = indices.first, edits.indices.contains(index) {
235+
if let selected = selected, sortedindices.contains(selected) { // If the selection is contained in the set
236+
if let index = indices.first, edits.indices.contains(index) { // Keep the same selection if it still exists.
229237
return index
230-
} else if let firstIndex = indices.first, firstIndex > edits.startIndex {
238+
} else if let firstIndex = indices.first, firstIndex > edits.startIndex { // Item before if it does not.
231239
nextIndex = edits.index(before: firstIndex)
232-
} else if let lastIndex = sortedindices.last, lastIndex < edits.endIndex {
240+
} else if let lastIndex = sortedindices.last, lastIndex < edits.endIndex { // Item after if prior item doesn't exist.
233241
nextIndex = edits.index(after: lastIndex)
234242
}
235243
} else {
@@ -248,23 +256,40 @@ extension MultiEditorViewController: MediaClipsEditorDelegate {
248256
}
249257
}
250258

259+
func shift(index: Int, moves: [(origin: Int, destination: Int)], edits: [Any]) -> Int {
260+
let indexMoves: [Int] = moves.map { origin, destination -> Int in
261+
if (index < origin && index < destination) || (index > origin && index > destination) {
262+
return 0
263+
} else {
264+
if destination >= index && origin < index {
265+
return -1
266+
} else if destination <= index && origin > index {
267+
return 1
268+
} else {
269+
return 0
270+
}
271+
}
272+
}
273+
return index + indexMoves.reduce(0, { $0 + $1 })
274+
}
275+
251276
func mediaClipWasMoved(from originIndex: Int, to destinationIndex: Int) {
252277
if let selected = selected {
253278
archive(index: selected)
254279
}
255280
frames.move(from: originIndex, to: destinationIndex)
256281

257-
let newIndex: Int
282+
let selectedIndex: Int
258283
if selected == originIndex {
259284
// When moving the selected frame just move it to the destination index
260-
newIndex = destinationIndex
285+
selectedIndex = destinationIndex
261286
} else {
262287
// Otherwise calculate the shifted index value
263-
newIndex = shift(index: selected ?? 0, indices: [originIndex], edits: frames)
288+
selectedIndex = shift(index: selected ?? 0, moves: [(originIndex, destinationIndex)], edits: frames)
264289
}
265290

266-
migratedIndex = newIndex
267-
selected = newIndex
291+
migratedIndex = selectedIndex
292+
selected = selectedIndex
268293
}
269294

270295
func mediaClipWasSelected(at: Int) {

Classes/Editor/Text/EditorTextView.swift

+3
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ final class EditorTextView: UIView, MainTextViewDelegate {
196196
struct Settings {
197197
/// The Font Selector button uses the current selected font (`font`) for its label
198198
let fontSelectorUsesFont: Bool
199+
/// Enables/disables progressive font resizing
200+
let resizesFonts: Bool
199201
}
200202

201203
private let settings: Settings
@@ -251,6 +253,7 @@ final class EditorTextView: UIView, MainTextViewDelegate {
251253
private func setUpMainTextView() {
252254
mainTextView.accessibilityIdentifier = "Editor Text Main View"
253255
mainTextView.translatesAutoresizingMaskIntoConstraints = false
256+
mainTextView.resizesFont = settings.resizesFonts
254257
addSubview(mainTextView)
255258

256259
let topMargin = Constants.topMargin + Constants.confirmButtonSize

Classes/Editor/Text/MainTextView.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ final class MainTextView: StylableTextView {
3535
resizeFont()
3636
centerContentVertically()
3737
}
38+
39+
var resizesFont: Bool = true
3840

3941
override init() {
4042
super.init()
@@ -88,7 +90,7 @@ final class MainTextView: StylableTextView {
8890
}
8991

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

9496
for fontSize in Constants.fontSizes {

Classes/MediaClips/MediaClipsCollectionCell.swift

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ final class MediaClipsCollectionCell: UICollectionViewCell {
7373
override func prepareForReuse() {
7474
super.prepareForReuse()
7575
clipImage.image = .none
76+
clipView.layer.borderWidth = MediaClipsCollectionCellConstants.borderWidth
7677
}
7778

7879
override var isSelected: Bool {

Classes/MediaClips/MediaClipsCollectionController.swift

+14-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,20 @@ final class MediaClipsCollectionController: UIViewController, UICollectionViewDe
6969
}
7070

7171
func select(index: Int) {
72-
mediaClipsCollectionView.collectionView.selectItem(at: IndexPath(item: index, section: 0), animated: false, scrollPosition: .left)
72+
let selectedIndexPath = IndexPath(item: index, section: 0)
73+
guard mediaClipsCollectionView.collectionView.indexPathsForSelectedItems?.contains(selectedIndexPath) == false else {
74+
return
75+
}
76+
mediaClipsCollectionView.collectionView.indexPathsForSelectedItems?.forEach({ indexPath in
77+
mediaClipsCollectionView.collectionView.deselectItem(at: indexPath, animated: false)
78+
})
79+
let scrollPosition: UICollectionView.ScrollPosition
80+
if mediaClipsCollectionView.collectionView.indexPathsForVisibleItems.contains(selectedIndexPath) {
81+
scrollPosition = []
82+
} else {
83+
scrollPosition = .left
84+
}
85+
mediaClipsCollectionView.collectionView.selectItem(at: selectedIndexPath, animated: false, scrollPosition: scrollPosition)
7386
}
7487

7588
func removeAllClips() {

Classes/MediaClips/MediaClipsCollectionView.swift

+10-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ private func createCollectionView() -> UICollectionView {
7272
let layout = UICollectionViewFlowLayout()
7373
configureCollectionLayout(layout: layout)
7474

75-
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
75+
let collectionView = InteractiveMovementsCrashFixCollectionView(frame: .zero, collectionViewLayout: layout)
7676
collectionView.accessibilityIdentifier = "Media Clips Collection"
7777
collectionView.backgroundColor = .clear
7878
configureCollection(collectionView: collectionView)
@@ -99,3 +99,12 @@ private func configureCollection(collectionView: UICollectionView) {
9999
collectionView.dragInteractionEnabled = true
100100
collectionView.reorderingCadence = .immediate
101101
}
102+
103+
// Fixes a crash in `_UIDragFeedbackGenerator`: https://github.com/tumblr/kanvas-ios/issues/98
104+
private class InteractiveMovementsCrashFixCollectionView: UICollectionView {
105+
// See https://stackoverflow.com/questions/51553223/handling-multiple-uicollectionview-interactivemovements-crash-uidragsnapping for more details
106+
override func cancelInteractiveMovement() {
107+
super.cancelInteractiveMovement()
108+
super.endInteractiveMovement() // animation will be ended early here
109+
}
110+
}

Classes/Settings/CameraSettings.swift

+4
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ public struct CameraFeatures {
172172
/// This scales the imported media to fill the screen by setting the `mediaContentMode` to `scaleAspectFill` on the pixel buffer views.
173173
/// The buffer views will resize their contents during drawing to fill the screen.
174174
public var scaleMediaToFill: Bool = false
175+
176+
/// Resizes Text View Fonts
177+
/// Whether or not to resize the text view fonts progressively to fit withinthe editing area.
178+
public var resizesFonts: Bool = true
175179
}
176180

177181
// A class that defines the settings for the Kanvas Camera

Kanvas.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |spec|
22
spec.name = "Kanvas"
3-
spec.version = "1.2.3"
3+
spec.version = "1.2.4"
44
spec.summary = "A custom camera built for iOS."
55
spec.homepage = "https://github.com/tumblr/kanvas-ios"
66
spec.license = "MPLv2"

KanvasExample/KanvasExampleTests/Editor/MultiEditor/MultiEditorControllerTests.swift

+40
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,45 @@ class MultiEditorControllerTests: FBSnapshotTestCase {
9898
_ = viewController.shouldExport()
9999
wait(for: [expectation], timeout: 2)
100100
}
101+
102+
func testDeletedIndex() {
103+
let segments = getPhotoSegment() + getPhotoSegment() + getPhotoSegment()
104+
let inFrames = frames(segments: segments)
105+
let vc = newViewController(frames: inFrames)
106+
107+
let frameMovedAhead = vc.shift(index: 2, moves: [(1,0)], edits: inFrames)
108+
XCTAssertEqual(frameMovedAhead, 2, "Selection shouldn't change")
109+
let frameMovedBehind = vc.shift(index: 0, moves: [(1,2)], edits: inFrames)
110+
XCTAssertEqual(frameMovedBehind, 0, "Selection shouldn't change")
111+
let frameMovedInFront = vc.shift(index: 1, moves: [(0,2)], edits: inFrames)
112+
XCTAssertEqual(frameMovedInFront, 0, "Selection should be moved back")
113+
let frameMovedInBack = vc.shift(index: 1, moves: [(2,0)], edits: inFrames)
114+
XCTAssertEqual(frameMovedInBack, 2, "Selection should be moved forward")
115+
}
116+
117+
func testRemovedIndex() {
118+
let segments = getPhotoSegment() + getPhotoSegment() + getPhotoSegment()
119+
var inFrames = frames(segments: segments)
120+
let vc = newViewController(frames: inFrames)
121+
122+
inFrames.removeLast(2)
123+
let deletedLast = vc.newIndex(indices: [2], selected: 2, edits: inFrames)
124+
XCTAssertEqual(deletedLast, 1, "Selection should move back")
125+
inFrames = inFrames + frames(segments: getPhotoSegment())
126+
inFrames.removeFirst(1)
127+
let deletedFirst = vc.newIndex(indices: [0], selected: 0, edits: inFrames)
128+
XCTAssertEqual(deletedFirst, 0, "Selection should not move")
129+
inFrames = frames(segments: getPhotoSegment()) + inFrames
130+
131+
inFrames.removeFirst(1)
132+
let deletedInFront = vc.newIndex(indices: [0], selected: 1, edits: inFrames)
133+
XCTAssertEqual(deletedInFront, 0, "Selection should be moved back")
134+
inFrames = frames(segments: getPhotoSegment()) + inFrames
135+
136+
inFrames.removeLast(2)
137+
let deletedInBack = vc.newIndex(indices: [1], selected: 0, edits: inFrames)
138+
XCTAssertEqual(deletedInBack, 0, "Selection shouldn't change")
139+
}
101140
}
102141

103142
final class MultiEditorControllerDelegateStub: MultiEditorComposerDelegate {
@@ -183,4 +222,5 @@ final class MultiEditorControllerDelegateStub: MultiEditorComposerDelegate {
183222
}
184223

185224

225+
186226
}

KanvasExample/KanvasExampleTests/Editor/Text/EditorTextControllerTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class EditorTextControllerTests: FBSnapshotTestCase {
1919
}
2020

2121
func newViewController() -> EditorTextController {
22-
let editorSettings = EditorTextController.Settings(textViewSettings: EditorTextView.Settings(fontSelectorUsesFont: false))
22+
let editorSettings = EditorTextController.Settings(textViewSettings: EditorTextView.Settings(fontSelectorUsesFont: false, resizesFonts: true))
2323
let controller = EditorTextController(settings: editorSettings)
2424
controller.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
2525
controller.view.setNeedsDisplay()

KanvasExample/KanvasExampleTests/Editor/Text/EditorTextViewTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ final class EditorTextViewTests: FBSnapshotTestCase {
2020
}
2121

2222
func newView() -> EditorTextView {
23-
let textViewSettings = EditorTextView.Settings(fontSelectorUsesFont: false)
23+
let textViewSettings = EditorTextView.Settings(fontSelectorUsesFont: false, resizesFonts: true)
2424
let view = EditorTextView(settings: textViewSettings)
2525
view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
2626
return view

KanvasExample/Podfile.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ PODS:
44
- FBSnapshotTestCase/Core (2.1.4)
55
- FBSnapshotTestCase/SwiftSupport (2.1.4):
66
- FBSnapshotTestCase/Core
7-
- Kanvas (1.2.2)
7+
- Kanvas (1.2.3)
88

99
DEPENDENCIES:
1010
- FBSnapshotTestCase (= 2.1.4)
@@ -20,7 +20,7 @@ EXTERNAL SOURCES:
2020

2121
SPEC CHECKSUMS:
2222
FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a
23-
Kanvas: 412d5b7502809153a6acac98f57923ad5d0251f8
23+
Kanvas: 97860c54ea07119c533a80d951ee8c1b39d8f386
2424

2525
PODFILE CHECKSUM: 14b28dd726149c0d01dba9154d5bb095d9ba6a18
2626

0 commit comments

Comments
 (0)