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

Native scroll #10050

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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: 2 additions & 0 deletions config/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export function makeFeatureFlags(env: {
pr: boolean;
}) {
return {
// Whether to install a service worker
serviceWorker: !env.dev && !env.pr,
// Print debug info to console about item moves
debugMoves: !env.release,
// Debug Service Worker
Expand Down
2 changes: 1 addition & 1 deletion src/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ infoLog(
initGoogleAnalytics();
safariTouchFix();

if ($DIM_FLAVOR !== 'dev') {
if ($featureFlags.serviceWorker) {
registerServiceWorker();
}

Expand Down
2 changes: 1 addition & 1 deletion src/app/dim-ui/SheetHorizontalScrollContainer.m.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
flex-direction: row;
justify-content: flex-start;
contain: content;
touch-action: none;
// touch-action: none;
}
62 changes: 2 additions & 60 deletions src/app/dim-ui/SheetHorizontalScrollContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import clsx from 'clsx';
import React, { useCallback, useRef } from 'react';
import React from 'react';
import styles from './SheetHorizontalScrollContainer.m.scss';

// After this many pixels of dragging in either direction, we consider ourselves to be part of a scrolling gesture.
const HORIZ_SCROLL_DRAG_THRESHOLD = 20;
/**
* We have issues on mobile where horizontal scrolling of flex components doesn't work for some unknown reason. This
* component is a workaround that captures pointer events when the pointer has been triggered via the down state and
Expand All @@ -18,61 +16,5 @@ export function SheetHorizontalScrollContainer({
className?: string;
children: React.ReactNode;
}) {
// This uses pointer events to directly set the scroll position based on dragging the items. This works around an
// iOS bug around nested draggables, but also is kinda nice on desktop. I wasn't able to get it to do an inertial
// animation after releasing.
const ref = useRef<HTMLDivElement>(null);
const dragStateRef = useRef<{
scrollPosition: number;
pointerDownPosition: number;
scrolling: boolean;
}>();
const handlePointerDown = useCallback((e: React.PointerEvent) => {
// Don't do any of this if the view isn't scrollable in the first place
if (ref.current!.scrollWidth <= ref.current!.clientWidth) {
return;
}

dragStateRef.current = {
pointerDownPosition: e.clientX,
scrollPosition: ref.current!.scrollLeft,
scrolling: false,
};
}, []);
const handlePointerUp = useCallback((e: React.PointerEvent) => {
dragStateRef.current = undefined;
ref.current!.releasePointerCapture(e.pointerId);
}, []);
const handlePointerMove = useCallback((e: React.PointerEvent) => {
if (dragStateRef.current !== undefined) {
const { scrollPosition, pointerDownPosition } = dragStateRef.current;
// Once we've moved HORIZ_SCROLL_DRAG_THRESHOLD in either direction,
// constrain to horizontal scrolling only
dragStateRef.current.scrolling ||=
Math.abs(e.clientX - pointerDownPosition) > HORIZ_SCROLL_DRAG_THRESHOLD;
if (dragStateRef.current.scrolling) {
// Only set the pointer capture once we've moved enough. This allows you
// to still keep scrolling even if the pointer leaves the scrollable
// area (which feels nice) but buttons still work. If we always capture
// in handlePointerDown, buttons won't work because all events get
// retargeted to the scroll area.
ref.current!.setPointerCapture(e.pointerId);
e.stopPropagation();
}
ref.current!.scrollLeft = scrollPosition - (e.clientX - pointerDownPosition);
}
}, []);

return (
<div
ref={ref}
className={clsx(styles.horizontalScrollContainer, className)}
onPointerDown={handlePointerDown}
onPointerMove={handlePointerMove}
onPointerUp={handlePointerUp}
onPointerCancel={handlePointerUp}
>
{children}
</div>
);
return <div className={clsx(styles.horizontalScrollContainer, className)}>{children}</div>;
}