react-native-enriched 0.2.0 → 0.3.0
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 +16 -17
- package/android/build.gradle +77 -72
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +21 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +7 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.h +194 -0
- package/android/lint.gradle +70 -0
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputConnectionWrapper.kt +140 -0
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +304 -83
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewLayoutManager.kt +3 -1
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +166 -51
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewPackage.kt +1 -3
- package/android/src/main/java/com/swmansion/enriched/MeasurementStore.kt +70 -21
- package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +21 -11
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeHtmlEvent.kt +8 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeSelectionEvent.kt +10 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateDeprecatedEvent.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateEvent.kt +9 -12
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeTextEvent.kt +10 -10
- package/android/src/main/java/com/swmansion/enriched/events/OnInputBlurEvent.kt +7 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnInputFocusEvent.kt +7 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnInputKeyPressEvent.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/events/OnLinkDetectedEvent.kt +13 -11
- package/android/src/main/java/com/swmansion/enriched/events/OnMentionDetectedEvent.kt +10 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnMentionEvent.kt +9 -8
- package/android/src/main/java/com/swmansion/enriched/events/OnRequestHtmlResultEvent.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +24 -5
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +10 -2
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedImageSpan.kt +34 -17
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +10 -4
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +14 -11
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +18 -11
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +174 -72
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +11 -5
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedBlockSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedHeadingSpan.kt +1 -2
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +1 -2
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedParagraphSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +1 -2
- package/android/src/main/java/com/swmansion/enriched/spans/utils/ForceRedrawSpan.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +155 -20
- package/android/src/main/java/com/swmansion/enriched/styles/InlineStyles.kt +25 -8
- package/android/src/main/java/com/swmansion/enriched/styles/ListStyles.kt +60 -20
- package/android/src/main/java/com/swmansion/enriched/styles/ParagraphStyles.kt +161 -25
- package/android/src/main/java/com/swmansion/enriched/styles/ParametrizedStyles.kt +128 -52
- package/android/src/main/java/com/swmansion/enriched/utils/AsyncDrawable.kt +10 -7
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedConstants.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedEditableFactory.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java +136 -87
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSelection.kt +71 -42
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt +183 -48
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannable.kt +82 -0
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannableStringBuilder.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/utils/Utils.kt +0 -70
- package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedSpanWatcher.kt +46 -14
- package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedTextWatcher.kt +34 -11
- package/android/src/main/new_arch/CMakeLists.txt +6 -0
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +6 -6
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +6 -6
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputComponentDescriptor.h +19 -19
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.cpp +40 -51
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +13 -15
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.cpp +23 -21
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.h +35 -36
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.cpp +4 -4
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.h +13 -14
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +33 -14
- package/ios/EnrichedTextInputView.h +26 -14
- package/ios/EnrichedTextInputView.mm +1209 -586
- package/ios/config/InputConfig.h +24 -6
- package/ios/config/InputConfig.mm +154 -38
- package/ios/{utils → extensions}/ColorExtension.mm +7 -5
- package/ios/extensions/FontExtension.mm +106 -0
- package/ios/{utils → extensions}/LayoutManagerExtension.h +1 -1
- package/ios/extensions/LayoutManagerExtension.mm +396 -0
- package/ios/{utils → extensions}/StringExtension.mm +19 -16
- package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/Props.h +194 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +95 -0
- package/ios/inputParser/InputParser.h +5 -5
- package/ios/inputParser/InputParser.mm +864 -380
- package/ios/inputTextView/InputTextView.h +1 -1
- package/ios/inputTextView/InputTextView.mm +100 -59
- package/ios/{utils → interfaces}/BaseStyleProtocol.h +2 -2
- package/ios/interfaces/ImageAttachment.h +10 -0
- package/ios/interfaces/ImageAttachment.mm +36 -0
- package/ios/interfaces/LinkRegexConfig.h +19 -0
- package/ios/interfaces/LinkRegexConfig.mm +37 -0
- package/ios/interfaces/MediaAttachment.h +23 -0
- package/ios/interfaces/MediaAttachment.mm +31 -0
- package/ios/{utils → interfaces}/MentionParams.h +0 -1
- package/ios/{utils → interfaces}/MentionStyleProps.mm +27 -20
- package/ios/{utils → interfaces}/StyleHeaders.h +37 -15
- package/ios/{utils → interfaces}/StyleTypeEnum.h +3 -0
- package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +11 -9
- package/ios/internals/EnrichedTextInputViewShadowNode.h +28 -25
- package/ios/internals/EnrichedTextInputViewShadowNode.mm +45 -40
- package/ios/internals/EnrichedTextInputViewState.h +3 -1
- package/ios/styles/BlockQuoteStyle.mm +189 -118
- package/ios/styles/BoldStyle.mm +110 -63
- package/ios/styles/CodeBlockStyle.mm +204 -128
- package/ios/styles/H1Style.mm +10 -4
- package/ios/styles/H2Style.mm +10 -4
- package/ios/styles/H3Style.mm +10 -4
- package/ios/styles/H4Style.mm +17 -0
- package/ios/styles/H5Style.mm +17 -0
- package/ios/styles/H6Style.mm +17 -0
- package/ios/styles/HeadingStyleBase.mm +148 -86
- package/ios/styles/ImageStyle.mm +75 -73
- package/ios/styles/InlineCodeStyle.mm +162 -88
- package/ios/styles/ItalicStyle.mm +76 -52
- package/ios/styles/LinkStyle.mm +411 -232
- package/ios/styles/MentionStyle.mm +363 -246
- package/ios/styles/OrderedListStyle.mm +171 -106
- package/ios/styles/StrikethroughStyle.mm +52 -35
- package/ios/styles/UnderlineStyle.mm +68 -46
- package/ios/styles/UnorderedListStyle.mm +169 -106
- package/ios/utils/OccurenceUtils.h +42 -42
- package/ios/utils/OccurenceUtils.mm +142 -119
- package/ios/utils/ParagraphAttributesUtils.h +10 -2
- package/ios/utils/ParagraphAttributesUtils.mm +182 -71
- package/ios/utils/ParagraphsUtils.h +2 -1
- package/ios/utils/ParagraphsUtils.mm +41 -27
- package/ios/utils/TextInsertionUtils.h +13 -2
- package/ios/utils/TextInsertionUtils.mm +38 -20
- package/ios/utils/WordsUtils.h +2 -1
- package/ios/utils/WordsUtils.mm +32 -22
- package/ios/utils/ZeroWidthSpaceUtils.h +3 -1
- package/ios/utils/ZeroWidthSpaceUtils.mm +145 -79
- package/lib/module/EnrichedTextInput.js +61 -2
- package/lib/module/EnrichedTextInput.js.map +1 -1
- package/lib/module/EnrichedTextInputNativeComponent.ts +149 -12
- package/lib/module/{normalizeHtmlStyle.js → utils/normalizeHtmlStyle.js} +12 -0
- package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
- package/lib/module/utils/regexParser.js +46 -0
- package/lib/module/utils/regexParser.js.map +1 -0
- package/lib/typescript/src/EnrichedTextInput.d.ts +24 -14
- package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +129 -12
- package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
- package/lib/typescript/src/utils/regexParser.d.ts +3 -0
- package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
- package/package.json +17 -6
- package/src/EnrichedTextInput.tsx +96 -13
- package/src/EnrichedTextInputNativeComponent.ts +149 -12
- package/src/index.tsx +2 -0
- package/src/{normalizeHtmlStyle.ts → utils/normalizeHtmlStyle.ts} +14 -2
- package/src/utils/regexParser.ts +56 -0
- package/ios/utils/FontExtension.mm +0 -91
- package/ios/utils/LayoutManagerExtension.mm +0 -286
- package/lib/module/normalizeHtmlStyle.js.map +0 -1
- package/lib/typescript/src/normalizeHtmlStyle.d.ts +0 -4
- package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +0 -1
- package/ios/{utils → extensions}/ColorExtension.h +0 -0
- package/ios/{utils → extensions}/FontExtension.h +0 -0
- package/ios/{utils → extensions}/StringExtension.h +1 -1
- package/ios/{utils → interfaces}/ImageData.h +0 -0
- package/ios/{utils → interfaces}/ImageData.mm +0 -0
- package/ios/{utils → interfaces}/LinkData.h +0 -0
- package/ios/{utils → interfaces}/LinkData.mm +0 -0
- package/ios/{utils → interfaces}/MentionParams.mm +0 -0
- package/ios/{utils → interfaces}/MentionStyleProps.h +1 -1
- /package/ios/{utils → interfaces}/StylePair.h +0 -0
- /package/ios/{utils → interfaces}/StylePair.mm +0 -0
- /package/ios/{utils → interfaces}/TextDecorationLineEnum.h +0 -0
- /package/ios/{utils → interfaces}/TextDecorationLineEnum.mm +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#pragma once
|
|
2
|
+
#include <ReactNativeEnriched/EnrichedTextInputViewState.h>
|
|
2
3
|
#include <ReactNativeEnriched/EventEmitters.h>
|
|
3
4
|
#include <ReactNativeEnriched/Props.h>
|
|
4
|
-
#include <
|
|
5
|
+
#include <jsi/jsi.h>
|
|
5
6
|
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
6
7
|
#include <react/renderer/core/LayoutConstraints.h>
|
|
7
|
-
#include <jsi/jsi.h>
|
|
8
8
|
|
|
9
9
|
namespace facebook::react {
|
|
10
10
|
|
|
@@ -13,29 +13,32 @@ JSI_EXPORT extern const char EnrichedTextInputViewComponentName[];
|
|
|
13
13
|
/*
|
|
14
14
|
* `ShadowNode` for <EnrichedTextInputView> component.
|
|
15
15
|
*/
|
|
16
|
-
class EnrichedTextInputViewShadowNode
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
16
|
+
class EnrichedTextInputViewShadowNode
|
|
17
|
+
: public ConcreteViewShadowNode<
|
|
18
|
+
EnrichedTextInputViewComponentName, EnrichedTextInputViewProps,
|
|
19
|
+
EnrichedTextInputViewEventEmitter, EnrichedTextInputViewState> {
|
|
20
|
+
public:
|
|
21
|
+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
22
|
+
EnrichedTextInputViewShadowNode(const ShadowNodeFragment &fragment,
|
|
23
|
+
const ShadowNodeFamily::Shared &family,
|
|
24
|
+
ShadowNodeTraits traits);
|
|
25
|
+
EnrichedTextInputViewShadowNode(const ShadowNode &sourceShadowNode,
|
|
26
|
+
const ShadowNodeFragment &fragment);
|
|
27
|
+
void dirtyLayoutIfNeeded();
|
|
28
|
+
Size
|
|
29
|
+
measureContent(const LayoutContext &layoutContext,
|
|
30
|
+
const LayoutConstraints &layoutConstraints) const override;
|
|
31
|
+
|
|
32
|
+
static ShadowNodeTraits BaseTraits() {
|
|
33
|
+
auto traits = ConcreteViewShadowNode::BaseTraits();
|
|
34
|
+
traits.set(ShadowNodeTraits::Trait::LeafYogaNode);
|
|
35
|
+
traits.set(ShadowNodeTraits::Trait::MeasurableYogaNode);
|
|
36
|
+
return traits;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private:
|
|
40
|
+
int localForceHeightRecalculationCounter_;
|
|
41
|
+
id setupMockTextInputView_() const;
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
} // namespace facebook::react
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
#import "EnrichedTextInputViewShadowNode.h"
|
|
2
|
+
#import "CoreText/CoreText.h"
|
|
2
3
|
#import <EnrichedTextInputView.h>
|
|
4
|
+
#import <React/RCTShadowView+Layout.h>
|
|
3
5
|
#import <react/utils/ManagedObjectWrapper.h>
|
|
4
6
|
#import <yoga/Yoga.h>
|
|
5
|
-
#import <React/RCTShadowView+Layout.h>
|
|
6
|
-
#import "CoreText/CoreText.h"
|
|
7
7
|
|
|
8
8
|
namespace facebook::react {
|
|
9
9
|
|
|
10
|
-
extern const char EnrichedTextInputViewComponentName[] =
|
|
10
|
+
extern const char EnrichedTextInputViewComponentName[] =
|
|
11
|
+
"EnrichedTextInputView";
|
|
11
12
|
|
|
12
13
|
EnrichedTextInputViewShadowNode::EnrichedTextInputViewShadowNode(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
): ConcreteViewShadowNode(fragment, family, traits) {
|
|
14
|
+
const ShadowNodeFragment &fragment, const ShadowNodeFamily::Shared &family,
|
|
15
|
+
ShadowNodeTraits traits)
|
|
16
|
+
: ConcreteViewShadowNode(fragment, family, traits) {
|
|
17
17
|
localForceHeightRecalculationCounter_ = 0;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
// mock input is used for the first measure calls that need to be done when the
|
|
20
|
+
// mock input is used for the first measure calls that need to be done when the
|
|
21
|
+
// real input isn't defined yet
|
|
21
22
|
id EnrichedTextInputViewShadowNode::setupMockTextInputView_() const {
|
|
22
23
|
// it's rendered far away from the viewport
|
|
23
24
|
const int veryFarAway = 20000;
|
|
24
25
|
const int mockSize = 1000;
|
|
25
|
-
EnrichedTextInputView *mockTextInputView_ = [[EnrichedTextInputView alloc]
|
|
26
|
+
EnrichedTextInputView *mockTextInputView_ = [[EnrichedTextInputView alloc]
|
|
27
|
+
initWithFrame:(CGRectMake(veryFarAway, veryFarAway, mockSize, mockSize))];
|
|
26
28
|
const auto props = this->getProps();
|
|
27
29
|
mockTextInputView_->blockEmitting = YES;
|
|
28
30
|
[mockTextInputView_ updateProps:props oldProps:nullptr];
|
|
@@ -30,69 +32,72 @@ id EnrichedTextInputViewShadowNode::setupMockTextInputView_() const {
|
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
EnrichedTextInputViewShadowNode::EnrichedTextInputViewShadowNode(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
): ConcreteViewShadowNode(sourceShadowNode, fragment) {
|
|
35
|
+
const ShadowNode &sourceShadowNode, const ShadowNodeFragment &fragment)
|
|
36
|
+
: ConcreteViewShadowNode(sourceShadowNode, fragment) {
|
|
36
37
|
dirtyLayoutIfNeeded();
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
void EnrichedTextInputViewShadowNode::dirtyLayoutIfNeeded() {
|
|
40
41
|
const auto state = this->getStateData();
|
|
41
42
|
const int receivedCounter = state.getForceHeightRecalculationCounter();
|
|
42
|
-
|
|
43
|
-
if(receivedCounter > localForceHeightRecalculationCounter_) {
|
|
43
|
+
|
|
44
|
+
if (receivedCounter > localForceHeightRecalculationCounter_) {
|
|
44
45
|
localForceHeightRecalculationCounter_ = receivedCounter;
|
|
45
46
|
YGNodeMarkDirty(&yogaNode_);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
Size EnrichedTextInputViewShadowNode::measureContent(
|
|
50
|
+
Size EnrichedTextInputViewShadowNode::measureContent(
|
|
51
|
+
const LayoutContext &layoutContext,
|
|
52
|
+
const LayoutConstraints &layoutConstraints) const {
|
|
50
53
|
const auto state = this->getStateData();
|
|
51
54
|
const auto componentRef = state.getComponentViewRef();
|
|
52
|
-
RCTInternalGenericWeakWrapper *weakWrapper =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
RCTInternalGenericWeakWrapper *weakWrapper =
|
|
56
|
+
(RCTInternalGenericWeakWrapper *)unwrapManagedObject(componentRef);
|
|
57
|
+
|
|
58
|
+
if (weakWrapper != nullptr) {
|
|
55
59
|
id componentObject = weakWrapper.object;
|
|
56
|
-
EnrichedTextInputView *typedComponentObject =
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
EnrichedTextInputView *typedComponentObject =
|
|
61
|
+
(EnrichedTextInputView *)componentObject;
|
|
62
|
+
|
|
63
|
+
if (typedComponentObject != nullptr) {
|
|
59
64
|
__block CGSize estimatedSize;
|
|
60
|
-
|
|
65
|
+
|
|
61
66
|
// synchronously dispatch to main thread if needed
|
|
62
|
-
if([NSThread isMainThread]) {
|
|
63
|
-
estimatedSize = [typedComponentObject
|
|
67
|
+
if ([NSThread isMainThread]) {
|
|
68
|
+
estimatedSize = [typedComponentObject
|
|
69
|
+
measureSize:layoutConstraints.maximumSize.width];
|
|
64
70
|
} else {
|
|
65
71
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
66
|
-
estimatedSize = [typedComponentObject
|
|
72
|
+
estimatedSize = [typedComponentObject
|
|
73
|
+
measureSize:layoutConstraints.maximumSize.width];
|
|
67
74
|
});
|
|
68
75
|
}
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
|
|
72
|
-
MIN(estimatedSize.height, layoutConstraints.maximumSize.height)
|
|
73
|
-
};
|
|
76
|
+
|
|
77
|
+
return {estimatedSize.width,
|
|
78
|
+
MIN(estimatedSize.height, layoutConstraints.maximumSize.height)};
|
|
74
79
|
}
|
|
75
80
|
} else {
|
|
76
81
|
__block CGSize estimatedSize;
|
|
77
|
-
|
|
82
|
+
|
|
78
83
|
// synchronously dispatch to main thread if needed
|
|
79
|
-
if([NSThread isMainThread]) {
|
|
84
|
+
if ([NSThread isMainThread]) {
|
|
80
85
|
EnrichedTextInputView *mockTextInputView = setupMockTextInputView_();
|
|
81
|
-
estimatedSize =
|
|
86
|
+
estimatedSize =
|
|
87
|
+
[mockTextInputView measureSize:layoutConstraints.maximumSize.width];
|
|
82
88
|
} else {
|
|
83
89
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
84
90
|
EnrichedTextInputView *mockTextInputView = setupMockTextInputView_();
|
|
85
|
-
estimatedSize =
|
|
91
|
+
estimatedSize =
|
|
92
|
+
[mockTextInputView measureSize:layoutConstraints.maximumSize.width];
|
|
86
93
|
});
|
|
87
94
|
}
|
|
88
95
|
|
|
89
|
-
return {
|
|
90
|
-
|
|
91
|
-
MIN(estimatedSize.height, layoutConstraints.maximumSize.height)
|
|
92
|
-
};
|
|
96
|
+
return {estimatedSize.width,
|
|
97
|
+
MIN(estimatedSize.height, layoutConstraints.maximumSize.height)};
|
|
93
98
|
}
|
|
94
|
-
|
|
99
|
+
|
|
95
100
|
return Size();
|
|
96
101
|
}
|
|
97
|
-
|
|
102
|
+
|
|
98
103
|
} // namespace facebook::react
|
|
@@ -5,13 +5,15 @@ namespace facebook::react {
|
|
|
5
5
|
|
|
6
6
|
class EnrichedTextInputViewState {
|
|
7
7
|
public:
|
|
8
|
-
EnrichedTextInputViewState()
|
|
8
|
+
EnrichedTextInputViewState()
|
|
9
|
+
: forceHeightRecalculationCounter_(0), componentViewRef_(nullptr) {}
|
|
9
10
|
EnrichedTextInputViewState(int counter, std::shared_ptr<void> ref) {
|
|
10
11
|
forceHeightRecalculationCounter_ = counter;
|
|
11
12
|
componentViewRef_ = ref;
|
|
12
13
|
}
|
|
13
14
|
int getForceHeightRecalculationCounter() const;
|
|
14
15
|
std::shared_ptr<void> getComponentViewRef() const;
|
|
16
|
+
|
|
15
17
|
private:
|
|
16
18
|
int forceHeightRecalculationCounter_{};
|
|
17
19
|
std::shared_ptr<void> componentViewRef_{};
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
#import "
|
|
1
|
+
#import "ColorExtension.h"
|
|
2
2
|
#import "EnrichedTextInputView.h"
|
|
3
3
|
#import "OccurenceUtils.h"
|
|
4
4
|
#import "ParagraphsUtils.h"
|
|
5
|
+
#import "StyleHeaders.h"
|
|
5
6
|
#import "TextInsertionUtils.h"
|
|
6
|
-
#import "ColorExtension.h"
|
|
7
7
|
|
|
8
8
|
@implementation BlockQuoteStyle {
|
|
9
9
|
EnrichedTextInputView *_input;
|
|
10
10
|
NSArray *_stylesToExclude;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
+ (StyleType)getStyleType {
|
|
13
|
+
+ (StyleType)getStyleType {
|
|
14
|
+
return BlockQuote;
|
|
15
|
+
}
|
|
14
16
|
|
|
15
|
-
+ (BOOL)isParagraphStyle {
|
|
17
|
+
+ (BOOL)isParagraphStyle {
|
|
18
|
+
return YES;
|
|
19
|
+
}
|
|
16
20
|
|
|
17
21
|
- (instancetype)initWithInput:(id)input {
|
|
18
22
|
self = [super init];
|
|
@@ -23,118 +27,158 @@
|
|
|
23
27
|
|
|
24
28
|
- (CGFloat)getHeadIndent {
|
|
25
29
|
// rectangle width + gap
|
|
26
|
-
return [_input->config blockquoteBorderWidth] +
|
|
30
|
+
return [_input->config blockquoteBorderWidth] +
|
|
31
|
+
[_input->config blockquoteGapWidth];
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
// the range will already be the full paragraph/s range
|
|
30
35
|
- (void)applyStyle:(NSRange)range {
|
|
31
36
|
BOOL isStylePresent = [self detectStyle:range];
|
|
32
|
-
if(range.length >= 1) {
|
|
33
|
-
isStylePresent ? [self removeAttributes:range]
|
|
37
|
+
if (range.length >= 1) {
|
|
38
|
+
isStylePresent ? [self removeAttributes:range]
|
|
39
|
+
: [self addAttributes:range withTypingAttr:YES];
|
|
34
40
|
} else {
|
|
35
41
|
isStylePresent ? [self removeTypingAttributes] : [self addTypingAttributes];
|
|
36
42
|
}
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
- (void)addAttributes:(NSRange)range {
|
|
40
|
-
NSArray *paragraphs =
|
|
41
|
-
|
|
45
|
+
- (void)addAttributes:(NSRange)range withTypingAttr:(BOOL)withTypingAttr {
|
|
46
|
+
NSArray *paragraphs =
|
|
47
|
+
[ParagraphsUtils getSeparateParagraphsRangesIn:_input->textView
|
|
48
|
+
range:range];
|
|
49
|
+
// if we fill empty lines with zero width spaces, we need to offset later
|
|
50
|
+
// ranges
|
|
42
51
|
NSInteger offset = 0;
|
|
43
52
|
NSRange preModificationRange = _input->textView.selectedRange;
|
|
44
|
-
|
|
53
|
+
|
|
45
54
|
// to not emit any space filling selection/text changes
|
|
46
55
|
_input->blockEmitting = YES;
|
|
47
|
-
|
|
48
|
-
for(NSValue *value in paragraphs) {
|
|
49
|
-
NSRange pRange = NSMakeRange([value rangeValue].location + offset,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
for (NSValue *value in paragraphs) {
|
|
58
|
+
NSRange pRange = NSMakeRange([value rangeValue].location + offset,
|
|
59
|
+
[value rangeValue].length);
|
|
60
|
+
|
|
61
|
+
// length 0 with first line, length 1 and newline with some empty lines in
|
|
62
|
+
// the middle
|
|
63
|
+
if (pRange.length == 0 ||
|
|
64
|
+
(pRange.length == 1 &&
|
|
65
|
+
[[NSCharacterSet newlineCharacterSet]
|
|
66
|
+
characterIsMember:[_input->textView.textStorage.string
|
|
67
|
+
characterAtIndex:pRange.location]])) {
|
|
68
|
+
[TextInsertionUtils insertText:@"\u200B"
|
|
69
|
+
at:pRange.location
|
|
70
|
+
additionalAttributes:nullptr
|
|
71
|
+
input:_input
|
|
72
|
+
withSelection:NO];
|
|
57
73
|
pRange = NSMakeRange(pRange.location, pRange.length + 1);
|
|
58
74
|
offset += 1;
|
|
59
75
|
}
|
|
60
|
-
|
|
61
|
-
[_input->textView.textStorage
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
|
|
77
|
+
[_input->textView.textStorage
|
|
78
|
+
enumerateAttribute:NSParagraphStyleAttributeName
|
|
79
|
+
inRange:pRange
|
|
80
|
+
options:0
|
|
81
|
+
usingBlock:^(id _Nullable value, NSRange range,
|
|
82
|
+
BOOL *_Nonnull stop) {
|
|
83
|
+
NSMutableParagraphStyle *pStyle =
|
|
84
|
+
[(NSParagraphStyle *)value mutableCopy];
|
|
85
|
+
pStyle.headIndent = [self getHeadIndent];
|
|
86
|
+
pStyle.firstLineHeadIndent = [self getHeadIndent];
|
|
87
|
+
[_input->textView.textStorage
|
|
88
|
+
addAttribute:NSParagraphStyleAttributeName
|
|
89
|
+
value:pStyle
|
|
90
|
+
range:range];
|
|
91
|
+
}];
|
|
69
92
|
}
|
|
70
|
-
|
|
93
|
+
|
|
71
94
|
// back to emitting
|
|
72
95
|
_input->blockEmitting = NO;
|
|
73
|
-
|
|
74
|
-
if(preModificationRange.length == 0) {
|
|
75
|
-
// fix selection if only one line was possibly made a list and filled with a
|
|
96
|
+
|
|
97
|
+
if (preModificationRange.length == 0) {
|
|
98
|
+
// fix selection if only one line was possibly made a list and filled with a
|
|
99
|
+
// space
|
|
76
100
|
_input->textView.selectedRange = preModificationRange;
|
|
77
101
|
} else {
|
|
78
102
|
// in other cases, fix the selection with newly made offsets
|
|
79
|
-
_input->textView.selectedRange = NSMakeRange(
|
|
103
|
+
_input->textView.selectedRange = NSMakeRange(
|
|
104
|
+
preModificationRange.location, preModificationRange.length + offset);
|
|
80
105
|
}
|
|
81
|
-
|
|
106
|
+
|
|
82
107
|
// also add typing attributes
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
108
|
+
if (withTypingAttr) {
|
|
109
|
+
NSMutableDictionary *typingAttrs =
|
|
110
|
+
[_input->textView.typingAttributes mutableCopy];
|
|
111
|
+
NSMutableParagraphStyle *pStyle =
|
|
112
|
+
[typingAttrs[NSParagraphStyleAttributeName] mutableCopy];
|
|
113
|
+
pStyle.headIndent = [self getHeadIndent];
|
|
114
|
+
pStyle.firstLineHeadIndent = [self getHeadIndent];
|
|
115
|
+
typingAttrs[NSParagraphStyleAttributeName] = pStyle;
|
|
116
|
+
_input->textView.typingAttributes = typingAttrs;
|
|
117
|
+
}
|
|
89
118
|
}
|
|
90
119
|
|
|
91
120
|
// does pretty much the same as addAttributes
|
|
92
121
|
- (void)addTypingAttributes {
|
|
93
|
-
[self addAttributes:_input->textView.selectedRange];
|
|
122
|
+
[self addAttributes:_input->textView.selectedRange withTypingAttr:YES];
|
|
94
123
|
}
|
|
95
124
|
|
|
96
125
|
- (void)removeAttributes:(NSRange)range {
|
|
97
|
-
NSArray *paragraphs =
|
|
98
|
-
|
|
99
|
-
|
|
126
|
+
NSArray *paragraphs =
|
|
127
|
+
[ParagraphsUtils getSeparateParagraphsRangesIn:_input->textView
|
|
128
|
+
range:range];
|
|
129
|
+
|
|
130
|
+
for (NSValue *value in paragraphs) {
|
|
100
131
|
NSRange pRange = [value rangeValue];
|
|
101
|
-
[_input->textView.textStorage
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
132
|
+
[_input->textView.textStorage
|
|
133
|
+
enumerateAttribute:NSParagraphStyleAttributeName
|
|
134
|
+
inRange:pRange
|
|
135
|
+
options:0
|
|
136
|
+
usingBlock:^(id _Nullable value, NSRange range,
|
|
137
|
+
BOOL *_Nonnull stop) {
|
|
138
|
+
NSMutableParagraphStyle *pStyle =
|
|
139
|
+
[(NSParagraphStyle *)value mutableCopy];
|
|
140
|
+
pStyle.headIndent = 0;
|
|
141
|
+
pStyle.firstLineHeadIndent = 0;
|
|
142
|
+
[_input->textView.textStorage
|
|
143
|
+
addAttribute:NSParagraphStyleAttributeName
|
|
144
|
+
value:pStyle
|
|
145
|
+
range:range];
|
|
146
|
+
}];
|
|
109
147
|
}
|
|
110
|
-
|
|
148
|
+
|
|
111
149
|
// also remove typing attributes
|
|
112
|
-
NSMutableDictionary *typingAttrs =
|
|
113
|
-
|
|
150
|
+
NSMutableDictionary *typingAttrs =
|
|
151
|
+
[_input->textView.typingAttributes mutableCopy];
|
|
152
|
+
NSMutableParagraphStyle *pStyle =
|
|
153
|
+
[typingAttrs[NSParagraphStyleAttributeName] mutableCopy];
|
|
114
154
|
pStyle.headIndent = 0;
|
|
115
155
|
pStyle.firstLineHeadIndent = 0;
|
|
116
156
|
typingAttrs[NSParagraphStyleAttributeName] = pStyle;
|
|
117
157
|
_input->textView.typingAttributes = typingAttrs;
|
|
118
158
|
}
|
|
119
159
|
|
|
120
|
-
// needed for the sake of style conflicts, needs to do exactly the same as
|
|
160
|
+
// needed for the sake of style conflicts, needs to do exactly the same as
|
|
161
|
+
// removeAttribtues
|
|
121
162
|
- (void)removeTypingAttributes {
|
|
122
163
|
[self removeAttributes:_input->textView.selectedRange];
|
|
123
164
|
}
|
|
124
165
|
|
|
125
166
|
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text {
|
|
126
|
-
if([self detectStyle:_input->textView.selectedRange] && text.length == 0) {
|
|
167
|
+
if ([self detectStyle:_input->textView.selectedRange] && text.length == 0) {
|
|
127
168
|
// backspace while the style is active
|
|
128
|
-
|
|
129
|
-
NSRange paragraphRange = [_input->textView.textStorage.string
|
|
130
|
-
|
|
131
|
-
|
|
169
|
+
|
|
170
|
+
NSRange paragraphRange = [_input->textView.textStorage.string
|
|
171
|
+
paragraphRangeForRange:_input->textView.selectedRange];
|
|
172
|
+
|
|
173
|
+
if (NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0))) {
|
|
132
174
|
// a backspace on the very first input's line quote
|
|
133
|
-
// it doesn't run textVieDidChange so we need to manually remove
|
|
175
|
+
// it doesn't run textVieDidChange so we need to manually remove
|
|
176
|
+
// attributes
|
|
134
177
|
[self removeAttributes:paragraphRange];
|
|
135
178
|
return YES;
|
|
136
|
-
} else if(range.location == paragraphRange.location - 1) {
|
|
137
|
-
// same case in other lines; here, the removed range location will be
|
|
179
|
+
} else if (range.location == paragraphRange.location - 1) {
|
|
180
|
+
// same case in other lines; here, the removed range location will be
|
|
181
|
+
// exactly 1 less than paragraph range location
|
|
138
182
|
[self removeAttributes:paragraphRange];
|
|
139
183
|
return YES;
|
|
140
184
|
}
|
|
@@ -142,79 +186,106 @@
|
|
|
142
186
|
return NO;
|
|
143
187
|
}
|
|
144
188
|
|
|
145
|
-
- (BOOL)styleCondition:(id _Nullable)value :(NSRange)range {
|
|
189
|
+
- (BOOL)styleCondition:(id _Nullable)value range:(NSRange)range {
|
|
146
190
|
NSParagraphStyle *pStyle = (NSParagraphStyle *)value;
|
|
147
|
-
return pStyle != nullptr && pStyle.headIndent == [self getHeadIndent] &&
|
|
191
|
+
return pStyle != nullptr && pStyle.headIndent == [self getHeadIndent] &&
|
|
192
|
+
pStyle.firstLineHeadIndent == [self getHeadIndent] &&
|
|
193
|
+
pStyle.textLists.count == 0;
|
|
148
194
|
}
|
|
149
195
|
|
|
150
196
|
- (BOOL)detectStyle:(NSRange)range {
|
|
151
|
-
if(range.length >= 1) {
|
|
152
|
-
return [OccurenceUtils detect:NSParagraphStyleAttributeName
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
197
|
+
if (range.length >= 1) {
|
|
198
|
+
return [OccurenceUtils detect:NSParagraphStyleAttributeName
|
|
199
|
+
withInput:_input
|
|
200
|
+
inRange:range
|
|
201
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
202
|
+
return [self styleCondition:value range:range];
|
|
203
|
+
}];
|
|
157
204
|
} else {
|
|
158
|
-
return [OccurenceUtils detect:NSParagraphStyleAttributeName
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
205
|
+
return [OccurenceUtils detect:NSParagraphStyleAttributeName
|
|
206
|
+
withInput:_input
|
|
207
|
+
atIndex:range.location
|
|
208
|
+
checkPrevious:YES
|
|
209
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
210
|
+
return [self styleCondition:value range:range];
|
|
211
|
+
}];
|
|
163
212
|
}
|
|
164
213
|
}
|
|
165
214
|
|
|
166
215
|
- (BOOL)anyOccurence:(NSRange)range {
|
|
167
|
-
return [OccurenceUtils any:NSParagraphStyleAttributeName
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
216
|
+
return [OccurenceUtils any:NSParagraphStyleAttributeName
|
|
217
|
+
withInput:_input
|
|
218
|
+
inRange:range
|
|
219
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
220
|
+
return [self styleCondition:value range:range];
|
|
221
|
+
}];
|
|
172
222
|
}
|
|
173
223
|
|
|
174
224
|
- (NSArray<StylePair *> *_Nullable)findAllOccurences:(NSRange)range {
|
|
175
|
-
return [OccurenceUtils all:NSParagraphStyleAttributeName
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
225
|
+
return [OccurenceUtils all:NSParagraphStyleAttributeName
|
|
226
|
+
withInput:_input
|
|
227
|
+
inRange:range
|
|
228
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
229
|
+
return [self styleCondition:value range:range];
|
|
230
|
+
}];
|
|
180
231
|
}
|
|
181
232
|
|
|
182
233
|
// general checkup correcting blockquote color
|
|
183
|
-
// since links, mentions and inline code affects coloring, the checkup gets done
|
|
234
|
+
// since links, mentions and inline code affects coloring, the checkup gets done
|
|
235
|
+
// only outside of them
|
|
184
236
|
- (void)manageBlockquoteColor {
|
|
185
|
-
if([[_input->config blockquoteColor]
|
|
237
|
+
if ([[_input->config blockquoteColor]
|
|
238
|
+
isEqualToColor:[_input->config primaryColor]]) {
|
|
186
239
|
return;
|
|
187
240
|
}
|
|
188
|
-
|
|
189
|
-
NSRange wholeRange =
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
241
|
+
|
|
242
|
+
NSRange wholeRange =
|
|
243
|
+
NSMakeRange(0, _input->textView.textStorage.string.length);
|
|
244
|
+
|
|
245
|
+
NSArray *paragraphs =
|
|
246
|
+
[ParagraphsUtils getSeparateParagraphsRangesIn:_input->textView
|
|
247
|
+
range:wholeRange];
|
|
248
|
+
for (NSValue *pValue in paragraphs) {
|
|
193
249
|
NSRange paragraphRange = [pValue rangeValue];
|
|
194
|
-
NSArray *properRanges = [OccurenceUtils getRangesWithout:_stylesToExclude
|
|
195
|
-
|
|
196
|
-
|
|
250
|
+
NSArray *properRanges = [OccurenceUtils getRangesWithout:_stylesToExclude
|
|
251
|
+
withInput:_input
|
|
252
|
+
inRange:paragraphRange];
|
|
253
|
+
|
|
254
|
+
for (NSValue *value in properRanges) {
|
|
197
255
|
NSRange currRange = [value rangeValue];
|
|
198
256
|
BOOL selfDetected = [self detectStyle:currRange];
|
|
199
|
-
|
|
200
|
-
[_input->textView.textStorage
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
257
|
+
|
|
258
|
+
[_input->textView.textStorage
|
|
259
|
+
enumerateAttribute:NSForegroundColorAttributeName
|
|
260
|
+
inRange:currRange
|
|
261
|
+
options:0
|
|
262
|
+
usingBlock:^(id _Nullable value, NSRange range,
|
|
263
|
+
BOOL *_Nonnull stop) {
|
|
264
|
+
UIColor *newColor = nullptr;
|
|
265
|
+
BOOL colorApplied = [(UIColor *)value
|
|
266
|
+
isEqualToColor:[_input->config blockquoteColor]];
|
|
267
|
+
|
|
268
|
+
if (colorApplied && !selfDetected) {
|
|
269
|
+
newColor = [_input->config primaryColor];
|
|
270
|
+
} else if (!colorApplied && selfDetected) {
|
|
271
|
+
newColor = [_input->config blockquoteColor];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (newColor != nullptr) {
|
|
275
|
+
[_input->textView.textStorage
|
|
276
|
+
addAttribute:NSForegroundColorAttributeName
|
|
277
|
+
value:newColor
|
|
278
|
+
range:currRange];
|
|
279
|
+
[_input->textView.textStorage
|
|
280
|
+
addAttribute:NSUnderlineColorAttributeName
|
|
281
|
+
value:newColor
|
|
282
|
+
range:currRange];
|
|
283
|
+
[_input->textView.textStorage
|
|
284
|
+
addAttribute:NSStrikethroughColorAttributeName
|
|
285
|
+
value:newColor
|
|
286
|
+
range:currRange];
|
|
287
|
+
}
|
|
288
|
+
}];
|
|
218
289
|
}
|
|
219
290
|
}
|
|
220
291
|
}
|