Skip to content

Commit

Permalink
Merge pull request #4719 from wikimedia/native-editor-undo-redo
Browse files Browse the repository at this point in the history
Native Editor - Add basic undo / redo support
  • Loading branch information
mazevedofs committed Jan 24, 2024
2 parents 83e85c5 + 668aaab commit 8e39b97
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 12 deletions.
Expand Up @@ -2,10 +2,12 @@ import Foundation
import UIKit

public protocol WKSourceEditorViewControllerDelegate: AnyObject {
func sourceEditorViewControllerDidTapFind(sourceEditorViewController: WKSourceEditorViewController)
func sourceEditorViewControllerDidRemoveFindInputAccessoryView(sourceEditorViewController: WKSourceEditorViewController)
func sourceEditorViewControllerDidTapFind(_ sourceEditorViewController: WKSourceEditorViewController)
func sourceEditorViewControllerDidRemoveFindInputAccessoryView(_ sourceEditorViewController: WKSourceEditorViewController)
func sourceEditorViewControllerDidTapLink(parameters: WKSourceEditorFormatterLinkWizardParameters)
func sourceEditorViewControllerDidTapImage()
func sourceEditorDidChangeUndoState(_ sourceEditorViewController: WKSourceEditorViewController, canUndo: Bool, canRedo: Bool)
func sourceEditorDidChangeText(_ sourceEditorViewController: WKSourceEditorViewController, didChangeText: Bool)
}

// MARK: NSNotification Names
Expand Down Expand Up @@ -106,7 +108,7 @@ public class WKSourceEditorViewController: WKComponentViewController {
}

if oldValue == .find && inputAccessoryViewType != .find {
delegate?.sourceEditorViewControllerDidRemoveFindInputAccessoryView(sourceEditorViewController: self)
delegate?.sourceEditorViewControllerDidRemoveFindInputAccessoryView(self)
}

switch inputAccessoryViewType {
Expand Down Expand Up @@ -253,6 +255,14 @@ public class WKSourceEditorViewController: WKComponentViewController {
public func insertImage(wikitext: String) {
textFrameworkMediator.linkFormatter?.insertImage(wikitext: wikitext, in: textView)
}

public func undo() {
textView.undoManager?.undo()
}

public func redo() {
textView.undoManager?.redo()
}
}

// MARK: - Private
Expand Down Expand Up @@ -401,6 +411,15 @@ extension WKSourceEditorViewController: UITextViewDelegate {
postUpdateButtonSelectionStatesNotification(withDelay: false)
}

public func textViewDidChange(_ textView: UITextView) {

DispatchQueue.main.async {
self.delegate?.sourceEditorDidChangeUndoState(self, canUndo: textView.undoManager?.canUndo ?? false, canRedo: textView.undoManager?.canRedo ?? false)
}

delegate?.sourceEditorDidChangeText(self, didChangeText: textView.attributedText.string != viewModel.initialText)
}

public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
// Don't allow emdash text changes. This throws off find & replace.
if text == "" {
Expand All @@ -417,7 +436,7 @@ extension WKSourceEditorViewController: WKEditorToolbarExpandingViewDelegate {

func toolbarExpandingViewDidTapFind(toolbarView: WKEditorToolbarExpandingView) {
inputAccessoryViewType = .find
delegate?.sourceEditorViewControllerDidTapFind(sourceEditorViewController: self)
delegate?.sourceEditorViewControllerDidTapFind(self)

if let visibleRange = textView.visibleRange {
textView.selectedRange = NSRange(location: visibleRange.location, length: 0)
Expand Down
11 changes: 9 additions & 2 deletions Components/Tests/ComponentsTests/WKSourceEditorTests.swift
Expand Up @@ -34,12 +34,19 @@ final class WKSourceEditorTests: XCTestCase {
}

extension WKSourceEditorTests: WKSourceEditorViewControllerDelegate {
func sourceEditorDidChangeUndoState(_ sourceEditorViewController: Components.WKSourceEditorViewController, canUndo: Bool, canRedo: Bool) {

}

func sourceEditorDidChangeText(_ sourceEditorViewController: Components.WKSourceEditorViewController, didChangeText: Bool) {

}

func sourceEditorViewControllerDidRemoveFindInputAccessoryView(sourceEditorViewController: Components.WKSourceEditorViewController) {
func sourceEditorViewControllerDidRemoveFindInputAccessoryView(_ sourceEditorViewController: Components.WKSourceEditorViewController) {

}

func sourceEditorViewControllerDidTapFind(sourceEditorViewController: Components.WKSourceEditorViewController) {
func sourceEditorViewControllerDidTapFind(_ sourceEditorViewController: Components.WKSourceEditorViewController) {

}

Expand Down
22 changes: 19 additions & 3 deletions Wikipedia/Code/PageEditorViewController.swift
Expand Up @@ -56,6 +56,7 @@ final class PageEditorViewController: UIViewController {

setTextSizeInAppEnvironment()
setupFocusNavigationView()
setupNavigationItemController()
loadWikitext()

apply(theme: theme)
Expand Down Expand Up @@ -85,6 +86,12 @@ final class PageEditorViewController: UIViewController {
NSLayoutConstraint.activate([leadingConstraint, trailingConstraint, topConstraint])
}

private func setupNavigationItemController() {
navigationItemController.progressButton.isEnabled = false
navigationItemController.undoButton.isEnabled = false
navigationItemController.redoButton.isEnabled = false
}

private func loadWikitext() {
fetcher.fetchSection(with: sectionID, articleURL: pageURL) { [weak self] (result) in
DispatchQueue.main.async { [weak self] in
Expand Down Expand Up @@ -231,16 +238,23 @@ extension PageEditorViewController: Themeable {
// MARK: - WKSourceEditorViewControllerDelegate

extension PageEditorViewController: WKSourceEditorViewControllerDelegate {
func sourceEditorDidChangeUndoState(_ sourceEditorViewController: Components.WKSourceEditorViewController, canUndo: Bool, canRedo: Bool) {
navigationItemController.undoButton.isEnabled = canUndo
navigationItemController.redoButton.isEnabled = canRedo
}

func sourceEditorViewControllerDidTapFind(sourceEditorViewController: WKSourceEditorViewController) {
func sourceEditorDidChangeText(_ sourceEditorViewController: Components.WKSourceEditorViewController, didChangeText: Bool) {
navigationItemController.progressButton.isEnabled = didChangeText
}

func sourceEditorViewControllerDidTapFind(_ sourceEditorViewController: WKSourceEditorViewController) {
showFocusNavigationView()
}

func sourceEditorViewControllerDidRemoveFindInputAccessoryView(sourceEditorViewController: Components.WKSourceEditorViewController) {
func sourceEditorViewControllerDidRemoveFindInputAccessoryView(_ sourceEditorViewController: Components.WKSourceEditorViewController) {
hideFocusNavigationView()
}


func sourceEditorViewControllerDidTapLink(parameters: WKSourceEditorFormatterLinkWizardParameters) {
guard let siteURL = pageURL.wmf_site else {
return
Expand Down Expand Up @@ -294,9 +308,11 @@ extension PageEditorViewController: SectionEditorNavigationItemControllerDelegat
}

func sectionEditorNavigationItemController(_ sectionEditorNavigationItemController: SectionEditorNavigationItemController, didTapUndoButton undoButton: UIBarButtonItem) {
sourceEditor.undo()
}

func sectionEditorNavigationItemController(_ sectionEditorNavigationItemController: SectionEditorNavigationItemController, didTapRedoButton redoButton: UIBarButtonItem) {
sourceEditor.redo()
}

func sectionEditorNavigationItemController(_ sectionEditorNavigationItemController: SectionEditorNavigationItemController, didTapReadingThemesControlsButton readingThemesControlsButton: UIBarButtonItem) {
Expand Down
2 changes: 1 addition & 1 deletion Wikipedia/Code/SectionEditorNavigationItemController.swift
Expand Up @@ -67,7 +67,7 @@ class SectionEditorNavigationItemController: NSObject, Themeable {
return BarButtonItem(title: CommonStrings.nextTitle, style: .done, target: self, action: #selector(progress(_:)), tintColorKeyPath: \Theme.colors.link)
}()

private lazy var redoButton: BarButtonItem = {
private(set) lazy var redoButton: BarButtonItem = {
return BarButtonItem(image: #imageLiteral(resourceName: "redo"), style: .plain, target: self, action: #selector(redo(_ :)), tintColorKeyPath: \Theme.colors.inputAccessoryButtonTint, accessibilityLabel: CommonStrings.redo)
}()

Expand Down
12 changes: 10 additions & 2 deletions WikipediaUITests/UITestHelperViewController.swift
Expand Up @@ -150,6 +150,14 @@ public class UITestHelperViewController: WKCanvasViewController {


extension UITestHelperViewController: WKSourceEditorViewControllerDelegate {
public func sourceEditorDidChangeUndoState(_ sourceEditorViewController: Components.WKSourceEditorViewController, canUndo: Bool, canRedo: Bool) {

}

public func sourceEditorDidChangeText(_ sourceEditorViewController: Components.WKSourceEditorViewController, didChangeText: Bool) {

}

public func sourceEditorViewControllerDidTapImage() {

}
Expand All @@ -158,11 +166,11 @@ extension UITestHelperViewController: WKSourceEditorViewControllerDelegate {

}

public func sourceEditorViewControllerDidRemoveFindInputAccessoryView(sourceEditorViewController: Components.WKSourceEditorViewController) {
public func sourceEditorViewControllerDidRemoveFindInputAccessoryView(_ sourceEditorViewController: Components.WKSourceEditorViewController) {

}

public func sourceEditorViewControllerDidTapFind(sourceEditorViewController: Components.WKSourceEditorViewController) {
public func sourceEditorViewControllerDidTapFind(_ sourceEditorViewController: Components.WKSourceEditorViewController) {

}

Expand Down

0 comments on commit 8e39b97

Please sign in to comment.