mirror of
https://github.com/Andre-Bzk/rin-mobile-userscript.git
synced 2026-11-15 09:33:08 +01:00
A viewforum page is not always a list of topics — a category page lists forums, and a forum page can carry both. Every row was treated as a topic, so on those pages the only link the row offered was the icon in its last-post column: the forum name was dropped, its description ended up in the muted footer line, and nothing was left to tap. Moving between forums on a phone was impossible. Rows are now classified by their first usable link, which relies on document order: a forum row names the forum before it links the last post. Detection prefers phpBB's own classes and falls back to the shape of the row, because the board runs a custom theme whose markup could not be verified — the page requires a login. That fallback needs a brake. The page scaffolding is itself a table, so a link outside any list row resolves to a row containing the whole document, which passed for a forum row and turned the page header, a stylesheet and inline scripts into a forum description. Rows carrying nested tables, forms or scripts are therefore rejected, and descriptions are read only from the title cell's own text.
329 lines
14 KiB
Markdown
329 lines
14 KiB
Markdown
# iOS Safari Userscripts — cs.rin.ru
|
||
|
||
[English](#english) | [Deutsch](#deutsch)
|
||
|
||
---
|
||
|
||
## English
|
||
|
||
A single userscript that rebuilds the phpBB2 pages of `cs.rin.ru` into a mobile
|
||
layout for Safari on iOS. It replaces the original table layout entirely: the
|
||
existing page content is hidden and a freshly built DOM is appended to `<body>`.
|
||
|
||
`rin-mobile.user.js` matches `*://cs.rin.ru/forum/*` and picks its view from the
|
||
page type:
|
||
|
||
| Page | View |
|
||
|---|---|
|
||
| `viewforum.php`, `search.php`, forum root | Topic and forum list as cards |
|
||
| `viewtopic.php` | Thread as a post stream with a fixed bottom navigation bar |
|
||
| anything else | Untouched — no styles are injected |
|
||
|
||
A `viewforum.php` page is not necessarily a list of topics: a category page
|
||
lists forums instead, and a forum page can carry both. Each table row is
|
||
therefore classified by its first usable link. Forum rows become cards with
|
||
name, description, subforum links and counts; topic rows keep their existing
|
||
card; category headers become section headings. Rows are recognised by phpBB's
|
||
own `forumlink` / `forumdesc` classes, and failing that by their shape — two
|
||
purely numeric columns are only ever a forum's topic and post count.
|
||
|
||
The thread navigation bar holds first / previous / next / last and a page
|
||
indicator. Tapping the indicator opens a sheet with a number field and a grid of
|
||
all pages. Targets are computed as `start = (page - 1) × per_page` rather than
|
||
taken from the rendered page links, because phpBB only ever shows a handful of
|
||
them. `per_page` is read from the `jumpto()` function the forum embeds in the
|
||
page; without it, only first page and the original previous/next links remain
|
||
available.
|
||
|
||
Both views carry a fixed breadcrumb bar at the top, taken from the forum's own
|
||
`Board index » … » Main Forum` trail. Without it there is no way back out of a
|
||
thread, because the original page is hidden and phpBB links the parent forum
|
||
nowhere else. The bar scrolls horizontally if the trail is too long for the
|
||
screen, and is left out entirely on pages that do not carry a trail. Note that
|
||
`Board index` leads to `index.php`, which the script does not rebuild — that
|
||
page arrives in its desktop layout.
|
||
|
||
The script runs at `document-start`, injects a mobile viewport meta tag, and
|
||
carries a `DEBUG` flag. While `DEBUG` is `true`, a green diagnostic overlay is
|
||
prepended to the page showing which view was chosen and how many rows were
|
||
converted. Set it to `false` before daily use.
|
||
|
||
### Installation on iOS
|
||
|
||
1. Install a userscript manager for Safari on iOS (for example *Userscripts*)
|
||
and enable it under *Settings → Safari → Extensions*.
|
||
2. Add `rin-mobile.user.js` to the manager's script directory.
|
||
3. Grant the extension permission for `cs.rin.ru`.
|
||
|
||
---
|
||
|
||
### Development
|
||
|
||
The script is developed on Windows in Chrome or Edge with Tampermonkey.
|
||
`dev/rin-mobile.dev.user.js` is a loader: it contains nothing but a metadata
|
||
block that pulls in the real script from disk via `@require`. Editing
|
||
`rin-mobile.user.js` and reloading the page is enough — no reinstall in
|
||
Tampermonkey.
|
||
|
||
#### ⚠️ Path adjustment required
|
||
|
||
The loader in `dev/` references the script by **absolute path**:
|
||
|
||
```js
|
||
// @require file:///C:/Projekte/ios_safari_userscripts/rin-mobile.user.js
|
||
```
|
||
|
||
This path is hardcoded and only valid on the machine it was written for. After
|
||
cloning the repository or moving the project folder, adjust the `@require` line
|
||
in `dev/rin-mobile.dev.user.js` to your own location.
|
||
|
||
Use forward slashes and the `file:///` prefix, including the drive letter —
|
||
`file:///D:/projects/ios_safari_userscripts/rin-mobile.user.js`. A `@require`
|
||
that cannot be resolved causes Tampermonkey to skip the script **entirely and
|
||
without an error message on the page**, which looks exactly like the script not
|
||
being installed at all.
|
||
|
||
#### Tampermonkey setup
|
||
|
||
Three settings are required; missing the first one is the most common cause of
|
||
"nothing happens":
|
||
|
||
1. `chrome://extensions` → Tampermonkey → enable **Allow user scripts**.
|
||
On older Chrome versions, enable **Developer mode** at the top right
|
||
instead. Without this, Manifest V3 blocks all injection.
|
||
2. Same page → enable **Allow access to file URLs**, so `@require file://`
|
||
can be resolved.
|
||
3. Tampermonkey dashboard → *Settings* → *Externals* → set the update interval
|
||
to **always**, otherwise the loader keeps serving a cached copy of the
|
||
script.
|
||
|
||
Then open the loader once via `file:///.../dev/rin-mobile.dev.user.js` —
|
||
Tampermonkey intercepts `.user.js` URLs and offers to install it.
|
||
|
||
Do not run the loader and the plain script side by side. If both are enabled in
|
||
Tampermonkey, the code executes twice on the same page, producing duplicate
|
||
cards and two debug overlays.
|
||
|
||
#### Test fixtures
|
||
|
||
`cs.rin.ru` requires a login, so save the pages you need once and iterate
|
||
against local copies:
|
||
|
||
1. Open the page while logged in, then in DevTools right-click `<html>` →
|
||
*Copy outerHTML*.
|
||
2. Save it as `dev/viewtopic.php.html` or `dev/viewforum.php.html`.
|
||
3. Serve the folder: `python -m http.server 8777 --directory .`
|
||
|
||
The file name matters twice over. The `.html` extension makes the server send
|
||
the file as HTML instead of offering it as a download, and the retained
|
||
`viewtopic.php` / `viewforum.php` part is what the loader's `@include` rules
|
||
and the page-type check in `rin-mobile.user.js` match against.
|
||
|
||
Forum images and stylesheets are missing from such a snapshot. That is fine for
|
||
layout work, because the script rebuilds the DOM anyway — only avatars stay
|
||
empty, since their `src` is carried over unchanged.
|
||
|
||
Note that a snapshot saved while logged out contains `span.link_removed`
|
||
placeholders instead of links, and may use different markup for author names
|
||
than the logged-in view.
|
||
|
||
#### Device emulation
|
||
|
||
DevTools → *Device Toolbar* (`Ctrl+Shift+M`) → *Edit…* → add a custom device
|
||
with **430 × 932** and DPR **3** for an iPhone 15 Pro Max, device type *Mobile*,
|
||
and an iOS Safari user agent string.
|
||
|
||
#### What desktop emulation cannot show
|
||
|
||
Chrome uses Blink, iOS Safari uses WebKit. These points have to be verified on
|
||
the device:
|
||
|
||
- `env(safe-area-inset-bottom)` in `.rm-nav` — always `0` in the emulator, so
|
||
the clearance for the home indicator is untested.
|
||
- A bottom `position: fixed` bar together with Safari's collapsing toolbar.
|
||
- `width: 100vw` — on the desktop the scrollbar counts towards it and creates
|
||
phantom overflow, so the debug overlay reports different numbers than iOS.
|
||
- `-webkit-text-size-adjust` and Safari's automatic font scaling.
|
||
- `-webkit-backdrop-filter` renders in Chrome, but looks different.
|
||
|
||
For higher fidelity without an iPhone, Playwright ships a real WebKit build for
|
||
Windows (`npx playwright install webkit`).
|
||
|
||
#### Troubleshooting
|
||
|
||
Install `dev/tm-test.user.js` — it injects a red bar and nothing else. If the
|
||
bar does not appear, the problem is Tampermonkey (see setup above), not the
|
||
script code. If it does appear, check the loader's *Externals* tab in the
|
||
Tampermonkey dashboard: an empty or failed entry means the `@require` path is
|
||
wrong.
|
||
|
||
If Tampermonkey keeps serving a stale copy despite the update interval, replace
|
||
the `file://` require with a local HTTP server, which does not cache:
|
||
|
||
```js
|
||
// @require http://localhost:8777/rin-mobile.user.js
|
||
```
|
||
|
||
### Repository layout
|
||
|
||
```
|
||
rin-mobile.user.js topic list → cards, thread → post stream
|
||
dev/
|
||
rin-mobile.dev.user.js loader, @require with absolute path
|
||
```
|
||
|
||
---
|
||
|
||
## Deutsch
|
||
|
||
Ein Userscript, das die phpBB2-Seiten von `cs.rin.ru` für Safari auf iOS in eine
|
||
mobile Ansicht umbaut. Es ersetzt das ursprüngliche Tabellenlayout vollständig:
|
||
der vorhandene Seiteninhalt wird ausgeblendet und ein neu gebautes DOM an
|
||
`<body>` gehängt.
|
||
|
||
`rin-mobile.user.js` greift auf `*://cs.rin.ru/forum/*` und wählt die Ansicht
|
||
anhand des Seitentyps:
|
||
|
||
| Seite | Ansicht |
|
||
|---|---|
|
||
| `viewforum.php`, `search.php`, Forumwurzel | Themen- und Forenliste als Karten |
|
||
| `viewtopic.php` | Thread als Beitragsstrom mit fixierter Navigationsleiste |
|
||
| alles andere | Unverändert — es werden keine Stile injiziert |
|
||
|
||
Eine `viewforum.php`-Seite ist nicht zwangsläufig eine Themenliste: eine
|
||
Kategorieseite listet Foren auf, eine Forenseite kann beides enthalten. Jede
|
||
Tabellenzeile wird deshalb anhand ihres ersten verwertbaren Links eingeordnet.
|
||
Forenzeilen werden zu Karten mit Name, Beschreibung, Unterforen und Zahlen,
|
||
Themenzeilen behalten ihre bisherige Karte, Kategoriezeilen werden zu
|
||
Zwischenüberschriften. Erkannt werden die Zeilen an phpBBs eigenen Klassen
|
||
`forumlink` / `forumdesc` und ersatzweise an ihrer Form — zwei rein numerische
|
||
Spalten hat nur eine Forenzeile mit Themen- und Beitragszahl.
|
||
|
||
Die Navigationsleiste im Thread enthält erste / vorherige / nächste / letzte
|
||
Seite und eine Positionsanzeige. Ein Tipp darauf öffnet ein Sheet mit
|
||
Zahlenfeld und einem Raster aller Seiten. Die Ziele werden als
|
||
`start = (Seite - 1) × per_page` berechnet und nicht aus den gerenderten
|
||
Seitenlinks übernommen, weil phpBB davon immer nur eine Handvoll anzeigt.
|
||
`per_page` stammt aus der `jumpto()`-Funktion, die das Forum in die Seite
|
||
einbettet; fehlt sie, bleiben nur die erste Seite und die ursprünglichen
|
||
Zurück-/Weiter-Links nutzbar.
|
||
|
||
Beide Ansichten haben oben eine fixierte Brotkrumenleiste, übernommen aus dem
|
||
`Board index » … » Main Forum`-Pfad des Forums. Ohne sie führt aus einem Thread
|
||
kein Weg zurück, weil die Originalseite ausgeblendet ist und phpBB das
|
||
Elternforum nirgends sonst verlinkt. Die Leiste lässt sich waagerecht schieben,
|
||
wenn der Pfad breiter ist als der Bildschirm, und entfällt auf Seiten ohne
|
||
Pfadangabe. `Board index` führt auf `index.php` — diese Seite baut das Script
|
||
nicht um, sie erscheint im Desktop-Layout.
|
||
|
||
Das Script läuft bei `document-start`, setzt ein mobiles Viewport-Meta-Tag und
|
||
hat ein `DEBUG`-Flag. Solange `DEBUG` auf `true` steht, wird ein grünes
|
||
Diagnose-Overlay über die Seite gelegt, das zeigt, welche Ansicht gewählt wurde
|
||
und wie viele Zeilen umgewandelt wurden. Für den täglichen Gebrauch auf `false`
|
||
setzen.
|
||
|
||
### Installation unter iOS
|
||
|
||
1. Einen Userscript-Manager für Safari unter iOS installieren (zum Beispiel
|
||
*Userscripts*) und unter *Einstellungen → Safari → Erweiterungen* aktivieren.
|
||
2. `rin-mobile.user.js` in das Script-Verzeichnis des Managers legen.
|
||
3. Der Erweiterung die Berechtigung für `cs.rin.ru` erteilen.
|
||
|
||
---
|
||
|
||
### Entwicklung
|
||
|
||
Entwickelt wird unter Windows in Chrome oder Edge mit Tampermonkey.
|
||
`dev/rin-mobile.dev.user.js` ist ein Loader: er enthält nur einen
|
||
Metadatenblock, der das eigentliche Script per `@require` von der Platte
|
||
einbindet. Es genügt, `rin-mobile.user.js` zu bearbeiten und die Seite neu zu
|
||
laden — keine Neuinstallation in Tampermonkey nötig.
|
||
|
||
#### ⚠️ Pfadanpassung erforderlich
|
||
|
||
Der Loader in `dev/` verweist mit einem **absoluten Pfad** auf das Script:
|
||
|
||
```js
|
||
// @require file:///C:/Projekte/ios_safari_userscripts/rin-mobile.user.js
|
||
```
|
||
|
||
Dieser Pfad ist fest eingetragen und gilt nur auf dem Rechner, für den er
|
||
geschrieben wurde. Nach dem Klonen des Repositories oder dem Verschieben des
|
||
Projektordners muss die `@require`-Zeile in `dev/rin-mobile.dev.user.js` auf den
|
||
eigenen Ablageort angepasst werden.
|
||
|
||
Dabei Schrägstriche und das Präfix `file:///` inklusive Laufwerksbuchstaben
|
||
verwenden — `file:///D:/projekte/ios_safari_userscripts/rin-mobile.user.js`.
|
||
Ein `@require`, das nicht aufgelöst werden kann, führt dazu, dass Tampermonkey
|
||
das Script **komplett und ohne Fehlermeldung auf der Seite** überspringt. Das
|
||
sieht exakt so aus, als wäre gar kein Script installiert.
|
||
|
||
#### Tampermonkey einrichten
|
||
|
||
Drei Einstellungen sind nötig; die erste ist die mit Abstand häufigste Ursache
|
||
für „es passiert überhaupt nichts":
|
||
|
||
1. `chrome://extensions` → Tampermonkey → **Nutzerskripte zulassen**
|
||
aktivieren. Bei älteren Chrome-Versionen stattdessen den
|
||
**Entwicklermodus** oben rechts einschalten. Ohne das blockiert Manifest V3
|
||
jede Injektion.
|
||
2. Auf derselben Seite → **Zugriff auf Datei-URLs zulassen** aktivieren, damit
|
||
`@require file://` aufgelöst werden kann.
|
||
3. Tampermonkey-Dashboard → *Einstellungen* → *Externals* → Update-Intervall auf
|
||
**immer** stellen, sonst liefert der Loader weiterhin eine zwischen
|
||
gespeicherte Fassung des Scripts aus.
|
||
|
||
Danach den Loader einmal über `file:///.../dev/rin-mobile.dev.user.js` öffnen —
|
||
Tampermonkey fängt `.user.js`-URLs ab und bietet die Installation an.
|
||
|
||
Den Loader nicht parallel zum unveränderten Script betreiben. Sind beide in
|
||
Tampermonkey aktiv, läuft der Code doppelt auf derselben Seite, mit doppelten
|
||
Karten und zwei Debug-Overlays als Folge.
|
||
|
||
#### Geräte-Emulation
|
||
|
||
DevTools → *Device Toolbar* (`Strg+Umschalt+M`) → *Edit…* → eigenes Gerät mit
|
||
**430 × 932** und DPR **3** für ein iPhone 15 Pro Max anlegen, Gerätetyp
|
||
*Mobile*, dazu einen iOS-Safari-User-Agent eintragen.
|
||
|
||
#### Was die Desktop-Emulation nicht zeigt
|
||
|
||
Chrome verwendet Blink, iOS Safari verwendet WebKit. Diese Punkte müssen am
|
||
Gerät geprüft werden:
|
||
|
||
- `env(safe-area-inset-bottom)` in `.rm-nav` — im Emulator immer `0`, die
|
||
Freihaltung für den Home-Indicator bleibt also ungetestet.
|
||
- Eine unten fixierte Leiste zusammen mit Safaris ein- und ausfahrender
|
||
Toolbar.
|
||
- `width: 100vw` — auf dem Desktop zählt die Scrollbar mit und erzeugt
|
||
Phantom-Overflow, das Debug-Overlay meldet dort andere Zahlen als unter iOS.
|
||
- `-webkit-text-size-adjust` und Safaris automatische Schriftvergrößerung.
|
||
- `-webkit-backdrop-filter` rendert in Chrome, sieht aber anders aus.
|
||
|
||
Für höhere Treue ohne iPhone bringt Playwright einen echten WebKit-Build für
|
||
Windows mit (`npx playwright install webkit`).
|
||
|
||
#### Fehlersuche
|
||
|
||
`dev/tm-test.user.js` installieren — das Script blendet nur einen roten Balken
|
||
ein, sonst nichts. Erscheint der Balken nicht, liegt das Problem bei
|
||
Tampermonkey (siehe Einrichtung oben) und nicht am Script-Code. Erscheint er,
|
||
im Tampermonkey-Dashboard den Tab *Externals* des Loaders prüfen: ein leerer
|
||
oder fehlgeschlagener Eintrag bedeutet, dass der `@require`-Pfad falsch ist.
|
||
|
||
Liefert Tampermonkey trotz Update-Intervall weiterhin einen veralteten Stand
|
||
aus, das `file://`-Require durch einen lokalen HTTP-Server ersetzen, der nicht
|
||
zwischenspeichert:
|
||
|
||
```js
|
||
// @require http://localhost:8777/rin-mobile.user.js
|
||
```
|
||
|
||
### Aufbau des Repositories
|
||
|
||
```
|
||
rin-mobile.user.js Themenliste → Karten, Thread → Beitragsstrom
|
||
dev/
|
||
rin-mobile.dev.user.js Loader, @require mit absolutem Pfad
|
||
```
|