-
Notifications
You must be signed in to change notification settings - Fork 21
feat: add ability to get html value imperatively #228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8945ee0
b49532b
835a11c
1c2ae28
1b9c173
3ef7ff8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.swmansion.enriched | ||
|
|
||
| import com.facebook.react.bridge.ReactApplicationContext | ||
| import com.facebook.react.bridge.UiThreadUtil | ||
| import com.facebook.react.module.annotations.ReactModule | ||
| import com.facebook.react.uimanager.UIManagerHelper | ||
| import com.swmansion.enriched.utils.EnrichedParser | ||
|
|
||
| @ReactModule(name = EnrichedTextInputModule.NAME) | ||
| class EnrichedTextInputModule(val reactContext: ReactApplicationContext) : | ||
| NativeEnrichedTextInputModuleSpec(reactContext) { | ||
| override fun getName(): String = NAME | ||
|
|
||
| override fun getHTMLValue(inputTag: Double): String? { | ||
| UiThreadUtil.assertOnUiThread() | ||
| val reactNode = inputTag.toInt() | ||
| val enrichedInput = getComponent(reactNode) | ||
| return enrichedInput?.getHtmlValue() ?: "" | ||
| } | ||
|
|
||
| private fun getComponent(reactTag: Int): EnrichedTextInputView? { | ||
| return try { | ||
| val uiManager = UIManagerHelper.getUIManagerForReactTag(reactContext, reactTag) | ||
| uiManager?.resolveView(reactTag) as? EnrichedTextInputView | ||
| } catch (_: Throwable) { | ||
| null | ||
| } | ||
| } | ||
|
|
||
| companion object { | ||
| const val NAME = "EnrichedTextInputModule" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,38 @@ | ||
| package com.swmansion.enriched | ||
|
|
||
| import com.facebook.react.ReactPackage | ||
| import com.facebook.react.BaseReactPackage | ||
| import com.facebook.react.uimanager.ViewManager | ||
| import com.facebook.react.bridge.NativeModule | ||
| import com.facebook.react.bridge.ReactApplicationContext | ||
| import com.facebook.react.uimanager.ViewManager | ||
| import java.util.ArrayList | ||
| import com.facebook.react.module.model.ReactModuleInfo | ||
| import com.facebook.react.module.model.ReactModuleInfoProvider | ||
| import java.util.HashMap | ||
|
|
||
| class EnrichedTextInputViewPackage : ReactPackage { | ||
| class EnrichedTextInputViewPackage : BaseReactPackage() { | ||
| override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> { | ||
| val viewManagers: MutableList<ViewManager<*, *>> = ArrayList() | ||
| viewManagers.add(EnrichedTextInputViewManager()) | ||
| return viewManagers | ||
| return listOf(EnrichedTextInputViewManager()) | ||
| } | ||
|
|
||
| override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> { | ||
| return emptyList() | ||
| } | ||
| } | ||
| override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { | ||
| return if (name == EnrichedTextInputModule.NAME) { | ||
| EnrichedTextInputModule(reactContext) | ||
| } else { | ||
| null | ||
| } | ||
| } | ||
|
|
||
| override fun getReactModuleInfoProvider(): ReactModuleInfoProvider { | ||
| return ReactModuleInfoProvider { | ||
| val moduleMap: MutableMap<String, ReactModuleInfo> = HashMap() | ||
| moduleMap[EnrichedTextInputModule.NAME] = ReactModuleInfo( | ||
| EnrichedTextInputModule.NAME, | ||
| EnrichedTextInputModule.NAME, | ||
| false, // canOverrideExistingModule | ||
| false, // needsEagerInit | ||
| false, // isCxxModule | ||
| true // isTurboModule | ||
| ) | ||
| moduleMap | ||
| } | ||
| } | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // | ||
| // EnrichedTextInputModule.h | ||
| // ReactNativeEnriched | ||
| // | ||
| // Created by Ivan Ignathuk on 04/11/2025. | ||
| // | ||
|
|
||
| #import <Foundation/Foundation.h> | ||
| #import <ReactNativeEnriched/RNEnrichedTextInputViewSpec.h> | ||
| #import <React/RCTBridge.h> | ||
| #import <React/RCTUIManager.h> | ||
|
|
||
| NS_ASSUME_NONNULL_BEGIN | ||
|
|
||
| @interface EnrichedTextInputModule : NSObject<NativeEnrichedTextInputModuleSpec> | ||
| @property (nonatomic, weak) RCTBridge *bridge; | ||
|
|
||
| @end | ||
|
|
||
| NS_ASSUME_NONNULL_END |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // | ||
| // EnrichedTextInputModule.m | ||
| // ReactNativeEnriched | ||
| // | ||
| // Created by Ivan Ignathuk on 04/11/2025. | ||
| // | ||
|
|
||
| #import "EnrichedTextInputModule.h" | ||
| #import "EnrichedTextInputView.h" | ||
|
|
||
| static UIView *findViewByReactTag(NSInteger reactTag, RCTBridge *bridge) { | ||
| if (bridge.uiManager) { | ||
| UIView *view = [bridge.uiManager viewForReactTag:@(reactTag)]; | ||
| if (view) { | ||
| return view; | ||
| } | ||
| } | ||
|
|
||
| return nil; | ||
| } | ||
|
|
||
| @implementation EnrichedTextInputModule | ||
|
|
||
| - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params { | ||
| return std::make_shared<facebook::react::NativeEnrichedTextInputModuleSpecJSI>(params); | ||
| } | ||
|
|
||
| - (nonnull NSString *)getHTMLValue:(NSInteger)inputTag { | ||
| __block NSString *value = @""; | ||
|
|
||
| dispatch_sync(dispatch_get_main_queue(), ^{ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't like the fact that we need
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, I have a compromise approach. We can keep this method and add another one
It would be nice to hear your point of view 🙂 |
||
| UIView *view = findViewByReactTag(inputTag, self.bridge); | ||
| if ([view isKindOfClass:[EnrichedTextInputView class]]) { | ||
| EnrichedTextInputView *enrichedTextView = (EnrichedTextInputView *)view; | ||
| value = [enrichedTextView getHTMLValue]; | ||
| } | ||
| }); | ||
|
|
||
| return value; | ||
| } | ||
|
|
||
| + (NSString *)moduleName { | ||
| return @"EnrichedTextInputModule"; | ||
| } | ||
|
|
||
| @end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { TurboModuleRegistry } from 'react-native'; | ||
| import type { TurboModule } from 'react-native'; | ||
| import type { Int32 } from 'react-native/Libraries/Types/CodegenTypes'; | ||
|
|
||
| interface Spec extends TurboModule { | ||
| getHTMLValue(inputTag: Int32): string; | ||
| } | ||
|
|
||
| export default TurboModuleRegistry.getEnforcing<Spec>( | ||
| 'EnrichedTextInputModule' | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like the fact that this PR introduces a native module. Why exactly is that needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is necessary because native commands do not allow you to return any values. If you have any other ideas on how the second option in this list can be implemented without a module, I would be happy to change the current implementation 🙂