DEV Community

orca forge
orca forge

Posted on Originally published at forge.workstyle.tech

Why Low-Performance Detection Stops Smartphone Dragging

📝 Originally published (in Japanese) at forge.workstyle.tech.

TL;DR The lite check sent some smartphones into a touch path that did not update pages during a slow drag. It used CPU core count, device memory, or the data saver setting to classify a device as low performance. Changing the threshold and removing that touch-path branch made drag updates work in a simulated four-core, 4 GB environment and on a real device.

Conclusion

The screen did not move when slowly dragging on a smartphone because JavaScript classified the device as low-powered and did not use the process that swaps pages in response to finger movement. After adjusting the low-performance threshold and touch handling branch so that every device uses dragging, I confirmed the behavior in both a test environment simulating 4 cores and 4 GB of memory and on a real device.

At First, I Suspected Browser Scrolling

At 6:13 p.m. on October 10, I added a feature that lets you switch slides by dragging your finger. A few hours later, someone who tried it on a real device sent in a report.

I’m trying it on my phone, but the opacity doesn’t change at all. There’s a hitch while scrolling, and then the next page appears.

My first thought was that the smartphone browser was handling vertical scrolling before anything else. It looked as though the slide extended one pixel past the bottom of the screen, leading the browser to treat the page as scrollable.

So I removed the overflow and routed all vertical finger movement through a script. For longer content, the script would add inertia to the scrolling. In other words, I wouldn’t leave scrolling to the browser.

But the next report was even worse:

“Even when I scroll up and down, the screen doesn’t move at all.”

If I stopped the browser from scrolling, the drag should have moved the screen. In reality, nothing happened, even when the person moved their finger slowly.

Why Did Dragging Stop When the Device Was Classified as Low-End?

The cause was the criteria used to classify a device as low-end. hardwareConcurrency is the number of logical CPU cores reported by the browser, and deviceMemory is an estimate of the device’s memory.

const lite = (navigator.hardwareConcurrency && navigator.hardwareConcurrency <= 4)
  || (navigator.deviceMemory && navigator.deviceMemory <= 4) || navigator.connection?.saveData;
Enter fullscreen mode Exit fullscreen mode

If the device has four or fewer CPU cores, 4 GB or less of memory, or data saver is enabled, lite becomes true. Even ordinary smartphones met these criteria.

On devices classified as low-end, the app didn’t use the logic that updates the screen in sync with a drag. It switched to advancing to the next item all at once only when you swiped quickly.

So the lack of response to a slow drag wasn’t caused by missed touch input. The app simply wasn’t running the logic that updates the screen in response to the touch movement. The first fix stopped relying on the browser to scroll, exposing that gap: even a slow drag no longer moved the page. The snag reported at 00:19 was also related to the same device classification.

Why the Problem Didn’t Reproduce on a Computer

I was checking the behavior on a computer with many CPU cores. Even when I mimicked a smartphone’s screen size and touch input, it didn’t meet the criteria for a low-performance device. I could match the screen size and touch behavior, but the navigator.hardwareConcurrency and navigator.deviceMemory conditions were different.

As a result, drag-and-drop reordering worked on the computer, while the smartphone took a different code path. The issue didn’t appear in my test environment; it only showed up on a real device. Simply shrinking the screen and enabling touch input wasn’t enough to reproduce the device detection.

How I Made Dragging Work Across Devices

At 01:55, I fixed the conditional that caused the issue. I changed the low-performance threshold from 4 to 2 and removed the condition that treated low-performance devices as swipes in the touch handler. Now every device uses drag behavior.

Before the fix, this condition turned the gesture into a swipe:

else if (lite || performance.now() < busyUntil) touch.mode = 'swipe';
Enter fullscreen mode Exit fullscreen mode

I removed this branch and made the touch handler set touch.mode = 'drag' regardless of the device. This reflects the distance your finger moves on screen instead of relying only on the logic that triggers when you flick quickly.

I also added a test to verify the fix. It mocks navigator as { hardwareConcurrency: 4, deviceMemory: 4 } and slowly drags in 20px increments. The test count increased from 31 to 32.

In an environment simulating 4 cores and 4 GB of memory, dragging 200px shifted the cover 79% of the way and brought the next page 21% into view. When I lifted my finger, the cover returned to its original position. Dragging 450px shifted the cover 61% of the way; when I lifted my finger, it advanced to page 2. These checks confirmed that the intermediate drag position appeared on screen even with values that trigger the low-performance classification.

What We Learned After It Worked on a Real Device

At 02:41, someone who had confirmed it was working on a real device reported, “The effect now works on smartphones.” The initial report made it clear that fixing browser scrolling alone wasn’t enough. The issue was that different devices were routed to different processing paths.

When treated as a low-performance device, the smartphone also missed out on the animated heading assembly and 3D display. After the device detection was fixed, both appeared on smartphones too.

However, we haven’t confirmed how performance was rated on the smartphone after the fix, and we don’t know which models were affected. Confirming that the animation works is separate from confirming that performance is acceptable on every device.

Key takeaways

  • Check the conditions and thresholds that make lite true.
  • Check whether touch handling routes low-performance devices away from drag updates.
  • Test with navigator set to { hardwareConcurrency: 4, deviceMemory: 4 } and drag slowly in 20px steps.
  • Check drag progress on a real device as well as with simulated screen size and touch input.

Top comments (0)