t3-code-android-nightly/apps/mobile/modules/t3-markdown-text/ios/T3MarkdownTextRun.mm
Julius Marminge 8dc07f199c
chore(mobile): upgrade to Expo SDK 58 and React Native 0.88 RC (#12045)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-10-01 10:51:22 -07:00

140 lines
4.3 KiB
Text

#import "T3MarkdownTextRun.h"
#import "T3MarkdownText.h"
#import "T3MarkdownTextRunComponentDescriptor.h"
#import <react/renderer/components/T3MarkdownTextSpec/EventEmitters.h>
#import <react/renderer/components/T3MarkdownTextSpec/Props.h>
#import <react/renderer/components/T3MarkdownTextSpec/RCTComponentViewHelpers.h>
#import <React/RCTFabricComponentsPlugins.h>
#import "Utils.h"
using namespace facebook::react;
@interface T3MarkdownTextRun () <RCTT3MarkdownTextRunViewProtocol>
@end
@implementation T3MarkdownTextRun {
NSString * _text;
NSString * _contextMenuConfig;
}
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<T3MarkdownTextRunComponentDescriptor>();
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const T3MarkdownTextRunProps>();
_props = defaultProps;
}
return self;
}
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
{
const auto &oldViewProps = *std::static_pointer_cast<T3MarkdownTextRunProps const>(_props);
const auto &newViewProps = *std::static_pointer_cast<T3MarkdownTextRunProps const>(props);
if (newViewProps.text != oldViewProps.text) {
NSString *text = [NSString stringWithUTF8String:newViewProps.text.c_str()];
_text = text;
}
if (newViewProps.contextMenuConfig != oldViewProps.contextMenuConfig) {
_contextMenuConfig = [NSString stringWithUTF8String:newViewProps.contextMenuConfig.c_str()];
}
[super updateProps:props oldProps:oldProps];
}
- (BOOL)hasContextMenu
{
return _contextMenuConfig.length > 0;
}
- (nullable UIMenu *)contextMenu
{
if (_contextMenuConfig.length == 0) {
return nil;
}
NSData *data = [_contextMenuConfig dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *config = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if (![config isKindOfClass:[NSDictionary class]]) {
return nil;
}
NSArray *actionConfigs = config[@"actions"];
if (![actionConfigs isKindOfClass:[NSArray class]] || actionConfigs.count == 0) {
return nil;
}
NSMutableArray<UIMenuElement *> *actions = [NSMutableArray arrayWithCapacity:actionConfigs.count];
__weak T3MarkdownTextRun *weakSelf = self;
for (NSDictionary *actionConfig in actionConfigs) {
if (![actionConfig isKindOfClass:[NSDictionary class]]) {
continue;
}
NSString *actionIdentifier = actionConfig[@"id"];
NSString *title = actionConfig[@"title"];
if (![actionIdentifier isKindOfClass:[NSString class]] ||
![title isKindOfClass:[NSString class]]) {
continue;
}
UIAction *action = [UIAction actionWithTitle:title
image:nil
identifier:actionIdentifier
handler:^(__kindof UIAction *selectedAction) {
[weakSelf onContextMenuAction:selectedAction.identifier];
}];
if ([actionConfig[@"disabled"] boolValue]) {
action.attributes = UIMenuElementAttributesDisabled;
}
[actions addObject:action];
}
if (actions.count == 0) {
return nil;
}
NSString *title = [config[@"title"] isKindOfClass:[NSString class]] ? config[@"title"] : @"";
return [UIMenu menuWithTitle:title children:actions];
}
- (void)onContextMenuAction:(NSString *)actionIdentifier
{
if (_eventEmitter != nullptr) {
std::dynamic_pointer_cast<const facebook::react::T3MarkdownTextRunEventEmitter>(_eventEmitter)
->onContextMenuAction(facebook::react::T3MarkdownTextRunEventEmitter::OnContextMenuAction{
static_cast<int>(self.tag),
actionIdentifier.UTF8String,
});
}
}
- (void)onPress {
if (_eventEmitter != nullptr) {
std::dynamic_pointer_cast<const facebook::react::T3MarkdownTextRunEventEmitter>(_eventEmitter)
->onPress(facebook::react::T3MarkdownTextRunEventEmitter::OnPress{});
}
}
- (void)onLongPress {
if (_eventEmitter != nullptr) {
std::dynamic_pointer_cast<const facebook::react::T3MarkdownTextRunEventEmitter>(_eventEmitter)
->onLongPress(facebook::react::T3MarkdownTextRunEventEmitter::OnLongPress{});
}
}
+ (BOOL)shouldBeRecycled {
return NO;
}
Class<RCTComponentViewProtocol> T3MarkdownTextRunCls(void)
{
return T3MarkdownTextRun.class;
}
@end