Skip to content
Open
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,10 +64,7 @@ class ParametrizedStyles(
}

val spanEnd = start + text.length
val span = EnrichedInputLinkSpan(url, view.htmlStyle, true)
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(start, spanEnd)
spannable.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.forSpan(span))

applyManualLinkSpan(spannable, start, spanEnd, url)
view.selection?.validateStyles()
isSettingLinkSpan = false
}
Expand All @@ -93,6 +90,7 @@ class ParametrizedStyles(
startCursorPosition: Int,
endCursorPosition: Int,
) {
afterTextChangedManualLinks(startCursorPosition, endCursorPosition)
afterTextChangedLinks(startCursorPosition, endCursorPosition)
detectActiveMention(s, startCursorPosition)
}
Expand Down Expand Up @@ -246,6 +244,54 @@ class ParametrizedStyles(
return true
}

private fun afterTextChangedManualLinks(
editStart: Int,
editEnd: Int,
) {
if (isSettingLinkSpan) return
val spannable = view.text as? Spannable ?: return
if (spannable.subSequence(editStart, editEnd).none { it == '\n' || it == '\r' }) return

spannable
.getSpans(editStart, editEnd, EnrichedInputLinkSpan::class.java)
.filter { it.getIsManual() }
.forEach { splitManualLinkOnNewlines(spannable, it) }
}

private fun splitManualLinkOnNewlines(
spannable: Spannable,
span: EnrichedInputLinkSpan,
) {
val start = spannable.getSpanStart(span)
val end = spannable.getSpanEnd(span)
val url = span.getUrl()
spannable.removeSpan(span)

var runStart = start
for (i in start..end) {
if (i == end || spannable[i] == '\n' || spannable[i] == '\r') {
if (runStart < i) applyManualLinkSpan(spannable, runStart, i, url)
runStart = i + 1
}
}
}

private fun applyManualLinkSpan(
spannable: Spannable,
start: Int,
end: Int,
url: String,
) {
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(start, end)
val span = EnrichedInputLinkSpan(url, view.htmlStyle, true)
spannable.setSpan(
span,
safeStart,
safeEnd,
EnrichedSpanFlags.forSpan(span),
)
}

private fun afterTextChangedLinks(
editStart: Int,
editEnd: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class EnrichedSelection(
var start: Int = 0
var end: Int = 0

private var previousLinkDetectedEvent: MutableMap<String, String> = mutableMapOf("text" to "", "url" to "")
private var previousLinkDetectedEvent: MutableMap<String, String> =
mutableMapOf("text" to "", "url" to "", "start" to "", "end" to "")
private var previousMentionDetectedEvent: MutableMap<String, String> = mutableMapOf("text" to "", "payload" to "")

fun onSelection(
Expand Down Expand Up @@ -279,14 +280,24 @@ class EnrichedSelection(
val text = spannable.substring(start, end).replace(EnrichedConstants.ZWS_STRING, "")
val url = span?.getUrl() ?: ""

// Prevents emitting unnecessary events
if (text == previousLinkDetectedEvent["text"] && url == previousLinkDetectedEvent["url"]) return

previousLinkDetectedEvent.put("text", text)
previousLinkDetectedEvent.put("url", url)

val visibleStart = start - spannable.zwsCountBefore(start)
val visibleEnd = end - spannable.zwsCountBefore(end)
val visibleStartString = visibleStart.toString()
val visibleEndString = visibleEnd.toString()

// Prevents emitting unnecessary events
if (text == previousLinkDetectedEvent["text"] &&
url == previousLinkDetectedEvent["url"] &&
visibleStartString == previousLinkDetectedEvent["start"] &&
visibleEndString == previousLinkDetectedEvent["end"]
) {
return
}

previousLinkDetectedEvent["text"] = text
previousLinkDetectedEvent["url"] = url
previousLinkDetectedEvent["start"] = visibleStartString
previousLinkDetectedEvent["end"] = visibleEndString

val context = view.context as ReactContext
val surfaceId = UIManagerHelper.getSurfaceId(context)
Expand Down
6 changes: 5 additions & 1 deletion apps/example/src/hooks/useEditorState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ export function useEditorState() {
const [isImageModalOpen, setIsImageModalOpen] = useState(false);
const [isValueModalOpen, setIsValueModalOpen] = useState(false);
const [currentHtml, setCurrentHtml] = useState('');
const [selection, setSelection] = useState<Selection>();
const [selection, setSelection] = useState<Selection>({
start: 0,
end: 0,
text: '',
});
const [stylesState, setStylesState] = useState<StylesState>(DEFAULT_STYLES);
const [currentLink, setCurrentLink] =
useState<CurrentLinkState>(DEFAULT_LINK_STATE);
Expand Down
7 changes: 5 additions & 2 deletions ios/EnrichedTextInputView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1644,8 +1644,11 @@ - (void)manageSelectionBasedChanges {
[attributesManager
manageTypingAttributesWithOnlySelection:onlySelectionChanged];

// always update active styles
[self tryUpdatingActiveStyles];
// When text changed, anyTextMayHaveBeenModified runs tryUpdatingActiveStyles
if ([_recentInputString isEqualToString:currentString]) {
// update active styles
[self tryUpdatingActiveStyles];
}
Comment thread
kacperzolkiewski marked this conversation as resolved.
}

- (void)handleWordModificationBasedChanges:(NSString *)word
Expand Down
5 changes: 4 additions & 1 deletion ios/styles/LinkStyle.mm
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,10 @@ - (void)handleManualLinks:(NSString *)word inRange:(NSRange)wordRange {
if ([manualLinkMinValue isEqualToLinkData:manualLinkMaxValue]) {
NSRange newRange =
NSMakeRange(manualLinkMinIdx, manualLinkMaxIdx - manualLinkMinIdx + 1);
[self applyLinkMetaWithData:manualLinkMinValue range:newRange];
LinkData *updatedData = [manualLinkMinValue copy];
updatedData.text =
[self.host.textView.textStorage.string substringWithRange:newRange];
[self applyLinkMetaWithData:updatedData range:newRange];
[self.host.attributesManager addDirtyRange:newRange];
}
}
Expand Down
Loading