Add option to enforce pasting plain text (#1429)
There are use cases in which we want to ignore the base class [NSTextView readablePasteboardTypes] return values, which mostly, include RTF and formatted URL types We want to ignore them in favor of plain text (NSPasteboardTypeString). This change allows to opt into a custom list of supported paste types. This is a follow-up to https://github.com/microsoft/react-native-macos/pull/1350
This commit is contained in:
Родитель
377063c627
Коммит
d8612d0376
|
@ -370,6 +370,26 @@ type MacOSProps = $ReadOnly<{|
|
|||
*/
|
||||
clearTextOnSubmit?: ?boolean,
|
||||
|
||||
/**
|
||||
* Fired when a supported element is pasted
|
||||
*
|
||||
* @platform macos
|
||||
*/
|
||||
onPaste?: (event: PasteEvent) => void,
|
||||
|
||||
/**
|
||||
* Enables Paste support for certain types of pasted types
|
||||
*
|
||||
* Possible values for `pastedTypes` are:
|
||||
*
|
||||
* - `'fileUrl'`
|
||||
* - `'image'`
|
||||
* - `'string'`
|
||||
*
|
||||
* @platform macos
|
||||
*/
|
||||
pastedTypes?: PastedTypesType,
|
||||
|
||||
/**
|
||||
* Configures keys that can be used to submit editing for the TextInput. Defaults to 'Enter' key.
|
||||
* @platform macos
|
||||
|
@ -537,10 +557,13 @@ type AndroidProps = $ReadOnly<{|
|
|||
underlineColorAndroid?: ?ColorValue,
|
||||
|}>;
|
||||
|
||||
export type PasteType = 'fileUrl' | 'image' | 'string'; // TODO(macOS GH#774)
|
||||
export type PastedTypesType = PasteType | $ReadOnlyArray<PasteType>; // TODO(macOS GH#774)
|
||||
|
||||
export type Props = $ReadOnly<{|
|
||||
...$Diff<ViewProps, $ReadOnly<{|style: ?ViewStyleProp|}>>,
|
||||
...IOSProps,
|
||||
...MacOSProps,
|
||||
...MacOSProps, // TODO(macOS GH#774)
|
||||
...AndroidProps,
|
||||
|
||||
/**
|
||||
|
@ -786,13 +809,6 @@ export type Props = $ReadOnly<{|
|
|||
*/
|
||||
onPressOut?: ?(event: PressEvent) => mixed,
|
||||
|
||||
/**
|
||||
* Fired when a supported element is pasted
|
||||
*
|
||||
* @platform macos
|
||||
*/
|
||||
onPaste?: (event: PasteEvent) => void, // TODO(macOS GH#774)
|
||||
|
||||
/**
|
||||
* Callback that is called when the text input selection is changed.
|
||||
* This will be called with
|
||||
|
|
|
@ -11,6 +11,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@interface RCTMultilineTextInputView : RCTBaseTextInputView
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS GH#774)
|
||||
- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes;
|
||||
#endif // ]TODO(macOS GH#774)
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -99,6 +99,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes {
|
||||
[_backedTextInputView setReadablePasteBoardTypes:readablePasteboardTypes];
|
||||
}
|
||||
#endif // ]TODO(macOS GH#774)
|
||||
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#import <React/RCTMultilineTextInputViewManager.h>
|
||||
#import <React/RCTMultilineTextInputView.h>
|
||||
#import <React/RCTUITextView.h> // TODO(macOS GH#774)
|
||||
|
||||
@implementation RCTMultilineTextInputViewManager
|
||||
|
||||
|
@ -22,4 +23,14 @@ RCT_EXPORT_MODULE()
|
|||
RCT_REMAP_NOT_OSX_VIEW_PROPERTY(dataDetectorTypes, backedTextInputView.dataDetectorTypes, UIDataDetectorTypes) // TODO(macOS GH#774)
|
||||
RCT_REMAP_OSX_VIEW_PROPERTY(dataDetectorTypes, backedTextInputView.enabledTextCheckingTypes, NSTextCheckingTypes) // TODO(macOS GH#774)
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS GH#774)
|
||||
RCT_CUSTOM_VIEW_PROPERTY(pastedTypes, NSArray<NSPasteboardType>*, RCTUITextView)
|
||||
{
|
||||
NSArray<NSPasteboardType> *types = json ? [RCTConvert NSPasteboardTypeArray:json] : nil;
|
||||
if ([view respondsToSelector:@selector(setReadablePasteBoardTypes:)]) {
|
||||
[view setReadablePasteBoardTypes: types];
|
||||
}
|
||||
}
|
||||
#endif // ]TODO(macOS GH#774)
|
||||
|
||||
@end
|
||||
|
|
|
@ -53,6 +53,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, assign) NSTextAlignment textAlignment;
|
||||
@property (nonatomic, copy, nullable) NSAttributedString *attributedText;
|
||||
- (NSSize)sizeThatFits:(NSSize)size;
|
||||
- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes;
|
||||
#endif // ]TODO(macOS GH#774)
|
||||
|
||||
@end
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
#endif // TODO(macOS GH#774)
|
||||
RCTBackedTextViewDelegateAdapter *_textInputDelegateAdapter;
|
||||
NSDictionary<NSAttributedStringKey, id> *_defaultTextAttributes;
|
||||
#if TARGET_OS_OSX // [TODO(macOS GH#774)
|
||||
NSArray<NSPasteboardType> *_readablePasteboardTypes;
|
||||
#endif // TODO(macOS GH#774)
|
||||
}
|
||||
|
||||
static UIFont *defaultPlaceholderFont()
|
||||
|
@ -177,6 +180,11 @@ static RCTUIColor *defaultPlaceholderColor() // TODO(OSS Candidate ISS#2710739)
|
|||
self.string = text;
|
||||
}
|
||||
|
||||
- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes
|
||||
{
|
||||
_readablePasteboardTypes = readablePasteboardTypes;
|
||||
}
|
||||
|
||||
- (void)setTypingAttributes:(__unused NSDictionary *)typingAttributes
|
||||
{
|
||||
// Prevent NSTextView from changing its own typing attributes out from under us.
|
||||
|
@ -344,9 +352,7 @@ static RCTUIColor *defaultPlaceholderColor() // TODO(OSS Candidate ISS#2710739)
|
|||
}
|
||||
- (NSArray *)readablePasteboardTypes
|
||||
{
|
||||
NSArray *types = [super readablePasteboardTypes];
|
||||
// TODO: Optionally support files/images with a prop
|
||||
return [types arrayByAddingObjectsFromArray:@[NSFilenamesPboardType, NSPasteboardTypePNG, NSPasteboardTypeTIFF]];
|
||||
return _readablePasteboardTypes ? _readablePasteboardTypes : [super readablePasteboardTypes];
|
||||
}
|
||||
|
||||
#endif // ]TODO(macOS GH#774)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#import <React/RCTInputAccessoryViewContent.h>
|
||||
#import <React/RCTTextAttributes.h>
|
||||
#import <React/RCTTextSelection.h>
|
||||
#import <React/RCTUITextView.h> // TODO(macOS GH#774)
|
||||
#import "../RCTTextUIKit.h" // TODO(macOS GH#774)
|
||||
|
||||
@implementation RCTBaseTextInputView {
|
||||
|
@ -680,10 +681,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)decoder)
|
|||
- (BOOL)textInputShouldHandlePaste:(__unused id)sender
|
||||
{
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
NSPasteboardType fileType = [pasteboard availableTypeFromArray:@[NSFilenamesPboardType, NSPasteboardTypePNG, NSPasteboardTypeTIFF]];
|
||||
|
||||
NSPasteboardType fileType = [pasteboard availableTypeFromArray:@[NSPasteboardTypeFileURL, NSPasteboardTypePNG, NSPasteboardTypeTIFF]];
|
||||
NSArray<NSPasteboardType>* pastedTypes = ((RCTUITextView*) self.backedTextInputView).readablePasteboardTypes;
|
||||
|
||||
// If there's a fileType that is of interest, notify JS. Also blocks notifying JS if it's a text paste
|
||||
if (_onPaste && fileType != nil) {
|
||||
if (_onPaste && fileType != nil && [pastedTypes containsObject:fileType]) {
|
||||
_onPaste([self dataTransferInfoFromPasteboard:pasteboard]);
|
||||
}
|
||||
|
||||
|
|
|
@ -1233,11 +1233,12 @@ RCT_JSON_ARRAY_CONVERTER(NSNumber)
|
|||
}
|
||||
|
||||
if ([type isEqualToString:@"fileUrl"]) {
|
||||
return @[NSFilenamesPboardType];
|
||||
return @[NSPasteboardTypeFileURL];
|
||||
} else if ([type isEqualToString:@"image"]) {
|
||||
return @[NSPasteboardTypePNG, NSPasteboardTypeTIFF];
|
||||
} else if ([type isEqualToString:@"string"]) {
|
||||
return @[NSPasteboardTypeString];
|
||||
}
|
||||
|
||||
return @[];
|
||||
}
|
||||
|
||||
|
@ -1246,11 +1247,11 @@ RCT_JSON_ARRAY_CONVERTER(NSNumber)
|
|||
if ([json isKindOfClass:[NSString class]]) {
|
||||
return [RCTConvert NSPasteboardType:json];
|
||||
} else if ([json isKindOfClass:[NSArray class]]) {
|
||||
NSMutableArray *mutablePastboardTypes = [NSMutableArray new];
|
||||
NSMutableArray *mutablePasteboardTypes = [NSMutableArray new];
|
||||
for (NSString *type in json) {
|
||||
[mutablePastboardTypes addObjectsFromArray:[RCTConvert NSPasteboardType:type]];
|
||||
return mutablePastboardTypes.copy;
|
||||
[mutablePasteboardTypes addObjectsFromArray:[RCTConvert NSPasteboardType:type]];
|
||||
}
|
||||
return mutablePasteboardTypes.copy;
|
||||
}
|
||||
return @[];
|
||||
}
|
||||
|
|
|
@ -427,7 +427,18 @@ function OnPaste(): React.Node {
|
|||
appendLog(JSON.stringify(e.nativeEvent.dataTransfer.types));
|
||||
setImageUri(e.nativeEvent.dataTransfer.files[0].uri);
|
||||
}}
|
||||
placeholder="MULTI LINE with onPaste() for PNG and TIFF images"
|
||||
pastedTypes={['string']}
|
||||
placeholder="MULTI LINE with onPaste() text from clipboard"
|
||||
/>
|
||||
<TextInput
|
||||
multiline={true}
|
||||
style={styles.multiline}
|
||||
onPaste={(e: PasteEvent) => {
|
||||
appendLog(JSON.stringify(e.nativeEvent.dataTransfer.types));
|
||||
setImageUri(e.nativeEvent.dataTransfer.files[0].uri);
|
||||
}}
|
||||
pastedTypes={['fileUrl', 'image', 'string']}
|
||||
placeholder="MULTI LINE with onPaste() for PNG/TIFF images from clipboard or fileUrl (via Finder) and text from clipboard"
|
||||
/>
|
||||
<Text style={{height: 30}}>{log.join('\n')}</Text>
|
||||
<Image
|
||||
|
|
Загрузка…
Ссылка в новой задаче