mirror of
https://github.com/Andre-Bzk/rin-mobile-userscript.git
synced 2026-11-15 09:33:08 +01:00
docs: lead with screenshots and correct outdated documentation
Both documents had drifted away from the repository they describe: they pointed at fixtures and a helper script that are not present, documented a local-server workflow that is no longer used, and filed one page type under the wrong view. Following them meant setting up things that cannot work while trusting claims that no longer held. The README also explained every design decision before showing a single result, so the question a reader asks first — what does this actually look like — took the longest to answer. Screenshots and a short feature list now carry that job. The reasoning stays where it is needed, next to the code. Restricting the dev loader to the live site closes a side effect that only surfaced locally: its patterns matched page names common enough that the stylesheet would have leaked into unrelated local projects. The version number existed in two places and had already drifted apart. Reading it back from the metadata block leaves one place to change it.
This commit is contained in:
@@ -1,18 +1,17 @@
|
|||||||
# CLAUDE.md
|
# CLAUDE.md
|
||||||
|
|
||||||
Ein Userscript, das die phpBB-Seiten von `cs.rin.ru` fuer Safari auf iOS in eine
|
Ein Userscript, das die phpBB3-Seiten von `cs.rin.ru` fuer Safari auf iOS in eine
|
||||||
mobile Ansicht umbaut. Kein Build, keine Abhaengigkeiten, kein `package.json` —
|
mobile Ansicht umbaut. Kein Build, keine Abhaengigkeiten, kein `package.json` —
|
||||||
die `.user.js`-Datei ist das Produkt.
|
die `.user.js`-Datei ist das Produkt.
|
||||||
|
|
||||||
| Datei | Greift auf | Zweck |
|
| Datei | Greift auf | Zweck |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `rin-mobile.user.js` | `*://cs.rin.ru/forum/*` | Beide Ansichten, Weiche nach Seitentyp |
|
| `rin-mobile.user.js` | `*://cs.rin.ru/forum/*` | Alle Ansichten, Weiche nach Seitentyp |
|
||||||
| `dev/rin-mobile.dev.user.js` | zusaetzlich `localhost:*` | Loader, bindet per `@require file:///` das echte Script ein |
|
| `dev/rin-mobile.dev.user.js` | `*://cs.rin.ru/forum/*` | Loader, bindet per `@require file:///` das echte Script ein |
|
||||||
| `dev/viewtopic.php` | — | Fixture: gespeicherter Thread, 1114 Seiten |
|
| `dev/viewtopic.php` | — | Fixture: gespeicherter Thread, `per_page=15`, 1114 Seiten |
|
||||||
| `dev/viewforum.php` | — | Fixture: Main Forum, 610 Seiten, mit Unterforen, Ankuendigungen und Stickies |
|
| `dev/viewforum.php` | — | Fixture: Main Forum, `per_page=100`, 610 Seiten, mit Unterforen, Ankuendigungen und Stickies |
|
||||||
| `dev/index.php` | — | Fixture: Forumwurzel, zwei Kategorien mit Forenzeilen, keine Paginierung |
|
| `dev/index.php` | — | Fixture: Forumwurzel, zwei Kategorien mit Forenzeilen, keine Paginierung, eingeloggt aufgenommen |
|
||||||
| `dev/ucp.php` | — | Fixture: Login-Formular (`mode=login`), nur ausgeloggter Zustand |
|
| `dev/ucp.php` | — | Fixture: Login-Formular (`mode=login`), nur ausgeloggter Zustand |
|
||||||
| `dev/after_login/ucp.php` | — | Fixture: dieselbe URL nach erfolgreichem Login, "Information"-Vorlage statt Formular |
|
|
||||||
| `dev/search.php` | — | Fixture: Suchformular ohne Treffer, eingeloggt aufgenommen |
|
| `dev/search.php` | — | Fixture: Suchformular ohne Treffer, eingeloggt aufgenommen |
|
||||||
| `dev/search2.php` | — | Fixture: Suchtreffer im Modus "Posts" (15 von 1438 Treffern, `t=63042`, `per_page=15`, 96 Seiten) |
|
| `dev/search2.php` | — | Fixture: Suchtreffer im Modus "Posts" (15 von 1438 Treffern, `t=63042`, `per_page=15`, 96 Seiten) |
|
||||||
|
|
||||||
@@ -20,6 +19,20 @@ Die Fixtures sind ueber `.gitignore` (`dev/*.php`) ausgeschlossen. Nach einem
|
|||||||
frischen Klon sind sie nicht da und muessen nach der Anleitung in der README neu
|
frischen Klon sind sie nicht da und muessen nach der Anleitung in der README neu
|
||||||
gespeichert werden — die Seite verlangt einen Login.
|
gespeichert werden — die Seite verlangt einen Login.
|
||||||
|
|
||||||
|
Der Loader greift ausschliesslich auf die echte Seite. Die Fixtures sind
|
||||||
|
Markup-Vorlagen fuer das jsdom-Harness und zum Nachlesen, keine Seiten zum
|
||||||
|
Anschauen im Browser — die Layoutarbeit laeuft in Chrome auf `cs.rin.ru`
|
||||||
|
selbst. Sie lokal auszuliefern verlangte `@include`-Regeln fuer `localhost`,
|
||||||
|
und die passen auf Seitennamen, die dort haeufig genug vorkommen (`index.php`,
|
||||||
|
alles mit `search` darin), dass der globale Teil des Stylesheets
|
||||||
|
(`html, body`, `img`, jeweils `!important`) in fremde lokale Projekte geriete.
|
||||||
|
Das Nachziehen waere billig, der Fehlersuchweg dorthin nicht.
|
||||||
|
|
||||||
|
Fuer den Zustand nach erfolgreichem Login (`ucp.php?mode=login` ohne Formular,
|
||||||
|
"Information"-Vorlage) liegt derzeit keine Fixture im Repo. `buildLoginInfo()`
|
||||||
|
wurde gegen einen Mitschnitt gebaut, der nicht mehr vorhanden ist; wer den
|
||||||
|
Zweig anfassen will, muss die Seite neu aufnehmen.
|
||||||
|
|
||||||
## Aufbau
|
## Aufbau
|
||||||
|
|
||||||
Ein IIFE, streng der Reihe nach:
|
Ein IIFE, streng der Reihe nach:
|
||||||
@@ -34,9 +47,20 @@ Ein IIFE, streng der Reihe nach:
|
|||||||
5. `pageState()`, `pageSheet()` und `pageNav()` — die Paginierung, von Liste
|
5. `pageState()`, `pageSheet()` und `pageNav()` — die Paginierung, von Liste
|
||||||
und Thread benutzt, nicht vom Login
|
und Thread benutzt, nicht vom Login
|
||||||
6. `buildList()`, `buildThread()` beziehungsweise `buildLogin()` lesen das
|
6. `buildList()`, `buildThread()` beziehungsweise `buildLogin()` lesen das
|
||||||
Original-DOM und bauen ein `div.rm-root`; alle drei haengen zum Schluss
|
Original-DOM und bauen ein `div.rm-root`; alle haengen zum Schluss
|
||||||
ueber `addCrumbs()` die fixierte Brotkrumenleiste an, die zugleich ueber
|
ueber `addCrumbs()` die fixierte Brotkrumenleiste an, die zugleich ueber
|
||||||
`loginState()` die Login/Logout-Pille traegt
|
`loginState()` die Login/Logout-Pille traegt. Zwei der drei Ansichten
|
||||||
|
verzweigen intern weiter, weil sich mehrere Seitenformen dieselbe URL
|
||||||
|
teilen:
|
||||||
|
- `buildList()` versucht zuerst `buildSearchForm()` (grosses Suchformular
|
||||||
|
auf `search.php`), dann `buildSearchResults()` (Trefferliste im Modus
|
||||||
|
"Posts", Karten ueber `buildHit()`); erst wenn beide `false` liefern,
|
||||||
|
laeuft das gewoehnliche Zeileneinsammeln
|
||||||
|
- `buildLogin()` faellt ohne Formular auf `buildLoginInfo()` zurueck
|
||||||
|
("Information"-Vorlage nach dem Absenden)
|
||||||
|
- `buildThread()` legt ueber `buildThreadSearch()` die zweite Leiste an,
|
||||||
|
die die Lupe in den Brotkrumen per `toggleThreadSearch()` ein- und
|
||||||
|
ausblendet
|
||||||
7. `run()` waehlt die Ansicht und haengt bei `DEBUG` das gruene Overlay an
|
7. `run()` waehlt die Ansicht und haengt bei `DEBUG` das gruene Overlay an
|
||||||
8. Start ueber `DOMContentLoaded`, falls `readyState === 'loading'`
|
8. Start ueber `DOMContentLoaded`, falls `readyState === 'loading'`
|
||||||
|
|
||||||
@@ -125,7 +149,10 @@ Titelzelle gebildet, nie aus deren gesamtem Text.
|
|||||||
Klassennamen aus der phpBB-Dokumentation (`forumlink`, `forumdesc`) deshalb
|
Klassennamen aus der phpBB-Dokumentation (`forumlink`, `forumdesc`) deshalb
|
||||||
zunaechst nur eine Vermutung; `dev/viewforum.php` bestaetigt sie inzwischen. Der
|
zunaechst nur eine Vermutung; `dev/viewforum.php` bestaetigt sie inzwischen. Der
|
||||||
Rueckfall auf die Form der Zeile bleibt trotzdem stehen — er kostet nichts und
|
Rueckfall auf die Form der Zeile bleibt trotzdem stehen — er kostet nichts und
|
||||||
traegt die Erkennung, wenn das Theme wechselt.
|
traegt die Erkennung, wenn das Theme wechselt. `rinDark` ist allerdings eine
|
||||||
|
Ableitung von subsilver2 und laedt dessen
|
||||||
|
`styles/subsilver2/template/forum_fn.js` mit — Klassennamen aus subsilver2 sind
|
||||||
|
deshalb eine brauchbare erste Annahme, wenn eine Seite noch keine Fixture hat.
|
||||||
|
|
||||||
**Die Brotkrumenleiste ist fixiert, nicht sticky.** `.rm-root` traegt
|
**Die Brotkrumenleiste ist fixiert, nicht sticky.** `.rm-root` traegt
|
||||||
`overflow:hidden` und wuerde damit zum Scrollport einer `position:sticky`
|
`overflow:hidden` und wuerde damit zum Scrollport einer `position:sticky`
|
||||||
@@ -137,8 +164,9 @@ Brotkrumen im Markup kein leerer Streifen bleibt.
|
|||||||
**Die Login-Erkennung ist inzwischen gegen eine echte Sitzung geprueft.**
|
**Die Login-Erkennung ist inzwischen gegen eine echte Sitzung geprueft.**
|
||||||
`loginState()` unterscheidet `a[href*="mode=login"]` von
|
`loginState()` unterscheidet `a[href*="mode=login"]` von
|
||||||
`a[href*="mode=logout"]` im Menuebalken und liest den Namen aus dem Muster
|
`a[href*="mode=logout"]` im Menuebalken und liest den Namen aus dem Muster
|
||||||
`Logout [ Name ]` im Linktext. `dev/index.php` und `dev/after_login/ucp.php`
|
`Logout [ Name ]` im Linktext. `dev/index.php`, `dev/search.php` und
|
||||||
sind eingeloggt aufgenommen (`Logout [ <Benutzername> ]`) und bestaetigen das Muster.
|
`dev/search2.php` sind eingeloggt aufgenommen (`Logout [ <Benutzername> ]`) und
|
||||||
|
bestaetigen das Muster.
|
||||||
Der Fallback bleibt trotzdem stehen: passt das Muster einmal nicht — andere
|
Der Fallback bleibt trotzdem stehen: passt das Muster einmal nicht — andere
|
||||||
Sprache, anderer Klammertyp — zeigt die Pille „Logout" ohne Namen, statt eine
|
Sprache, anderer Klammertyp — zeigt die Pille „Logout" ohne Namen, statt eine
|
||||||
Ausnahme zu werfen.
|
Ausnahme zu werfen.
|
||||||
@@ -151,7 +179,9 @@ liegt aber keine Fixture vor). `buildLoginInfo()` erkennt die Vorlage deshalb
|
|||||||
an ihrer Form — eine Kopfzeile mit genau einer `th`-Zelle, gefolgt von einer
|
an ihrer Form — eine Kopfzeile mit genau einer `th`-Zelle, gefolgt von einer
|
||||||
`td.row1`-Nachrichtenzelle — nicht am Wortlaut, und uebernimmt die Zelle
|
`td.row1`-Nachrichtenzelle — nicht am Wortlaut, und uebernimmt die Zelle
|
||||||
unveraendert wie das Formular selbst. Findet `buildLogin()` weder Formular
|
unveraendert wie das Formular selbst. Findet `buildLogin()` weder Formular
|
||||||
noch diese Form, baut es nichts; die Originalseite bleibt sichtbar.
|
noch diese Form, baut es nichts; die Originalseite bleibt sichtbar. Achtung:
|
||||||
|
die Fixture, gegen die das gebaut wurde, liegt nicht mehr im Repo — der Zweig
|
||||||
|
ist derzeit nicht nachpruefbar, ohne die Seite neu aufzunehmen.
|
||||||
|
|
||||||
**`index.php` wird ueber `location.pathname` erkannt, nicht ueber
|
**`index.php` wird ueber `location.pathname` erkannt, nicht ueber
|
||||||
`here`.** Der Login-Redirect haengt "index.php" gelegentlich als Wert eines
|
`here`.** Der Login-Redirect haengt "index.php" gelegentlich als Wert eines
|
||||||
@@ -228,6 +258,15 @@ Suchformular auf `search.php`.** Sowohl `viewforum.php` als auch
|
|||||||
allein liesse sich das grosse Formular nicht von den kleinen unterscheiden.
|
allein liesse sich das grosse Formular nicht von den kleinen unterscheiden.
|
||||||
Der mehrfach waehlbare Forenwaehler existiert dagegen nur im grossen Formular.
|
Der mehrfach waehlbare Forenwaehler existiert dagegen nur im grossen Formular.
|
||||||
|
|
||||||
|
**Die Vorbelegung des Forenwaehlers haengt an der harten Forum-ID 10.**
|
||||||
|
`buildSearchForm()` waehlt `option[value="10"]` (Main Forum) vor und setzt
|
||||||
|
`input[name="sc"][value="0"]` (Unterforen: No), weil das serverseitige
|
||||||
|
Formular sonst mit leerem Waehler und „Search subforums: Yes" startet. Beides
|
||||||
|
ist eine Bequemlichkeit, keine Funktion: vergibt das Forum die IDs neu oder
|
||||||
|
benennt es das Hauptforum um, greift die Vorauswahl stumm nicht mehr — das
|
||||||
|
Formular bleibt bedienbar, steht dann aber wieder auf der Servervorgabe. Kein
|
||||||
|
Fehlerfall, aber auch nichts, was von selbst auffaellt.
|
||||||
|
|
||||||
**Die Textfelder des Suchformulars tragen `style="width: 300px"` direkt im
|
**Die Textfelder des Suchformulars tragen `style="width: 300px"` direkt im
|
||||||
Markup.** Eine externe Regel ohne `!important` sticht dagegen nicht, egal wie
|
Markup.** Eine externe Regel ohne `!important` sticht dagegen nicht, egal wie
|
||||||
spezifisch der Selektor ist — `buildSearchForm()` entfernt das
|
spezifisch der Selektor ist — `buildSearchForm()` entfernt das
|
||||||
@@ -289,9 +328,19 @@ alle `inputToButton()`. Ungeprueft, ob `-webkit-appearance:none` allein bei
|
|||||||
einer anderen iOS-Version genuegt haette — der Wechsel auf `<button>` umgeht
|
einer anderen iOS-Version genuegt haette — der Wechsel auf `<button>` umgeht
|
||||||
die Frage, statt sie zu beantworten.
|
die Frage, statt sie zu beantworten.
|
||||||
|
|
||||||
**`DEBUG` steht auf `true`** und muss vor dem Ausliefern auf `false`. Die
|
**`DEBUG` muss vor dem Ausliefern auf `false` stehen** (aktuell tut es das).
|
||||||
Versionsnummer steht doppelt: im `@version`-Header und im Text des
|
Solange es auf `true` steht, haengt `run()` das gruene Overlay an — das ist
|
||||||
Debug-Overlays.
|
der einzige Effekt des Flags, ein vergessenes `true` bricht nichts, sieht auf
|
||||||
|
dem Geraet aber unfertig aus.
|
||||||
|
|
||||||
|
**Die Versionsnummer steht nur im `@version`-Header.** Das Overlay liest sie
|
||||||
|
ueber `GM_info.script.version` zurueck, statt sie ein zweites Mal als Literal
|
||||||
|
zu fuehren — genau das lief zwischen 3.13 und 3.14 auseinander, ohne dass es
|
||||||
|
jemandem auffiel, weil das Overlay im Auslieferzustand ohnehin aus ist. Wer
|
||||||
|
den Overlay-Text anfasst: keinen neuen Versionsliteral einbauen. Fehlt
|
||||||
|
`GM_info` (Manager ohne diese API), zeigt das Overlay den Namen ohne Version;
|
||||||
|
das ist der gewollte Rueckfall, weil eine fehlende Angabe harmloser ist als
|
||||||
|
eine falsche.
|
||||||
|
|
||||||
## Testen
|
## Testen
|
||||||
|
|
||||||
@@ -315,6 +364,9 @@ Drei Stolpersteine dabei:
|
|||||||
Sinnvolle Faelle: erste Seite, zweite Seite, Mitte, letzte Seite, dazu die
|
Sinnvolle Faelle: erste Seite, zweite Seite, Mitte, letzte Seite, dazu die
|
||||||
Degradation ohne `per_page` und ein Thread ohne Paginierung. Fixture-Eckdaten:
|
Degradation ohne `per_page` und ein Thread ohne Paginierung. Fixture-Eckdaten:
|
||||||
`f=10&t=68689`, `per_page = 15`, 1114 Seiten, letzte Seite `start=16695`.
|
`f=10&t=68689`, `per_page = 15`, 1114 Seiten, letzte Seite `start=16695`.
|
||||||
|
Am Beitrag selbst zu pruefen: alles hinter dem ersten `<hr>` im `postbody`
|
||||||
|
landet als zugeklapptes `details` („Signatur") am Kartenfuss, Beitraege ohne
|
||||||
|
`<hr>` behalten ihren Text vollstaendig im Koerper.
|
||||||
|
|
||||||
Dieselben Faelle gelten seit 3.5 fuer die Liste, die sich die Leiste mit dem
|
Dieselben Faelle gelten seit 3.5 fuer die Liste, die sich die Leiste mit dem
|
||||||
Thread teilt. Eckdaten von `dev/viewforum.php`: `f=10`, `per_page = 100`, 610
|
Thread teilt. Eckdaten von `dev/viewforum.php`: `f=10`, `per_page = 100`, 610
|
||||||
@@ -337,16 +389,17 @@ dieselbe Forenliste ohne die Klassen `forumlink`/`forumdesc` — die muss ueber
|
|||||||
die Zahlenspalten dasselbe Ergebnis liefern.
|
die Zahlenspalten dasselbe Ergebnis liefern.
|
||||||
|
|
||||||
Fuer den Login genuegt `dev/ucp.php` unveraendert: geprueft werden das
|
Fuer den Login genuegt `dev/ucp.php` unveraendert: geprueft werden das
|
||||||
uebernommene Formular (Username-/Passwortfeld, `sid`, `redirect`, Submit) und
|
uebernommene Formular (Username-/Passwortfeld, `sid`, `redirect`, Submit), der
|
||||||
die Pille im ausgeloggten Zustand. Fuer den eingeloggten Zustand der Pille
|
Regeltext als zugeklapptes `details` („Regeln") und die Pille im ausgeloggten
|
||||||
`dev/index.php` oder `dev/after_login/ucp.php` laden — beide sind eingeloggt
|
Zustand. Fuer den eingeloggten Zustand der Pille `dev/index.php`,
|
||||||
|
`dev/search.php` oder `dev/search2.php` laden — alle drei sind eingeloggt
|
||||||
aufgenommen und tragen das echte `Logout [ Name ]`-Markup.
|
aufgenommen und tragen das echte `Logout [ Name ]`-Markup.
|
||||||
|
|
||||||
Fuer die Meldung nach dem Login genuegt `dev/after_login/ucp.php`
|
Die Meldung nach dem Login (`buildLoginInfo()`) ist mangels Fixture nicht
|
||||||
unveraendert, URL `ucp.php?mode=login`: geprueft werden Titel, uebernommene
|
nachpruefbar. Wer sie anfasst, nimmt `ucp.php?mode=login` nach einem echten
|
||||||
Nachricht samt Link und die Pille. Zu pruefen ist ausserdem, dass `dev/ucp.php`
|
Login neu auf; zu pruefen waeren dann Titel, uebernommene Nachricht samt Link
|
||||||
(das Formular, gleiche URL) weiterhin die Formular-Zweig traf und nicht in die
|
und die Pille — und dass `dev/ucp.php` (das Formular, gleiche URL) weiterhin
|
||||||
Meldungs-Erkennung faellt.
|
im Formular-Zweig landet und nicht in die Meldungs-Erkennung faellt.
|
||||||
|
|
||||||
Fuer die Forumwurzel genuegt `dev/index.php`, URL `index.php?sid=…`: zwei
|
Fuer die Forumwurzel genuegt `dev/index.php`, URL `index.php?sid=…`: zwei
|
||||||
Kategorien mit zusammen 16 Forenkarten, keine Paginierung. Zu pruefen ist
|
Kategorien mit zusammen 16 Forenkarten, keine Paginierung. Zu pruefen ist
|
||||||
@@ -360,15 +413,15 @@ inline-`style`-Attribute der Textfelder und die Schnellzugriffs-Chips aus
|
|||||||
`p.searchbar`. Zu pruefen ist ausserdem `dev/viewforum.php` auf derselben
|
`p.searchbar`. Zu pruefen ist ausserdem `dev/viewforum.php` auf derselben
|
||||||
Weiche: dessen eingebettetes `#forum-search`-Mini-Formular teilt sich Aktion
|
Weiche: dessen eingebettetes `#forum-search`-Mini-Formular teilt sich Aktion
|
||||||
und `keywords`-Feld mit dem grossen Suchformular und darf `buildSearchForm()`
|
und `keywords`-Feld mit dem grossen Suchformular und darf `buildSearchForm()`
|
||||||
nicht faelschlich auslösen, die Forenliste muss wie gewohnt Karten liefern.
|
nicht faelschlich ausloesen, die Forenliste muss wie gewohnt Karten liefern.
|
||||||
|
|
||||||
Fuer Suchtreffer genuegt `dev/search2.php` unveraendert, URL beliebig (die
|
Fuer Suchtreffer genuegt `dev/search2.php` unveraendert, URL beliebig (die
|
||||||
Erkennung haengt nicht an `location`, sondern an `p.topictitle` im Markup):
|
Erkennung haengt nicht an `location`, sondern an `p.topictitle` im Markup):
|
||||||
geprueft werden alle 15 Trefferkarten, die verschobene "Searched topic /
|
geprueft werden alle 15 Trefferkarten, die verschobene "Searched topic /
|
||||||
Search term used"-Zelle samt ihrer beiden Links, Autor und Zeitstempel pro
|
Search term used"-Zelle samt ihrer beiden Links, Autor und Zeitstempel pro
|
||||||
Treffer, die per Regex getrennten Antworten-/Views-Zahlen, der verschobene
|
Treffer, die per Regex getrennten Antworten-/Views-Zahlen, der verschobene
|
||||||
`td.postbody`-Beitragsauszug und die Seitennavigation (`per_page=15`, 96
|
`td.postbody`-Beitragsauszug, der „Zum Beitrag ↓"-Link am Kartenfuss und die
|
||||||
Seiten). Zu pruefen ist ausserdem, dass `dev/search.php` (das leere Formular)
|
Seitennavigation (`per_page=15`, 96 Seiten). Zu pruefen ist ausserdem, dass `dev/search.php` (das leere Formular)
|
||||||
weiterhin den Formular-Zweig trifft und nicht in die Treffer-Erkennung faellt,
|
weiterhin den Formular-Zweig trifft und nicht in die Treffer-Erkennung faellt,
|
||||||
und dass `dev/viewforum.php` weiterhin normale Karten liefert — beide haben
|
und dass `dev/viewforum.php` weiterhin normale Karten liefert — beide haben
|
||||||
kein `p.topictitle`. Der Modus "Topics" (`sr=topics`) ist mangels Fixture
|
kein `p.topictitle`. Der Modus "Topics" (`sr=topics`) ist mangels Fixture
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
## English
|
## English
|
||||||
|
|
||||||
A single userscript that rebuilds the phpBB2 pages of `cs.rin.ru` into a mobile
|
A single userscript that rebuilds the phpBB3 pages of `cs.rin.ru` into a mobile
|
||||||
layout for Safari on iOS. It replaces the original table layout entirely: the
|
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>`.
|
existing page content is hidden and a freshly built DOM is appended to `<body>`.
|
||||||
|
|
||||||
@@ -15,111 +15,57 @@ page type:
|
|||||||
|
|
||||||
| Page | View |
|
| Page | View |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `viewforum.php`, `search.php`, `index.php`, forum root | Topic and forum list as cards |
|
| `viewforum.php`, `index.php`, forum root | Topic and forum list as cards |
|
||||||
|
| `search.php` | The query form restyled, or — for a submitted search in "Posts" mode — its hits as cards |
|
||||||
| `viewtopic.php` | Thread as a post stream with a fixed bottom navigation bar |
|
| `viewtopic.php` | Thread as a post stream with a fixed bottom navigation bar |
|
||||||
| `ucp.php?mode=login` | Login form, restyled in place; on the same URL after a successful submit, the resulting information page instead |
|
| `ucp.php?mode=login` | Login form, restyled in place; on the same URL after a successful submit, the resulting information page instead |
|
||||||
| anything else | Untouched — no styles are injected |
|
| anything else | Untouched — no styles are injected |
|
||||||
|
|
||||||
A `viewforum.php` page is not necessarily a list of topics: a category page
|
### Screenshots
|
||||||
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.
|
|
||||||
|
|
||||||
Forums, global announcements, announcements, stickies and topics all end up in
|
| Forum list, with the sections above the topics collapsed | Thread, with the in-topic search bar revealed |
|
||||||
the same stream of cards, which loses the separation the original page draws
|
|---|---|
|
||||||
between them. A header strip naming the section and its card count is therefore
|
| <img src="docs/Screenshot_mobile_1.png" alt="Forum list as cards: breadcrumb bar with magnifier, an open FOREN section with four forum cards, collapsed GLOBAL ANNOUNCEMENTS, ANNOUNCEMENTS and STICKIES strips, and the page bar showing 1 / 610" width="100%"> | <img src="docs/Screenshot_mobile_2.png" alt="Thread view: breadcrumbs, a second bar with a search field, and a post card with avatar, author, rank and post count above the message" width="100%"> |
|
||||||
inserted wherever the kind changes, and forum cards additionally carry a
|
| **Search form, top: quick links and forum picker** | **Search form, bottom: options and buttons** |
|
||||||
coloured left edge. The label is taken from the board's own separator row
|
| <img src="docs/Screenshot_mobile_3.png" alt="Search form: quick links as chips, the keyword fields and the forum picker with Main Forum preselected" width="100%"> | <img src="docs/Screenshot_mobile_4.png" alt="Search form continued: search subforums set to No, the remaining option groups, and the Search and Reset buttons" width="100%"> |
|
||||||
(`Global Announcements`, `Stickies`, `Topics`), so sections this script does not
|
|
||||||
know are named correctly too. Which kind a topic row is comes from the icon in
|
|
||||||
its first column, not from its title. The strip is left out directly below a
|
|
||||||
category heading, which already introduces the forums under it.
|
|
||||||
|
|
||||||
Tapping a header collapses its section. Global announcements, announcements and
|
### What it does
|
||||||
stickies start collapsed: they precede the topics on *every* page of a forum and
|
|
||||||
otherwise fill the first screen. The state is stored per kind in `localStorage`,
|
|
||||||
so collapsing stickies once applies to every forum. `localStorage` is used
|
|
||||||
rather than `GM_setValue` because it needs no `@grant` and behaves the same in
|
|
||||||
Tampermonkey and in the iOS app; the trade-off is that Safari may clear
|
|
||||||
script-writable storage after long inactivity, which resets the sections to
|
|
||||||
their default.
|
|
||||||
|
|
||||||
Both views share the same fixed navigation bar at the bottom: first / previous /
|
The original page is hidden and a mobile layout is built from the same data,
|
||||||
next / last and a page indicator. Tapping the indicator opens a sheet with a
|
one view per page type:
|
||||||
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. In the list the bar is
|
|
||||||
built only where there is more than one page — forum pages run to hundreds of
|
|
||||||
them, category pages to one.
|
|
||||||
|
|
||||||
Both views carry a fixed breadcrumb bar at the top, taken from the forum's own
|
- **Lists as cards.** Forum and topic rows become cards with title, description,
|
||||||
`Board index » … » Main Forum` trail. Without it there is no way back out of a
|
counts and last post; category headers become section headings.
|
||||||
thread, because the original page is hidden and phpBB links the parent forum
|
- **Section strips.** Forums, announcements, stickies and topics are separated
|
||||||
nowhere else. The bar scrolls horizontally if the trail is too long for the
|
by a header carrying the section name and its card count. Announcements and
|
||||||
screen, and is left out entirely on pages that do not carry a trail.
|
stickies start collapsed — they repeat above the topics on *every* page of a
|
||||||
|
forum. Tapping a header toggles its section, and the state is remembered per
|
||||||
|
section across forums.
|
||||||
|
- **Fixed page bar.** First / previous / next / last and a page indicator.
|
||||||
|
Tapping the indicator opens a sheet with a number field and every page of the
|
||||||
|
forum or thread, not just the handful phpBB renders.
|
||||||
|
- **Fixed breadcrumb bar** with a login pill showing the account name. Without
|
||||||
|
it there is no way back out of a thread, since the original page is hidden.
|
||||||
|
- **Search from anywhere.** With a session, a magnifier sits next to the pill:
|
||||||
|
it opens `search.php`, or inside a thread reveals a bar that searches the
|
||||||
|
topic.
|
||||||
|
- **Readable posts.** Avatar, author, rank and timestamp above the message;
|
||||||
|
signatures fold into a collapsed box.
|
||||||
|
- **Forms are moved, not rebuilt.** Login, search and the page after a
|
||||||
|
successful login reuse the original elements, so hidden fields and the plain
|
||||||
|
server-side POST stay intact. The search form starts on Main Forum with
|
||||||
|
subforums off, and the board rules on the login page fold away.
|
||||||
|
- **Search hits as cards** in "Posts" display mode, each with a link straight to
|
||||||
|
the post. "Topics" mode falls through to the regular list view.
|
||||||
|
|
||||||
The breadcrumb bar also carries a login pill, built on every page the script
|
The script's own labels are German; anything taken from the board keeps its
|
||||||
touches, not only the login form itself. Session state is read from the
|
original wording — `FOREN` in the first screenshot is the script's name for a
|
||||||
forum's own menu bar: a `mode=login` link means logged out, a `mode=logout`
|
group the board does not label, while `STICKIES` and `TOPICS` are the board's
|
||||||
link means logged in, and the pill switches between a "Login" link and the
|
own words.
|
||||||
account name accordingly. The name is parsed from the link text with a
|
|
||||||
`Logout [ Name ]` pattern, confirmed against a real logged-in session's markup;
|
|
||||||
if it ever fails to match — a different language, a different bracket style —
|
|
||||||
the pill still shows "Logout", just without a name, rather than breaking.
|
|
||||||
|
|
||||||
Once a session exists, the login pill also carries a magnifier button
|
It runs at `document-start` and injects a mobile viewport meta tag. A `DEBUG`
|
||||||
directly to its left, so it does not compete with the breadcrumb trail for
|
flag in the source, off by default, adds a green diagnostic overlay showing the
|
||||||
space and only shows up where cs.rin.ru's own search is actually reachable.
|
version, the chosen view and how many rows were converted.
|
||||||
Outside a thread it links straight to `search.php`; inside one it instead
|
|
||||||
reveals a second bar under the crumbs with a search field, reusing the
|
|
||||||
original "Search this topic…" form in place rather than rebuilding it, so the
|
|
||||||
hidden topic-id and scope fields stay intact.
|
|
||||||
|
|
||||||
The login form itself is not rebuilt from scratch: the original `<form>`
|
|
||||||
element is moved into the new layout and restyled, table rows collapsed to a
|
|
||||||
vertical stack. Reusing the element rather than reconstructing it keeps the
|
|
||||||
hidden `sid` and `redirect` fields, the `autologin` / `viewonline` checkboxes
|
|
||||||
and the plain server-side POST intact — the script never talks to the forum's
|
|
||||||
session handling directly, it only changes how the existing form looks.
|
|
||||||
|
|
||||||
Submitting the form re-renders the same URL with a generic "Information"
|
|
||||||
template instead of the form — a short confirmation ("You have been
|
|
||||||
successfully logged in.") before phpBB's own `<meta refresh>` moves on to the
|
|
||||||
forum index. The script recognises this template by its shape (a single-cell
|
|
||||||
header followed by a message cell), not by its wording, and restyles it the
|
|
||||||
same way as the form: the original cell — message and link included — is
|
|
||||||
reused in place rather than rebuilt.
|
|
||||||
|
|
||||||
`search.php` gets its own treatment when it shows the query form rather than
|
|
||||||
results. It is recognised by its forum picker — a `select[name="fid[]"]`
|
|
||||||
multi-select that only exists on this form, not on the small "Search this
|
|
||||||
forum…" / "Search this topic…" widgets embedded elsewhere — and then moved
|
|
||||||
into the new layout the same way the login form is: table rows collapsed to a
|
|
||||||
vertical stack, radio groups and selects restyled for touch, and the quick
|
|
||||||
links above it ("View new posts", "View your posts", …) turned into a row of
|
|
||||||
chips. "Search in forums" defaults to Main Forum and "Search subforums"
|
|
||||||
defaults to No, overriding the server's own blank/Yes defaults, since that is
|
|
||||||
the scope most searches from the mobile view actually want.
|
|
||||||
|
|
||||||
A submitted search lands back on `search.php`, now with results — which, in
|
|
||||||
the "Posts" display mode the in-thread search bar produces, look nothing like
|
|
||||||
a topic list: each hit is a post excerpt with its own author, timestamp, and
|
|
||||||
forum/topic context. Recognised by a `p.topictitle` marker unique to this
|
|
||||||
mode, these get their own cards, built before the regular list view's row
|
|
||||||
scanning would otherwise misread the topic and profile links inside them. The
|
|
||||||
"Topics" display mode is not handled specially — no fixture shows what it
|
|
||||||
looks like, so it still falls through to the regular list view, which may or
|
|
||||||
may not render it sensibly.
|
|
||||||
|
|
||||||
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
|
### Installation on iOS
|
||||||
|
|
||||||
@@ -179,26 +125,28 @@ cards and two debug overlays.
|
|||||||
|
|
||||||
#### Test fixtures
|
#### Test fixtures
|
||||||
|
|
||||||
`cs.rin.ru` requires a login, so save the pages you need once and iterate
|
Layout work happens on the live site, with the loader active in Chrome. The
|
||||||
against local copies:
|
saved pages under `dev/` serve a different purpose: `cs.rin.ru` requires a
|
||||||
|
login, and its markup is the only source for what the script has to cope with,
|
||||||
|
so the pages that matter are kept as snapshots — as a reference to read, and as
|
||||||
|
input for a throwaway jsdom harness when a change needs to be checked against
|
||||||
|
several pages at once.
|
||||||
|
|
||||||
1. Open the page while logged in, then in DevTools right-click `<html>` →
|
1. Open the page while logged in, then in DevTools right-click `<html>` →
|
||||||
*Copy outerHTML*.
|
*Copy outerHTML*.
|
||||||
2. Save it as `dev/viewtopic.php.html` or `dev/viewforum.php.html`.
|
2. Save it under the page's own name — `dev/viewtopic.php`, `dev/viewforum.php`,
|
||||||
3. Serve the folder: `python -m http.server 8777 --directory .`
|
`dev/index.php`, `dev/ucp.php`, `dev/search.php`.
|
||||||
|
|
||||||
The file name matters twice over. The `.html` extension makes the server send
|
The loader deliberately matches `cs.rin.ru` only, so these files are not meant
|
||||||
the file as HTML instead of offering it as a download, and the retained
|
to be opened in the browser. Serving them locally would take `@include` rules
|
||||||
`viewtopic.php` / `viewforum.php` part is what the loader's `@include` rules
|
for `localhost`, and those match on page names common enough (`index.php`,
|
||||||
and the page-type check in `rin-mobile.user.js` match against.
|
anything containing `search`) that the script would inject its stylesheet into
|
||||||
|
unrelated local projects.
|
||||||
|
|
||||||
Forum images and stylesheets are missing from such a snapshot. That is fine for
|
A snapshot saved while logged out contains `span.link_removed` placeholders
|
||||||
layout work, because the script rebuilds the DOM anyway — only avatars stay
|
instead of links, and may use different markup for author names than the
|
||||||
empty, since their `src` is carried over unchanged.
|
logged-in view — worth knowing before puzzling over a fixture that behaves
|
||||||
|
differently from the real page.
|
||||||
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
|
#### Device emulation
|
||||||
|
|
||||||
@@ -224,32 +172,35 @@ Windows (`npx playwright install webkit`).
|
|||||||
|
|
||||||
#### Troubleshooting
|
#### Troubleshooting
|
||||||
|
|
||||||
Install `dev/tm-test.user.js` — it injects a red bar and nothing else. If the
|
If nothing happens at all, separate the two possible causes before reading any
|
||||||
bar does not appear, the problem is Tampermonkey (see setup above), not the
|
code. Check the loader's *Externals* tab in the Tampermonkey dashboard: an
|
||||||
script code. If it does appear, check the loader's *Externals* tab in the
|
empty or failed entry means the `@require` path is wrong. If the entry is
|
||||||
Tampermonkey dashboard: an empty or failed entry means the `@require` path is
|
there and the script still does nothing, set `DEBUG = true` in
|
||||||
wrong.
|
`rin-mobile.user.js` — the green overlay appears on every page the script
|
||||||
|
touches, so its absence means the script never ran, while an overlay reporting
|
||||||
|
`ansicht=keine` means it ran but the URL matched no view.
|
||||||
|
|
||||||
If Tampermonkey keeps serving a stale copy despite the update interval, replace
|
If Tampermonkey keeps serving a stale copy despite the update interval, open
|
||||||
the `file://` require with a local HTTP server, which does not cache:
|
the loader's *Externals* tab and trigger an update on the `@require` entry by
|
||||||
|
hand, or disable and re-enable the loader — both discard the cached copy.
|
||||||
```js
|
|
||||||
// @require http://localhost:8777/rin-mobile.user.js
|
|
||||||
```
|
|
||||||
|
|
||||||
### Repository layout
|
### Repository layout
|
||||||
|
|
||||||
```
|
```
|
||||||
rin-mobile.user.js topic list → cards, thread → post stream
|
rin-mobile.user.js all views: lists, thread, login, search
|
||||||
|
CLAUDE.md notes for working on the script
|
||||||
dev/
|
dev/
|
||||||
rin-mobile.dev.user.js loader, @require with absolute path
|
rin-mobile.dev.user.js loader, @require with absolute path
|
||||||
|
*.php saved pages, markup reference, not in git
|
||||||
|
docs/
|
||||||
|
Screenshot_mobile_*.png the screenshots above
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Deutsch
|
## Deutsch
|
||||||
|
|
||||||
Ein Userscript, das die phpBB2-Seiten von `cs.rin.ru` für Safari auf iOS in eine
|
Ein Userscript, das die phpBB3-Seiten von `cs.rin.ru` für Safari auf iOS in eine
|
||||||
mobile Ansicht umbaut. Es ersetzt das ursprüngliche Tabellenlayout vollständig:
|
mobile Ansicht umbaut. Es ersetzt das ursprüngliche Tabellenlayout vollständig:
|
||||||
der vorhandene Seiteninhalt wird ausgeblendet und ein neu gebautes DOM an
|
der vorhandene Seiteninhalt wird ausgeblendet und ein neu gebautes DOM an
|
||||||
`<body>` gehängt.
|
`<body>` gehängt.
|
||||||
@@ -259,121 +210,61 @@ anhand des Seitentyps:
|
|||||||
|
|
||||||
| Seite | Ansicht |
|
| Seite | Ansicht |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `viewforum.php`, `search.php`, `index.php`, Forumwurzel | Themen- und Forenliste als Karten |
|
| `viewforum.php`, `index.php`, Forumwurzel | Themen- und Forenliste als Karten |
|
||||||
|
| `search.php` | Das Suchformular umgestylt oder — bei abgeschickter Suche im Modus „Posts" — die Treffer als Karten |
|
||||||
| `viewtopic.php` | Thread als Beitragsstrom mit fixierter Navigationsleiste |
|
| `viewtopic.php` | Thread als Beitragsstrom mit fixierter Navigationsleiste |
|
||||||
| `ucp.php?mode=login` | Login-Formular, an Ort und Stelle umgestylt; auf derselben URL nach erfolgreichem Absenden stattdessen die Informationsseite |
|
| `ucp.php?mode=login` | Login-Formular, an Ort und Stelle umgestylt; auf derselben URL nach erfolgreichem Absenden stattdessen die Informationsseite |
|
||||||
| alles andere | Unverändert — es werden keine Stile injiziert |
|
| alles andere | Unverändert — es werden keine Stile injiziert |
|
||||||
|
|
||||||
Eine `viewforum.php`-Seite ist nicht zwangsläufig eine Themenliste: eine
|
### Screenshots
|
||||||
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.
|
|
||||||
|
|
||||||
Foren, globale Ankündigungen, Ankündigungen, Stickies und Themen landen alle im
|
| Forenliste, die Abschnitte über den Themen zugeklappt | Thread, mit eingeblendeter Suchleiste |
|
||||||
selben Kartenstrom, womit die Trennung verlorengeht, die die Originalseite
|
|---|---|
|
||||||
zwischen ihnen zieht. Bei jedem Wechsel wird deshalb ein Gruppenkopf mit dem
|
| <img src="docs/Screenshot_mobile_1.png" alt="Forenliste als Karten: Brotkrumenleiste mit Lupe, aufgeklappter Abschnitt FOREN mit vier Forenkarten, zugeklappte Streifen für GLOBAL ANNOUNCEMENTS, ANNOUNCEMENTS und STICKIES, unten die Seitenleiste mit 1 / 610" width="100%"> | <img src="docs/Screenshot_mobile_2.png" alt="Thread-Ansicht: Brotkrumen, zweite Leiste mit Suchfeld, darunter eine Beitragskarte mit Avatar, Autor, Rang und Beitragszahl über dem Text" width="100%"> |
|
||||||
Namen des Abschnitts und der Zahl seiner Karten eingezogen; Forenkarten tragen
|
| **Suchformular, oben: Schnellzugriffe und Forenwähler** | **Suchformular, unten: Optionen und Schaltflächen** |
|
||||||
zusätzlich eine farbige linke Kante. Die Beschriftung stammt aus der Trennzeile
|
| <img src="docs/Screenshot_mobile_3.png" alt="Suchformular: Schnellzugriffe als Chips, die Feldgruppen für Suchbegriffe und der Forenwähler mit vorausgewähltem Main Forum" width="100%"> | <img src="docs/Screenshot_mobile_4.png" alt="Suchformular, Fortsetzung: Unterforen auf No, die übrigen Optionsgruppen sowie die Schaltflächen Search und Reset" width="100%"> |
|
||||||
der Seite selbst (`Global Announcements`, `Stickies`, `Topics`), damit auch
|
|
||||||
Abschnitte richtig heißen, die dieses Script nicht kennt. Welcher Art eine
|
|
||||||
Themenzeile ist, verrät das Symbol ihrer ersten Spalte, nicht der Titel. Direkt
|
|
||||||
unter einer Kategorieüberschrift entfällt der Gruppenkopf, weil die Überschrift
|
|
||||||
die Foren darunter schon einleitet.
|
|
||||||
|
|
||||||
Ein Tipp auf den Kopf klappt seinen Abschnitt zu. Globale Ankündigungen,
|
### Was das Script liefert
|
||||||
Ankündigungen und Stickies starten zugeklappt: sie stehen auf *jeder* Seite
|
|
||||||
eines Forums vor den Themen und füllen sonst den ersten Bildschirm. Der Zustand
|
|
||||||
liegt je Art in `localStorage`, einmal zugeklappte Stickies gelten also in jedem
|
|
||||||
Forum. `localStorage` statt `GM_setValue`, weil es ohne `@grant` auskommt und
|
|
||||||
sich in Tampermonkey wie in der iOS-App gleich verhält; dafür kann Safari
|
|
||||||
schreibbaren Speicher nach längerer Nichtnutzung räumen, dann stehen die
|
|
||||||
Abschnitte wieder auf ihrer Voreinstellung.
|
|
||||||
|
|
||||||
Beide Ansichten teilen sich dieselbe fixierte Navigationsleiste am unteren
|
Die Originalseite wird ausgeblendet und aus denselben Daten eine mobile Ansicht
|
||||||
Rand: erste / vorherige / nächste / letzte Seite und eine Positionsanzeige. Ein
|
gebaut, je eine pro Seitentyp:
|
||||||
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. In der Liste entsteht die Leiste nur, wo es mehr
|
|
||||||
als eine Seite gibt — Forenseiten haben hunderte, Kategorieseiten eine.
|
|
||||||
|
|
||||||
Beide Ansichten haben oben eine fixierte Brotkrumenleiste, übernommen aus dem
|
- **Listen als Karten.** Foren- und Themenzeilen werden zu Karten mit Titel,
|
||||||
`Board index » … » Main Forum`-Pfad des Forums. Ohne sie führt aus einem Thread
|
Beschreibung, Zahlen und letztem Beitrag, Kategoriezeilen zu
|
||||||
kein Weg zurück, weil die Originalseite ausgeblendet ist und phpBB das
|
Zwischenüberschriften.
|
||||||
Elternforum nirgends sonst verlinkt. Die Leiste lässt sich waagerecht schieben,
|
- **Gruppenköpfe.** Foren, Ankündigungen, Stickies und Themen trennt jeweils ein
|
||||||
wenn der Pfad breiter ist als der Bildschirm, und entfällt auf Seiten ohne
|
Kopf mit dem Namen des Abschnitts und der Zahl seiner Karten. Ankündigungen
|
||||||
Pfadangabe.
|
und Stickies starten zugeklappt — sie stehen auf *jeder* Seite eines Forums
|
||||||
|
über den Themen. Ein Tipp auf den Kopf klappt seinen Abschnitt um, der Zustand
|
||||||
|
gilt je Abschnitt über alle Foren hinweg.
|
||||||
|
- **Fixierte Seitenleiste.** Erste / vorherige / nächste / letzte Seite und eine
|
||||||
|
Positionsanzeige. Ein Tipp darauf öffnet ein Sheet mit Zahlenfeld und allen
|
||||||
|
Seiten des Forums oder Threads, nicht nur der Handvoll, die phpBB rendert.
|
||||||
|
- **Fixierte Brotkrumenleiste** mit einer Login-Pille, die den Kontonamen zeigt.
|
||||||
|
Ohne sie führt aus einem Thread kein Weg zurück, weil die Originalseite
|
||||||
|
ausgeblendet ist.
|
||||||
|
- **Suche von überall.** Besteht eine Sitzung, sitzt neben der Pille eine Lupe:
|
||||||
|
sie öffnet `search.php` oder blendet innerhalb eines Threads eine Leiste ein,
|
||||||
|
die das Thema durchsucht.
|
||||||
|
- **Lesbare Beiträge.** Avatar, Autor, Rang und Zeitstempel über dem Text,
|
||||||
|
Signaturen wandern in einen zugeklappten Kasten.
|
||||||
|
- **Formulare werden verschoben, nicht nachgebaut.** Login, Suche und die Seite
|
||||||
|
nach erfolgreichem Login übernehmen die Original-Elemente, damit versteckte
|
||||||
|
Felder und der schlichte serverseitige POST erhalten bleiben. Das Suchformular
|
||||||
|
startet auf Main Forum ohne Unterforen, die Forenregeln im Login klappen weg.
|
||||||
|
- **Suchtreffer als Karten** im Anzeigemodus „Posts", jeder mit einem Link
|
||||||
|
direkt zum Beitrag. Der Modus „Topics" läuft durch die gewöhnliche
|
||||||
|
Listenansicht.
|
||||||
|
|
||||||
Die Brotkrumenleiste trägt außerdem eine Login-Pille, gebaut auf jeder Seite,
|
Die Beschriftungen des Scripts sind deutsch, alles aus dem Forum Übernommene
|
||||||
die das Script anfasst — nicht nur auf dem Login-Formular selbst. Der
|
behält seinen Wortlaut — `FOREN` im ersten Screenshot ist die Bezeichnung des
|
||||||
Sitzungszustand wird aus dem Menübalken der Originalseite gelesen: ein
|
Scripts für eine Gruppe, die die Seite selbst nicht beschriftet, `STICKIES` und
|
||||||
`mode=login`-Link bedeutet ausgeloggt, ein `mode=logout`-Link eingeloggt, die
|
`TOPICS` sind ihre eigenen Worte.
|
||||||
Pille wechselt entsprechend zwischen einem „Login"-Link und dem Kontonamen.
|
|
||||||
Der Name wird über das Muster `Logout [ Name ]` aus dem Linktext gelesen, das
|
|
||||||
gegen das Markup einer echten eingeloggten Sitzung bestätigt ist; greift es
|
|
||||||
einmal nicht — andere Sprache, andere Klammerform — bleibt die Pille bei
|
|
||||||
„Logout" stehen, nur ohne Namen, statt zu reißen.
|
|
||||||
|
|
||||||
Besteht eine Sitzung, trägt die Login-Pille zusätzlich einen Lupen-Button
|
Das Script läuft bei `document-start` und setzt ein mobiles Viewport-Meta-Tag.
|
||||||
direkt links neben sich, damit er nicht mit der Brotkrumenleiste um Platz
|
Ein `DEBUG`-Flag im Quelltext, standardmäßig aus, legt ein grünes
|
||||||
konkurriert, und erscheint nur dort, wo cs.rins eigene Suche überhaupt
|
Diagnose-Overlay über die Seite: Version, gewählte Ansicht und Zahl der
|
||||||
erreichbar ist. Außerhalb eines Threads führt er direkt zu `search.php`;
|
umgewandelten Zeilen.
|
||||||
innerhalb eines Threads blendet er stattdessen eine zweite Leiste unter den
|
|
||||||
Brotkrumen mit einem Suchfeld ein — das ist das Original-Formular „Search this
|
|
||||||
topic…", unverändert an Ort und Stelle wiederverwendet statt neu gebaut, damit
|
|
||||||
die versteckten Felder für Themen-Id und Suchbereich erhalten bleiben.
|
|
||||||
|
|
||||||
Das Login-Formular selbst wird nicht neu gebaut: das Original-`<form>`-Element
|
|
||||||
wandert unverändert in das neue Layout und wird umgestylt, Tabellenzeilen
|
|
||||||
werden zu einer senkrechten Abfolge zusammengeklappt. Die Wiederverwendung
|
|
||||||
statt Neubau erhält die versteckten Felder `sid` und `redirect`, die
|
|
||||||
Checkboxen `autologin` / `viewonline` und den schlichten serverseitigen POST —
|
|
||||||
das Script spricht nie selbst mit der Sitzungsverwaltung des Forums, es ändert
|
|
||||||
nur, wie das vorhandene Formular aussieht.
|
|
||||||
|
|
||||||
Nach dem Absenden liefert dieselbe URL statt des Formulars eine allgemeine
|
|
||||||
„Information"-Vorlage aus — eine kurze Bestätigung („You have been
|
|
||||||
successfully logged in."), bevor phpBBs eigenes `<meta refresh>` zum
|
|
||||||
Forenindex weiterleitet. Das Script erkennt diese Vorlage an ihrer Form, nicht
|
|
||||||
am Wortlaut (eine Kopfzeile mit einer einzelnen Zelle, gefolgt von einer
|
|
||||||
Nachrichtenzelle), und stylt sie wie das Formular um: die Original-Zelle —
|
|
||||||
Nachricht und Link inklusive — wandert unverändert an ihren Platz statt neu
|
|
||||||
gebaut zu werden.
|
|
||||||
|
|
||||||
`search.php` bekommt eine eigene Behandlung, wenn es das Suchformular statt
|
|
||||||
Treffern zeigt. Erkannt wird das am Forenwähler — einem Mehrfachauswahlfeld
|
|
||||||
`select[name="fid[]"]`, das es nur in diesem Formular gibt, nicht in den
|
|
||||||
kleinen „Search this forum…" / „Search this topic…"-Widgets an anderer
|
|
||||||
Stelle — und dann wie das Login-Formular in das neue Layout verschoben:
|
|
||||||
Tabellenzeilen zu einer senkrechten Abfolge zusammengeklappt, Radio-Gruppen
|
|
||||||
und Auswahlfelder für Touch umgestylt, die Schnellzugriffe darüber („View new
|
|
||||||
posts", „View your posts", …) zu einer Reihe aus Chips. „Search in forums"
|
|
||||||
ist dabei standardmäßig auf Main Forum vorausgewählt, „Search subforums" auf
|
|
||||||
No — statt der leeren/„Yes"-Vorgabe des Servers, weil das dem Suchumfang
|
|
||||||
entspricht, der von der mobilen Ansicht aus meistens gewollt ist.
|
|
||||||
|
|
||||||
Eine abgeschickte Suche landet wieder auf `search.php`, diesmal mit Treffern —
|
|
||||||
die im Anzeigemodus „Posts", den die Suchleiste im Thread erzeugt, aber
|
|
||||||
überhaupt nicht wie eine Themenliste aussehen: jeder Treffer ist ein
|
|
||||||
Beitragsauszug mit eigenem Autor, Zeitstempel und Forum-/Thema-Kontext.
|
|
||||||
Erkannt an einem Merkmal (`p.topictitle`), das es nur in diesem Modus gibt,
|
|
||||||
bekommen sie eigene Karten, gebaut bevor das Zeileneinsammeln der gewöhnlichen
|
|
||||||
Listenansicht die enthaltenen Themen- und Profillinks falsch deuten würde.
|
|
||||||
Der Anzeigemodus „Topics" bekommt keine eigene Behandlung — keine Fixture
|
|
||||||
zeigt, wie er aussieht, er läuft also weiterhin durch die gewöhnliche
|
|
||||||
Listenansicht, was passend sein kann oder auch nicht.
|
|
||||||
|
|
||||||
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
|
### Installation unter iOS
|
||||||
|
|
||||||
@@ -433,6 +324,31 @@ Den Loader nicht parallel zum unveränderten Script betreiben. Sind beide in
|
|||||||
Tampermonkey aktiv, läuft der Code doppelt auf derselben Seite, mit doppelten
|
Tampermonkey aktiv, läuft der Code doppelt auf derselben Seite, mit doppelten
|
||||||
Karten und zwei Debug-Overlays als Folge.
|
Karten und zwei Debug-Overlays als Folge.
|
||||||
|
|
||||||
|
#### Testfixtures
|
||||||
|
|
||||||
|
Die Layoutarbeit findet auf der echten Seite statt, mit dem Loader aktiv in
|
||||||
|
Chrome. Die gespeicherten Seiten unter `dev/` dienen etwas anderem: `cs.rin.ru`
|
||||||
|
verlangt einen Login, und sein Markup ist die einzige Quelle dafür, womit das
|
||||||
|
Script zurechtkommen muss. Die relevanten Seiten liegen deshalb als Mitschnitt
|
||||||
|
vor — zum Nachlesen und als Eingabe für ein Wegwerf-Harness mit jsdom, wenn
|
||||||
|
eine Änderung gegen mehrere Seiten auf einmal zu prüfen ist.
|
||||||
|
|
||||||
|
1. Die Seite eingeloggt öffnen, in den DevTools mit der rechten Maustaste auf
|
||||||
|
`<html>` → *Copy outerHTML*.
|
||||||
|
2. Unter dem Namen der Seite ablegen — `dev/viewtopic.php`,
|
||||||
|
`dev/viewforum.php`, `dev/index.php`, `dev/ucp.php`, `dev/search.php`.
|
||||||
|
|
||||||
|
Der Loader greift bewusst nur auf `cs.rin.ru`, diese Dateien sind also nicht
|
||||||
|
zum Öffnen im Browser gedacht. Sie lokal auszuliefern verlangte
|
||||||
|
`@include`-Regeln für `localhost`, und die passen auf Seitennamen, die dort
|
||||||
|
häufig genug vorkommen (`index.php`, alles mit „search" darin), dass das Script
|
||||||
|
sein Stylesheet in fremde lokale Projekte injizieren würde.
|
||||||
|
|
||||||
|
Ein ausgeloggt gespeicherter Mitschnitt enthält statt der Links
|
||||||
|
`span.link_removed`-Platzhalter und kann Autorennamen anders auszeichnen als
|
||||||
|
die eingeloggte Ansicht — gut zu wissen, bevor man über eine Fixture rätselt,
|
||||||
|
die sich anders verhält als die echte Seite.
|
||||||
|
|
||||||
#### Geräte-Emulation
|
#### Geräte-Emulation
|
||||||
|
|
||||||
DevTools → *Device Toolbar* (`Strg+Umschalt+M`) → *Edit…* → eigenes Gerät mit
|
DevTools → *Device Toolbar* (`Strg+Umschalt+M`) → *Edit…* → eigenes Gerät mit
|
||||||
@@ -458,24 +374,27 @@ Windows mit (`npx playwright install webkit`).
|
|||||||
|
|
||||||
#### Fehlersuche
|
#### Fehlersuche
|
||||||
|
|
||||||
`dev/tm-test.user.js` installieren — das Script blendet nur einen roten Balken
|
Passiert überhaupt nichts, zuerst die beiden möglichen Ursachen trennen, bevor
|
||||||
ein, sonst nichts. Erscheint der Balken nicht, liegt das Problem bei
|
Code gelesen wird. Im Tampermonkey-Dashboard den Tab *Externals* des Loaders
|
||||||
Tampermonkey (siehe Einrichtung oben) und nicht am Script-Code. Erscheint er,
|
prüfen: ein leerer oder fehlgeschlagener Eintrag bedeutet, dass der
|
||||||
im Tampermonkey-Dashboard den Tab *Externals* des Loaders prüfen: ein leerer
|
`@require`-Pfad falsch ist. Ist der Eintrag da und trotzdem passiert nichts, in
|
||||||
oder fehlgeschlagener Eintrag bedeutet, dass der `@require`-Pfad falsch ist.
|
`rin-mobile.user.js` `DEBUG = true` setzen — das grüne Overlay erscheint auf
|
||||||
|
jeder Seite, die das Script anfasst. Bleibt es aus, lief das Script gar nicht;
|
||||||
|
meldet es `ansicht=keine`, lief es, aber die URL passte auf keine Ansicht.
|
||||||
|
|
||||||
Liefert Tampermonkey trotz Update-Intervall weiterhin einen veralteten Stand
|
Liefert Tampermonkey trotz Update-Intervall weiterhin einen veralteten Stand
|
||||||
aus, das `file://`-Require durch einen lokalen HTTP-Server ersetzen, der nicht
|
aus, im Tab *Externals* des Loaders den `@require`-Eintrag von Hand
|
||||||
zwischenspeichert:
|
aktualisieren oder den Loader einmal deaktivieren und wieder aktivieren —
|
||||||
|
beides verwirft die zwischengespeicherte Fassung.
|
||||||
```js
|
|
||||||
// @require http://localhost:8777/rin-mobile.user.js
|
|
||||||
```
|
|
||||||
|
|
||||||
### Aufbau des Repositories
|
### Aufbau des Repositories
|
||||||
|
|
||||||
```
|
```
|
||||||
rin-mobile.user.js Themenliste → Karten, Thread → Beitragsstrom
|
rin-mobile.user.js alle Ansichten: Listen, Thread, Login, Suche
|
||||||
|
CLAUDE.md Notizen zur Arbeit am Script
|
||||||
dev/
|
dev/
|
||||||
rin-mobile.dev.user.js Loader, @require mit absolutem Pfad
|
rin-mobile.dev.user.js Loader, @require mit absolutem Pfad
|
||||||
|
*.php gespeicherte Seiten, Markup-Vorlage, nicht in git
|
||||||
|
docs/
|
||||||
|
Screenshot_mobile_*.png die Screenshots oben
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -2,12 +2,8 @@
|
|||||||
// @name [DEV] RIN Mobile
|
// @name [DEV] RIN Mobile
|
||||||
// @namespace rin-dev
|
// @namespace rin-dev
|
||||||
// @description Dev-Loader: laedt rin-mobile.user.js live von der Platte
|
// @description Dev-Loader: laedt rin-mobile.user.js live von der Platte
|
||||||
// @version 2.0
|
// @version 2.1
|
||||||
// @match *://cs.rin.ru/forum/*
|
// @match *://cs.rin.ru/forum/*
|
||||||
// @include http://localhost:*/*viewforum*
|
|
||||||
// @include http://127.0.0.1:*/*viewforum*
|
|
||||||
// @include http://localhost:*/*viewtopic*
|
|
||||||
// @include http://127.0.0.1:*/*viewtopic*
|
|
||||||
// @require file:///C:/Projekte/ios_safari_userscripts/rin-mobile.user.js
|
// @require file:///C:/Projekte/ios_safari_userscripts/rin-mobile.user.js
|
||||||
// @run-at document-start
|
// @run-at document-start
|
||||||
// @grant none
|
// @grant none
|
||||||
@@ -15,3 +11,8 @@
|
|||||||
|
|
||||||
// Der eigentliche Code steckt in der @require-Datei.
|
// Der eigentliche Code steckt in der @require-Datei.
|
||||||
// Aenderungen dort greifen nach einem Reload der Seite.
|
// Aenderungen dort greifen nach einem Reload der Seite.
|
||||||
|
//
|
||||||
|
// Der Loader laeuft nur auf der echten Seite. Die Fixtures unter dev/ sind
|
||||||
|
// Markup-Vorlagen fuer das jsdom-Harness, keine Seiten zum Anschauen im
|
||||||
|
// Browser — dafuer braeuchte es einen lokalen Server und passende
|
||||||
|
// @include-Zeilen, die auf localhost zu breit streuen wuerden.
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
+10
-1
@@ -12,6 +12,14 @@
|
|||||||
var DEBUG = false;
|
var DEBUG = false;
|
||||||
var log = [];
|
var log = [];
|
||||||
|
|
||||||
|
// Die Version steht ausschliesslich im Metadatenblock. Ein zweiter Literal
|
||||||
|
// im Code lief beim Release regelmaessig davon weg, ohne dass es auffiel —
|
||||||
|
// GM_info liest denselben Header zurueck. Fehlt es (Userscript-Manager ohne
|
||||||
|
// GM_info), bleibt das Overlay ohne Versionsangabe, statt eine falsche zu
|
||||||
|
// zeigen.
|
||||||
|
var VERSION = (typeof GM_info !== 'undefined' && GM_info.script &&
|
||||||
|
GM_info.script.version) || '';
|
||||||
|
|
||||||
function h() { return document.head || document.documentElement; }
|
function h() { return document.head || document.documentElement; }
|
||||||
|
|
||||||
function txt(el) { return (el ? el.textContent || '' : '')
|
function txt(el) { return (el ? el.textContent || '' : '')
|
||||||
@@ -1696,7 +1704,8 @@
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
var d = document.createElement('div');
|
var d = document.createElement('div');
|
||||||
d.className = 'rm-dbg';
|
d.className = 'rm-dbg';
|
||||||
d.textContent = 'RIN Mobile v3.13\n' + log.join('\n');
|
d.textContent = 'RIN Mobile' + (VERSION ? ' v' + VERSION : '') +
|
||||||
|
'\n' + log.join('\n');
|
||||||
document.body.insertBefore(d, document.body.firstChild);
|
document.body.insertBefore(d, document.body.firstChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user