fix: handle typing in non editable paragraphs#97
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves cross-platform editing behavior around non-editable (read-only) paragraph blocks in the Enriched Text Input, aiming to make typing after read-only blocks and deleting read-only blocks behave more intuitively and consistently on iOS and Android.
Changes:
- iOS: add utilities to insert text after a read-only paragraph by auto-prepending a newline, and to delete an entire read-only paragraph in one backspace action.
- iOS: extend
ParagraphsUtilswith an “at end of read-only paragraph” detector and wire the new insertion/deletion behaviors intoUITextViewDelegate. - Android: adjust the non-editable paragraph input filter to allow insertion after a non-editable paragraph by prepending a newline, and add watcher logic to remove a non-editable paragraph span after a boundary backspace.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| ios/utils/Text/TextInsertionUtils.mm | Adds iOS helpers for inserting after / deleting read-only paragraphs. |
| ios/utils/Text/TextInsertionUtils.h | Exposes new iOS helper APIs. |
| ios/utils/Text/ParagraphsUtils.mm | Adds isAtEndOfReadOnlyParagraph detection. |
| ios/utils/Text/ParagraphsUtils.h | Declares new paragraph utility API. |
| ios/EnrichedTextInputView.mm | Integrates new iOS insertion/deletion behavior into text input delegate flow. |
| android/src/main/java/com/swmansion/enriched/watchers/EnrichedTextWatcher.kt | Tracks and removes a non-editable paragraph span after boundary deletions. |
| android/src/main/java/com/swmansion/enriched/inputFilters/NonEditableParagraphFilter.kt | Allows inserting after a non-editable paragraph by prepending a newline. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| NSRange readOnlyRange = NSMakeRange(0, 0); | ||
| id readOnly = [storage attribute:ReadOnlyParagraphKey | ||
| atIndex:range.location - 1 | ||
| effectiveRange:&readOnlyRange]; | ||
|
|
||
| if (readOnly == nil || NSMaxRange(readOnlyRange) < range.location) { | ||
| return NO; | ||
| } |
|
@IvanIhnatsiuk On web, when deleting a block from editor there is a confirmation dialog: Saga.19.mp4 |
|
@HelgaBabut We have already discussed this with Marius and decided to postpone it until the redesign of planning items. https://github.com/7Mountains/7m-mobile/issues/882. @Marius7Mountains could you confirm that? |
|
I think this is different from the redesign of the planning items, the first example a 2-step verification for deleting including option to also delete the task/planning item entirely everywhere (same as in https://github.com/7Mountains/7m-mobile/issues/882). The second (in the instance editor) is a 2-step verification when the user attempts to delete a block. @HelgaBabut , to be honest I haven't seen this 2-step verification before in the instance editor, is it a user group setting perhaps to turn on verification? |
I don't think there is any group permission, I checked for feature flag and group permissions and did not find anything related to this. Did you test with automation blocks in the linear instance? |
Summary
This pull request introduces improved handling for inserting and deleting text around non-editable (read-only) paragraphs in both Android and iOS implementations of the Enriched Text Input. The changes ensure a more intuitive user experience when interacting with non-editable content, such as allowing insertion of new lines after non-editable paragraphs and enabling deletion of entire non-editable paragraphs with a single backspace.
Android Enhancements:
getNonEditableSpanBeforeCursorto detect non-editable spans directly before the cursor, supporting the improved insertion logic.iOS Enhancements:
These changes improve the consistency and intuitiveness of editing text around non-editable paragraphs across platforms.
Test Plan
Provide clear steps so another contributor can reproduce the behavior or verify the feature works.
For example:
Screenshots / Videos
Screen.Recording.2026-06-04.at.01.05.12.mov
Screen.Recording.2026-06-04.at.01.06.59.mov
Compatibility