@fendent/react-native-enriched 0.5.2-fork.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/LICENSE +20 -0
- package/README.md +343 -0
- package/ReactNativeEnriched.podspec +31 -0
- package/android/build.gradle +106 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +197 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +72 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ComponentDescriptors.cpp +22 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ComponentDescriptors.h +24 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.cpp +434 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.h +391 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.cpp +173 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.h +833 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ShadowNodes.cpp +17 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ShadowNodes.h +23 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/States.cpp +16 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/States.h +20 -0
- package/android/gradle.properties +5 -0
- package/android/lint.gradle +70 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/swmansion/enriched/ReactNativeEnrichedPackage.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/common/AsyncDrawable.kt +126 -0
- package/android/src/main/java/com/swmansion/enriched/common/CheckboxDrawable.kt +81 -0
- package/android/src/main/java/com/swmansion/enriched/common/EnrichedConstants.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/common/EnrichedStyle.kt +57 -0
- package/android/src/main/java/com/swmansion/enriched/common/ForceRedrawSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/common/GumboNormalizer.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/common/MentionStyle.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/common/ResourceManager.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java +956 -0
- package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedSpanFactory.kt +79 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBlockQuoteSpan.kt +53 -0
- 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 +92 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCodeBlockSpan.kt +81 -0
- 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/common/spans/EnrichedImageSpan.kt +184 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedInlineCodeSpan.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedItalicSpan.kt +12 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedLinkSpan.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedMentionSpan.kt +35 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedOrderedListSpan.kt +79 -0
- 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/common/spans/EnrichedUnorderedListSpan.kt +62 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedBlockSpan.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedHeadingSpan.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedInlineSpan.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedParagraphSpan.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedSpan.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputConnectionWrapper.kt +140 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputSpannableFactory.kt +83 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt +1120 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewLayoutManager.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewManager.kt +478 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/MeasurementStore.kt +225 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/MentionHandler.kt +55 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeHtmlEvent.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeSelectionEvent.kt +30 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeStateEvent.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeTextEvent.kt +30 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnContextMenuItemPressEvent.kt +35 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputBlurEvent.kt +25 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputFocusEvent.kt +25 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputKeyPressEvent.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnLinkDetectedEvent.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnMentionDetectedEvent.kt +30 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnMentionEvent.kt +34 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnPasteImagesEvent.kt +47 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnRequestHtmlResultEvent.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnSubmitEditingEvent.kt +29 -0
- 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 +16 -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/textinput/spans/EnrichedLineHeightSpan.kt +44 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedSpans.kt +241 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/interfaces/EnrichedInputSpan.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/HtmlStyle.kt +372 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/InlineStyles.kt +164 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ListStyles.kt +263 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParagraphStyles.kt +434 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParametrizedStyles.kt +394 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedEditableFactory.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSelection.kt +320 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpanState.kt +310 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannable.kt +106 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannableStringBuilder.kt +24 -0
- 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/textinput/watchers/EnrichedSpanWatcher.kt +107 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/watchers/EnrichedTextWatcher.kt +74 -0
- package/android/src/main/new_arch/CMakeLists.txt +62 -0
- package/android/src/main/new_arch/GumboNormalizerJni.cpp +14 -0
- 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/ReactNativeEnrichedSpec/EnrichedTextInputComponentDescriptor.h +35 -0
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputMeasurementManager.cpp +53 -0
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputMeasurementManager.h +25 -0
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputShadowNode.cpp +35 -0
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputShadowNode.h +53 -0
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputState.cpp +9 -0
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputState.h +24 -0
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/conversions.h +27 -0
- package/android/src/main/res/drawable/broken_image.xml +10 -0
- package/cpp/CMakeLists.txt +50 -0
- package/cpp/GumboParser/GumboParser.h +34043 -0
- package/cpp/README.md +59 -0
- package/cpp/parser/GumboNormalizer.c +915 -0
- package/cpp/parser/GumboParser.cpp +16 -0
- package/cpp/parser/GumboParser.hpp +23 -0
- package/cpp/tests/GumboParserTest.cpp +457 -0
- package/ios/EnrichedTextInputView.h +53 -0
- package/ios/EnrichedTextInputView.mm +2360 -0
- package/ios/EnrichedTextInputViewManager.mm +13 -0
- package/ios/attributesManager/AttributesManager.h +17 -0
- package/ios/attributesManager/AttributesManager.mm +195 -0
- package/ios/config/InputConfig.h +104 -0
- package/ios/config/InputConfig.mm +664 -0
- package/ios/extensions/ColorExtension.h +7 -0
- package/ios/extensions/ColorExtension.mm +38 -0
- package/ios/extensions/FontExtension.h +11 -0
- package/ios/extensions/FontExtension.mm +72 -0
- package/ios/extensions/ImageExtension.h +34 -0
- package/ios/extensions/ImageExtension.mm +165 -0
- package/ios/extensions/LayoutManagerExtension.h +6 -0
- package/ios/extensions/LayoutManagerExtension.mm +443 -0
- package/ios/extensions/StringExtension.h +15 -0
- package/ios/extensions/StringExtension.mm +69 -0
- package/ios/generated/ReactNativeEnrichedSpec/ComponentDescriptors.cpp +22 -0
- package/ios/generated/ReactNativeEnrichedSpec/ComponentDescriptors.h +24 -0
- package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.cpp +434 -0
- package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.h +391 -0
- package/ios/generated/ReactNativeEnrichedSpec/Props.cpp +173 -0
- package/ios/generated/ReactNativeEnrichedSpec/Props.h +833 -0
- package/ios/generated/ReactNativeEnrichedSpec/RCTComponentViewHelpers.h +582 -0
- package/ios/generated/ReactNativeEnrichedSpec/ShadowNodes.cpp +17 -0
- package/ios/generated/ReactNativeEnrichedSpec/ShadowNodes.h +23 -0
- package/ios/generated/ReactNativeEnrichedSpec/States.cpp +16 -0
- package/ios/generated/ReactNativeEnrichedSpec/States.h +20 -0
- package/ios/inputParser/InputParser.h +11 -0
- package/ios/inputParser/InputParser.mm +1463 -0
- package/ios/inputTextView/InputTextView.h +6 -0
- package/ios/inputTextView/InputTextView.mm +285 -0
- package/ios/interfaces/AttributeEntry.h +9 -0
- package/ios/interfaces/AttributeEntry.mm +4 -0
- package/ios/interfaces/BaseStyleProtocol.h +17 -0
- package/ios/interfaces/ImageAttachment.h +11 -0
- package/ios/interfaces/ImageAttachment.mm +107 -0
- package/ios/interfaces/ImageData.h +10 -0
- package/ios/interfaces/ImageData.mm +4 -0
- package/ios/interfaces/LinkData.h +11 -0
- package/ios/interfaces/LinkData.mm +29 -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/interfaces/MentionParams.h +8 -0
- package/ios/interfaces/MentionParams.mm +4 -0
- package/ios/interfaces/MentionStyleProps.h +13 -0
- package/ios/interfaces/MentionStyleProps.mm +63 -0
- package/ios/interfaces/StyleBase.h +36 -0
- package/ios/interfaces/StyleBase.mm +256 -0
- package/ios/interfaces/StyleHeaders.h +102 -0
- package/ios/interfaces/StylePair.h +9 -0
- package/ios/interfaces/StylePair.mm +4 -0
- package/ios/interfaces/StyleTypeEnum.h +26 -0
- package/ios/interfaces/TextDecorationLineEnum.h +6 -0
- package/ios/interfaces/TextDecorationLineEnum.mm +4 -0
- package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +19 -0
- package/ios/internals/EnrichedTextInputViewShadowNode.h +44 -0
- package/ios/internals/EnrichedTextInputViewShadowNode.mm +103 -0
- package/ios/internals/EnrichedTextInputViewState.cpp +10 -0
- package/ios/internals/EnrichedTextInputViewState.h +22 -0
- package/ios/styles/BlockQuoteStyle.mm +55 -0
- package/ios/styles/BoldStyle.mm +37 -0
- package/ios/styles/CheckboxListStyle.mm +153 -0
- package/ios/styles/CodeBlockStyle.mm +49 -0
- package/ios/styles/H1Style.mm +20 -0
- package/ios/styles/H2Style.mm +20 -0
- package/ios/styles/H3Style.mm +20 -0
- package/ios/styles/H4Style.mm +20 -0
- package/ios/styles/H5Style.mm +20 -0
- package/ios/styles/H6Style.mm +20 -0
- package/ios/styles/HeadingStyleBase.mm +65 -0
- package/ios/styles/ImageStyle.mm +146 -0
- package/ios/styles/InlineCodeStyle.mm +65 -0
- package/ios/styles/ItalicStyle.mm +37 -0
- package/ios/styles/LinkStyle.mm +532 -0
- package/ios/styles/MentionStyle.mm +538 -0
- package/ios/styles/OrderedListStyle.mm +86 -0
- package/ios/styles/StrikethroughStyle.mm +25 -0
- package/ios/styles/UnderlineStyle.mm +24 -0
- package/ios/styles/UnorderedListStyle.mm +86 -0
- package/ios/utils/CheckboxHitTestUtils.h +10 -0
- package/ios/utils/CheckboxHitTestUtils.mm +122 -0
- package/ios/utils/DotReplacementUtils.h +10 -0
- package/ios/utils/DotReplacementUtils.mm +68 -0
- package/ios/utils/KeyboardUtils.h +7 -0
- package/ios/utils/KeyboardUtils.mm +31 -0
- package/ios/utils/OccurenceUtils.h +44 -0
- package/ios/utils/OccurenceUtils.mm +179 -0
- package/ios/utils/ParagraphAttributesUtils.h +15 -0
- package/ios/utils/ParagraphAttributesUtils.mm +257 -0
- package/ios/utils/RangeUtils.h +12 -0
- package/ios/utils/RangeUtils.mm +183 -0
- package/ios/utils/TextBlockTapGestureRecognizer.h +17 -0
- package/ios/utils/TextBlockTapGestureRecognizer.mm +56 -0
- package/ios/utils/TextInsertionUtils.h +17 -0
- package/ios/utils/TextInsertionUtils.mm +64 -0
- package/ios/utils/WordsUtils.h +7 -0
- package/ios/utils/WordsUtils.mm +98 -0
- package/ios/utils/ZeroWidthSpaceUtils.h +9 -0
- package/ios/utils/ZeroWidthSpaceUtils.mm +270 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/native/EnrichedTextInput.js +304 -0
- package/lib/module/native/EnrichedTextInput.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/spec/EnrichedTextInputNativeComponent.ts +517 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/EnrichedTextInputDefaultProps.js +12 -0
- package/lib/module/utils/EnrichedTextInputDefaultProps.js.map +1 -0
- package/lib/module/utils/normalizeHtmlStyle.js +155 -0
- package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
- package/lib/module/utils/nullthrows.js +9 -0
- package/lib/module/utils/nullthrows.js.map +1 -0
- package/lib/module/utils/regexParser.js +46 -0
- package/lib/module/utils/regexParser.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/native/EnrichedTextInput.d.ts +3 -0
- package/lib/typescript/src/native/EnrichedTextInput.d.ts.map +1 -0
- package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts +397 -0
- package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +447 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils/EnrichedTextInputDefaultProps.d.ts +10 -0
- package/lib/typescript/src/utils/EnrichedTextInputDefaultProps.d.ts.map +1 -0
- 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/nullthrows.d.ts +2 -0
- package/lib/typescript/src/utils/nullthrows.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 +226 -0
- package/react-native.config.js +13 -0
- package/src/index.tsx +20 -0
- package/src/native/EnrichedTextInput.tsx +370 -0
- package/src/spec/EnrichedTextInputNativeComponent.ts +517 -0
- package/src/types.ts +499 -0
- package/src/utils/EnrichedTextInputDefaultProps.ts +9 -0
- package/src/utils/normalizeHtmlStyle.ts +199 -0
- package/src/utils/nullthrows.ts +7 -0
- package/src/utils/regexParser.ts +56 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
package com.swmansion.enriched.textinput.styles
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import com.facebook.react.bridge.ColorPropConverter
|
|
5
|
+
import com.facebook.react.bridge.ReactContext
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap
|
|
7
|
+
import com.facebook.react.uimanager.PixelUtil
|
|
8
|
+
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
|
|
9
|
+
import com.swmansion.enriched.common.EnrichedStyle
|
|
10
|
+
import com.swmansion.enriched.common.MentionStyle
|
|
11
|
+
import com.swmansion.enriched.textinput.EnrichedTextInputView
|
|
12
|
+
import kotlin.Float
|
|
13
|
+
import kotlin.Int
|
|
14
|
+
import kotlin.String
|
|
15
|
+
import kotlin.math.ceil
|
|
16
|
+
|
|
17
|
+
class HtmlStyle : EnrichedStyle {
|
|
18
|
+
private var style: ReadableMap? = null
|
|
19
|
+
private var view: EnrichedTextInputView? = null
|
|
20
|
+
|
|
21
|
+
// Default values are ignored as they are specified on the JS side.
|
|
22
|
+
// They are specified only because they are required by the constructor.
|
|
23
|
+
// JS passes them as a prop - so they are initialized after the constructor is called.
|
|
24
|
+
override var h1FontSize: Int = 72
|
|
25
|
+
override var h1Bold: Boolean = false
|
|
26
|
+
|
|
27
|
+
override var h2FontSize: Int = 64
|
|
28
|
+
override var h2Bold: Boolean = false
|
|
29
|
+
|
|
30
|
+
override var h3FontSize: Int = 56
|
|
31
|
+
override var h3Bold: Boolean = false
|
|
32
|
+
|
|
33
|
+
override var h4FontSize: Int = 48
|
|
34
|
+
override var h4Bold: Boolean = false
|
|
35
|
+
|
|
36
|
+
override var h5FontSize: Int = 40
|
|
37
|
+
override var h5Bold: Boolean = false
|
|
38
|
+
|
|
39
|
+
override var h6FontSize: Int = 32
|
|
40
|
+
override var h6Bold: Boolean = false
|
|
41
|
+
|
|
42
|
+
override var blockquoteColor: Int? = null
|
|
43
|
+
override var blockquoteBorderColor: Int = Color.BLACK
|
|
44
|
+
override var blockquoteStripeWidth: Int = 2
|
|
45
|
+
override var blockquoteGapWidth: Int = 16
|
|
46
|
+
|
|
47
|
+
override var olGapWidth: Int = 16
|
|
48
|
+
override var olMarginLeft: Int = 24
|
|
49
|
+
override var olMarkerFontWeight: Int? = null
|
|
50
|
+
override var olMarkerColor: Int? = null
|
|
51
|
+
|
|
52
|
+
override var ulGapWidth: Int = 16
|
|
53
|
+
override var ulMarginLeft: Int = 24
|
|
54
|
+
override var ulBulletSize: Int = 8
|
|
55
|
+
override var ulBulletColor: Int = Color.BLACK
|
|
56
|
+
|
|
57
|
+
override var ulCheckboxBoxSize: Int = 50
|
|
58
|
+
override var ulCheckboxGapWidth: Int = 16
|
|
59
|
+
override var ulCheckboxMarginLeft: Int = 24
|
|
60
|
+
override var ulCheckboxBoxColor: Int = Color.BLACK
|
|
61
|
+
|
|
62
|
+
override var aColor: Int = Color.BLACK
|
|
63
|
+
override var aUnderline: Boolean = true
|
|
64
|
+
|
|
65
|
+
override var codeBlockColor: Int = Color.BLACK
|
|
66
|
+
override var codeBlockBackgroundColor: Int = Color.BLACK
|
|
67
|
+
override var codeBlockRadius: Float = 4f
|
|
68
|
+
|
|
69
|
+
override var inlineCodeColor: Int = Color.BLACK
|
|
70
|
+
override var inlineCodeBackgroundColor: Int = Color.BLACK
|
|
71
|
+
|
|
72
|
+
override var mentionsStyle: MutableMap<String, MentionStyle> = mutableMapOf()
|
|
73
|
+
|
|
74
|
+
constructor(view: EnrichedTextInputView?, style: ReadableMap?) {
|
|
75
|
+
this.view = view
|
|
76
|
+
this.style = style
|
|
77
|
+
|
|
78
|
+
invalidateStyles()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fun invalidateStyles() {
|
|
82
|
+
val style = this.style ?: return
|
|
83
|
+
|
|
84
|
+
val h1Style = style.getMap("h1")
|
|
85
|
+
h1FontSize = parseFloat(h1Style, "fontSize").toInt()
|
|
86
|
+
h1Bold = h1Style?.getBoolean("bold") == true
|
|
87
|
+
|
|
88
|
+
val h2Style = style.getMap("h2")
|
|
89
|
+
h2FontSize = parseFloat(h2Style, "fontSize").toInt()
|
|
90
|
+
h2Bold = h2Style?.getBoolean("bold") == true
|
|
91
|
+
|
|
92
|
+
val h3Style = style.getMap("h3")
|
|
93
|
+
h3FontSize = parseFloat(h3Style, "fontSize").toInt()
|
|
94
|
+
h3Bold = h3Style?.getBoolean("bold") == true
|
|
95
|
+
|
|
96
|
+
val h4Style = style.getMap("h4")
|
|
97
|
+
h4FontSize = parseFloat(h4Style, "fontSize").toInt()
|
|
98
|
+
h4Bold = h4Style?.getBoolean("bold") == true
|
|
99
|
+
|
|
100
|
+
val h5Style = style.getMap("h5")
|
|
101
|
+
h5FontSize = parseFloat(h5Style, "fontSize").toInt()
|
|
102
|
+
h5Bold = h5Style?.getBoolean("bold") == true
|
|
103
|
+
|
|
104
|
+
val h6Style = style.getMap("h6")
|
|
105
|
+
h6FontSize = parseFloat(h6Style, "fontSize").toInt()
|
|
106
|
+
h6Bold = h6Style?.getBoolean("bold") == true
|
|
107
|
+
|
|
108
|
+
val blockquoteStyle = style.getMap("blockquote")
|
|
109
|
+
blockquoteColor = parseOptionalColor(blockquoteStyle, "color")
|
|
110
|
+
blockquoteBorderColor = parseColor(blockquoteStyle, "borderColor")
|
|
111
|
+
blockquoteGapWidth = parseFloat(blockquoteStyle, "gapWidth").toInt()
|
|
112
|
+
blockquoteStripeWidth = parseFloat(blockquoteStyle, "borderWidth").toInt()
|
|
113
|
+
|
|
114
|
+
val olStyle = style.getMap("ol")
|
|
115
|
+
val userDefinedMarginLeft = parseFloat(olStyle, "marginLeft").toInt()
|
|
116
|
+
val calculatedMarginLeft = calculateOlMarginLeft(view, userDefinedMarginLeft)
|
|
117
|
+
olMarginLeft = calculatedMarginLeft
|
|
118
|
+
olGapWidth = parseFloat(olStyle, "gapWidth").toInt()
|
|
119
|
+
olMarkerColor = parseOptionalColor(olStyle, "markerColor")
|
|
120
|
+
olMarkerFontWeight = parseOptionalFontWeight(olStyle, "markerFontWeight")
|
|
121
|
+
|
|
122
|
+
val ulStyle = style.getMap("ul")
|
|
123
|
+
ulBulletColor = parseColor(ulStyle, "bulletColor")
|
|
124
|
+
ulGapWidth = parseFloat(ulStyle, "gapWidth").toInt()
|
|
125
|
+
ulMarginLeft = parseFloat(ulStyle, "marginLeft").toInt()
|
|
126
|
+
ulBulletSize = parseFloat(ulStyle, "bulletSize").toInt()
|
|
127
|
+
|
|
128
|
+
val ulCheckboxStyle = style.getMap("ulCheckbox")
|
|
129
|
+
ulCheckboxBoxSize = parseFloat(ulCheckboxStyle, "boxSize").toInt()
|
|
130
|
+
ulCheckboxGapWidth = parseFloat(ulCheckboxStyle, "gapWidth").toInt()
|
|
131
|
+
ulCheckboxMarginLeft = parseFloat(ulCheckboxStyle, "marginLeft").toInt()
|
|
132
|
+
ulCheckboxBoxColor = parseColor(ulCheckboxStyle, "boxColor")
|
|
133
|
+
|
|
134
|
+
val aStyle = style.getMap("a")
|
|
135
|
+
aColor = parseColor(aStyle, "color")
|
|
136
|
+
aUnderline = parseIsUnderline(aStyle)
|
|
137
|
+
|
|
138
|
+
val codeBlockStyle = style.getMap("codeblock")
|
|
139
|
+
codeBlockRadius = parseFloat(codeBlockStyle, "borderRadius")
|
|
140
|
+
codeBlockColor = parseColor(codeBlockStyle, "color")
|
|
141
|
+
codeBlockBackgroundColor = parseColorWithOpacity(codeBlockStyle, "backgroundColor", 80)
|
|
142
|
+
|
|
143
|
+
val inlineCodeStyle = style.getMap("code")
|
|
144
|
+
inlineCodeColor = parseColor(inlineCodeStyle, "color")
|
|
145
|
+
inlineCodeBackgroundColor = parseColorWithOpacity(inlineCodeStyle, "backgroundColor", 80)
|
|
146
|
+
|
|
147
|
+
val mentionStyle = style.getMap("mention")
|
|
148
|
+
mentionsStyle = parseMentionsStyle(mentionStyle)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private fun parseFloat(
|
|
152
|
+
map: ReadableMap?,
|
|
153
|
+
key: String,
|
|
154
|
+
): Float {
|
|
155
|
+
val safeMap = ensureValueIsSet(map, key)
|
|
156
|
+
|
|
157
|
+
val value = safeMap.getDouble(key)
|
|
158
|
+
return ceil(PixelUtil.toPixelFromSP(value))
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private fun parseColorWithOpacity(
|
|
162
|
+
map: ReadableMap?,
|
|
163
|
+
key: String,
|
|
164
|
+
opacity: Int,
|
|
165
|
+
): Int {
|
|
166
|
+
val color = parseColor(map, key)
|
|
167
|
+
return withOpacity(color, opacity)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private fun parseOptionalColor(
|
|
171
|
+
map: ReadableMap?,
|
|
172
|
+
key: String,
|
|
173
|
+
): Int? {
|
|
174
|
+
if (map == null) return null
|
|
175
|
+
if (!map.hasKey(key)) return null
|
|
176
|
+
if (map.isNull(key)) return null
|
|
177
|
+
|
|
178
|
+
return parseColor(map, key)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private fun parseColor(
|
|
182
|
+
map: ReadableMap?,
|
|
183
|
+
key: String,
|
|
184
|
+
): Int {
|
|
185
|
+
val safeMap = ensureValueIsSet(map, key)
|
|
186
|
+
|
|
187
|
+
val color = safeMap.getDouble(key)
|
|
188
|
+
val parsedColor = ColorPropConverter.getColor(color, view?.context as ReactContext)
|
|
189
|
+
if (parsedColor == null) {
|
|
190
|
+
throw Error("Specified color value is not supported: $color")
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return parsedColor
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private fun withOpacity(
|
|
197
|
+
color: Int,
|
|
198
|
+
alpha: Int,
|
|
199
|
+
): Int {
|
|
200
|
+
// Do not apply opacity to transparent color
|
|
201
|
+
if (Color.alpha(color) == 0) return color
|
|
202
|
+
val a = alpha.coerceIn(0, 255)
|
|
203
|
+
return (color and 0x00FFFFFF) or (a shl 24)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private fun parseIsUnderline(map: ReadableMap?): Boolean {
|
|
207
|
+
val underline = map?.getString("textDecorationLine")
|
|
208
|
+
val isEnabled = underline == "underline"
|
|
209
|
+
val isDisabled = underline == "none"
|
|
210
|
+
|
|
211
|
+
if (isEnabled) return true
|
|
212
|
+
if (isDisabled) return false
|
|
213
|
+
|
|
214
|
+
throw Error("Specified textDecorationLine value is not supported: $underline. Supported values are 'underline' and 'none'.")
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private fun calculateOlMarginLeft(
|
|
218
|
+
view: EnrichedTextInputView?,
|
|
219
|
+
userMargin: Int,
|
|
220
|
+
): Int {
|
|
221
|
+
val fontSize = view?.fontSize?.toInt() ?: 0
|
|
222
|
+
val leadMargin = fontSize / 2
|
|
223
|
+
|
|
224
|
+
return leadMargin + userMargin
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private fun ensureValueIsSet(
|
|
228
|
+
map: ReadableMap?,
|
|
229
|
+
key: String,
|
|
230
|
+
): ReadableMap {
|
|
231
|
+
if (map == null) throw Error("Style map cannot be null")
|
|
232
|
+
|
|
233
|
+
if (!map.hasKey(key)) throw Error("Style map must contain key: $key")
|
|
234
|
+
|
|
235
|
+
if (map.isNull(key)) throw Error("Style map cannot contain null value for key: $key")
|
|
236
|
+
|
|
237
|
+
return map
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
private fun parseMentionsStyle(mentionsStyle: ReadableMap?): MutableMap<String, MentionStyle> {
|
|
241
|
+
if (mentionsStyle == null) throw Error("Mentions style cannot be null")
|
|
242
|
+
|
|
243
|
+
val parsedMentionsStyle: MutableMap<String, MentionStyle> = mutableMapOf()
|
|
244
|
+
|
|
245
|
+
val iterator = mentionsStyle.keySetIterator()
|
|
246
|
+
while (iterator.hasNextKey()) {
|
|
247
|
+
val key = iterator.nextKey()
|
|
248
|
+
val value = mentionsStyle.getMap(key)
|
|
249
|
+
|
|
250
|
+
if (value == null) throw Error("Mention style for key '$key' cannot be null")
|
|
251
|
+
|
|
252
|
+
val color = parseColor(value, "color")
|
|
253
|
+
val backgroundColor = parseColorWithOpacity(value, "backgroundColor", 80)
|
|
254
|
+
val isUnderline = parseIsUnderline(value)
|
|
255
|
+
val parsedStyle = MentionStyle(color, backgroundColor, isUnderline)
|
|
256
|
+
parsedMentionsStyle.put(key, parsedStyle)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return parsedMentionsStyle
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private fun parseOptionalFontWeight(
|
|
263
|
+
map: ReadableMap?,
|
|
264
|
+
key: String,
|
|
265
|
+
): Int? {
|
|
266
|
+
if (map == null) return null
|
|
267
|
+
if (!map.hasKey(key)) return null
|
|
268
|
+
if (map.isNull(key)) return null
|
|
269
|
+
|
|
270
|
+
val fontWeight = map.getString(key) ?: return null
|
|
271
|
+
return parseFontWeight(fontWeight)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
override fun equals(other: Any?): Boolean {
|
|
275
|
+
if (this === other) return true
|
|
276
|
+
if (other !is HtmlStyle) return false
|
|
277
|
+
|
|
278
|
+
return h1FontSize == other.h1FontSize &&
|
|
279
|
+
h1Bold == other.h1Bold &&
|
|
280
|
+
h2FontSize == other.h2FontSize &&
|
|
281
|
+
h2Bold == other.h2Bold &&
|
|
282
|
+
h3FontSize == other.h3FontSize &&
|
|
283
|
+
h3Bold == other.h3Bold &&
|
|
284
|
+
h4FontSize == other.h4FontSize &&
|
|
285
|
+
h4Bold == other.h4Bold &&
|
|
286
|
+
h5FontSize == other.h5FontSize &&
|
|
287
|
+
h5Bold == other.h5Bold &&
|
|
288
|
+
h6FontSize == other.h6FontSize &&
|
|
289
|
+
h6Bold == other.h6Bold &&
|
|
290
|
+
|
|
291
|
+
blockquoteColor == other.blockquoteColor &&
|
|
292
|
+
blockquoteBorderColor == other.blockquoteBorderColor &&
|
|
293
|
+
blockquoteStripeWidth == other.blockquoteStripeWidth &&
|
|
294
|
+
blockquoteGapWidth == other.blockquoteGapWidth &&
|
|
295
|
+
|
|
296
|
+
olGapWidth == other.olGapWidth &&
|
|
297
|
+
olMarginLeft == other.olMarginLeft &&
|
|
298
|
+
olMarkerFontWeight == other.olMarkerFontWeight &&
|
|
299
|
+
olMarkerColor == other.olMarkerColor &&
|
|
300
|
+
|
|
301
|
+
ulGapWidth == other.ulGapWidth &&
|
|
302
|
+
ulMarginLeft == other.ulMarginLeft &&
|
|
303
|
+
ulBulletSize == other.ulBulletSize &&
|
|
304
|
+
ulBulletColor == other.ulBulletColor &&
|
|
305
|
+
|
|
306
|
+
ulCheckboxBoxSize == other.ulCheckboxBoxSize &&
|
|
307
|
+
ulCheckboxGapWidth == other.ulCheckboxGapWidth &&
|
|
308
|
+
ulCheckboxMarginLeft == other.ulCheckboxMarginLeft &&
|
|
309
|
+
ulCheckboxBoxColor == other.ulCheckboxBoxColor &&
|
|
310
|
+
|
|
311
|
+
aColor == other.aColor &&
|
|
312
|
+
aUnderline == other.aUnderline &&
|
|
313
|
+
|
|
314
|
+
codeBlockColor == other.codeBlockColor &&
|
|
315
|
+
codeBlockBackgroundColor == other.codeBlockBackgroundColor &&
|
|
316
|
+
codeBlockRadius == other.codeBlockRadius &&
|
|
317
|
+
|
|
318
|
+
inlineCodeColor == other.inlineCodeColor &&
|
|
319
|
+
inlineCodeBackgroundColor == other.inlineCodeBackgroundColor &&
|
|
320
|
+
|
|
321
|
+
mentionsStyle == other.mentionsStyle
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
override fun hashCode(): Int {
|
|
325
|
+
var result = h1FontSize.hashCode()
|
|
326
|
+
result = 31 * result + h1Bold.hashCode()
|
|
327
|
+
result = 31 * result + h2FontSize.hashCode()
|
|
328
|
+
result = 31 * result + h2Bold.hashCode()
|
|
329
|
+
result = 31 * result + h3FontSize.hashCode()
|
|
330
|
+
result = 31 * result + h3Bold.hashCode()
|
|
331
|
+
result = 31 * result + h4FontSize.hashCode()
|
|
332
|
+
result = 31 * result + h4Bold.hashCode()
|
|
333
|
+
result = 31 * result + h5FontSize.hashCode()
|
|
334
|
+
result = 31 * result + h5Bold.hashCode()
|
|
335
|
+
result = 31 * result + h6FontSize.hashCode()
|
|
336
|
+
result = 31 * result + h6Bold.hashCode()
|
|
337
|
+
|
|
338
|
+
result = 31 * result + (blockquoteColor ?: 0)
|
|
339
|
+
result = 31 * result + blockquoteBorderColor.hashCode()
|
|
340
|
+
result = 31 * result + blockquoteStripeWidth.hashCode()
|
|
341
|
+
result = 31 * result + blockquoteGapWidth.hashCode()
|
|
342
|
+
|
|
343
|
+
result = 31 * result + olGapWidth.hashCode()
|
|
344
|
+
result = 31 * result + olMarginLeft.hashCode()
|
|
345
|
+
result = 31 * result + (olMarkerFontWeight?.hashCode() ?: 0)
|
|
346
|
+
result = 31 * result + (olMarkerColor ?: 0)
|
|
347
|
+
|
|
348
|
+
result = 31 * result + ulGapWidth.hashCode()
|
|
349
|
+
result = 31 * result + ulMarginLeft.hashCode()
|
|
350
|
+
result = 31 * result + ulBulletSize.hashCode()
|
|
351
|
+
result = 31 * result + ulBulletColor.hashCode()
|
|
352
|
+
|
|
353
|
+
result = 31 * result + ulCheckboxBoxSize.hashCode()
|
|
354
|
+
result = 31 * result + ulCheckboxGapWidth.hashCode()
|
|
355
|
+
result = 31 * result + ulCheckboxMarginLeft.hashCode()
|
|
356
|
+
result = 31 * result + ulCheckboxBoxColor.hashCode()
|
|
357
|
+
|
|
358
|
+
result = 31 * result + aColor.hashCode()
|
|
359
|
+
result = 31 * result + aUnderline.hashCode()
|
|
360
|
+
|
|
361
|
+
result = 31 * result + codeBlockColor.hashCode()
|
|
362
|
+
result = 31 * result + codeBlockBackgroundColor.hashCode()
|
|
363
|
+
result = 31 * result + codeBlockRadius.hashCode()
|
|
364
|
+
|
|
365
|
+
result = 31 * result + inlineCodeColor.hashCode()
|
|
366
|
+
result = 31 * result + inlineCodeBackgroundColor.hashCode()
|
|
367
|
+
|
|
368
|
+
result = 31 * result + mentionsStyle.hashCode()
|
|
369
|
+
|
|
370
|
+
return result
|
|
371
|
+
}
|
|
372
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
package com.swmansion.enriched.textinput.styles
|
|
2
|
+
|
|
3
|
+
import android.text.Editable
|
|
4
|
+
import android.text.Spannable
|
|
5
|
+
import com.swmansion.enriched.textinput.EnrichedTextInputView
|
|
6
|
+
import com.swmansion.enriched.textinput.spans.EnrichedSpans
|
|
7
|
+
import com.swmansion.enriched.textinput.utils.getSafeSpanBoundaries
|
|
8
|
+
|
|
9
|
+
class InlineStyles(
|
|
10
|
+
private val view: EnrichedTextInputView,
|
|
11
|
+
) {
|
|
12
|
+
private fun <T> setSpan(
|
|
13
|
+
spannable: Spannable,
|
|
14
|
+
type: Class<T>,
|
|
15
|
+
start: Int,
|
|
16
|
+
end: Int,
|
|
17
|
+
) {
|
|
18
|
+
val previousSpanStart = (start - 1).coerceAtLeast(0)
|
|
19
|
+
val previousSpanEnd = previousSpanStart + 1
|
|
20
|
+
val nextSpanStart = (end + 1).coerceAtMost(spannable.length)
|
|
21
|
+
val nextSpanEnd = (nextSpanStart + 1).coerceAtMost(spannable.length)
|
|
22
|
+
val previousSpans = spannable.getSpans(previousSpanStart, previousSpanEnd, type)
|
|
23
|
+
val nextSpans = spannable.getSpans(nextSpanStart, nextSpanEnd, type)
|
|
24
|
+
var minimum = start
|
|
25
|
+
var maximum = end
|
|
26
|
+
|
|
27
|
+
for (span in previousSpans) {
|
|
28
|
+
val spanStart = spannable.getSpanStart(span)
|
|
29
|
+
minimum = spanStart.coerceAtMost(minimum)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (span in nextSpans) {
|
|
33
|
+
val spanEnd = spannable.getSpanEnd(span)
|
|
34
|
+
maximum = spanEnd.coerceAtLeast(maximum)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
val spans = spannable.getSpans(minimum, maximum, type)
|
|
38
|
+
for (span in spans) {
|
|
39
|
+
spannable.removeSpan(span)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
val span = type.getDeclaredConstructor(HtmlStyle::class.java).newInstance(view.htmlStyle)
|
|
43
|
+
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(minimum, maximum)
|
|
44
|
+
spannable.setSpan(span, safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private fun <T> setAndMergeSpans(
|
|
48
|
+
spannable: Spannable,
|
|
49
|
+
type: Class<T>,
|
|
50
|
+
start: Int,
|
|
51
|
+
end: Int,
|
|
52
|
+
) {
|
|
53
|
+
val spans = spannable.getSpans(start, end, type)
|
|
54
|
+
|
|
55
|
+
// No spans setup for current selection, means we just need to assign new span
|
|
56
|
+
if (spans.isEmpty()) {
|
|
57
|
+
setSpan(spannable, type, start, end)
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
var setSpanOnFinish = false
|
|
62
|
+
|
|
63
|
+
// Some spans are present, we have to remove spans and (optionally) apply new spans
|
|
64
|
+
for (span in spans) {
|
|
65
|
+
val spanStart = spannable.getSpanStart(span)
|
|
66
|
+
val spanEnd = spannable.getSpanEnd(span)
|
|
67
|
+
var finalStart: Int? = null
|
|
68
|
+
var finalEnd: Int? = null
|
|
69
|
+
if (spanStart == -1 || spanEnd == -1) continue
|
|
70
|
+
|
|
71
|
+
spannable.removeSpan(span)
|
|
72
|
+
|
|
73
|
+
if (start == spanStart && end == spanEnd) {
|
|
74
|
+
setSpanOnFinish = false
|
|
75
|
+
} else if (start > spanStart && end < spanEnd) {
|
|
76
|
+
setSpan(spannable, type, spanStart, start)
|
|
77
|
+
setSpan(spannable, type, end, spanEnd)
|
|
78
|
+
} else if (start == spanStart && end < spanEnd) {
|
|
79
|
+
finalStart = end
|
|
80
|
+
finalEnd = spanEnd
|
|
81
|
+
} else if (start > spanStart && end == spanEnd) {
|
|
82
|
+
finalStart = spanStart
|
|
83
|
+
finalEnd = start
|
|
84
|
+
} else if (start > spanStart) {
|
|
85
|
+
finalStart = spanStart
|
|
86
|
+
finalEnd = end
|
|
87
|
+
} else if (start < spanStart && end < spanEnd) {
|
|
88
|
+
finalStart = start
|
|
89
|
+
finalEnd = spanEnd
|
|
90
|
+
} else {
|
|
91
|
+
setSpanOnFinish = true
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!setSpanOnFinish && finalStart != null && finalEnd != null) {
|
|
95
|
+
setSpan(spannable, type, finalStart, finalEnd)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (setSpanOnFinish) {
|
|
100
|
+
setSpan(spannable, type, start, end)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
fun afterTextChanged(
|
|
105
|
+
s: Editable,
|
|
106
|
+
endCursorPosition: Int,
|
|
107
|
+
) {
|
|
108
|
+
for ((style, config) in EnrichedSpans.inlineSpans) {
|
|
109
|
+
val start = view.spanState?.getStart(style) ?: continue
|
|
110
|
+
var end = endCursorPosition
|
|
111
|
+
val spans = s.getSpans(start, end, config.clazz)
|
|
112
|
+
|
|
113
|
+
for (span in spans) {
|
|
114
|
+
end = s.getSpanEnd(span).coerceAtLeast(end)
|
|
115
|
+
s.removeSpan(span)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
setSpan(s, config.clazz, start, end)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
fun toggleStyle(name: String) {
|
|
123
|
+
if (view.selection == null) return
|
|
124
|
+
val (start, end) = view.selection.getInlineSelection()
|
|
125
|
+
val config = EnrichedSpans.inlineSpans[name] ?: return
|
|
126
|
+
val type = config.clazz
|
|
127
|
+
|
|
128
|
+
// We either start or end current span
|
|
129
|
+
if (start == end) {
|
|
130
|
+
val styleStart = view.spanState?.getStart(name)
|
|
131
|
+
|
|
132
|
+
if (styleStart != null) {
|
|
133
|
+
view.spanState.setStart(name, null)
|
|
134
|
+
} else {
|
|
135
|
+
view.spanState?.setStart(name, start)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
val spannable = view.text as Spannable
|
|
142
|
+
setAndMergeSpans(spannable, type, start, end)
|
|
143
|
+
view.selection.validateStyles()
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
fun removeStyle(
|
|
147
|
+
name: String,
|
|
148
|
+
start: Int,
|
|
149
|
+
end: Int,
|
|
150
|
+
): Boolean {
|
|
151
|
+
val config = EnrichedSpans.inlineSpans[name] ?: return false
|
|
152
|
+
val spannable = view.text as Spannable
|
|
153
|
+
val spans = spannable.getSpans(start, end, config.clazz)
|
|
154
|
+
if (spans.isEmpty()) return false
|
|
155
|
+
|
|
156
|
+
for (span in spans) {
|
|
157
|
+
spannable.removeSpan(span)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return true
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
fun getStyleRange(): Pair<Int, Int> = view.selection?.getInlineSelection() ?: Pair(0, 0)
|
|
164
|
+
}
|