Skip to content

Commit

Permalink
changing webkit hack
Browse files Browse the repository at this point in the history
  • Loading branch information
alexreardon committed Jul 22, 2019
1 parent ca8287f commit 8858522
Showing 1 changed file with 28 additions and 72 deletions.
100 changes: 28 additions & 72 deletions src/view/use-drag-handle/sensor/use-touch-sensor.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import supportedPageVisibilityEventName from '../util/supported-page-visibility-
import createPostDragEventPreventer, {
type EventPreventer,
} from '../util/create-post-drag-event-preventer';
import useLayoutEffect from '../../use-isomorphic-layout-effect';

export type Args = {|
callbacks: Callbacks,
Expand All @@ -36,75 +37,13 @@ type TouchWithForce = Touch & {
force: number,
};

type WebkitHack = {|
preventTouchMove: () => void,
releaseTouchMove: () => void,
|};

export const timeForLongPress: number = 150;
// Decreased from 150 as a work around for an issue for forcepress on iOS
// https://github.com/atlassian/react-beautiful-dnd/issues/1401
export const timeForLongPress: number = 120;
export const forcePressThreshold: number = 0.15;
const touchStartMarshal: EventMarshal = createEventMarshal();
const noop = (): void => {};

// Webkit does not allow event.preventDefault() in dynamically added handlers
// So we add an always listening event handler to get around this :(
// webkit bug: https://bugs.webkit.org/show_bug.cgi?id=184250
const webkitHack: WebkitHack = (() => {
const stub: WebkitHack = {
preventTouchMove: noop,
releaseTouchMove: noop,
};

// Do nothing when server side rendering
if (typeof window === 'undefined') {
return stub;
}

// Device has no touch support - no point adding the touch listener
if (!('ontouchstart' in window)) {
return stub;
}

// Not adding any user agent testing as everything pretends to be webkit

let isBlocking: boolean = false;

// Adding a persistent event handler
window.addEventListener(
'touchmove',
(event: TouchEvent) => {
// We let the event go through as normal as nothing
// is blocking the touchmove
if (!isBlocking) {
return;
}

// Our event handler would have worked correctly if the browser
// was not webkit based, or an older version of webkit.
if (event.defaultPrevented) {
return;
}

// Okay, now we need to step in and fix things
event.preventDefault();

// Forcing this to be non-passive so we can get every touchmove
// Not activating in the capture phase like the dynamic touchmove we add.
// Technically it would not matter if we did this in the capture phase
},
{ passive: false, capture: false },
);

const preventTouchMove = () => {
isBlocking = true;
};
const releaseTouchMove = () => {
isBlocking = false;
};

return { preventTouchMove, releaseTouchMove };
})();

export default function useTouchSensor(args: Args): OnTouchStart {
const {
callbacks,
Expand Down Expand Up @@ -143,7 +82,6 @@ export default function useTouchSensor(args: Args): OnTouchStart {
schedule.cancel();
unbindWindowEventsRef.current();
touchStartMarshal.reset();
webkitHack.releaseTouchMove();
hasMovedRef.current = false;
onCaptureEnd();

Expand Down Expand Up @@ -196,11 +134,15 @@ export default function useTouchSensor(args: Args): OnTouchStart {
hasMovedRef.current = true;
}

const { clientX, clientY } = event.touches[0];
const touch: ?Touch = event.touches[0];

if (!touch) {
return;
}

const point: Position = {
x: clientX,
y: clientY,
x: touch.clientX,
y: touch.clientY,
};

// We need to prevent the default event in order to block native scrolling
Expand Down Expand Up @@ -437,11 +379,25 @@ export default function useTouchSensor(args: Args): OnTouchStart {
// browser interactions as possible.
// This includes navigation on anchors which we want to preserve
touchStartMarshal.handle();

// A webkit only hack to prevent touch move events
webkitHack.preventTouchMove();
startPendingDrag(event);
};

// This is needed for safari
// Simply adding a non capture, non passive 'touchmove' listener.
// This forces event.preventDefault() in dynamically added
// touchmove event handlers to actually work
// https://github.com/atlassian/react-beautiful-dnd/issues/1374
useLayoutEffect(function webkitHack() {
const unbind = bindEvents(window, [
{
eventName: 'touchmove',
fn: noop,
options: { capture: false, passive: false },
},
]);

return unbind;
}, []);

return onTouchStart;
}

0 comments on commit 8858522

Please sign in to comment.