Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate (back) to New Arch #103

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 0 additions & 2 deletions __tests__/usecase/settings/UploadSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import {
import type { RootStackParamList } from '../../../src/usecase/Root';
import UploadSettings from '../../../src/usecase/settings/UploadSettings';

jest.mock('../../../src/usecase/shared/UndoTextInput', () => 'TextInput');

describe('UploadSettings', () => {
it('stores the configured settings', async () => {
const store = configureStore({ reducer });
Expand Down
2 changes: 1 addition & 1 deletion app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default {
name: IS_PROD ? 'WeechatRN' : 'WeechatRN (Dev)',
description: 'Weechat relay client using websockets',
slug: 'WeechatRN',
newArchEnabled: false,
newArchEnabled: true,
ios: {
bundleIdentifier: IS_PROD
? 'com.matthoran.weechatrn'
Expand Down
16 changes: 16 additions & 0 deletions patches/react-native-reanimated+3.16.6+002+fix-onlayout.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
diff --git a/node_modules/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp b/node_modules/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp
index 673ebd1..d5cb067 100644
--- a/node_modules/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp
+++ b/node_modules/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp
@@ -621,6 +621,11 @@ bool NativeReanimatedModule::handleRawEvent(
if (eventType.rfind("top", 0) == 0) {
eventType = "on" + eventType.substr(3);
}
+
+ if (!isAnyHandlerWaitingForEvent(eventType, tag)) {
+ return false;
+ }
+
jsi::Runtime &rt = uiWorkletRuntime_->getJSIRuntime();
#if REACT_NATIVE_MINOR_VERSION >= 73
const auto &eventPayload = rawEvent.eventPayload;
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
diff --git a/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp b/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp
index 4ad8463..70ccf81 100644
--- a/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp
+++ b/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp
@@ -78,7 +78,7 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
propsMap[&family].emplace_back(props);
});

- rootNode = cloneShadowTreeWithNewProps(*rootNode, propsMap);
+ rootNode = cloneShadowTreeWithNewPropsUnmounted(rootNode, propsMap);

// If the commit comes from React Native then pause commits from
// Reanimated since the ShadowTree to be committed by Reanimated may not
diff --git a/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ShadowTreeCloner.cpp b/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ShadowTreeCloner.cpp
index 5795b73..02637a6 100644
--- a/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ShadowTreeCloner.cpp
+++ b/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ShadowTreeCloner.cpp
@@ -1,5 +1,6 @@
#ifdef RCT_NEW_ARCH_ENABLED

+#include <react/renderer/core/DynamicPropsUtilities.h>
#include <reanimated/Fabric/ShadowTreeCloner.h>

#include <ranges>
@@ -7,6 +8,29 @@

namespace reanimated {

+ChildrenMap calculateChildrenMap(
+ const RootShadowNode &oldRootNode,
+ const PropsMap &propsMap) {
+ ChildrenMap childrenMap;
+
+ for (auto &[family, _] : propsMap) {
+ const auto ancestors = family->getAncestors(oldRootNode);
+
+ for (const auto &[parentNode, index] :
+ std::ranges::reverse_view(ancestors)) {
+ const auto parentFamily = &parentNode.get().getFamily();
+ auto &affectedChildren = childrenMap[parentFamily];
+
+ if (affectedChildren.contains(index)) {
+ continue;
+ }
+
+ affectedChildren.insert(index);
+ }
+ }
+ return childrenMap;
+}
+
ShadowNode::Unshared cloneShadowTreeWithNewPropsRecursive(
const ShadowNode &shadowNode,
const ChildrenMap &childrenMap,
@@ -43,33 +67,92 @@ ShadowNode::Unshared cloneShadowTreeWithNewPropsRecursive(
return result;
}

-RootShadowNode::Unshared cloneShadowTreeWithNewProps(
- const RootShadowNode &oldRootNode,
+ShadowNode::Unshared cloneShadowTreeWithNewPropsUnmountedRecursive(
+ ShadowNode::Shared const &oldShadowNode,
+ const ChildrenMap &childrenMap,
const PropsMap &propsMap) {
- ChildrenMap childrenMap;
+ if (oldShadowNode->getHasBeenPromoted()) {
+ return cloneShadowTreeWithNewPropsRecursive(
+ *oldShadowNode, childrenMap, propsMap);
+ }

- for (auto &[family, _] : propsMap) {
- const auto ancestors = family->getAncestors(oldRootNode);
+ auto shadowNode = std::const_pointer_cast<ShadowNode>(oldShadowNode);
+ auto layoutableShadowNode =
+ std::dynamic_pointer_cast<LayoutableShadowNode>(shadowNode);
+ if (layoutableShadowNode) {
+ layoutableShadowNode->dirtyLayout();
+ }

- for (const auto &[parentNode, index] :
- std::ranges::reverse_view(ancestors)) {
- const auto parentFamily = &parentNode.get().getFamily();
- auto &affectedChildren = childrenMap[parentFamily];
+ const auto family = &shadowNode->getFamily();
+ const auto affectedChildrenIt = childrenMap.find(family);
+ const auto propsIt = propsMap.find(family);
+ auto children = shadowNode->getChildren();

- if (affectedChildren.contains(index)) {
- continue;
+ if (affectedChildrenIt != childrenMap.end()) {
+ for (const auto index : affectedChildrenIt->second) {
+ auto clone = cloneShadowTreeWithNewPropsUnmountedRecursive(
+ children[index], childrenMap, propsMap);
+ if (clone != children[index]) {
+ shadowNode->replaceChild(*children[index], clone, index);
}
+ }
+ }

- affectedChildren.insert(index);
+ Props::Shared newProps = nullptr;
+
+ if (propsIt != propsMap.end()) {
+ PropsParserContext propsParserContext{
+ shadowNode->getSurfaceId(), *shadowNode->getContextContainer()};
+ newProps = shadowNode->getProps();
+ for (const auto &props : propsIt->second) {
+ newProps = shadowNode->getComponentDescriptor().cloneProps(
+ propsParserContext, newProps, RawProps(props));
}
}

+ if (newProps) {
+ auto &props = shadowNode->getProps();
+ auto &mutableProps = const_cast<Props::Shared &>(props);
+
+#ifdef ANDROID
+ auto &newPropsRef = const_cast<Props &>(*newProps);
+ newPropsRef.rawProps = mergeDynamicProps(
+ mutableProps->rawProps,
+ newProps->rawProps,
+ NullValueStrategy::Override);
+#endif
+ mutableProps = newProps;
+ auto layoutableShadowNode =
+ static_pointer_cast<YogaLayoutableShadowNode>(shadowNode);
+ layoutableShadowNode->updateYogaProps();
+ }
+
+ return shadowNode;
+}
+
+RootShadowNode::Unshared cloneShadowTreeWithNewProps(
+ const RootShadowNode &oldRootNode,
+ const PropsMap &propsMap) {
+ auto childrenMap = calculateChildrenMap(oldRootNode, propsMap);
+
// This cast is safe, because this function returns a clone
// of the oldRootNode, which is an instance of RootShadowNode
return std::static_pointer_cast<RootShadowNode>(
cloneShadowTreeWithNewPropsRecursive(oldRootNode, childrenMap, propsMap));
}

+RootShadowNode::Unshared cloneShadowTreeWithNewPropsUnmounted(
+ RootShadowNode::Unshared const &oldRootNode,
+ const PropsMap &propsMap) {
+ auto childrenMap = calculateChildrenMap(*oldRootNode, propsMap);
+
+ // This cast is safe, because this function returns a clone
+ // of the oldRootNode, which is an instance of RootShadowNode
+ return std::static_pointer_cast<RootShadowNode>(
+ cloneShadowTreeWithNewPropsUnmountedRecursive(
+ oldRootNode, childrenMap, propsMap));
+}
+
} // namespace reanimated

#endif // RCT_NEW_ARCH_ENABLED
diff --git a/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ShadowTreeCloner.h b/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ShadowTreeCloner.h
index e3f9f6d..8240776 100644
--- a/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ShadowTreeCloner.h
+++ b/node_modules/react-native-reanimated/Common/cpp/reanimated/Fabric/ShadowTreeCloner.h
@@ -24,6 +24,10 @@ RootShadowNode::Unshared cloneShadowTreeWithNewProps(
const RootShadowNode &oldRootNode,
const PropsMap &propsMap);

+RootShadowNode::Unshared cloneShadowTreeWithNewPropsUnmounted(
+ RootShadowNode::Unshared const &oldRootShadowNode,
+ const PropsMap &propsMap);
+
} // namespace reanimated

#endif // RCT_NEW_ARCH_ENABLED
3 changes: 1 addition & 2 deletions src/usecase/settings/ConnectionSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import type { StoreState } from '../../store';
import { setConnectionInfoAction } from '../../store/actions';
import type { RootStackParamList } from '../Root';
import { styles } from './styles';
import UndoTextInput from '../shared/UndoTextInput';

const connector = connect((state: StoreState) => ({
hostname: state.connection.hostname || '',
Expand Down Expand Up @@ -111,7 +110,7 @@ class ConnectionSettings extends React.PureComponent<Props, State> {
click the connect icon. Hostname will be prepended with the
appropriate scheme (http(s)://) and suffixed with /weechat.
</Text>
<UndoTextInput
<TextInput
style={styles.input}
placeholderTextColor="#4157af"
keyboardType="url"
Expand Down
13 changes: 6 additions & 7 deletions src/usecase/settings/UploadSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { KeyboardAvoidingView } from '../../../modules/keyboard-avoiding-view';
import { setMediaUploadOptionsAction } from '../../store/actions';
import { useAppDispatch, useAppSelector } from '../../store/hooks';
import type { RootStackParamList } from '../Root';
import UndoTextInput from '../shared/UndoTextInput';
import { styles } from './styles';

type NavigationProps = StackScreenProps<
Expand Down Expand Up @@ -100,7 +99,7 @@ const UploadSettings: React.FC<NavigationProps> = ({ navigation }) => {
from the camera roll. Press the button twice to upload media from
elsewhere on your device. Press and hold the button to take a photo.
</Text>
<UndoTextInput
<TextInput
style={styles.input}
placeholderTextColor="#4157af"
keyboardType="url"
Expand All @@ -123,7 +122,7 @@ const UploadSettings: React.FC<NavigationProps> = ({ navigation }) => {
</View>
{state.basicAuth && (
<>
<UndoTextInput
<TextInput
style={styles.input}
placeholderTextColor="#4157af"
keyboardType="email-address"
Expand All @@ -144,7 +143,7 @@ const UploadSettings: React.FC<NavigationProps> = ({ navigation }) => {
/>
</>
)}
<UndoTextInput
<TextInput
style={styles.input}
placeholderTextColor="#4157af"
autoCapitalize="none"
Expand All @@ -153,7 +152,7 @@ const UploadSettings: React.FC<NavigationProps> = ({ navigation }) => {
onChangeText={(fieldName) => setState({ fieldName })}
value={state.fieldName}
/>
<UndoTextInput
<TextInput
style={styles.input}
placeholderTextColor="#4157af"
autoCapitalize="none"
Expand All @@ -172,7 +171,7 @@ const UploadSettings: React.FC<NavigationProps> = ({ navigation }) => {
columnGap: 10
}}
>
<UndoTextInput
<TextInput
style={[styles.input, { minWidth: 300, flexGrow: 1 }]}
placeholderTextColor="#4157af"
autoCapitalize="none"
Expand All @@ -181,7 +180,7 @@ const UploadSettings: React.FC<NavigationProps> = ({ navigation }) => {
value={headerName}
onChangeText={(text) => setUploadOptionsHeaderName(index, text)}
/>
<UndoTextInput
<TextInput
style={[styles.input, { minWidth: 300, flexGrow: 1 }]}
placeholderTextColor="#4157af"
autoCapitalize="none"
Expand Down
27 changes: 0 additions & 27 deletions src/usecase/shared/UndoTextInput.tsx

This file was deleted.

Loading