Skip to content

Commit 0f71e70

Browse files
committed
Add Commit Scaffolding for Gestures (#32451)
This adds a `ReactFiberApplyGesture` which is basically intended to be a fork of the phases in `ReactFiberCommitWork` except for the fake commit that `useSwipeTransition` does. So far none of the phases are actually implemented yet. This is just the scaffolding around them so I can fill them in later. The important bit is that we call `startViewTransition` (via the `startGestureTransition` Config) when a gesture starts. We add a paused animation to prevent the transition from committing (even if the ScrollTimeline goes to 100%). This also locks the documents so that we can't commit any other Transitions until it completes. When the gesture completes (scroll end) then we stop the gesture View Transition. If there's no new work scheduled we do that immediately but if there was any new work already scheduled, then we assume that this will potentially commit the new state. So we wait for that to finish. This lets us lock the animation in its state instead of snapping back and then applying the real update. Using this technique we can't actually run a View Transition from the current state to the actual committed state because it would snap back to the beginning and then run the View Transition from there. Therefore any new commit needs to skip View Transitions even if it should've technically animated to that state. We assume that the new state is the same as the optimistic state you already swiped to. An alternative to this technique could be to commit the optimistic state when we cancel and then apply any new updates o top of that. I might explore that in the future. Regardless it's important that the `action` associated with the swipe schedules some work before we cancel. Otherwise it risks reverting first. So I had to update this in the fixture. DiffTrain build for [3607f48](3607f48)
1 parent 57b7e4c commit 0f71e70

23 files changed

+1340
-590
lines changed

compiled-rn/VERSION_NATIVE_FB

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
19.1.0-native-fb-92e65ca6-20250225
1+
19.1.0-native-fb-3607f483-20250227

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOM-dev.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<56436c579d87368984d7eb14c779d096>>
10+
* @generated SignedSource<<0155acee191910091deb8961e6d1a605>>
1111
*/
1212

1313
"use strict";
@@ -404,5 +404,5 @@ __DEV__ &&
404404
exports.useFormStatus = function () {
405405
return resolveDispatcher().useHostTransitionStatus();
406406
};
407-
exports.version = "19.1.0-native-fb-92e65ca6-20250225";
407+
exports.version = "19.1.0-native-fb-3607f483-20250227";
408408
})();

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOM-prod.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<e4b9cf98d3b16cc2b748b73213bfc465>>
10+
* @generated SignedSource<<043ca5876df60de73faa86f59a7977d2>>
1111
*/
1212

1313
"use strict";
@@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
203203
exports.useFormStatus = function () {
204204
return ReactSharedInternals.H.useHostTransitionStatus();
205205
};
206-
exports.version = "19.1.0-native-fb-92e65ca6-20250225";
206+
exports.version = "19.1.0-native-fb-3607f483-20250227";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOM-profiling.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<e4b9cf98d3b16cc2b748b73213bfc465>>
10+
* @generated SignedSource<<043ca5876df60de73faa86f59a7977d2>>
1111
*/
1212

1313
"use strict";
@@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
203203
exports.useFormStatus = function () {
204204
return ReactSharedInternals.H.useHostTransitionStatus();
205205
};
206-
exports.version = "19.1.0-native-fb-92e65ca6-20250225";
206+
exports.version = "19.1.0-native-fb-3607f483-20250227";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMClient-dev.js

Lines changed: 243 additions & 169 deletions
Large diffs are not rendered by default.

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMClient-prod.js

Lines changed: 98 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<8c4f6be6880b7120a83f6c67762cf32a>>
10+
* @generated SignedSource<<c3749b89cd430e0eba1a46dbbe34b22d>>
1111
*/
1212

1313
/*
@@ -11949,7 +11949,7 @@ function flushSpawnedWork() {
1194911949
0 !== (finishedWork.flags & 10256)
1195011950
? (pendingEffectsStatus = 5)
1195111951
: ((pendingEffectsStatus = 0),
11952-
(pendingEffectsRoot = null),
11952+
(pendingFinishedWork = pendingEffectsRoot = null),
1195311953
releaseRootPooledCache(root, root.pendingLanes));
1195411954
var remainingLanes = root.pendingLanes;
1195511955
0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null);
@@ -11996,13 +11996,81 @@ function flushSpawnedWork() {
1199611996
flushSyncWorkAcrossRoots_impl(0, !1);
1199711997
}
1199811998
}
11999+
function flushGestureMutations() {
12000+
if (6 === pendingEffectsStatus) {
12001+
pendingEffectsStatus = 0;
12002+
var root = pendingEffectsRoot,
12003+
prevTransition = ReactSharedInternals.T;
12004+
ReactSharedInternals.T = null;
12005+
var previousPriority = ReactDOMSharedInternals.p;
12006+
ReactDOMSharedInternals.p = 2;
12007+
var prevExecutionContext = executionContext;
12008+
executionContext |= 4;
12009+
try {
12010+
var rootContainer = root.containerInfo,
12011+
documentElement =
12012+
9 === rootContainer.nodeType
12013+
? rootContainer.documentElement
12014+
: rootContainer.ownerDocument.documentElement;
12015+
null !== documentElement &&
12016+
"" === documentElement.style.viewTransitionName &&
12017+
((documentElement.style.viewTransitionName = "none"),
12018+
documentElement.animate(
12019+
{ opacity: [0, 0], pointerEvents: ["none", "none"] },
12020+
{
12021+
duration: 0,
12022+
fill: "forwards",
12023+
pseudoElement: "::view-transition-group(root)"
12024+
}
12025+
),
12026+
documentElement.animate(
12027+
{ width: [0, 0], height: [0, 0] },
12028+
{ duration: 0, fill: "forwards", pseudoElement: "::view-transition" }
12029+
));
12030+
} finally {
12031+
(executionContext = prevExecutionContext),
12032+
(ReactDOMSharedInternals.p = previousPriority),
12033+
(ReactSharedInternals.T = prevTransition);
12034+
}
12035+
pendingEffectsStatus = 7;
12036+
}
12037+
}
1199912038
function releaseRootPooledCache(root, remainingLanes) {
1200012039
0 === (root.pooledCacheLanes &= remainingLanes) &&
1200112040
((remainingLanes = root.pooledCache),
1200212041
null != remainingLanes &&
1200312042
((root.pooledCache = null), releaseCache(remainingLanes)));
1200412043
}
1200512044
function flushPendingEffects(wasDelayedCommit) {
12045+
flushGestureMutations();
12046+
flushGestureMutations();
12047+
if (7 === pendingEffectsStatus) {
12048+
pendingEffectsStatus = 0;
12049+
var root = pendingEffectsRoot;
12050+
pendingFinishedWork = pendingEffectsRoot = null;
12051+
pendingEffectsLanes = 0;
12052+
var prevTransition = ReactSharedInternals.T;
12053+
ReactSharedInternals.T = null;
12054+
var previousPriority = ReactDOMSharedInternals.p;
12055+
ReactDOMSharedInternals.p = 2;
12056+
var prevExecutionContext = executionContext;
12057+
executionContext |= 4;
12058+
try {
12059+
var rootContainer = root.containerInfo,
12060+
documentElement =
12061+
9 === rootContainer.nodeType
12062+
? rootContainer.documentElement
12063+
: rootContainer.ownerDocument.documentElement;
12064+
null !== documentElement &&
12065+
"none" === documentElement.style.viewTransitionName &&
12066+
(documentElement.style.viewTransitionName = "");
12067+
} finally {
12068+
(executionContext = prevExecutionContext),
12069+
(ReactDOMSharedInternals.p = previousPriority),
12070+
(ReactSharedInternals.T = prevTransition);
12071+
}
12072+
ensureRootIsScheduled(root);
12073+
}
1200612074
flushMutationEffects();
1200712075
flushLayoutEffects();
1200812076
flushSpawnedWork();
@@ -12024,7 +12092,7 @@ function flushPassiveEffects() {
1202412092
var root$jscomp$0 = pendingEffectsRoot,
1202512093
lanes = pendingEffectsLanes;
1202612094
pendingEffectsStatus = 0;
12027-
pendingEffectsRoot = null;
12095+
pendingFinishedWork = pendingEffectsRoot = null;
1202812096
pendingEffectsLanes = 0;
1202912097
if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(331));
1203012098
var prevExecutionContext = executionContext;
@@ -12465,20 +12533,20 @@ function extractEvents$1(
1246512533
}
1246612534
}
1246712535
for (
12468-
var i$jscomp$inline_1539 = 0;
12469-
i$jscomp$inline_1539 < simpleEventPluginEvents.length;
12470-
i$jscomp$inline_1539++
12536+
var i$jscomp$inline_1563 = 0;
12537+
i$jscomp$inline_1563 < simpleEventPluginEvents.length;
12538+
i$jscomp$inline_1563++
1247112539
) {
12472-
var eventName$jscomp$inline_1540 =
12473-
simpleEventPluginEvents[i$jscomp$inline_1539],
12474-
domEventName$jscomp$inline_1541 =
12475-
eventName$jscomp$inline_1540.toLowerCase(),
12476-
capitalizedEvent$jscomp$inline_1542 =
12477-
eventName$jscomp$inline_1540[0].toUpperCase() +
12478-
eventName$jscomp$inline_1540.slice(1);
12540+
var eventName$jscomp$inline_1564 =
12541+
simpleEventPluginEvents[i$jscomp$inline_1563],
12542+
domEventName$jscomp$inline_1565 =
12543+
eventName$jscomp$inline_1564.toLowerCase(),
12544+
capitalizedEvent$jscomp$inline_1566 =
12545+
eventName$jscomp$inline_1564[0].toUpperCase() +
12546+
eventName$jscomp$inline_1564.slice(1);
1247912547
registerSimpleEvent(
12480-
domEventName$jscomp$inline_1541,
12481-
"on" + capitalizedEvent$jscomp$inline_1542
12548+
domEventName$jscomp$inline_1565,
12549+
"on" + capitalizedEvent$jscomp$inline_1566
1248212550
);
1248312551
}
1248412552
registerSimpleEvent(ANIMATION_END, "onAnimationEnd");
@@ -15999,16 +16067,16 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
1599916067
0 === i && attemptExplicitHydrationTarget(target);
1600016068
}
1600116069
};
16002-
var isomorphicReactPackageVersion$jscomp$inline_1787 = React.version;
16070+
var isomorphicReactPackageVersion$jscomp$inline_1811 = React.version;
1600316071
if (
16004-
"19.1.0-native-fb-92e65ca6-20250225" !==
16005-
isomorphicReactPackageVersion$jscomp$inline_1787
16072+
"19.1.0-native-fb-3607f483-20250227" !==
16073+
isomorphicReactPackageVersion$jscomp$inline_1811
1600616074
)
1600716075
throw Error(
1600816076
formatProdErrorMessage(
1600916077
527,
16010-
isomorphicReactPackageVersion$jscomp$inline_1787,
16011-
"19.1.0-native-fb-92e65ca6-20250225"
16078+
isomorphicReactPackageVersion$jscomp$inline_1811,
16079+
"19.1.0-native-fb-3607f483-20250227"
1601216080
)
1601316081
);
1601416082
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
@@ -16028,24 +16096,24 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
1602816096
null === componentOrElement ? null : componentOrElement.stateNode;
1602916097
return componentOrElement;
1603016098
};
16031-
var internals$jscomp$inline_2248 = {
16099+
var internals$jscomp$inline_2282 = {
1603216100
bundleType: 0,
16033-
version: "19.1.0-native-fb-92e65ca6-20250225",
16101+
version: "19.1.0-native-fb-3607f483-20250227",
1603416102
rendererPackageName: "react-dom",
1603516103
currentDispatcherRef: ReactSharedInternals,
16036-
reconcilerVersion: "19.1.0-native-fb-92e65ca6-20250225"
16104+
reconcilerVersion: "19.1.0-native-fb-3607f483-20250227"
1603716105
};
1603816106
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
16039-
var hook$jscomp$inline_2249 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
16107+
var hook$jscomp$inline_2283 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
1604016108
if (
16041-
!hook$jscomp$inline_2249.isDisabled &&
16042-
hook$jscomp$inline_2249.supportsFiber
16109+
!hook$jscomp$inline_2283.isDisabled &&
16110+
hook$jscomp$inline_2283.supportsFiber
1604316111
)
1604416112
try {
16045-
(rendererID = hook$jscomp$inline_2249.inject(
16046-
internals$jscomp$inline_2248
16113+
(rendererID = hook$jscomp$inline_2283.inject(
16114+
internals$jscomp$inline_2282
1604716115
)),
16048-
(injectedHook = hook$jscomp$inline_2249);
16116+
(injectedHook = hook$jscomp$inline_2283);
1604916117
} catch (err) {}
1605016118
}
1605116119
exports.createRoot = function (container, options) {
@@ -16137,4 +16205,4 @@ exports.hydrateRoot = function (container, initialChildren, options) {
1613716205
listenToAllSupportedEvents(container);
1613816206
return new ReactDOMHydrationRoot(initialChildren);
1613916207
};
16140-
exports.version = "19.1.0-native-fb-92e65ca6-20250225";
16208+
exports.version = "19.1.0-native-fb-3607f483-20250227";

0 commit comments

Comments
 (0)