mattermost-mobile-upstream/libraries/@mattermost/secure-pdf-viewer/ios/RCTSecurePDFViewerComponentView.mm
Elias Nahum b6fc85385e
Migrate from RNN to Expo router (#9402)
* Expo-Router partial migration

* Full migration to ExpoRouter

* i18n

* add tests

* Merge branch 'main' into expo-router

* align package-lock.json

* i18n

* feedback review

* feedback review

* android 16kb patch

* Refactored emoji picker keyboard using a state machine

* set android launch_screen in drawables instead of layout

* no conditional hooks

* remove duplicate call in test

* address feedback

* fix tests and address more feedback

* small corrections

* small corrections

* small corrections

* fix draft test

* fix draft test 2

* remove navigateToScreen in draff test

* fix nit in draft test

* remove doc file

* Feedback review

* fix snapshots

* improve test coverage

* fix i18n

* Upgrade t o RN 0.83, other dependencies and new architecture (#9737)

* library hardware-keyboard android new arch support fix

* library rnshare android new arch support fix

* library rnutils android new arch support fix

* library secure-pdf-viewer add new arch support

* Enable new arch on iOS and Android

* update emm and network client with new-arch

* update intune to use new-arch

* performance improvements

* fix tests

* fixes post input on new-arch

* fix android emoji picker

* remove doc

* run tests in parallel

* upgrade to React Native 0.83.9, Expo 55, React 19, and New Architecture

Bumps core dependencies to their latest versions:
- React Native 0.77.3 → 0.83.9 (New Architecture enabled)
- React 18.3.1 → 19.2.5
- Expo SDK 52 → 55
- TypeScript 5.8.3 → 6.0.3
- Node.js 22.16.0 → 24.15.0
- react-native-reanimated 3.17.3 → 4.3.0
- Various other dependency upgrades

Migrates iOS AppDelegate from Objective-C to Swift, updates Android
build tooling and Gradle wrapper, refreshes all patches and font
assets, and adapts app code, tests, and CI workflows throughout for
API changes introduced by these upgrades.

* remove unecessary dismissKeyboard in notifications

* feedback review

* update intune to use new-arch

* update @mattermost deps

* missing i18n string

* additional fixes

* update fastlane
2026-05-13 17:44:55 +08:00

187 lines
6.7 KiB
Plaintext

#ifdef RCT_NEW_ARCH_ENABLED
#import "RCTSecurePDFViewerComponentView.h"
#import <React/RCTConversions.h>
#import <React/RCTComponentViewFactory.h>
#import <React/RCTFabricComponentsPlugins.h>
#import <React/RCTViewComponentView.h>
#import "react/renderer/components/SecurePdfViewer/ComponentDescriptors.h"
#import "react/renderer/components/SecurePdfViewer/EventEmitters.h"
#import "react/renderer/components/SecurePdfViewer/Props.h"
#import "react/renderer/components/SecurePdfViewer/RCTComponentViewHelpers.h"
#if __has_include("secure_pdf_viewer-Swift.h")
#import "secure_pdf_viewer-Swift.h"
#else
#import <secure_pdf_viewer/secure_pdf_viewer-Swift.h>
#endif
using namespace facebook::react;
@interface RCTSecurePDFViewerComponentView ()
@end
@implementation RCTSecurePDFViewerComponentView {
SecurePdfViewerComponentView *_swiftView;
std::shared_ptr<const SecurePdfViewerProps> _props;
std::shared_ptr<const SecurePdfViewerEventEmitter> _eventEmitter;
BOOL _needsForceUpdate;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const SecurePdfViewerProps>();
_props = defaultProps;
_needsForceUpdate = NO;
_swiftView = [[SecurePdfViewerComponentView alloc] initWithFrame:self.bounds];
_swiftView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.contentView = _swiftView;
}
return self;
}
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps {
const auto &oldViewProps = *std::static_pointer_cast<SecurePdfViewerProps const>(_props);
const auto &newViewProps = *std::static_pointer_cast<SecurePdfViewerProps const>(props);
// Force update source if the component was recycled, even if the source is the same
if (oldViewProps.source != newViewProps.source || _needsForceUpdate) {
_swiftView.source = [NSString stringWithUTF8String:newViewProps.source.c_str()];
_needsForceUpdate = NO;
}
if (oldViewProps.password != newViewProps.password || _needsForceUpdate) {
if (!newViewProps.password.empty()) {
_swiftView.password = [NSString stringWithUTF8String:newViewProps.password.c_str()];
}
}
if (oldViewProps.allowLinks != newViewProps.allowLinks) {
_swiftView.allowLinks = newViewProps.allowLinks;
}
[super updateProps:props oldProps:oldProps];
_props = std::static_pointer_cast<const SecurePdfViewerProps>(props);
}
- (void)updateEventEmitter:(EventEmitter::Shared const &)eventEmitter {
[super updateEventEmitter:eventEmitter];
_eventEmitter = std::static_pointer_cast<SecurePdfViewerEventEmitter const>(eventEmitter);
__weak __typeof(self) weakSelf = self;
_swiftView.onLinkPressed = ^(NSDictionary *payload) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf && strongSelf->_eventEmitter) {
auto eventEmitter = strongSelf->_eventEmitter;
SecurePdfViewerEventEmitter::OnLinkPressed event;
event.url = std::string([[payload objectForKey:@"url"] UTF8String] ?: "");
eventEmitter->onLinkPressed(event);
}
};
_swiftView.onLinkPressedDisabled = ^(NSDictionary *payload) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf && strongSelf->_eventEmitter) {
auto eventEmitter = strongSelf->_eventEmitter;
eventEmitter->onLinkPressedDisabled({});
}
};
_swiftView.onLoad = ^(NSDictionary *payload) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf && strongSelf->_eventEmitter) {
auto eventEmitter = strongSelf->_eventEmitter;
eventEmitter->onLoad({});
}
};
_swiftView.onPasswordRequired = ^(NSDictionary *payload) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf && strongSelf->_eventEmitter) {
auto eventEmitter = strongSelf->_eventEmitter;
SecurePdfViewerEventEmitter::OnPasswordRequired event;
event.maxAttempts = [[payload objectForKey:@"maxAttempts"] intValue];
event.remainingAttempts = [[payload objectForKey:@"remainingAttempts"] intValue];
eventEmitter->onPasswordRequired(event);
}
};
_swiftView.onPasswordFailed = ^(NSDictionary *payload) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf && strongSelf->_eventEmitter) {
auto eventEmitter = strongSelf->_eventEmitter;
SecurePdfViewerEventEmitter::OnPasswordFailed event;
event.remainingAttempts = [[payload objectForKey:@"remainingAttempts"] intValue];
eventEmitter->onPasswordFailed(event);
}
};
_swiftView.onPasswordFailureLimitReached = ^(NSDictionary *payload) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf && strongSelf->_eventEmitter) {
auto eventEmitter = strongSelf->_eventEmitter;
SecurePdfViewerEventEmitter::OnPasswordFailureLimitReached event;
event.maxAttempts = [[payload objectForKey:@"maxAttempts"] intValue];
eventEmitter->onPasswordFailureLimitReached(event);
}
};
_swiftView.onLoadError = ^(NSDictionary *payload) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf && strongSelf->_eventEmitter) {
auto eventEmitter = strongSelf->_eventEmitter;
SecurePdfViewerEventEmitter::OnLoadError event;
event.message = std::string([[payload objectForKey:@"message"] UTF8String] ?: "");
eventEmitter->onLoadError(event);
}
};
_swiftView.onTap = ^(NSDictionary *payload) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf && strongSelf->_eventEmitter) {
auto eventEmitter = strongSelf->_eventEmitter;
SecurePdfViewerEventEmitter::OnTap event;
event.x = [[payload objectForKey:@"x"] doubleValue];
event.y = [[payload objectForKey:@"y"] doubleValue];
eventEmitter->onTap(event);
}
};
}
- (void)prepareForRecycle {
[super prepareForRecycle];
// Do NOT set _props or _eventEmitter to nullptr - Fabric will handle lifecycle
// Clear event handlers to prevent stale callbacks
_swiftView.onLinkPressed = nil;
_swiftView.onLinkPressedDisabled = nil;
_swiftView.onLoad = nil;
_swiftView.onPasswordRequired = nil;
_swiftView.onPasswordFailed = nil;
_swiftView.onPasswordFailureLimitReached = nil;
_swiftView.onLoadError = nil;
_swiftView.onTap = nil;
// Clear the PDF document and reset state to prevent showing old content
[_swiftView resetPDFState];
_swiftView.password = nil;
// Set flag to force update on next props, even if source is the same
_needsForceUpdate = YES;
}
+ (ComponentDescriptorProvider)componentDescriptorProvider {
return concreteComponentDescriptorProvider<SecurePdfViewerComponentDescriptor>();
}
@end
Class<RCTComponentViewProtocol> SecurePdfViewerCls(void) {
return RCTSecurePDFViewerComponentView.class;
}
#endif