Skip to content

Fix guide images, and the service class the timetable hides in an icon - #9

Merged
ialakey merged 3 commits into
masterfrom
fix/guide-images-and-train-rank
Sep 6, 2026
Merged

Fix guide images, and the service class the timetable hides in an icon#9
ialakey merged 3 commits into
masterfrom
fix/guide-images-and-train-rank

Conversation

@ialakey

@ialakey ialakey commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Two things reported as "it doesn't work", both of which turned out to be a
column of someone else's markup being read the wrong way.

Guide images were placeholders

srb.guide runs Hugo behind lazysizes. Every image looks like this:

<img class="lazyload blur-up"
     src=/media/soko_hu_6409ba5140e498ce.webp      <!-- blurred stub, 462 bytes -->
     data-srcset="…480w, …1080w, …1280w, …2268w"   <!-- the real files -->
     data-src=>

The scraper read src, so 257 of the guide's 283 images were blurred stubs
of a few hundred bytes — the worst 20 pixels wide. It now prefers data-srcset
and takes the widest variant a phone can use, capped at 1280px: the 2268px
original is twelve times the bytes of the 480w for pixels no phone here has.
assets/data/guide.json is re-scraped with the fixed tool; a sample of ten
images went from ~460 bytes to 10–95 KB.

On screen:

  • Tap an image to open it full screen. Pinch and double-tap were always
    there but invisible, so the viewer has zoom buttons too — four steps of 1.6x,
    the last step out returning to the fitted size, and a double-tap back to
    fitted resets the buttons with it.
  • Inline images are capped at half a screen; a portrait screenshot at full
    width used to push the rest of the article off the page.
  • The inline image and the viewer both report a failed load instead of leaving
    a gap, and the viewer shows download progress.

Note for after the merge: the app prefers the guide it downloads from GitHub
over the bundled copy, so existing installs correct themselves within a day of
this landing on master (or immediately via Settings → check now).

The class of train never showed

The route card and the station board each have a badge for the service class,
and it was always absent. The timetable renders that column as
<img title="REGIO VOZ">, not text, so the cell's text was empty and the badge
was never built. Cells now fall back to the titles of the images they contain,
which also recovers the Ponuda column the parser had been dropping — travel
classes, bicycle carriage, and whether a reservation is required. That reads
under the badges on a route card:

03:23 ──── 06:36 ──── 09:59
[Train 2901] [REGIO VOZ]
Prvi razred · Drugi razred · Bicikla - Ograničen broj mesta

Verification

  • flutter analyze clean; 89 tests pass, including 8 new ones for the srcset
    picker
  • The live timetable test now asserts both recovered columns arrive, since
    neither has a visible failure mode — they just go quiet if the markup changes
  • Checked on an Android 16 emulator: guide photos render sharp at full size,
    tap opens the viewer, the zoom buttons step in and back to fitted, and
    Beograd Centar → Niš shows four runs with their class and offer

The route card and the station board both have a badge for the service class,
and it never appeared. w3.srbvoz.rs renders that column as `<img title="REGIO
VOZ">` rather than text, so reading the cell's text gave an empty string and
`if (connection.rank.isNotEmpty)` was never true.

Cells now fall back to the titles of the images they contain, which also
recovers the "Ponuda" column the parser had been dropping: travel classes,
bicycle carriage, and whether a reservation is required. That reads under the
badges on a route card, where it answers the question people actually open the
timetable with.

The live test asserts both columns arrive, since neither has a visible failure
mode — they simply go quiet if the markup changes back.
The guide shipped 283 blurred smudges instead of photographs. srb.guide runs
Hugo behind lazysizes: every image carries a blurred placeholder of a few
hundred bytes in `src`, with the real file in `data-srcset` / `data-src`. The
scraper read `src` first, so 257 of the 283 images were placeholders — the
worst of them 20 pixels wide.

The scraper now prefers the srcset, taking the widest variant a phone can use.
That cap is 1280px: the site publishes up to 2268px, which is twelve times the
bytes of the 480w for pixels no phone here has.

On screen:

- Tap an image to open it full screen. Pinch and double-tap were always there
  but invisible, so the viewer also has zoom buttons — four steps of 1.6x, with
  the last step out returning to the fitted size. A double-tap back to fitted
  resets the buttons with it.
- Inline images are capped at half a screen. A portrait screenshot at full
  width pushed the rest of the article off the page.
- Both the inline image and the viewer report a failed load rather than
  leaving a gap, and the viewer shows download progress.

`assets/data/guide.json` is re-scraped with the fixed tool. Note that the app
prefers the copy it downloads from GitHub over the bundled one, so the images
only correct themselves for existing installs once this is on master.
Both were reported as "it does not work" and both turned out to be columns of
someone else's markup being read the wrong way, which is worth writing down
where the next person will look.
@ialakey
ialakey merged commit 7f74eed into master Sep 6, 2026
2 checks passed
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.

1 participant