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

Native Editor - Add link and image support #4711

Merged
merged 18 commits into from
Jan 11, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class WKEditorToolbarButton: WKComponentView {
set {
button.isSelected = newValue
updateColors()
accessibilityTraits = newValue ? [.button, .selected] : [.button]
accessibilityTraits = button.accessibilityTraits
}
}

Expand All @@ -75,7 +75,7 @@ class WKEditorToolbarButton: WKComponentView {
set {
button.isEnabled = newValue
updateColors()
accessibilityTraits = newValue ? [.button, .selected] : [.button, .notEnabled]
accessibilityTraits = button.accessibilityTraits
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ protocol WKEditorToolbarExpandingViewDelegate: AnyObject {
func toolbarExpandingViewDidTapFind(toolbarView: WKEditorToolbarExpandingView)
func toolbarExpandingViewDidTapFormatText(toolbarView: WKEditorToolbarExpandingView)
func toolbarExpandingViewDidTapTemplate(toolbarView: WKEditorToolbarExpandingView, isSelected: Bool)
func toolbarExpandingViewDidTapLink(toolbarView: WKEditorToolbarExpandingView, isSelected: Bool)
func toolbarExpandingViewDidTapImage(toolbarView: WKEditorToolbarExpandingView)
func toolbarExpandingViewDidTapUnorderedList(toolbarView: WKEditorToolbarExpandingView, isSelected: Bool)
func toolbarExpandingViewDidTapOrderedList(toolbarView: WKEditorToolbarExpandingView, isSelected: Bool)
func toolbarExpandingViewDidTapIncreaseIndent(toolbarView: WKEditorToolbarExpandingView)
Expand Down Expand Up @@ -46,7 +48,7 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
@IBOutlet private weak var citationButton: WKEditorToolbarButton!
@IBOutlet private weak var linkButton: WKEditorToolbarButton!
@IBOutlet private weak var templateButton: WKEditorToolbarButton!
@IBOutlet private weak var mediaButton: WKEditorToolbarButton!
@IBOutlet private weak var imageButton: WKEditorToolbarButton!
@IBOutlet private weak var findInPageButton: WKEditorToolbarButton!

@IBOutlet private weak var unorderedListButton: WKEditorToolbarButton!
Expand Down Expand Up @@ -96,9 +98,9 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
templateButton.addTarget(self, action: #selector(tappedTemplate), for: .touchUpInside)
templateButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonTemplate

mediaButton.setImage(WKSFSymbolIcon.for(symbol: .photo), for: .normal)
mediaButton.addTarget(self, action: #selector(tappedMedia), for: .touchUpInside)
mediaButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonMedia
imageButton.setImage(WKSFSymbolIcon.for(symbol: .photo), for: .normal)
imageButton.addTarget(self, action: #selector(tappedMedia), for: .touchUpInside)
imageButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonMedia

findInPageButton.setImage(WKSFSymbolIcon.for(symbol: .docTextMagnifyingGlass), for: .normal)
findInPageButton.addTarget(self, action: #selector(tappedFindInPage), for: .touchUpInside)
Expand Down Expand Up @@ -137,6 +139,7 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {

cursorRightButton.setImage(WKIcon.chevronRight, for: .normal)
cursorRightButton.addTarget(self, action: #selector(tappedCursorRight), for: .touchUpInside)
cursorRightButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonCursorRight

NotificationCenter.default.addObserver(self, selector: #selector(updateButtonSelectionState(_:)), name: Notification.WKSourceEditorSelectionState, object: nil)
}
Expand All @@ -149,6 +152,8 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
}

templateButton.isSelected = selectionState.isHorizontalTemplate
linkButton.isSelected = selectionState.isSimpleLink
imageButton.isEnabled = !selectionState.isBold && !selectionState.isItalics && !selectionState.isSimpleLink

unorderedListButton.isSelected = selectionState.isBulletSingleList || selectionState.isBulletMultipleList
unorderedListButton.isEnabled = !selectionState.isNumberSingleList && !selectionState.isNumberMultipleList
Expand Down Expand Up @@ -223,6 +228,7 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
}

@objc private func tappedLink() {
delegate?.toolbarExpandingViewDidTapLink(toolbarView: self, isSelected: linkButton.isSelected)
}

@objc private func tappedUnorderedList() {
Expand Down Expand Up @@ -262,6 +268,7 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
}

@objc private func tappedMedia() {
delegate?.toolbarExpandingViewDidTapImage(toolbarView: self)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,9 @@
<outlet property="expandButton" destination="jLt-zh-HFv" id="LkK-4N-EDh"/>
<outlet property="findInPageButton" destination="ysd-bl-nOt" id="YnS-6B-WJp"/>
<outlet property="formatTextButton" destination="q5y-cw-4pq" id="EVV-8g-wME"/>
<outlet property="imageButton" destination="Oyz-BA-g0g" id="Gxu-b5-3Sp"/>
<outlet property="increaseIndentionButton" destination="YcQ-k6-ZuB" id="phQ-vm-eKH"/>
<outlet property="linkButton" destination="lOp-Bv-UED" id="I7F-zV-jom"/>
<outlet property="mediaButton" destination="Oyz-BA-g0g" id="Gxu-b5-3Sp"/>
<outlet property="orderedListButton" destination="Usg-R3-2O9" id="8Qf-xg-gjD"/>
<outlet property="primaryContainerView" destination="BWO-2h-I64" id="8BW-Xe-ftH"/>
<outlet property="scrollView" destination="ZnR-ux-s6T" id="cvF-Ya-s9R"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ protocol WKEditorToolbarHighlightViewDelegate: AnyObject {
func toolbarHighlightViewDidTapBold(toolbarView: WKEditorToolbarHighlightView, isSelected: Bool)
func toolbarHighlightViewDidTapItalics(toolbarView: WKEditorToolbarHighlightView, isSelected: Bool)
func toolbarHighlightViewDidTapTemplate(toolbarView: WKEditorToolbarHighlightView, isSelected: Bool)
func toolbarHighlightViewDidTapLink(toolbarView: WKEditorToolbarHighlightView, isSelected: Bool)
func toolbarHighlightViewDidTapShowMore(toolbarView: WKEditorToolbarHighlightView)
}

Expand Down Expand Up @@ -67,6 +68,7 @@ class WKEditorToolbarHighlightView: WKEditorToolbarView {
boldButton.isSelected = selectionState.isBold
italicsButton.isSelected = selectionState.isItalics
templateButton.isSelected = selectionState.isHorizontalTemplate
linkButton.isSelected = selectionState.isSimpleLink
}

// MARK: - Button Actions
Expand All @@ -86,6 +88,7 @@ class WKEditorToolbarHighlightView: WKEditorToolbarView {
}

@objc private func tappedLink() {
delegate?.toolbarHighlightViewDidTapLink(toolbarView: self, isSelected: linkButton.isSelected)
}

@objc private func tappedTemplate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ protocol WKEditorInputViewDelegate: AnyObject {
func didTapDecreaseIndent()
func didTapHeading(type: WKEditorInputView.HeadingButtonType)
func didTapStrikethrough(isSelected: Bool)
func didTapLink(isSelected: Bool)
}

class WKEditorInputView: WKComponentView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class WKEditorToolbarPlainView: WKEditorToolbarView {
boldButton.isSelected = selectionState.isBold
italicsButton.isSelected = selectionState.isItalics
templateButton.isSelected = selectionState.isHorizontalTemplate
linkButton.isSelected = selectionState.isSimpleLink
}

// MARK: Button Actions
Expand All @@ -78,5 +79,6 @@ class WKEditorToolbarPlainView: WKEditorToolbarView {
}

@objc private func tappedLink() {
delegate?.didTapLink(isSelected: linkButton.isSelected)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import Foundation
import ComponentsObjC

enum WKSourceEditorFormatterLinkButtonAction {
case edit
case insert
}

public struct WKSourceEditorFormatterLinkWizardParameters {
public let editPageTitle: String?
public let editPageLabel: String?
public let insertSearchTerm: String?
let preselectedTextRange: UITextRange
}

extension WKSourceEditorFormatterLink {

func linkWizardParameters(action: WKSourceEditorFormatterLinkButtonAction, in textView: UITextView) -> WKSourceEditorFormatterLinkWizardParameters? {

switch action {
case .edit:
expandSelectedRangeUpToNearestFormattingStrings(startingFormattingString: "[[", endingFormattingString: "]]", in: textView)

guard let selectedTextRange = textView.selectedTextRange,
let selectedText = textView.text(in: selectedTextRange) else {
return nil
}

let splitText = selectedText.split(separator: "|").map {String($0)}

switch splitText.count {
case 1:
return WKSourceEditorFormatterLinkWizardParameters(editPageTitle: splitText[0], editPageLabel: nil, insertSearchTerm: nil, preselectedTextRange: selectedTextRange)
case 2:
return WKSourceEditorFormatterLinkWizardParameters(editPageTitle: splitText[0], editPageLabel: splitText[1], insertSearchTerm: nil, preselectedTextRange: selectedTextRange)
default:
return nil
}

case .insert:

guard let selectedTextRange = textView.selectedTextRange,
let selectedText = textView.text(in: selectedTextRange) else {
return nil
}

return WKSourceEditorFormatterLinkWizardParameters(editPageTitle: nil, editPageLabel: nil, insertSearchTerm: selectedText, preselectedTextRange: selectedTextRange)
}


}

func insertLink(in textView: UITextView, pageTitle: String, preselectedTextRange: UITextRange) {
var content = "[[\(pageTitle)]]"

guard let selectedText = textView.text(in: preselectedTextRange) else {
return
}

if pageTitle != selectedText {
content = "[[\(pageTitle)|\(selectedText)]]"
}

textView.replace(preselectedTextRange, withText: content)

if let newStartPosition = textView.position(from: preselectedTextRange.start, offset: 2),
let newEndPosition = textView.position(from: preselectedTextRange.start, offset: content.count-2) {
textView.selectedTextRange = textView.textRange(from: newStartPosition, to: newEndPosition)
}

}

func editLink(in textView: UITextView, newPageTitle: String, newPageLabel: String?, preselectedTextRange: UITextRange) {
if let newPageLabel, !newPageLabel.isEmpty {
textView.replace(preselectedTextRange, withText: "\(newPageTitle)|\(newPageLabel)")
} else {
textView.replace(preselectedTextRange, withText: "\(newPageTitle)")
}
}

func removeLink(in textView: UITextView, preselectedTextRange: UITextRange) {

guard let selectedText = textView.text(in: preselectedTextRange) else {
return
}

if let markupStartPosition = textView.position(from: preselectedTextRange.start, offset: -2),
let markupEndPosition = textView.position(from: preselectedTextRange.end, offset: 2),
let newSelectedRange = textView.textRange(from: markupStartPosition, to: markupEndPosition) {
textView.replace(newSelectedRange, withText: selectedText)

if let newStartPosition = textView.position(from: preselectedTextRange.start, offset: -2),
let newEndPosition = textView.position(from: preselectedTextRange.end, offset: -2) {
textView.selectedTextRange = textView.textRange(from: newStartPosition, to: newEndPosition)
}
}
}

func insertImage(wikitext: String, in textView: UITextView) {

guard let selectedTextRange = textView.selectedTextRange else {
return
}

textView.replace(selectedTextRange, withText: wikitext)
}
}
Loading