Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import type {HostInstance} from '../../../src/private/types/HostInstance';
import type {
DataTransfer,
GestureResponderEvent,
NativeSyntheticEvent,
ScrollEvent,
Expand Down Expand Up @@ -108,20 +109,7 @@ export type SettingChangeEvent = NativeSyntheticEvent<

export type PasteEvent = NativeSyntheticEvent<
$ReadOnly<{|
dataTransfer: {|
files: $ReadOnlyArray<{|
height: number,
size: number,
type: string,
uri: string,
width: number,
|}>,
items: $ReadOnlyArray<{|
kind: string,
type: string,
|}>,
types: $ReadOnlyArray<string>,
|},
dataTransfer: DataTransfer,
|}>,
>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import type {HostInstance} from '../../../src/private/types/HostInstance';
import type {____TextStyle_Internal as TextStyleInternal} from '../../StyleSheet/StyleSheetTypes';
import type {
DataTransfer,
GestureResponderEvent,
NativeSyntheticEvent,
ScrollEvent,
Expand Down Expand Up @@ -143,20 +144,7 @@ export type SettingChangeEvent = NativeSyntheticEvent<

export type PasteEvent = NativeSyntheticEvent<
$ReadOnly<{|
dataTransfer: {|
files: $ReadOnlyArray<{|
height: number,
size: number,
type: string,
uri: string,
width: number,
|}>,
items: $ReadOnlyArray<{|
kind: string,
type: string,
|}>,
types: $ReadOnlyArray<string>,
|},
dataTransfer: DataTransfer,
|}>,
>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ NS_ASSUME_NONNULL_BEGIN
#if TARGET_OS_OSX // [macOS
// UITextInput method for OSX
- (CGSize)sizeThatFits:(CGSize)size;
- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes;
#endif // macOS]

// This protocol disallows direct access to `text` property because
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong, nullable) RCTUIColor *selectionColor;
@property (weak, nullable) id<RCTUITextFieldDelegate> delegate;
@property (nonatomic, assign) CGFloat pointScaleFactor;

- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes;
#endif // macOS]

@property (nonatomic, getter=isGhostTextChanging) BOOL ghostTextChanging; // [macOS]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ @implementation RCTUITextField {
#endif // [macOS]
#if TARGET_OS_OSX // [macOS
BOOL _isUpdatingPlaceholderText;
NSArray<NSPasteboardType> *_readablePasteboardTypes;
#endif // macOS]
}

Expand Down Expand Up @@ -705,5 +706,12 @@ - (void)keyUp:(NSEvent *)event {
}
}
#endif // macOS]

#if TARGET_OS_OSX // [macOS
- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes
{
_readablePasteboardTypes = readablePasteboardTypes;
}
#endif // macOS]

@end
15 changes: 10 additions & 5 deletions packages/react-native/Libraries/Types/CoreEventTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,19 +307,24 @@ export interface FocusEvent extends NativeSyntheticEvent<NativeFocusEvent> {}
export interface BlueEvent extends NativeSyntheticEvent<NativeBlurEvent> {}

// Drag and Drop types
export interface DataTransferItem {
export interface DataTransferFile {
name: string;
kind: string;
type: string;
type: string | null | undefined;
uri: string;
size?: number | undefined;
width?: number | undefined;
height?: number | undefined;
}

export interface DataTransferItem {
kind: string;
type: string | null | undefined;
}

export interface DataTransfer {
files: ReadonlyArray<DataTransferItem>;
types: ReadonlyArray<string>;
files: ReadonlyArray<DataTransferFile>;
items: ReadonlyArray<DataTransferItem>;
types: ReadonlyArray<string | null | undefined>;
}

export interface DragEvent extends MouseEvent {
Expand Down
15 changes: 10 additions & 5 deletions packages/react-native/Libraries/Types/CoreEventTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,19 +333,24 @@ export type MouseEvent = NativeSyntheticEvent<
>;

// [macOS
export type DataTransferItem = $ReadOnly<{
export type DataTransferFile = $ReadOnly<{
name: string,
kind: string,
type: string,
type: ?string,
uri: string,
size?: number,
width?: number,
height?: number,
}>;

export type DataTransferItem = $ReadOnly<{
kind: string,
type: ?string,
}>;

export type DataTransfer = $ReadOnly<{
files: $ReadOnlyArray<DataTransferItem>,
types: $ReadOnlyArray<string>,
files: $ReadOnlyArray<DataTransferFile>,
items: $ReadOnlyArray<DataTransferItem>,
types: $ReadOnlyArray<?string>,
}>;

export type DragEvent = NativeSyntheticEvent<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2711,20 +2711,7 @@ export type SettingChangeEvent = NativeSyntheticEvent<
>;
export type PasteEvent = NativeSyntheticEvent<
$ReadOnly<{|
dataTransfer: {|
files: $ReadOnlyArray<{|
height: number,
size: number,
type: string,
uri: string,
width: number,
|}>,
items: $ReadOnlyArray<{|
kind: string,
type: string,
|}>,
types: $ReadOnlyArray<string>,
|},
dataTransfer: DataTransfer,
|}>,
>;
export type SubmitKeyEvent = $ReadOnly<{|
Expand Down Expand Up @@ -3119,20 +3106,7 @@ export type SettingChangeEvent = NativeSyntheticEvent<
>;
export type PasteEvent = NativeSyntheticEvent<
$ReadOnly<{|
dataTransfer: {|
files: $ReadOnlyArray<{|
height: number,
size: number,
type: string,
uri: string,
width: number,
|}>,
items: $ReadOnlyArray<{|
kind: string,
type: string,
|}>,
types: $ReadOnlyArray<string>,
|},
dataTransfer: DataTransfer,
|}>,
>;
export type SubmitKeyEvent = $ReadOnly<{|
Expand Down Expand Up @@ -8548,18 +8522,22 @@ export type MouseEvent = NativeSyntheticEvent<
timestamp: number,
}>,
>;
export type DataTransferItem = $ReadOnly<{
export type DataTransferFile = $ReadOnly<{
name: string,
kind: string,
type: string,
type: ?string,
uri: string,
size?: number,
width?: number,
height?: number,
}>;
export type DataTransferItem = $ReadOnly<{
kind: string,
type: ?string,
}>;
export type DataTransfer = $ReadOnly<{
files: $ReadOnlyArray<DataTransferItem>,
types: $ReadOnlyArray<string>,
files: $ReadOnlyArray<DataTransferFile>,
items: $ReadOnlyArray<DataTransferItem>,
types: $ReadOnlyArray<?string>,
}>;
export type DragEvent = NativeSyntheticEvent<
$ReadOnly<{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,13 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
_backedTextInputView.disableKeyboardShortcuts = newTextInputProps.disableKeyboardShortcuts;
}

#if TARGET_OS_OSX // [macOS
if (newTextInputProps.traits.pastedTypes!= oldTextInputProps.traits.pastedTypes) {
NSArray<NSPasteboardType> *types = RCTPasteboardTypeArrayFromProps(newTextInputProps.traits.pastedTypes);
[_backedTextInputView setReadablePasteBoardTypes:types];
}
#endif // macOS]

[super updateProps:props oldProps:oldProps];

#if TARGET_OS_IOS // [macOS] [visionOS]
Expand Down Expand Up @@ -602,7 +609,19 @@ - (BOOL)textInputShouldHandleKeyEvent:(nonnull NSEvent *)event {
}

- (BOOL)textInputShouldHandlePaste:(nonnull id<RCTBackedTextInputViewProtocol>)sender {
return YES;
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSPasteboardType fileType = [pasteboard availableTypeFromArray:@[NSFilenamesPboardType, NSPasteboardTypePNG, NSPasteboardTypeTIFF]];
NSArray<NSPasteboardType>* pastedTypes = ((RCTUITextView*) _backedTextInputView).readablePasteboardTypes;

// If there's a fileType that is of interest, notify JS. Also blocks notifying JS if it's a text paste
if (_eventEmitter && fileType != nil && [pastedTypes containsObject:fileType]) {
auto const &textInputEventEmitter = *std::static_pointer_cast<TextInputEventEmitter const>(_eventEmitter);
DataTransfer dataTransfer = [self dataTransferForPasteboard:pasteboard];
textInputEventEmitter.onPaste({.dataTransfer = std::move(dataTransfer)});
}

// Only allow pasting text.
return fileType == nil;
}

#endif // macOS]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ NS_ASSUME_NONNULL_BEGIN

#if TARGET_OS_OSX // [macOS
- (BOOL)handleKeyboardEvent:(NSEvent *)event;
- (void)buildDataTransferItems:(std::vector<facebook::react::DataTransferItem> &)dataTransferItems forPasteboard:(NSPasteboard *)pasteboard;
- (facebook::react::DataTransfer)dataTransferForPasteboard:(NSPasteboard *)pasteboard;
#endif // macOS]

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
self.toolTip = nil;
}
}
#endif // [macOS]
#endif // macOS]

_needsInvalidateLayer = _needsInvalidateLayer || needsInvalidateLayer;

Expand Down Expand Up @@ -1714,7 +1714,12 @@ - (void)keyUp:(NSEvent *)event {
Drop,
};

- (void)buildDataTransferItems:(std::vector<DataTransferItem> &)dataTransferItems forPasteboard:(NSPasteboard *)pasteboard {
- (DataTransfer)dataTransferForPasteboard:(NSPasteboard *)pasteboard {
DataTransfer dataTransfer{};
auto &files = dataTransfer.files;
auto &items = dataTransfer.items;
auto &types = dataTransfer.types;

NSArray *fileNames = [pasteboard propertyListForType:NSFilenamesPboardType] ?: @[];
for (NSString *file in fileNames) {
NSURL *fileURL = [NSURL fileURLWithPath:file];
Expand All @@ -1739,25 +1744,31 @@ - (void)buildDataTransferItems:(std::vector<DataTransferItem> &)dataTransferItem
forKey:NSURLFileSizeKey
error:&fileSizeError];

DataTransferItem transferItem = {
std::string typeString = MIMETypeString != nil ? [MIMETypeString UTF8String] : "";

DataTransferFile fileEntry = {
.name = fileURL.lastPathComponent ? fileURL.lastPathComponent.UTF8String : "",
.kind = "file",
.type = MIMETypeString ? MIMETypeString.UTF8String : "",
.type = typeString,
.uri = fileURL.path ? fileURL.path.UTF8String : "",
};

if (success) {
transferItem.size = fileSizeValue.intValue;
fileEntry.size = fileSizeValue.intValue;
}

if ([MIMETypeString hasPrefix:@"image/"]) {
NSImage *image = [[NSImage alloc] initWithContentsOfURL:fileURL];
CGImageRef cgImage = [image CGImageForProposedRect:nil context:nil hints:nil];
transferItem.width = static_cast<int>(CGImageGetWidth(cgImage));
transferItem.height = static_cast<int>(CGImageGetHeight(cgImage));
fileEntry.width = static_cast<int>(CGImageGetWidth(cgImage));
fileEntry.height = static_cast<int>(CGImageGetHeight(cgImage));
}

dataTransferItems.push_back(transferItem);

files.push_back(fileEntry);
items.push_back({
.kind = "file",
.type = typeString,
});
types.push_back(typeString);
}
}

Expand All @@ -1769,18 +1780,26 @@ - (void)buildDataTransferItems:(std::vector<DataTransferItem> &)dataTransferItem
CGImageRef cgImage = [image CGImageForProposedRect:nil context:nil hints:nil];

NSString *dataURLString = RCTDataURL(MIMETypeString, imageData).absoluteString;
std::string typeString = MIMETypeString != nil ? [MIMETypeString UTF8String] : "";

DataTransferItem transferItem = {
.kind = "image",
.type = MIMETypeString ? MIMETypeString.UTF8String : "",
DataTransferFile fileEntry = {
.name = "",
.type = typeString,
.uri = dataURLString ? dataURLString.UTF8String : "",
.size = static_cast<int>(imageData.length),
.width = static_cast<int>(CGImageGetWidth(cgImage)),
.height = static_cast<int>(CGImageGetHeight(cgImage)),
};

dataTransferItems.push_back(transferItem);
fileEntry.size = static_cast<int>(imageData.length);
fileEntry.width = static_cast<int>(CGImageGetWidth(cgImage));
fileEntry.height = static_cast<int>(CGImageGetHeight(cgImage));

files.push_back(fileEntry);
items.push_back({
.kind = "image",
.type = typeString,
});
types.push_back(typeString);
}
return dataTransfer;
}

- (void)emitDragEvent:(DragEventType)eventType draggingInfo:(id<NSDraggingInfo>)sender {
Expand All @@ -1791,8 +1810,7 @@ - (void)emitDragEvent:(DragEventType)eventType draggingInfo:(id<NSDraggingInfo>)
NSPoint locationInWindow = sender.draggingLocation;
NSPasteboard *pasteboard = sender.draggingPasteboard;

std::vector<DataTransferItem> dataTransferItems{};
[self buildDataTransferItems:dataTransferItems forPasteboard:pasteboard];
DataTransfer dataTransfer = [self dataTransferForPasteboard:pasteboard];

NSPoint locationInView = [self convertPoint:locationInWindow fromView:nil];
NSEventModifierFlags modifierFlags = self.window.currentEvent.modifierFlags;
Expand All @@ -1808,7 +1826,7 @@ - (void)emitDragEvent:(DragEventType)eventType draggingInfo:(id<NSDraggingInfo>)
.shiftKey = static_cast<bool>(modifierFlags & NSEventModifierFlagShift),
.metaKey = static_cast<bool>(modifierFlags & NSEventModifierFlagCommand),
},
.dataTransferItems = dataTransferItems,
.dataTransfer = dataTransfer,
};

switch (eventType) {
Expand Down
Loading
Loading