Skip to content

Commit

Permalink
Support directional key commands
Browse files Browse the repository at this point in the history
  • Loading branch information
hthi-atlassian committed Oct 9, 2023
1 parent f6d08b8 commit 566fe54
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Proton/Proton.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@
1BFFEF1C23C334D200D2BA35 /* InlineEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BFFEF1B23C334D200D2BA35 /* InlineEditorView.swift */; };
1BFFEF1F23C3366200D2BA35 /* MockAttachmentOffsetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BFFEF1E23C3366200D2BA35 /* MockAttachmentOffsetProvider.swift */; };
1BFFEF2123C33EA900D2BA35 /* PanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BFFEF2023C33EA900D2BA35 /* PanelView.swift */; };
7D0C8C6B2ACFD56100D2F5D1 /* MockKeyboardPress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0C8C6A2ACFD56100D2F5D1 /* MockKeyboardPress.swift */; };
7D0C8C6D2AD25D4A00D2F5D1 /* EditorKeyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0C8C6C2AD25D4A00D2F5D1 /* EditorKeyTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -307,6 +309,8 @@
1BFFEF1B23C334D200D2BA35 /* InlineEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineEditorView.swift; sourceTree = "<group>"; };
1BFFEF1E23C3366200D2BA35 /* MockAttachmentOffsetProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAttachmentOffsetProvider.swift; sourceTree = "<group>"; };
1BFFEF2023C33EA900D2BA35 /* PanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelView.swift; sourceTree = "<group>"; };
7D0C8C6A2ACFD56100D2F5D1 /* MockKeyboardPress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockKeyboardPress.swift; sourceTree = "<group>"; };
7D0C8C6C2AD25D4A00D2F5D1 /* EditorKeyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorKeyTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -460,6 +464,7 @@
1B45CDDA23C04BE3001EB196 /* RichTextViewSnapshotTests.swift */,
1B4B60C5247F692D002B63CF /* ListsSnapshotTests.swift */,
1BFDC810254AA11F00BD83BD /* ListParserTests.swift */,
7D0C8C6C2AD25D4A00D2F5D1 /* EditorKeyTests.swift */,
);
path = Core;
sourceTree = "<group>";
Expand Down Expand Up @@ -487,6 +492,7 @@
1B82570323C48C350033A0A9 /* MockRichTextViewDelegate.swift */,
1B30A3632489E11F00FA1D48 /* MockRichTextViewListDelegate.swift */,
1B30A3612489DC7B00FA1D48 /* MockListFormattingProvider.swift */,
7D0C8C6A2ACFD56100D2F5D1 /* MockKeyboardPress.swift */,
);
path = Mocks;
sourceTree = "<group>";
Expand Down Expand Up @@ -1094,6 +1100,7 @@
1BFFEF1723C333B400D2BA35 /* EditorTestViewController.swift in Sources */,
1B45CDCE23BF18A5001EB196 /* XCTestHelpers.swift in Sources */,
1B45CDDB23C04BE3001EB196 /* RichTextViewSnapshotTests.swift in Sources */,
7D0C8C6B2ACFD56100D2F5D1 /* MockKeyboardPress.swift in Sources */,
1B2BC0D823CF17E300407DEE /* EditorContentTransformerTests.swift in Sources */,
1B45CDD923C0484A001EB196 /* RichTextViewTests.swift in Sources */,
1BC25B542448768200FF88AC /* EditorContextDelegateTests.swift in Sources */,
Expand All @@ -1108,6 +1115,7 @@
1B45CDCB23BF1621001EB196 /* MockDefaultTextFormattingProvider.swift in Sources */,
1BD185D0284D839C001F4FBC /* GridViewAttachmentSnapshotTests.swift in Sources */,
1B45CDA923BEED0E001EB196 /* AutogrowingTextViewTests.swift in Sources */,
7D0C8C6D2AD25D4A00D2F5D1 /* EditorKeyTests.swift in Sources */,
1BD185BF284C2A66001F4FBC /* GridTests.swift in Sources */,
1B3D19CA2483484A00B3AB59 /* EditorListsSnapshotTests.swift in Sources */,
1B183D9223CEEED900AE83E5 /* EditorContentEncoderTests.swift in Sources */,
Expand Down
15 changes: 15 additions & 0 deletions Proton/Sources/Swift/Core/RichTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ class RichTextView: AutogrowingTextView {
getNestedEditors(for: self)
}

override public func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
guard #available(iOS 13.4, *) else { return }
var handled: Bool = false
presses.forEach { press in
guard
let key = press.key,
let editorKey = EditorKey(key.charactersIgnoringModifiers)
else { return }
richTextViewDelegate?.richTextView(self, shouldHandle: editorKey, modifierFlags: key.modifierFlags, at: self.selectedRange, handled: &handled)
}
if handled == false {
super.pressesBegan(presses, with: event)
}
}

private func getNestedEditors(for containerView: UIView) -> [RichTextView] {
var textViews = [RichTextView]()
for view in containerView.subviews {
Expand Down
12 changes: 12 additions & 0 deletions Proton/Sources/Swift/Core/RichTextViewDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,25 @@ public enum EditorKey {
case enter
case backspace
case tab
case left
case right
case up
case down

init?(_ string: String) {
switch string {
case "\t":
self = .tab
case "\n", "\r":
self = .enter
case UIKeyCommand.inputUpArrow:
self = .up
case UIKeyCommand.inputDownArrow:
self = .down
case UIKeyCommand.inputLeftArrow:
self = .left
case UIKeyCommand.inputRightArrow:
self = .right
default:
return nil
}
Expand Down
4 changes: 4 additions & 0 deletions Proton/Sources/Swift/Editor/EditorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ open class EditorView: UIView {
set { richTextView.inputView = newValue }
}

open override var isFirstResponder: Bool {
richTextView.isFirstResponder
}

required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ public class ListTextProcessor: TextProcessing {
else { return }

editor.deleteBackward()

default:
break
}
}

Expand Down
41 changes: 41 additions & 0 deletions Proton/Tests/Core/EditorKeyTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// EditorKeyTests.swift
// ProtonTests
//
// Created by Hon Thi on 8/10/2023.
// Copyright © 2023 Rajdeep Kwatra. All rights reserved.
//

import XCTest
@testable import Proton

final class EditorKeyTests: XCTestCase {
func test_ReturnsTab() {
XCTAssertEqual(EditorKey("\t"), EditorKey.tab)
}

func test_ReturnsEnter() {
XCTAssertEqual(EditorKey("\r"), EditorKey.enter)
XCTAssertEqual(EditorKey("\n"), EditorKey.enter)
}

func test_ReturnsUp() {
XCTAssertEqual(EditorKey(UIKeyCommand.inputUpArrow), EditorKey.up)
}

func test_ReturnsDown() {
XCTAssertEqual(EditorKey(UIKeyCommand.inputDownArrow), EditorKey.down)
}

func test_ReturnsLeft() {
XCTAssertEqual(EditorKey(UIKeyCommand.inputLeftArrow), EditorKey.left)
}

func test_ReturnsRight() {
XCTAssertEqual(EditorKey(UIKeyCommand.inputRightArrow), EditorKey.right)
}

func testReturnsNil() {
XCTAssertNil(EditorKey("any"))
}
}
36 changes: 36 additions & 0 deletions Proton/Tests/Core/Mocks/MockKeyboardPress.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// MockKeyboardPress.swift
// ProtonTests
//
// Created by Hon Thi on 6/10/2023.
// Copyright © 2023 Rajdeep Kwatra. All rights reserved.
//

import UIKit

@available(iOS 13.4, *)
class MockUIPress: UIPress {
var _characters: String
override var key: UIKey? {
MockUIKey(characters: _characters)
}

init(characters: String) {
self._characters = characters
}
}

@available(iOS 13.4, *)
class MockUIKey: UIKey {
var _characters: String
override var charactersIgnoringModifiers: String { _characters }

init(characters: String) {
self._characters = characters
super.init()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
23 changes: 23 additions & 0 deletions Proton/Tests/Core/RichTextViewContextTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,29 @@ class RichTextViewContextTests: XCTestCase {
waitForExpectations(timeout: 1.0)
}

func testReceiveRightKey() {
guard #available(iOS 13.4, *) else { return }
let testExpectation = expectation(description: #function)
let mockTextViewDelegate = MockRichTextViewDelegate()

let context = RichTextEditorContext.default
let textView = RichTextView(context: context)
textView.richTextViewDelegate = mockTextViewDelegate
context.textViewDidBeginEditing(textView)
textView.text = "Sample text"

let selectedRange = NSRange.zero
textView.selectedRange = selectedRange

mockTextViewDelegate.onShouldHandleKey = { _, key, _, range, _ in
XCTAssertEqual(key, EditorKey.right)
testExpectation.fulfill()
}

textView.pressesBegan(Set(arrayLiteral: MockUIPress(characters: UIKeyCommand.inputRightArrow)), with: nil)
waitForExpectations(timeout: 1.0)
}

func testInvokesTextDidChange() {
let testExpectation = expectation(description: #function)
let mockTextViewDelegate = MockRichTextViewDelegate()
Expand Down

0 comments on commit 566fe54

Please sign in to comment.