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
10 changes: 1 addition & 9 deletions packages/react-art/src/ReactFiberConfigART.js
Original file line number Diff line number Diff line change
Expand Up @@ -560,15 +560,7 @@ export function createViewTransitionInstance(
export type GestureTimeline = null;

export function getCurrentGestureOffset(provider: GestureTimeline): number {
throw new Error('useSwipeTransition is not yet supported in react-art.');
}

export function subscribeToGestureDirection(
provider: GestureTimeline,
currentOffset: number,
directionCallback: (direction: boolean) => void,
): () => void {
throw new Error('useSwipeTransition is not yet supported in react-art.');
throw new Error('startGestureTransition is not yet supported in react-art.');
}

export function clearContainer(container) {
Expand Down
22 changes: 0 additions & 22 deletions packages/react-debug-tools/src/ReactDebugHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type {
Usable,
Thenable,
ReactDebugInfo,
StartGesture,
} from 'shared/ReactTypes';
import type {
ContextDependency,
Expand Down Expand Up @@ -132,9 +131,6 @@ function getPrimitiveStackCache(): Map<string, Array<any>> {
if (typeof Dispatcher.useEffectEvent === 'function') {
Dispatcher.useEffectEvent((args: empty) => {});
}
if (typeof Dispatcher.useSwipeTransition === 'function') {
Dispatcher.useSwipeTransition(null, null, null);
}
} finally {
readHookLog = hookLog;
hookLog = [];
Expand Down Expand Up @@ -753,23 +749,6 @@ function useEffectEvent<Args, F: (...Array<Args>) => mixed>(callback: F): F {
return callback;
}

function useSwipeTransition<T>(
previous: T,
current: T,
next: T,
): [T, StartGesture] {
nextHook();
hookLog.push({
displayName: null,
primitive: 'SwipeTransition',
stackError: new Error(),
value: current,
debugInfo: null,
dispatcherHookName: 'SwipeTransition',
});
return [current, () => () => {}];
}

const Dispatcher: DispatcherType = {
readContext,

Expand All @@ -796,7 +775,6 @@ const Dispatcher: DispatcherType = {
useMemoCache,
useCacheRefresh,
useEffectEvent,
useSwipeTransition,
};

// create a proxy to throw a custom error
Expand Down
52 changes: 6 additions & 46 deletions packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,9 @@ export function cloneRootViewTransitionContainer(

const containerParent = containerInstance.parentNode;
if (containerParent === null) {
throw new Error('Cannot use a useSwipeTransition() in a detached root.');
throw new Error(
'Cannot use a startGestureTransition() on a detached root.',
);
}

const clone: HTMLElement = containerInstance.cloneNode(false);
Expand Down Expand Up @@ -1464,7 +1466,9 @@ export function removeRootViewTransitionClone(
}
const containerParent = containerInstance.parentNode;
if (containerParent === null) {
throw new Error('Cannot use a useSwipeTransition() in a detached root.');
throw new Error(
'Cannot use a startGestureTransition() on a detached root.',
);
}
// We assume that the clone is still within the same parent.
containerParent.removeChild(clone);
Expand Down Expand Up @@ -2172,50 +2176,6 @@ export function getCurrentGestureOffset(provider: GestureTimeline): number {
return typeof time === 'number' ? time : time.value;
}

export function subscribeToGestureDirection(
provider: GestureTimeline,
currentOffset: number,
directionCallback: (direction: boolean) => void,
): () => void {
if (
typeof ScrollTimeline === 'function' &&
provider instanceof ScrollTimeline
) {
// For ScrollTimeline we optimize to only update the current time on scroll events.
const element = provider.source;
const scrollCallback = () => {
const newTime = provider.currentTime;
if (newTime !== null) {
const newValue = typeof newTime === 'number' ? newTime : newTime.value;
if (newValue !== currentOffset) {
directionCallback(newValue > currentOffset);
}
}
};
element.addEventListener('scroll', scrollCallback, false);
return () => {
element.removeEventListener('scroll', scrollCallback, false);
};
} else {
// For other AnimationTimelines, such as DocumentTimeline, we just update every rAF.
// TODO: Optimize ViewTimeline using an IntersectionObserver if it becomes common.
const rafCallback = () => {
const newTime = provider.currentTime;
if (newTime !== null) {
const newValue = typeof newTime === 'number' ? newTime : newTime.value;
if (newValue !== currentOffset) {
directionCallback(newValue > currentOffset);
}
}
callbackID = requestAnimationFrame(rafCallback);
};
let callbackID = requestAnimationFrame(rafCallback);
return () => {
cancelAnimationFrame(callbackID);
};
}
}

type EventListenerOptionsOrUseCapture =
| boolean
| {
Expand Down
12 changes: 3 additions & 9 deletions packages/react-native-renderer/src/ReactFiberConfigNative.js
Original file line number Diff line number Diff line change
Expand Up @@ -692,15 +692,9 @@ export function createViewTransitionInstance(
export type GestureTimeline = null;

export function getCurrentGestureOffset(provider: GestureTimeline): number {
throw new Error('useSwipeTransition is not yet supported in React Native.');
}

export function subscribeToGestureDirection(
provider: GestureTimeline,
currentOffset: number,
directionCallback: (direction: boolean) => void,
): () => void {
throw new Error('useSwipeTransition is not yet supported in React Native.');
throw new Error(
'startGestureTransition is not yet supported in React Native.',
);
}

export function clearContainer(container: Container): void {
Expand Down
8 changes: 0 additions & 8 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -865,14 +865,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
return 0;
},

subscribeToGestureDirection(
provider: GestureTimeline,
currentOffset: number,
directionCallback: (direction: boolean) => void,
): () => void {
return () => {};
},

resetTextContent(instance: Instance): void {
instance.text = null;
},
Expand Down
8 changes: 4 additions & 4 deletions packages/react-reconciler/src/ReactFiberApplyGesture.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ function recursivelyInsertNewFiber(
// had any effect.
if (finishedWork.flags & Update) {
console.error(
'useSwipeTransition() caused something to render a new <%s>. ' +
'startGestureTransition() caused something to render a new <%s>. ' +
'This is not possible in the current implementation. ' +
"Make sure that the swipe doesn't mount any new <%s> elements.",
finishedWork.type,
Expand Down Expand Up @@ -789,7 +789,7 @@ function insertDestinationClonesOfFiber(
commitUpdate(instance, type, oldProps, newProps, finishedWork);
if (viewTransitionMutationContext) {
console.error(
'useSwipeTransition() caused something to mutate <%s>. ' +
'startGestureTransition() caused something to mutate <%s>. ' +
'This is not possible in the current implementation. ' +
"Make sure that the swipe doesn't update any state which " +
'causes <%s> to change.',
Expand Down Expand Up @@ -977,10 +977,10 @@ export function insertDestinationClones(
if (!didWarnForRootClone) {
didWarnForRootClone = true;
console.warn(
'useSwipeTransition() caused something to mutate or relayout the root. ' +
'startGestureTransition() caused something to mutate or relayout the root. ' +
'This currently requires a clone of the whole document. Make sure to ' +
'add a <ViewTransition> directly around an absolutely positioned DOM node ' +
'to minimize the impact of any changes caused by the Swipe Transition.',
'to minimize the impact of any changes caused by the Gesture Transition.',
);
}
}
Expand Down
28 changes: 1 addition & 27 deletions packages/react-reconciler/src/ReactFiberConcurrentUpdates.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,7 @@ import {
throwIfInfiniteUpdateLoopDetected,
getWorkInProgressRoot,
} from './ReactFiberWorkLoop';
import {
NoLane,
NoLanes,
mergeLanes,
markHiddenUpdate,
markRootUpdated,
GestureLane,
} from './ReactFiberLane';
import {NoLane, NoLanes, mergeLanes, markHiddenUpdate} from './ReactFiberLane';
import {NoFlags, Placement, Hydrating} from './ReactFiberFlags';
import {HostRoot, OffscreenComponent} from './ReactWorkTags';
import {OffscreenVisible} from './ReactFiberActivityComponent';
Expand Down Expand Up @@ -176,25 +169,6 @@ export function enqueueConcurrentRenderForLane(
return getRootForUpdatedFiber(fiber);
}

export function enqueueGestureRender(fiber: Fiber): FiberRoot | null {
// We can't use the concurrent queuing for these so this is basically just a
// short cut for marking the lane on the parent path. It is possible for a
// gesture render to suspend and then in the gap get another gesture starting.
// However, marking the lane doesn't make much different in this case because
// it would have to call startGesture with the same exact provider as was
// already rendering. Because otherwise it has no effect on the Hook itself.
// TODO: We could potentially solve this case by popping a ScheduledGesture
// off the root's queue while we're rendering it so that it can't dedupe
// and so new startGesture with the same provider would create a new
// ScheduledGesture which goes into a separate render pass anyway.
// This is such an edge case it probably doesn't matter much.
const root = markUpdateLaneFromFiberToRoot(fiber, null, GestureLane);
if (root !== null) {
markRootUpdated(root, GestureLane);
}
return root;
}

// Calling this function outside this module should only be done for backwards
// compatibility and should always be accompanied by a warning.
export function unsafe_markUpdateLaneFromFiberToRoot(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,3 @@ export type ViewTransitionInstance = null | {name: string, ...};
export const createViewTransitionInstance = shim;
export type GestureTimeline = any;
export const getCurrentGestureOffset = shim;
export const subscribeToGestureDirection = shim;
83 changes: 1 addition & 82 deletions packages/react-reconciler/src/ReactFiberGestureScheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ import {
includesTransitionLane,
} from './ReactFiberLane';
import {ensureRootIsScheduled} from './ReactFiberRootScheduler';
import {
subscribeToGestureDirection,
getCurrentGestureOffset,
stopViewTransition,
} from './ReactFiberConfig';
import {getCurrentGestureOffset, stopViewTransition} from './ReactFiberConfig';

// This type keeps track of any scheduled or active gestures.
export type ScheduledGesture = {
Expand All @@ -31,85 +27,11 @@ export type ScheduledGesture = {
rangePrevious: number, // The end along the timeline where the previous state is reached.
rangeCurrent: number, // The starting offset along the timeline.
rangeNext: number, // The end along the timeline where the next state is reached.
cancel: () => void, // Cancel the subscription to direction change. // TODO: Delete this.
running: null | RunningViewTransition, // Used to cancel the running transition after we're done.
prev: null | ScheduledGesture, // The previous scheduled gesture in the queue for this root.
next: null | ScheduledGesture, // The next scheduled gesture in the queue for this root.
};

// TODO: Delete this when deleting useSwipeTransition.
export function scheduleGestureLegacy(
root: FiberRoot,
provider: GestureTimeline,
initialDirection: boolean,
rangePrevious: number,
rangeCurrent: number,
rangeNext: number,
): ScheduledGesture {
let prev = root.pendingGestures;
while (prev !== null) {
if (prev.provider === provider) {
// Existing instance found.
prev.count++;
return prev;
}
const next = prev.next;
if (next === null) {
break;
}
prev = next;
}
const isFlippedDirection = rangePrevious > rangeNext;
// Add new instance to the end of the queue.
const cancel = subscribeToGestureDirection(
provider,
rangeCurrent,
(direction: boolean) => {
if (isFlippedDirection) {
direction = !direction;
}
if (gesture.direction !== direction) {
gesture.direction = direction;
if (gesture.prev === null && root.pendingGestures !== gesture) {
// This gesture is not in the schedule, meaning it was already rendered.
// We need to rerender in the new direction. Insert it into the first slot
// in case other gestures are queued after the on-going one.
const existing = root.pendingGestures;
gesture.next = existing;
if (existing !== null) {
existing.prev = gesture;
}
root.pendingGestures = gesture;
// Schedule the lane on the root. The Fibers will already be marked as
// long as the gesture is active on that Hook.
root.pendingLanes |= GestureLane;
ensureRootIsScheduled(root);
}
// TODO: If we're currently rendering this gesture, we need to restart it.
}
},
);
const gesture: ScheduledGesture = {
provider: provider,
count: 1,
direction: initialDirection,
rangePrevious: rangePrevious,
rangeCurrent: rangeCurrent,
rangeNext: rangeNext,
cancel: cancel,
running: null,
prev: prev,
next: null,
};
if (prev === null) {
root.pendingGestures = gesture;
} else {
prev.next = gesture;
}
ensureRootIsScheduled(root);
return gesture;
}

export function scheduleGesture(
root: FiberRoot,
provider: GestureTimeline,
Expand All @@ -133,7 +55,6 @@ export function scheduleGesture(
rangePrevious: -1,
rangeCurrent: -1,
rangeNext: -1,
cancel: () => {}, // TODO: Delete this with useSwipeTransition.
running: null,
prev: prev,
next: null,
Expand Down Expand Up @@ -210,8 +131,6 @@ export function cancelScheduledGesture(
): void {
gesture.count--;
if (gesture.count === 0) {
const cancelDirectionSubscription = gesture.cancel;
cancelDirectionSubscription();
// Delete the scheduled gesture from the pending queue.
deleteScheduledGesture(root, gesture);
// TODO: If we're currently rendering this gesture, we need to restart the render
Expand Down
Loading
Loading