Skip to content

feat(app): adaptive image quality on slow connections + data-saver toggle#1724

Open
MrDirkelz wants to merge 2 commits into
mainfrom
1720-app-re-add-network-speed-test-for-image-quality-selection
Open

feat(app): adaptive image quality on slow connections + data-saver toggle#1724
MrDirkelz wants to merge 2 commits into
mainfrom
1720-app-re-add-network-speed-test-for-image-quality-selection

Conversation

@MrDirkelz

@MrDirkelz MrDirkelz commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Serve lighter images when bandwidth is constrained, decided by three signals (OR): a measured-slow connection, a new user Data Saver toggle, and the OS/browser Data Saver flag.

  • useNetworkSpeed: probe-based speed estimate (times a download of a small same-origin asset) instead of navigator.connection.downlink, which is Chromium-only. Same code path on every browser; refreshes on startup, regained connectivity, tab focus, and toggling Data Saver off; throttled and skipped when offline or already saving data.
  • LImageProvider: in reduced-data mode, trim the srcset ladder to <=600px (keeping the smallest) and advertise reduced sizes. Recomputes live.
  • LToggle: native toggle (no HeadlessUI), themed for the app; used for the Settings Data Saver control.
  • SettingsPage: connection speed now reads the live composable value; adds the Data Saver card, i18n'd via new settings.data_saver.* keys.
  • globalConfig: add persisted userDataSaverEnabled; drop the unused Chromium-only getConnectionSpeed.
  • api: seed settings.data_saver.{title,description} in lang-eng / lang-fra.

Adds app/public/network-probe.bin (100 KB incompressible) as the probe target. New unit tests for the composable, LToggle, and the image trim.|

image

…ggle

Serve lighter images when bandwidth is constrained, decided by three
signals (OR): a measured-slow connection, a new user Data Saver toggle,
and the OS/browser Data Saver flag.

- useNetworkSpeed: probe-based speed estimate (times a download of a
  small same-origin asset) instead of navigator.connection.downlink,
  which is Chromium-only. Same code path on every browser; refreshes on
  startup, regained connectivity, tab focus, and toggling Data Saver off;
  throttled and skipped when offline or already saving data.
- LImageProvider: in reduced-data mode, trim the srcset ladder to <=600px
  (keeping the smallest) and advertise reduced `sizes`. Recomputes live.
- LToggle: native <button role="switch"> toggle (no HeadlessUI), themed
  for the app; used for the Settings Data Saver control.
- SettingsPage: connection speed now reads the live composable value; adds
  the Data Saver card, i18n'd via new settings.data_saver.* keys.
- globalConfig: add persisted userDataSaverEnabled; drop the unused
  Chromium-only getConnectionSpeed.
- api: seed settings.data_saver.{title,description} in lang-eng / lang-fra.

Adds app/public/network-probe.bin (100 KB incompressible) as the probe
target. New unit tests for the composable, LToggle, and the image trim.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MrDirkelz MrDirkelz linked an issue Jun 22, 2026 that may be closed by this pull request
The data-saver image reduction from b505823 didn't actually shrink
images on mobile. Two reasons: sizesReducedMap equals the mobile slot
width for every thumbnail (only the hero halved), and `sizes` is
DPR-blind, so a 144px thumbnail on a DPR-3 phone fetched the same ~432px
(600w) variant in both normal and reduced mode.

Replace the srcset-ladder capping (capFiles/REDUCED_MAX_WIDTH) with a
DPR cap on the reduced `sizes`: divide the reduced slot width by the
device pixel ratio (down to REDUCED_DPR_CAP=1) so a retina device
fetches a ~1x image instead of 2-3x. The full srcset ladder is kept
intact — only `sizes` shrinks — so quality recovers automatically when
the connection improves. No-op on 1x displays.

A `width` attribute would not help here: with w-descriptor srcsets the
browser selects purely from `sizes` x DPR.

Tests: drop the three trim tests; add DPR-cap tests (mock
devicePixelRatio=3) asserting the reduced/declarative `sizes` is 48px
and the full ladder is retained. Existing tests pass unchanged (jsdom
DPR=1, where the scale is a no-op).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@ivanslabbert ivanslabbert left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add note in settings when detecting that the browser is in low-data mode, stating why the setting is disabled (as the browser setting takes preference). Note to be in end-user understandable language with i18n support

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to useNetworkSpeedEstimator (or something shorter that better describes the composable)

* Settings page surfaces the live number so the constants below can be tuned against real readings.
*/

const isTestEnv = import.meta.env.MODE === "test";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should preferably not have testing switches in the production code. This causes our tests to run in a different environment than in production. See if you can mock rather?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When browser data savings mode is detected, force the toggle to the on position (visual only, do NOT set the app level data saving mode to true), and add a note that browser data saving mode is detected.

When slow network speed is detected (and neither browser or app level data saving mode is enabled), add a note that data saving mode will be applied due to slow network conditions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

APP: Re-add network speed test for image quality selection

2 participants