Merge commit '891b6b0c14d820d38f0a0b8f5ebf749c5cd14a94' into amgleitman/0.64-merge-head

This commit is contained in:
Adam Gleitman 2021-09-22 14:23:22 -07:00
Родитель 2fd7f46a8e 891b6b0c14
Коммит 4f80fbd4eb
10 изменённых файлов: 301 добавлений и 168 удалений

Просмотреть файл

@ -39,6 +39,7 @@ rn_android_library(
react_native_target("java/com/facebook/react/common:common"),
react_native_target("java/com/facebook/react/uimanager:uimanager"),
react_native_target("java/com/facebook/react/views/view:view"),
react_native_target("java/com/facebook/react/views/text:text"),
react_native_target("java/com/facebook/react/touch:touch"),
],
exported_deps = [

Просмотреть файл

@ -37,6 +37,7 @@ import com.facebook.infer.annotation.ThreadConfined;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.NativeArray;
import com.facebook.react.bridge.NativeMap;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
@ -74,6 +75,7 @@ import com.facebook.react.fabric.mounting.mountitems.UpdatePropsMountItem;
import com.facebook.react.fabric.mounting.mountitems.UpdateStateMountItem;
import com.facebook.react.modules.core.ReactChoreographer;
import com.facebook.react.modules.i18nmanager.I18nUtil;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ReactRoot;
import com.facebook.react.uimanager.ReactRootViewTagGenerator;
import com.facebook.react.uimanager.StateWrapper;
@ -82,6 +84,7 @@ import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.ViewManagerPropertyUpdater;
import com.facebook.react.uimanager.ViewManagerRegistry;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.text.TextLayoutManager;
import com.facebook.systrace.Systrace;
import java.util.ArrayDeque;
import java.util.ArrayList;
@ -443,6 +446,18 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
return new BatchMountItem(rootTag, items, size, commitNumber);
}
@DoNotStrip
@SuppressWarnings("unused")
private NativeArray measureLines(
ReadableMap attributedString, ReadableMap paragraphAttributes, float width, float height) {
return (NativeArray)
TextLayoutManager.measureLines(
mReactApplicationContext,
attributedString,
paragraphAttributes,
PixelUtil.toPixelFromDIP(width));
}
@DoNotStrip
@SuppressWarnings("unused")
private long measure(

Просмотреть файл

@ -27,6 +27,7 @@ import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ReactAccessibilityDelegate;
@ -257,51 +258,19 @@ public class TextLayoutManager {
return sb;
}
public static long measureText(
Context context,
ReadableMap attributedString,
ReadableMap paragraphAttributes,
private static Layout createLayout(
Spannable text,
BoringLayout.Metrics boring,
float width,
YogaMeasureMode widthYogaMeasureMode,
float height,
YogaMeasureMode heightYogaMeasureMode,
ReactTextViewManagerCallback reactTextViewManagerCallback,
@Nullable float[] attachmentsPositions) {
// TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic)
TextPaint textPaint = sTextPaintInstance;
Spannable text;
if (attributedString.hasKey("cacheId")) {
int cacheId = attributedString.getInt("cacheId");
if (sTagToSpannableCache.containsKey(cacheId)) {
text = sTagToSpannableCache.get(cacheId);
} else {
return 0;
}
} else {
text = getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback);
}
int textBreakStrategy =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(TEXT_BREAK_STRATEGY_KEY));
boolean includeFontPadding =
paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY)
? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY)
: DEFAULT_INCLUDE_FONT_PADDING;
if (text == null) {
throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout");
}
BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint);
float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN;
// technically, width should never be negative, but there is currently a bug in
boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0;
boolean includeFontPadding,
int textBreakStrategy) {
Layout layout;
int spanLength = text.length();
boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0;
TextPaint textPaint = sTextPaintInstance;
float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN;
if (boring == null
&& (unconstrainedWidth
|| (!YogaConstants.isUndefined(desiredWidth) && desiredWidth <= width))) {
@ -367,6 +336,55 @@ public class TextLayoutManager {
.build();
}
}
return layout;
}
public static long measureText(
Context context,
ReadableMap attributedString,
ReadableMap paragraphAttributes,
float width,
YogaMeasureMode widthYogaMeasureMode,
float height,
YogaMeasureMode heightYogaMeasureMode,
ReactTextViewManagerCallback reactTextViewManagerCallback,
@Nullable float[] attachmentsPositions) {
// TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic)
TextPaint textPaint = sTextPaintInstance;
Spannable text;
if (attributedString.hasKey("cacheId")) {
int cacheId = attributedString.getInt("cacheId");
if (sTagToSpannableCache.containsKey(cacheId)) {
text = sTagToSpannableCache.get(cacheId);
} else {
return 0;
}
} else {
text = getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback);
}
int textBreakStrategy =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(TEXT_BREAK_STRATEGY_KEY));
boolean includeFontPadding =
paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY)
? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY)
: DEFAULT_INCLUDE_FONT_PADDING;
if (text == null) {
throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout");
}
BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint);
float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN;
// technically, width should never be negative, but there is currently a bug in
boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0;
Layout layout =
createLayout(
text, boring, width, widthYogaMeasureMode, includeFontPadding, textBreakStrategy);
int maximumNumberOfLines =
paragraphAttributes.hasKey(MAXIMUM_NUMBER_OF_LINES_KEY)
@ -408,9 +426,9 @@ public class TextLayoutManager {
// follows a similar logic than used in pre-fabric (see ReactTextView.onLayout method).
int attachmentIndex = 0;
int lastAttachmentFoundInSpan;
for (int i = 0; i < spanLength; i = lastAttachmentFoundInSpan) {
for (int i = 0; i < text.length(); i = lastAttachmentFoundInSpan) {
lastAttachmentFoundInSpan =
text.nextSpanTransition(i, spanLength, TextInlineViewPlaceholderSpan.class);
text.nextSpanTransition(i, text.length(), TextInlineViewPlaceholderSpan.class);
TextInlineViewPlaceholderSpan[] placeholders =
text.getSpans(i, lastAttachmentFoundInSpan, TextInlineViewPlaceholderSpan.class);
for (TextInlineViewPlaceholderSpan placeholder : placeholders) {
@ -432,7 +450,7 @@ public class TextLayoutManager {
// There's a bug on Samsung devices where calling getPrimaryHorizontal on
// the last offset in the layout will result in an endless loop. Work around
// this bug by avoiding getPrimaryHorizontal in that case.
if (start == spanLength - 1) {
if (start == text.length() - 1) {
placeholderLeftPosition =
isRtlParagraph
// Equivalent to `layout.getLineLeft(line)` but `getLineLeft` returns incorrect
@ -502,6 +520,29 @@ public class TextLayoutManager {
return YogaMeasureOutput.make(widthInSP, heightInSP);
}
public static WritableArray measureLines(
@NonNull Context context,
ReadableMap attributedString,
ReadableMap paragraphAttributes,
float width) {
TextPaint textPaint = sTextPaintInstance;
Spannable text = getOrCreateSpannableForText(context, attributedString, null);
BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint);
int textBreakStrategy =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(TEXT_BREAK_STRATEGY_KEY));
boolean includeFontPadding =
paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY)
? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY)
: DEFAULT_INCLUDE_FONT_PADDING;
Layout layout =
createLayout(
text, boring, width, YogaMeasureMode.EXACTLY, includeFontPadding, textBreakStrategy);
return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context);
}
// TODO T31905686: This class should be private
public static class SetSpanOperation {
protected int start, end;

Просмотреть файл

@ -169,7 +169,6 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) {
content.paragraphAttributes,
layoutConstraints);
#ifndef ANDROID
if (getConcreteProps().onTextLayout) {
auto linesMeasurements = textLayoutManager_->measureLines(
content.attributedString,
@ -177,7 +176,6 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) {
measurement.size);
getConcreteEventEmitter().onTextLayout(linesMeasurements);
}
#endif
if (content.attachments.empty()) {
// No attachments to layout.

Просмотреть файл

@ -10,6 +10,40 @@
namespace facebook {
namespace react {
static Rect rectFromDynamic(folly::dynamic const &data) {
Point origin;
origin.x = data.getDefault("x", 0).getDouble();
origin.y = data.getDefault("y", 0).getDouble();
Size size;
size.width = data.getDefault("width", 0).getDouble();
size.height = data.getDefault("height", 0).getDouble();
Rect frame;
frame.origin = origin;
frame.size = size;
return frame;
}
LineMeasurement::LineMeasurement(
std::string text,
Rect frame,
Float descender,
Float capHeight,
Float ascender,
Float xHeight)
: text(text),
frame(frame),
descender(descender),
capHeight(capHeight),
ascender(ascender) {}
LineMeasurement::LineMeasurement(folly::dynamic const &data)
: text(data.getDefault("text", "").getString()),
frame(rectFromDynamic(data)),
descender(data.getDefault("descender", 0).getDouble()),
capHeight(data.getDefault("capHeight", 0).getDouble()),
ascender(data.getDefault("ascender", 0).getDouble()),
xHeight(data.getDefault("xHeight", 0).getDouble()) {}
bool LineMeasurement::operator==(LineMeasurement const &rhs) const {
return std::tie(
this->text,

Просмотреть файл

@ -24,6 +24,16 @@ struct LineMeasurement {
Float ascender;
Float xHeight;
LineMeasurement(
std::string text,
Rect frame,
Float descender,
Float capHeight,
Float ascender,
Float xHeight);
LineMeasurement(folly::dynamic const &data);
bool operator==(LineMeasurement const &rhs) const;
};

Просмотреть файл

@ -98,6 +98,50 @@ TextMeasurement TextLayoutManager::measureCachedSpannableById(
return TextMeasurement{size, attachments};
}
LinesMeasurements TextLayoutManager::measureLines(
AttributedString attributedString,
ParagraphAttributes paragraphAttributes,
Size size) const {
const jni::global_ref<jobject> &fabricUIManager =
contextContainer_->at<jni::global_ref<jobject>>("FabricUIManager");
static auto measureLines =
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
->getMethod<NativeArray::javaobject(
ReadableMap::javaobject,
ReadableMap::javaobject,
jfloat,
jfloat)>("measureLines");
auto serializedAttributedString = toDynamic(attributedString);
local_ref<ReadableNativeMap::javaobject> attributedStringRNM =
ReadableNativeMap::newObjectCxxArgs(serializedAttributedString);
local_ref<ReadableNativeMap::javaobject> paragraphAttributesRNM =
ReadableNativeMap::newObjectCxxArgs(toDynamic(paragraphAttributes));
local_ref<ReadableMap::javaobject> attributedStringRM = make_local(
reinterpret_cast<ReadableMap::javaobject>(attributedStringRNM.get()));
local_ref<ReadableMap::javaobject> paragraphAttributesRM = make_local(
reinterpret_cast<ReadableMap::javaobject>(paragraphAttributesRNM.get()));
auto array = measureLines(
fabricUIManager,
attributedStringRM.get(),
paragraphAttributesRM.get(),
size.width,
size.height);
auto dynamicArray = cthis(array)->consume();
LinesMeasurements lineMeasurements;
lineMeasurements.reserve(dynamicArray.size());
for (auto const &data : dynamicArray) {
lineMeasurements.push_back(LineMeasurement(data));
}
return lineMeasurements;
}
TextMeasurement TextLayoutManager::doMeasure(
AttributedString attributedString,
ParagraphAttributes paragraphAttributes,

Просмотреть файл

@ -46,6 +46,15 @@ class TextLayoutManager {
ParagraphAttributes paragraphAttributes,
LayoutConstraints layoutConstraints) const;
/*
* Measures lines of `attributedString` using native text rendering
* infrastructure.
*/
LinesMeasurements measureLines(
AttributedString attributedString,
ParagraphAttributes paragraphAttributes,
Size size) const;
/*
* Returns an opaque pointer to platform-specific TextLayoutManager.
* Is used on a native views layer to delegate text rendering to the manager.

Просмотреть файл

@ -510,8 +510,8 @@ SPEC CHECKSUMS:
CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
DoubleConversion: 2b45d0f8e156a5b02354c8a4062de64d41ccb4e0
FBLazyVector: be96ff5ddc8762ebad9f7aa25ec5548d92f6eb13
FBReactNativeSpec: 2f6114e367cc9f9330fd6cf145dd56a41ac0a5c2
FBLazyVector: ab9bc1abaad967275f368fec7338076623de84bc
FBReactNativeSpec: 725315ac74f0e173d6b5051e7612fc3bf7196ea5
Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3
@ -522,33 +522,33 @@ SPEC CHECKSUMS:
glog: 789873d01e4b200777d0a09bc23d548446758699
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
RCT-Folly: 55d0039b24e192081ec0b2257f7bd9f42e382fb7
RCTRequired: 29abaea42d11b55dc4416cf3c6fc63a2a2f8a4f6
RCTTypeSafety: 2d6fdb69390d492bb0121be8e362b936d89a83d0
React: 2e77ccbe3820e5b726c1bfa5d76ebf3639d2e624
React-callinvoker: f83f10e61f666362d63045bd2e9fa0ac4c562eb2
React-Core: 0f533e477a7d85f616767a8378ce3ecdf0a107c3
React-CoreModules: 1bb04ffd718f50ac6c905badd07c33fd73c2ee44
React-cxxreact: f4bca80e9a784bd9103dad290e98e8b8db01e903
React-jsi: ebc752bab65e3584fd8d6bb42fa203998ca128ab
React-jsiexecutor: e54040f675335398696bf98c3a96e5c3ab25310a
React-jsinspector: a26fdcbb1ddeef87b48c7d245dcfafc947b28349
React-perflogger: 5d58ef97cdfe17c09913a76c73787afa4d8293a4
React-RCTActionSheet: cd7ee54205dc9cb5e314ac47c6f86bd7ee318c95
React-RCTAnimation: eafc659e92f8a4042a183c303e019da27c7f70c0
React-RCTBlob: f37c088901d659b998624a82c0743f6d06857855
React-RCTImage: c09da3d5aa56d904960cbbf8053721442dc16bb0
React-RCTLinking: 42aea5beb1b916998888108b21c84aa04006c47c
React-RCTNetwork: bf0375d06bafbfbbcf13432a8e29cb566a23802d
React-RCTPushNotification: b4acb243224b167ea548777c93915b93381ca9b6
React-RCTSettings: 393cce35dc361345af1f3df79d39ecac0ee40d20
React-RCTTest: 6c08cc250a83a74c0112e4f620630762cc7238df
React-RCTText: dd6fbf4ee023124a4fe0bfb1cc0689d453979625
React-RCTVibration: 9ab10ad1c8a47a520b85b345ab9a4f4128ddece5
React-runtimeexecutor: f38d137573b912af78493a139b3d6ee24af03b98
RCTRequired: be09d070a0403ab5fd4a61d2d0e33c7934606dd8
RCTTypeSafety: d535db16fe11a7aeefab886b248f9f40553fc35b
React: 632d9bfd0d2ebb2ee59da8f2ea30e86332a93db1
React-callinvoker: 7e80b7c0234aa4641d9f0c430a0e351ad88be343
React-Core: fb995a2ae7deb27d3a28ce59e76fb16f66240c1d
React-CoreModules: 47a1a2e8511b1becd6c517ffb9f845e277d2a0cc
React-cxxreact: 9027d3fea2551ae0baf6459b52920a0058d98a17
React-jsi: ab6099830710881c6fb9e8a8625a99a8d7ffa8b7
React-jsiexecutor: d1b26623ceaa1a3463d6dbbbdee78b25dbd2933d
React-jsinspector: 5617c75b22620490c4eba6aec6e3f413b307cdbf
React-perflogger: b1ab1854dc90b1e30dfcefe891ccbf1ee7ad91f2
React-RCTActionSheet: 23fa3ab74a8df6a0304bb80675b62cca9f48eb3c
React-RCTAnimation: 199458414744d214f07e692f2b480c7b6f4ba306
React-RCTBlob: 86a4bd10ead2375038102f9377c49d38e917979c
React-RCTImage: 3d39033c9164a61b34603d47db9460c9b75891d3
React-RCTLinking: 0ec1b549935c2202f8d6d0db3c7b119a49cea088
React-RCTNetwork: 7734aee17f2af29832f09fafa88e7bb7482741e6
React-RCTPushNotification: f6eeb265e0c7d554e7a0dd6c6788c7b25b2e4d4e
React-RCTSettings: aadf840e47aa7633d9137f59cc4a21645855fdad
React-RCTTest: e6fafe4a579cf2f717703b73f61b3e3cccf595a3
React-RCTText: 0111ffb42e2a9dec3333e370eae6b8ce2a8f05b9
React-RCTVibration: d5503cee4b3c774fd229b6ab70da280ed4697a5d
React-runtimeexecutor: 0219cbeaaf15cd8aa2de564f63f0a5ff194f8b03
React-TurboModuleCxx-RNW: 18bb71af41fe34c8b12a56bef60aae7ee32b0817
React-TurboModuleCxx-WinRTPort: f42f2365a3bb1aa71594dd755665cb0db98fe2bf
ReactCommon: d9bc39a8ec4f930bf47723072e94f9978882a339
Yoga: 19f37db1c20d7fd087ac7da338920ca7e3204110
React-TurboModuleCxx-WinRTPort: 858129d8ad888b26e8c2140be144184d78613b30
ReactCommon: dfec2c622c81cf59f382729fbd1eb95e6d51df71
Yoga: 49925aeb9303e7336561ca244f4d3c70a5757c5f
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: cb260f8f7765c910b68f8267cbd74709f6ae6e54

Просмотреть файл

@ -12,115 +12,96 @@
const React = require('react');
const {
StyleSheet,
View,
Text,
TouchableHighlight,
Share,
} = require('react-native');
const {StyleSheet, View, Text, Button, Share} = require('react-native');
type Props = $ReadOnly<{||}>;
type State = {|result: string|};
const shareMessage = () => {
Share.share({
message: ('Our top priority for React Native is to match the expectations people have for each platform. This is why React Native renders to platform primitives. We value native look-and-feel over cross-platform consistency.' +
'For example, the TextInput in React Native renders to a UITextField on iOS. This ensures that integration with password managers and keyboard controls work out of the box. By using platform primitives, React Native apps are also able to stay up-to-date with design and behavior changes from new releases of Android and iOS.': string),
});
};
class ShareMessageExample extends React.Component<Props, State> {
_shareMessage: Function;
_shareText: Function;
_showResult: Function;
const shareText = () => {
Share.share(
{
title: 'Massive Scale',
message: ('Hundreds of screens in the Facebook app are implemented with React Native. The Facebook app is used by billions of people on a huge range of devices. This is why we invest in the most challenging problems at scale.' +
'Deploying React Native in our apps lets us identify problems that we wouldnt see at a smaller scale. For example, Facebook focuses on improving performance across a broad spectrum of devices from the newest iPhone to many older generations of Android devices. This focus informs our architecture projects such as Hermes, Fabric, and TurboModules.': string),
url: 'https://reactnative.dev/blog/2020/07/17/react-native-principles',
},
{
subject: 'MUST READ: Massive Scale',
dialogTitle: 'Share React Native Blog',
excludedActivityTypes: ['com.apple.UIKit.activity.PostToTwitter'],
tintColor: 'blue',
},
);
};
constructor(props) {
super(props);
const ShareMessageWithoutTitle = () => {
return (
<View style={styles.container}>
<Text style={styles.title}>Native Experience</Text>
<Text>
Our top priority for React Native is to match the expectations people
have for each platform. This is why React Native renders to platform
primitives. We value native look-and-feel over cross-platform
consistency. For example, the TextInput in React Native renders to a
UITextField on iOS. This ensures that integration with password managers
and keyboard controls work out of the box. By using platform primitives,
React Native apps are also able to stay up-to-date with design and
behavior changes from new releases of Android and iOS.
</Text>
<Button title="SHARE" onPress={shareMessage} />
</View>
);
};
this._shareMessage = this._shareMessage.bind(this);
this._shareText = this._shareText.bind(this);
this._showResult = this._showResult.bind(this);
this.state = {
result: '',
};
}
render() {
return (
<View>
<TouchableHighlight style={styles.wrapper} onPress={this._shareMessage}>
<View style={styles.button}>
<Text>Click to share message</Text>
</View>
</TouchableHighlight>
<TouchableHighlight style={styles.wrapper} onPress={this._shareText}>
<View style={styles.button}>
<Text>Click to share message, URL and title</Text>
</View>
</TouchableHighlight>
<Text>{this.state.result}</Text>
</View>
);
}
_shareMessage() {
Share.share({
message:
'React Native | A framework for building native apps using React',
})
.then(this._showResult)
.catch(error => this.setState({result: 'error: ' + error.message}));
}
_shareText() {
Share.share(
{
message: 'A framework for building native apps using React',
url: 'https://reactnative.dev/',
title: 'React Native',
},
{
subject: 'A subject to go in the email heading',
dialogTitle: 'Share React Native website',
excludedActivityTypes: ['com.apple.UIKit.activity.PostToTwitter'],
tintColor: 'green',
},
)
.then(this._showResult)
.catch(error => this.setState({result: 'error: ' + error.message}));
}
_showResult(result) {
if (result.action === Share.sharedAction) {
if (result.activityType) {
this.setState({
result: 'shared with an activityType: ' + result.activityType,
});
} else {
this.setState({result: 'shared'});
}
} else if (result.action === Share.dismissedAction) {
this.setState({result: 'dismissed'});
}
}
}
const ShareMessageWithTitle = () => {
return (
<View style={styles.container}>
<Text style={styles.title}>Massive Scale</Text>
<Text>
Hundreds of screens in the Facebook app are implemented with React
Native. The Facebook app is used by billions of people on a huge range
of devices. This is why we invest in the most challenging problems at
scale. Deploying React Native in our apps lets us identify problems that
we wouldnt see at a smaller scale. For example, Facebook focuses on
improving performance across a broad spectrum of devices from the newest
iPhone to many older generations of Android devices. This focus informs
our architecture projects such as Hermes, Fabric, and TurboModules.
</Text>
<Button title="SHARE" onPress={shareText} />
</View>
);
};
const styles = StyleSheet.create({
wrapper: {
borderRadius: 5,
marginBottom: 5,
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
button: {
backgroundColor: '#eeeeee',
padding: 10,
title: {
fontSize: 30,
margin: 10,
textAlign: 'center',
},
});
exports.framework = 'React';
exports.title = 'Share';
exports.category = 'Basic';
exports.documentationURL = 'https://reactnative.dev/docs/share';
exports.description = 'Share data with other Apps.';
exports.examples = [
{
title: 'Share Text Content',
title: 'Share message',
render(): React.Node {
return <ShareMessageExample />;
return <ShareMessageWithoutTitle />;
},
},
{
title: 'Share message, URL (iOS) and title (Android)',
render(): React.Node {
return <ShareMessageWithTitle />;
},
},
];