react-native-enriched 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/android/build.gradle +3 -3
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +1 -0
- package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.cpp +1 -1
- package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.h +1 -1
- package/{ios/generated/RNEnrichedTextInputViewSpec → android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec}/EventEmitters.cpp +31 -29
- package/{ios/generated/RNEnrichedTextInputViewSpec → android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec}/EventEmitters.h +22 -25
- package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.h +57 -0
- package/android/gradle.properties +5 -5
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewPackage.kt → ReactNativeEnrichedPackage.kt} +3 -2
- package/android/src/main/java/com/swmansion/enriched/{utils → common}/AsyncDrawable.kt +40 -8
- package/android/src/main/java/com/swmansion/enriched/common/CheckboxDrawable.kt +81 -0
- package/android/src/main/java/com/swmansion/enriched/{utils → common}/EnrichedConstants.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/common/EnrichedStyle.kt +57 -0
- package/android/src/main/java/com/swmansion/enriched/{spans/utils → common}/ForceRedrawSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/common/MentionStyle.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/{utils → common}/ResourceManager.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{utils → common/parser}/EnrichedParser.java +126 -99
- package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedSpanFactory.kt +79 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedBlockQuoteSpan.kt +9 -13
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBoldSpan.kt +12 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCheckboxListSpan.kt +91 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedCodeBlockSpan.kt +8 -12
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH1Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH2Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH3Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH4Span.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH5Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH6Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedImageSpan.kt +43 -38
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedInlineCodeSpan.kt +7 -11
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedItalicSpan.kt +12 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedLinkSpan.kt +7 -11
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedMentionSpan.kt +6 -10
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedOrderedListSpan.kt +12 -21
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedStrikeThroughSpan.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnderlineSpan.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedUnorderedListSpan.kt +9 -13
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedBlockSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedHeadingSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedInlineSpan.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedParagraphSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedSpan.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedZeroWidthSpaceSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputConnectionWrapper.kt → textinput/EnrichedTextInputConnectionWrapper.kt} +2 -2
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputSpannableFactory.kt +83 -0
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputView.kt → textinput/EnrichedTextInputView.kt} +87 -51
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewLayoutManager.kt → textinput/EnrichedTextInputViewLayoutManager.kt} +1 -1
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewManager.kt → textinput/EnrichedTextInputViewManager.kt} +24 -17
- package/android/src/main/java/com/swmansion/enriched/{MeasurementStore.kt → textinput/MeasurementStore.kt} +5 -4
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/MentionHandler.kt +2 -2
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeHtmlEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeSelectionEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeStateEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeTextEvent.kt +2 -2
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnInputBlurEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnInputFocusEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnInputKeyPressEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnLinkDetectedEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnMentionDetectedEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnMentionEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnPasteImagesEvent.kt +47 -0
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnRequestHtmlResultEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBlockQuoteSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBoldSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCheckboxListSpan.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCodeBlockSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH1Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH2Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH3Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH4Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH5Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH6Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputImageSpan.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputInlineCodeSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputItalicSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputLinkSpan.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputMentionSpan.kt +18 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputOrderedListSpan.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputStrikeThroughSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnderlineSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnorderedListSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → textinput/spans}/EnrichedSpans.kt +39 -30
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/interfaces/EnrichedInputSpan.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/HtmlStyle.kt +58 -43
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/InlineStyles.kt +4 -4
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ListStyles.kt +77 -26
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ParagraphStyles.kt +30 -25
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ParametrizedStyles.kt +19 -19
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedEditableFactory.kt +2 -2
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSelection.kt +15 -14
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSpanState.kt +15 -50
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSpannable.kt +3 -3
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSpannableStringBuilder.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/RichContentReceiver.kt +127 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/Utils.kt +106 -0
- package/android/src/main/java/com/swmansion/enriched/{watchers → textinput/watchers}/EnrichedSpanWatcher.kt +10 -10
- package/android/src/main/java/com/swmansion/enriched/{watchers → textinput/watchers}/EnrichedTextWatcher.kt +3 -3
- package/android/src/main/new_arch/CMakeLists.txt +1 -1
- package/android/src/main/new_arch/ReactNativeEnrichedSpec.cpp +11 -0
- package/android/src/main/new_arch/ReactNativeEnrichedSpec.h +15 -0
- package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputMeasurementManager.h +1 -1
- package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputShadowNode.h +2 -2
- package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/conversions.h +1 -1
- package/ios/EnrichedTextInputView.h +1 -0
- package/ios/EnrichedTextInputView.mm +274 -55
- package/ios/config/InputConfig.h +10 -0
- package/ios/config/InputConfig.mm +119 -0
- package/ios/extensions/ImageExtension.h +35 -0
- package/ios/extensions/ImageExtension.mm +156 -0
- package/ios/extensions/LayoutManagerExtension.mm +115 -95
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.cpp +1 -1
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.h +1 -1
- package/{android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec → ios/generated/ReactNativeEnrichedSpec}/EventEmitters.cpp +31 -29
- package/{android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec → ios/generated/ReactNativeEnrichedSpec}/EventEmitters.h +22 -25
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.h +57 -0
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/RCTComponentViewHelpers.h +21 -0
- package/ios/inputParser/InputParser.mm +135 -8
- package/ios/inputTextView/InputTextView.mm +118 -0
- package/ios/interfaces/ImageAttachment.h +1 -0
- package/ios/interfaces/ImageAttachment.mm +43 -4
- package/ios/interfaces/StyleHeaders.h +13 -2
- package/ios/interfaces/StyleTypeEnum.h +1 -0
- package/ios/internals/EnrichedTextInputViewState.cpp +6 -6
- package/ios/styles/CheckboxListStyle.mm +321 -0
- package/ios/styles/H1Style.mm +3 -0
- package/ios/styles/H2Style.mm +3 -0
- package/ios/styles/H3Style.mm +3 -0
- package/ios/styles/H4Style.mm +3 -0
- package/ios/styles/H5Style.mm +3 -0
- package/ios/styles/H6Style.mm +3 -0
- package/ios/styles/HeadingStyleBase.mm +150 -78
- package/ios/utils/CheckboxHitTestUtils.h +10 -0
- package/ios/utils/CheckboxHitTestUtils.mm +123 -0
- package/ios/utils/ParagraphAttributesUtils.mm +83 -53
- package/ios/utils/TextBlockTapGestureRecognizer.h +17 -0
- package/ios/utils/TextBlockTapGestureRecognizer.mm +56 -0
- package/ios/utils/ZeroWidthSpaceUtils.mm +14 -3
- package/lib/module/EnrichedTextInput.js +36 -11
- package/lib/module/EnrichedTextInput.js.map +1 -1
- package/lib/module/{EnrichedTextInputNativeComponent.ts → spec/EnrichedTextInputNativeComponent.ts} +40 -9
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/normalizeHtmlStyle.js +6 -0
- package/lib/module/utils/normalizeHtmlStyle.js.map +1 -1
- package/lib/module/utils/nullthrows.js +9 -0
- package/lib/module/utils/nullthrows.js.map +1 -0
- package/lib/typescript/src/EnrichedTextInput.d.ts +9 -49
- package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/{EnrichedTextInputNativeComponent.d.ts → spec/EnrichedTextInputNativeComponent.d.ts} +33 -8
- package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +58 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +2 -2
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -1
- package/lib/typescript/src/utils/nullthrows.d.ts +2 -0
- package/lib/typescript/src/utils/nullthrows.d.ts.map +1 -0
- package/lib/typescript/src/utils/regexParser.d.ts +1 -1
- package/lib/typescript/src/utils/regexParser.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/EnrichedTextInput.tsx +49 -62
- package/src/index.tsx +3 -1
- package/src/{EnrichedTextInputNativeComponent.ts → spec/EnrichedTextInputNativeComponent.ts} +40 -9
- package/src/types.ts +59 -0
- package/src/utils/normalizeHtmlStyle.ts +8 -5
- package/src/utils/nullthrows.ts +7 -0
- package/src/utils/regexParser.ts +1 -1
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateDeprecatedEvent.kt +0 -21
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +0 -17
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +0 -16
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +0 -15
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +0 -15
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +0 -3
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +0 -9
- package/android/src/main/java/com/swmansion/enriched/utils/Utils.kt +0 -21
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +0 -22
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +0 -26
- package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +0 -1
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.cpp +0 -0
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.cpp +0 -0
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.h +0 -0
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.cpp +0 -0
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.h +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputComponentDescriptor.h +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputMeasurementManager.cpp +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputShadowNode.cpp +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputState.cpp +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputState.h +0 -0
- /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.cpp +0 -0
- /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.cpp +0 -0
- /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.h +0 -0
- /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.cpp +0 -0
- /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.h +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#import "EnrichedTextInputView.h"
|
|
2
2
|
#import "FontExtension.h"
|
|
3
3
|
#import "OccurenceUtils.h"
|
|
4
|
+
#import "ParagraphsUtils.h"
|
|
4
5
|
#import "StyleHeaders.h"
|
|
5
6
|
#import "TextInsertionUtils.h"
|
|
6
7
|
|
|
@@ -13,6 +14,9 @@
|
|
|
13
14
|
- (CGFloat)getHeadingFontSize {
|
|
14
15
|
return 0;
|
|
15
16
|
}
|
|
17
|
+
- (NSString *)getHeadingLevelString {
|
|
18
|
+
return @"";
|
|
19
|
+
}
|
|
16
20
|
- (BOOL)isHeadingBold {
|
|
17
21
|
return false;
|
|
18
22
|
}
|
|
@@ -27,7 +31,6 @@
|
|
|
27
31
|
- (instancetype)initWithInput:(id)input {
|
|
28
32
|
self = [super init];
|
|
29
33
|
self->input = input;
|
|
30
|
-
_lastAppliedFontSize = 0.0;
|
|
31
34
|
return self;
|
|
32
35
|
}
|
|
33
36
|
|
|
@@ -41,20 +44,50 @@
|
|
|
41
44
|
} else {
|
|
42
45
|
isStylePresent ? [self removeTypingAttributes] : [self addTypingAttributes];
|
|
43
46
|
}
|
|
44
|
-
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
- (NSTextList *)getTextListObject {
|
|
50
|
+
return [[NSTextList alloc]
|
|
51
|
+
initWithMarkerFormat:[NSString
|
|
52
|
+
stringWithFormat:@"{heading:%@}",
|
|
53
|
+
[self getHeadingLevelString]]
|
|
54
|
+
options:0];
|
|
45
55
|
}
|
|
46
56
|
|
|
47
57
|
// the range will already be the proper full paragraph/s range
|
|
48
58
|
- (void)addAttributes:(NSRange)range withTypingAttr:(BOOL)withTypingAttr {
|
|
49
|
-
[
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
NSTextList *textListMarker = [self getTextListObject];
|
|
60
|
+
NSArray *paragraphs =
|
|
61
|
+
[ParagraphsUtils getSeparateParagraphsRangesIn:[self typedInput]->textView
|
|
62
|
+
range:range];
|
|
63
|
+
for (NSValue *value in paragraphs) {
|
|
64
|
+
NSRange paragraphRange = [value rangeValue];
|
|
65
|
+
|
|
66
|
+
[[self typedInput]->textView.textStorage
|
|
67
|
+
enumerateAttribute:NSParagraphStyleAttributeName
|
|
68
|
+
inRange:paragraphRange
|
|
69
|
+
options:0
|
|
70
|
+
usingBlock:^(id _Nullable value, NSRange range,
|
|
71
|
+
BOOL *_Nonnull stop) {
|
|
72
|
+
NSMutableParagraphStyle *pStyle =
|
|
73
|
+
[(NSParagraphStyle *)value mutableCopy];
|
|
74
|
+
pStyle.textLists = @[ textListMarker ];
|
|
75
|
+
[[self typedInput]->textView.textStorage
|
|
76
|
+
addAttribute:NSParagraphStyleAttributeName
|
|
77
|
+
value:pStyle
|
|
78
|
+
range:range];
|
|
79
|
+
}];
|
|
80
|
+
|
|
81
|
+
[[self typedInput]->textView.textStorage
|
|
82
|
+
enumerateAttribute:NSFontAttributeName
|
|
83
|
+
inRange:paragraphRange
|
|
84
|
+
options:0
|
|
85
|
+
usingBlock:^(id _Nullable value, NSRange range,
|
|
86
|
+
BOOL *_Nonnull stop) {
|
|
87
|
+
UIFont *font = (UIFont *)value;
|
|
88
|
+
if (font == nullptr) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
58
91
|
UIFont *newFont = [font setSize:[self getHeadingFontSize]];
|
|
59
92
|
if ([self isHeadingBold]) {
|
|
60
93
|
newFont = [newFont setBold];
|
|
@@ -63,9 +96,8 @@
|
|
|
63
96
|
addAttribute:NSFontAttributeName
|
|
64
97
|
value:newFont
|
|
65
98
|
range:range];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
[[self typedInput]->textView.textStorage endEditing];
|
|
99
|
+
}];
|
|
100
|
+
}
|
|
69
101
|
|
|
70
102
|
// also toggle typing attributes
|
|
71
103
|
if (withTypingAttr) {
|
|
@@ -76,34 +108,57 @@
|
|
|
76
108
|
// will always be called on empty paragraphs so only typing attributes can be
|
|
77
109
|
// changed
|
|
78
110
|
- (void)addTypingAttributes {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
111
|
+
NSMutableDictionary *newTypingAttrs =
|
|
112
|
+
[[self typedInput]->textView.typingAttributes mutableCopy];
|
|
113
|
+
|
|
114
|
+
NSMutableParagraphStyle *pStyle =
|
|
115
|
+
[newTypingAttrs[NSParagraphStyleAttributeName] mutableCopy];
|
|
116
|
+
if (pStyle != nullptr) {
|
|
117
|
+
pStyle.textLists = @[ [self getTextListObject] ];
|
|
118
|
+
newTypingAttrs[NSParagraphStyleAttributeName] = pStyle;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
UIFont *currentFontAttr = (UIFont *)newTypingAttrs[NSFontAttributeName];
|
|
82
122
|
if (currentFontAttr != nullptr) {
|
|
83
|
-
NSMutableDictionary *newTypingAttrs =
|
|
84
|
-
[[self typedInput]->textView.typingAttributes mutableCopy];
|
|
85
123
|
UIFont *newFont = [currentFontAttr setSize:[self getHeadingFontSize]];
|
|
86
124
|
if ([self isHeadingBold]) {
|
|
87
125
|
newFont = [newFont setBold];
|
|
88
126
|
}
|
|
89
127
|
newTypingAttrs[NSFontAttributeName] = newFont;
|
|
90
|
-
[self typedInput]->textView.typingAttributes = newTypingAttrs;
|
|
91
128
|
}
|
|
129
|
+
|
|
130
|
+
[self typedInput]->textView.typingAttributes = newTypingAttrs;
|
|
92
131
|
}
|
|
93
132
|
|
|
94
133
|
// we need to remove the style from the whole paragraph
|
|
95
134
|
- (void)removeAttributes:(NSRange)range {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
135
|
+
NSArray *paragraphs =
|
|
136
|
+
[ParagraphsUtils getSeparateParagraphsRangesIn:[self typedInput]->textView
|
|
137
|
+
range:range];
|
|
138
|
+
|
|
139
|
+
for (NSValue *value in paragraphs) {
|
|
140
|
+
NSRange paragraphRange = [value rangeValue];
|
|
141
|
+
[[self typedInput]->textView.textStorage
|
|
142
|
+
enumerateAttribute:NSParagraphStyleAttributeName
|
|
143
|
+
inRange:paragraphRange
|
|
144
|
+
options:0
|
|
145
|
+
usingBlock:^(id _Nullable value, NSRange range,
|
|
146
|
+
BOOL *_Nonnull stop) {
|
|
147
|
+
NSMutableParagraphStyle *pStyle =
|
|
148
|
+
[(NSParagraphStyle *)value mutableCopy];
|
|
149
|
+
pStyle.textLists = @[];
|
|
150
|
+
[[self typedInput]->textView.textStorage
|
|
151
|
+
addAttribute:NSParagraphStyleAttributeName
|
|
152
|
+
value:pStyle
|
|
153
|
+
range:range];
|
|
154
|
+
}];
|
|
155
|
+
|
|
156
|
+
[[self typedInput]->textView.textStorage
|
|
157
|
+
enumerateAttribute:NSFontAttributeName
|
|
158
|
+
inRange:paragraphRange
|
|
159
|
+
options:0
|
|
160
|
+
usingBlock:^(id _Nullable value, NSRange range,
|
|
161
|
+
BOOL *_Nonnull stop) {
|
|
107
162
|
UIFont *newFont = [(UIFont *)value
|
|
108
163
|
setSize:[[[self typedInput]->config scaledPrimaryFontSize]
|
|
109
164
|
floatValue]];
|
|
@@ -114,60 +169,57 @@
|
|
|
114
169
|
addAttribute:NSFontAttributeName
|
|
115
170
|
value:newFont
|
|
116
171
|
range:range];
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
[[self typedInput]->textView.textStorage endEditing];
|
|
172
|
+
}];
|
|
173
|
+
}
|
|
120
174
|
|
|
121
175
|
// typing attributes still need to be removed
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
176
|
+
NSMutableDictionary *newTypingAttrs =
|
|
177
|
+
[[self typedInput]->textView.typingAttributes mutableCopy];
|
|
178
|
+
|
|
179
|
+
NSMutableParagraphStyle *pStyle =
|
|
180
|
+
[newTypingAttrs[NSParagraphStyleAttributeName] mutableCopy];
|
|
181
|
+
if (pStyle != nullptr) {
|
|
182
|
+
pStyle.textLists = @[];
|
|
183
|
+
newTypingAttrs[NSParagraphStyleAttributeName] = pStyle;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
UIFont *currentFontAttr = (UIFont *)newTypingAttrs[NSFontAttributeName];
|
|
125
187
|
if (currentFontAttr != nullptr) {
|
|
126
|
-
NSMutableDictionary *newTypingAttrs =
|
|
127
|
-
[[self typedInput]->textView.typingAttributes mutableCopy];
|
|
128
188
|
UIFont *newFont = [currentFontAttr
|
|
129
189
|
setSize:[[[self typedInput]->config scaledPrimaryFontSize] floatValue]];
|
|
130
190
|
if ([self isHeadingBold]) {
|
|
131
191
|
newFont = [newFont removeBold];
|
|
132
192
|
}
|
|
133
193
|
newTypingAttrs[NSFontAttributeName] = newFont;
|
|
134
|
-
[self typedInput]->textView.typingAttributes = newTypingAttrs;
|
|
135
194
|
}
|
|
195
|
+
|
|
196
|
+
[self typedInput]->textView.typingAttributes = newTypingAttrs;
|
|
136
197
|
}
|
|
137
198
|
|
|
138
199
|
- (void)removeTypingAttributes {
|
|
139
|
-
//
|
|
140
|
-
// called in conflicting styles logic
|
|
141
|
-
// there as well
|
|
200
|
+
// All the heading still needs to be removed because this function may be
|
|
201
|
+
// called in conflicting styles logic. Typing attributes already get removed
|
|
202
|
+
// in there as well.
|
|
142
203
|
[self removeAttributes:[self typedInput]->textView.selectedRange];
|
|
143
204
|
}
|
|
144
205
|
|
|
145
|
-
// when the traits already change, the getHeadginFontSize will return the new
|
|
146
|
-
// font size and no headings would be properly detected, so that's why we have
|
|
147
|
-
// to use the latest applied font size rather than that value.
|
|
148
206
|
- (BOOL)styleCondition:(id _Nullable)value range:(NSRange)range {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if (self.lastAppliedFontSize > 0.0) {
|
|
155
|
-
return font.pointSize == self.lastAppliedFontSize;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return font.pointSize == [self getHeadingFontSize];
|
|
207
|
+
NSParagraphStyle *paragraph = (NSParagraphStyle *)value;
|
|
208
|
+
return paragraph != nullptr && paragraph.textLists.count == 1 &&
|
|
209
|
+
[paragraph.textLists.firstObject.markerFormat
|
|
210
|
+
isEqualToString:[self getTextListObject].markerFormat];
|
|
159
211
|
}
|
|
160
212
|
|
|
161
213
|
- (BOOL)detectStyle:(NSRange)range {
|
|
162
214
|
if (range.length >= 1) {
|
|
163
|
-
return [OccurenceUtils detect:
|
|
215
|
+
return [OccurenceUtils detect:NSParagraphStyleAttributeName
|
|
164
216
|
withInput:[self typedInput]
|
|
165
217
|
inRange:range
|
|
166
218
|
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
167
219
|
return [self styleCondition:value range:range];
|
|
168
220
|
}];
|
|
169
221
|
} else {
|
|
170
|
-
return [OccurenceUtils detect:
|
|
222
|
+
return [OccurenceUtils detect:NSParagraphStyleAttributeName
|
|
171
223
|
withInput:[self typedInput]
|
|
172
224
|
atIndex:range.location
|
|
173
225
|
checkPrevious:YES
|
|
@@ -178,7 +230,7 @@
|
|
|
178
230
|
}
|
|
179
231
|
|
|
180
232
|
- (BOOL)anyOccurence:(NSRange)range {
|
|
181
|
-
return [OccurenceUtils any:
|
|
233
|
+
return [OccurenceUtils any:NSParagraphStyleAttributeName
|
|
182
234
|
withInput:[self typedInput]
|
|
183
235
|
inRange:range
|
|
184
236
|
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
@@ -187,7 +239,7 @@
|
|
|
187
239
|
}
|
|
188
240
|
|
|
189
241
|
- (NSArray<StylePair *> *_Nullable)findAllOccurences:(NSRange)range {
|
|
190
|
-
return [OccurenceUtils all:
|
|
242
|
+
return [OccurenceUtils all:NSParagraphStyleAttributeName
|
|
191
243
|
withInput:[self typedInput]
|
|
192
244
|
inRange:range
|
|
193
245
|
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
@@ -208,31 +260,51 @@
|
|
|
208
260
|
additionalAttributes:nullptr
|
|
209
261
|
input:[self typedInput]
|
|
210
262
|
withSelection:YES];
|
|
211
|
-
// remove the
|
|
263
|
+
// remove the attributes at the new selection
|
|
212
264
|
[self removeAttributes:[self typedInput]->textView.selectedRange];
|
|
213
265
|
return YES;
|
|
214
266
|
}
|
|
215
267
|
return NO;
|
|
216
268
|
}
|
|
217
269
|
|
|
218
|
-
//
|
|
219
|
-
// text
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
for (StylePair *pair in occurences) {
|
|
226
|
-
NSRange occurenceRange = [pair.rangeValue rangeValue];
|
|
227
|
-
NSRange paragraphRange = [[self typedInput]->textView.textStorage.string
|
|
228
|
-
paragraphRangeForRange:occurenceRange];
|
|
229
|
-
if (!NSEqualRanges(occurenceRange, paragraphRange)) {
|
|
230
|
-
// we have a heading but it does not span its whole paragraph - let's fix
|
|
231
|
-
// it
|
|
232
|
-
[self addAttributes:paragraphRange withTypingAttr:NO];
|
|
233
|
-
}
|
|
270
|
+
// Backspacing a line after a heading "into" a heading will not result in the
|
|
271
|
+
// text not receiving heading font attributes.
|
|
272
|
+
// Hence, we fix these attributes then.
|
|
273
|
+
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text {
|
|
274
|
+
// Must be a backspace.
|
|
275
|
+
if (text.length != 0) {
|
|
276
|
+
return NO;
|
|
234
277
|
}
|
|
235
|
-
|
|
278
|
+
|
|
279
|
+
// Backspace must have removed a newline character.
|
|
280
|
+
NSString *removedString =
|
|
281
|
+
[[self typedInput]->textView.textStorage.string substringWithRange:range];
|
|
282
|
+
if ([removedString
|
|
283
|
+
rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]]
|
|
284
|
+
.location == NSNotFound) {
|
|
285
|
+
return NO;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Heading style must have been present in a paragraph before the backspaced
|
|
289
|
+
// range.
|
|
290
|
+
NSRange paragraphBeforeBackspaceRange =
|
|
291
|
+
[[self typedInput]->textView.textStorage.string
|
|
292
|
+
paragraphRangeForRange:NSMakeRange(range.location, 0)];
|
|
293
|
+
if (![self detectStyle:paragraphBeforeBackspaceRange]) {
|
|
294
|
+
return NO;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Manually do the replacing.
|
|
298
|
+
[TextInsertionUtils replaceText:text
|
|
299
|
+
at:range
|
|
300
|
+
additionalAttributes:nullptr
|
|
301
|
+
input:[self typedInput]
|
|
302
|
+
withSelection:YES];
|
|
303
|
+
// Reapply attributes at the beginning of the backspaced range (it will cover
|
|
304
|
+
// the whole paragraph properly).
|
|
305
|
+
[self addAttributes:NSMakeRange(range.location, 0) withTypingAttr:YES];
|
|
306
|
+
|
|
307
|
+
return YES;
|
|
236
308
|
}
|
|
237
309
|
|
|
238
310
|
@end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#import "CheckboxHitTestUtils.h"
|
|
2
|
+
#import "EnrichedTextInputView.h"
|
|
3
|
+
#import "InputConfig.h"
|
|
4
|
+
#import "StyleHeaders.h"
|
|
5
|
+
|
|
6
|
+
static const CGFloat kCheckboxHitSlopLeft = 8.0;
|
|
7
|
+
static const CGFloat kCheckboxHitSlopVertical = 6.0;
|
|
8
|
+
|
|
9
|
+
@implementation CheckboxHitTestUtils
|
|
10
|
+
|
|
11
|
+
// MARK: - Coordinate helpers
|
|
12
|
+
|
|
13
|
+
+ (CGPoint)containerPointFromViewPoint:(CGPoint)point
|
|
14
|
+
textView:(UITextView *)textView {
|
|
15
|
+
return CGPointMake(point.x - textView.textContainerInset.left,
|
|
16
|
+
point.y - textView.textContainerInset.top);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// MARK: - Glyph lookup
|
|
20
|
+
|
|
21
|
+
+ (NSUInteger)glyphIndexAtContainerPoint:(CGPoint)point
|
|
22
|
+
textView:(UITextView *)textView {
|
|
23
|
+
return [textView.layoutManager glyphIndexForPoint:point
|
|
24
|
+
inTextContainer:textView.textContainer
|
|
25
|
+
fractionOfDistanceThroughGlyph:nil];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// MARK: - Checkbox detection
|
|
29
|
+
|
|
30
|
+
+ (BOOL)isCheckboxGlyph:(NSUInteger)glyphIndex
|
|
31
|
+
inInput:(EnrichedTextInputView *)input {
|
|
32
|
+
UITextView *textView = input->textView;
|
|
33
|
+
NSLayoutManager *layoutManager = textView.layoutManager;
|
|
34
|
+
NSTextStorage *storage = textView.textStorage;
|
|
35
|
+
|
|
36
|
+
NSUInteger charIndex =
|
|
37
|
+
[layoutManager characterIndexForGlyphAtIndex:glyphIndex];
|
|
38
|
+
|
|
39
|
+
if (charIndex >= storage.length) {
|
|
40
|
+
return NO;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
CheckboxListStyle *checkboxListStyle =
|
|
44
|
+
(CheckboxListStyle *)
|
|
45
|
+
input->stylesDict[@([CheckboxListStyle getStyleType])];
|
|
46
|
+
|
|
47
|
+
if (!checkboxListStyle) {
|
|
48
|
+
return NO;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return [checkboxListStyle detectStyle:NSMakeRange(charIndex, 0)];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// MARK: - Checkbox rect
|
|
55
|
+
|
|
56
|
+
+ (CGRect)checkboxRectForGlyphIndex:(NSUInteger)glyphIndex
|
|
57
|
+
inInput:(EnrichedTextInputView *)input {
|
|
58
|
+
UITextView *textView = input->textView;
|
|
59
|
+
NSLayoutManager *layoutManager = textView.layoutManager;
|
|
60
|
+
InputConfig *config = input->config;
|
|
61
|
+
|
|
62
|
+
if (!config) {
|
|
63
|
+
return CGRectNull;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
CGRect lineRect = [layoutManager lineFragmentRectForGlyphAtIndex:glyphIndex
|
|
67
|
+
effectiveRange:nil];
|
|
68
|
+
|
|
69
|
+
CGFloat originX = lineRect.origin.x + config.checkboxListMarginLeft;
|
|
70
|
+
|
|
71
|
+
CGFloat originY = lineRect.origin.y +
|
|
72
|
+
(lineRect.size.height - config.checkboxListBoxSize) / 2.0;
|
|
73
|
+
|
|
74
|
+
return CGRectMake(originX, originY, config.checkboxListBoxSize,
|
|
75
|
+
config.checkboxListBoxSize);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// MARK: - Hit rect
|
|
79
|
+
|
|
80
|
+
+ (CGRect)expandedHitRectFromCheckboxRect:(CGRect)rect {
|
|
81
|
+
if (CGRectIsNull(rect))
|
|
82
|
+
return rect;
|
|
83
|
+
|
|
84
|
+
return CGRectInset(rect, -kCheckboxHitSlopLeft, -kCheckboxHitSlopVertical);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// MARK: - Public API
|
|
88
|
+
|
|
89
|
+
+ (NSInteger)hitTestCheckboxAtPoint:(CGPoint)point
|
|
90
|
+
inInput:(EnrichedTextInputView *)input {
|
|
91
|
+
UITextView *textView = input->textView;
|
|
92
|
+
|
|
93
|
+
CGPoint containerPoint = [self containerPointFromViewPoint:point
|
|
94
|
+
textView:textView];
|
|
95
|
+
|
|
96
|
+
NSUInteger glyphIndex = [self glyphIndexAtContainerPoint:containerPoint
|
|
97
|
+
textView:textView];
|
|
98
|
+
|
|
99
|
+
if (glyphIndex == NSNotFound) {
|
|
100
|
+
return -1;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (![self isCheckboxGlyph:glyphIndex inInput:input]) {
|
|
104
|
+
return -1;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
CGRect checkboxRect = [self checkboxRectForGlyphIndex:glyphIndex
|
|
108
|
+
inInput:input];
|
|
109
|
+
|
|
110
|
+
if (CGRectIsNull(checkboxRect)) {
|
|
111
|
+
return -1;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
CGRect hitRect = [self expandedHitRectFromCheckboxRect:checkboxRect];
|
|
115
|
+
|
|
116
|
+
if (!CGRectContainsPoint(hitRect, containerPoint)) {
|
|
117
|
+
return -1;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return [textView.layoutManager characterIndexForGlyphAtIndex:glyphIndex];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@end
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
typedInput->stylesDict[@([BlockQuoteStyle getStyleType])];
|
|
23
23
|
CodeBlockStyle *cbStyle =
|
|
24
24
|
typedInput->stylesDict[@([CodeBlockStyle getStyleType])];
|
|
25
|
+
CheckboxListStyle *cbLStyle =
|
|
26
|
+
typedInput->stylesDict[@([CheckboxListStyle getStyleType])];
|
|
25
27
|
|
|
26
28
|
if (typedInput == nullptr) {
|
|
27
29
|
return NO;
|
|
@@ -57,17 +59,35 @@
|
|
|
57
59
|
// applied
|
|
58
60
|
// - reapply the paragraph style that was present so that a zero width space
|
|
59
61
|
// appears here
|
|
60
|
-
NSArray *handledStyles = @[ ulStyle, olStyle, bqStyle, cbStyle ];
|
|
62
|
+
NSArray *handledStyles = @[ ulStyle, olStyle, bqStyle, cbStyle, cbLStyle ];
|
|
61
63
|
for (id<BaseStyleProtocol> style in handledStyles) {
|
|
62
64
|
if ([style detectStyle:nonNewlineRange]) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
// For checkbox lists, preserve the current checked state
|
|
66
|
+
if (style == cbLStyle) {
|
|
67
|
+
BOOL isCurrentlyChecked =
|
|
68
|
+
[cbLStyle getCheckboxStateAt:range.location];
|
|
69
|
+
[TextInsertionUtils replaceText:text
|
|
70
|
+
at:range
|
|
71
|
+
additionalAttributes:nullptr
|
|
72
|
+
input:typedInput
|
|
73
|
+
withSelection:YES];
|
|
74
|
+
typedInput->textView.typingAttributes =
|
|
75
|
+
typedInput->defaultTypingAttributes;
|
|
76
|
+
[cbLStyle addAttributesWithCheckedValue:isCurrentlyChecked
|
|
77
|
+
inRange:NSMakeRange(range.location, 0)
|
|
78
|
+
withTypingAttr:YES];
|
|
79
|
+
} else {
|
|
80
|
+
[TextInsertionUtils replaceText:text
|
|
81
|
+
at:range
|
|
82
|
+
additionalAttributes:nullptr
|
|
83
|
+
input:typedInput
|
|
84
|
+
withSelection:YES];
|
|
85
|
+
typedInput->textView.typingAttributes =
|
|
86
|
+
typedInput->defaultTypingAttributes;
|
|
87
|
+
[style addAttributes:NSMakeRange(range.location, 0)
|
|
88
|
+
withTypingAttr:YES];
|
|
89
|
+
}
|
|
90
|
+
|
|
71
91
|
return YES;
|
|
72
92
|
}
|
|
73
93
|
}
|
|
@@ -116,63 +136,73 @@
|
|
|
116
136
|
return NO;
|
|
117
137
|
}
|
|
118
138
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
139
|
+
// Must be a backspace.
|
|
140
|
+
if (text.length > 0) {
|
|
141
|
+
return NO;
|
|
142
|
+
}
|
|
122
143
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
144
|
+
// Backspace must have removed a newline character.
|
|
145
|
+
NSString *removedString =
|
|
146
|
+
[typedInput->textView.textStorage.string substringWithRange:range];
|
|
147
|
+
if ([removedString
|
|
148
|
+
rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]]
|
|
149
|
+
.location == NSNotFound) {
|
|
150
|
+
return NO;
|
|
151
|
+
}
|
|
130
152
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
153
|
+
NSRange leftRange = [typedInput->textView.textStorage.string
|
|
154
|
+
paragraphRangeForRange:NSMakeRange(range.location, 0)];
|
|
134
155
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
156
|
+
id<BaseStyleProtocol> leftParagraphStyle = nullptr;
|
|
157
|
+
for (NSNumber *key in typedInput->stylesDict) {
|
|
158
|
+
id<BaseStyleProtocol> style = typedInput->stylesDict[key];
|
|
159
|
+
if ([[style class] isParagraphStyle] && [style detectStyle:leftRange]) {
|
|
160
|
+
leftParagraphStyle = style;
|
|
139
161
|
}
|
|
162
|
+
}
|
|
140
163
|
|
|
141
|
-
|
|
142
|
-
|
|
164
|
+
if (leftParagraphStyle == nullptr) {
|
|
165
|
+
return NO;
|
|
166
|
+
}
|
|
143
167
|
|
|
144
|
-
|
|
168
|
+
// index out of bounds
|
|
169
|
+
NSUInteger rightRangeStart = range.location + range.length;
|
|
170
|
+
if (rightRangeStart >= typedInput->textView.textStorage.string.length) {
|
|
171
|
+
return NO;
|
|
172
|
+
}
|
|
145
173
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
range:rightRange];
|
|
149
|
-
NSArray *blockingStyles =
|
|
150
|
-
[typedInput getPresentStyleTypesFrom:typedInput->blockingStyles[@(type)]
|
|
151
|
-
range:rightRange];
|
|
152
|
-
NSArray *allToBeRemoved =
|
|
153
|
-
[conflictingStyles arrayByAddingObjectsFromArray:blockingStyles];
|
|
174
|
+
NSRange rightRange = [typedInput->textView.textStorage.string
|
|
175
|
+
paragraphRangeForRange:NSMakeRange(rightRangeStart, 1)];
|
|
154
176
|
|
|
155
|
-
|
|
156
|
-
id<BaseStyleProtocol> styleClass = typedInput->stylesDict[style];
|
|
177
|
+
StyleType type = [[leftParagraphStyle class] getStyleType];
|
|
157
178
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
179
|
+
NSArray *conflictingStyles = [typedInput
|
|
180
|
+
getPresentStyleTypesFrom:typedInput->conflictingStyles[@(type)]
|
|
181
|
+
range:rightRange];
|
|
182
|
+
NSArray *blockingStyles =
|
|
183
|
+
[typedInput getPresentStyleTypesFrom:typedInput->blockingStyles[@(type)]
|
|
184
|
+
range:rightRange];
|
|
185
|
+
NSArray *allToBeRemoved =
|
|
186
|
+
[conflictingStyles arrayByAddingObjectsFromArray:blockingStyles];
|
|
161
187
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
}
|
|
188
|
+
for (NSNumber *style in allToBeRemoved) {
|
|
189
|
+
id<BaseStyleProtocol> styleClass = typedInput->stylesDict[style];
|
|
166
190
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
191
|
+
// for ranges, we need to remove each occurence
|
|
192
|
+
NSArray<StylePair *> *allOccurences =
|
|
193
|
+
[styleClass findAllOccurences:rightRange];
|
|
194
|
+
|
|
195
|
+
for (StylePair *pair in allOccurences) {
|
|
196
|
+
[styleClass removeAttributes:[pair.rangeValue rangeValue]];
|
|
197
|
+
}
|
|
173
198
|
}
|
|
174
199
|
|
|
175
|
-
|
|
200
|
+
[TextInsertionUtils replaceText:text
|
|
201
|
+
at:range
|
|
202
|
+
additionalAttributes:nullptr
|
|
203
|
+
input:typedInput
|
|
204
|
+
withSelection:YES];
|
|
205
|
+
return YES;
|
|
176
206
|
}
|
|
177
207
|
|
|
178
208
|
/**
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
typedef NS_ENUM(NSInteger, TextBlockTapKind) {
|
|
2
|
+
TextBlockTapKindNone = 0,
|
|
3
|
+
TextBlockTapKindCheckbox,
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
@class EnrichedTextInputView;
|
|
7
|
+
|
|
8
|
+
@interface TextBlockTapGestureRecognizer : UITapGestureRecognizer
|
|
9
|
+
- (instancetype _Nonnull)initWithInput:(id _Nonnull)input
|
|
10
|
+
action:(SEL _Nonnull)action;
|
|
11
|
+
|
|
12
|
+
@property(nonatomic, weak) EnrichedTextInputView *input;
|
|
13
|
+
|
|
14
|
+
@property(nonatomic, assign, readonly) TextBlockTapKind tapKind;
|
|
15
|
+
@property(nonatomic, assign, readonly) NSInteger characterIndex;
|
|
16
|
+
|
|
17
|
+
@end
|