feat: mark the boundary between forums and topics in the list view

A forum page carries its subforums and its topics in tables of their own,
each with a header. Rebuilding the page into one stream of cards dissolves
that separation: both kinds render identically, so where the subforums end
and the topics begin was no longer visible, and a single card gave no hint
whether tapping it opens a forum or a thread.

A header naming the kind and its count is therefore inserted wherever the
kind changes, and forum cards are tinted and edged. Directly below a
category heading the header is suppressed — on the forum root that heading
already introduces the forums under it, and repeating the kind there adds
a strip per category for nothing.

Counting requires knowing how many cards a block actually yields, which is
not the number of rows: rows that turn out to be layout or fail conversion
drop out. The cards are therefore built completely before any of them is
emitted.
This commit is contained in:
Andre
2026-08-02 15:11:47 +02:00
parent 3609d9e151
commit 4ce48b3875
3 changed files with 75 additions and 10 deletions
+55 -10
View File
@@ -1,7 +1,7 @@
// ==UserScript==
// @name RIN Mobile
// @description Mobile Ansicht fuer cs.rin.ru: Themenlisten als Karten, Threads als Beitragsstrom
// @version 3.2
// @version 3.3
// @match *://cs.rin.ru/forum/*
// @run-at document-start
// ==/UserScript==
@@ -98,6 +98,16 @@
border:1px solid rgba(128,128,128,.4);
text-decoration:none !important; color:inherit !important; }
/* Foren und Themen stehen auf einer Forenseite in derselben Tabelle
untereinander. Im Kartenstrom unterscheiden sie sich sonst nur am Text,
der Uebergang von den Unterforen zu den Themen ist nicht mehr zu sehen. */
.rm-group { display:flex; align-items:baseline; justify-content:space-between;
gap:10px; padding:11px 14px; font-size:12px; font-weight:700;
text-transform:uppercase; letter-spacing:.07em; opacity:.75;
background:rgba(128,128,128,.16);
border-bottom:1px solid rgba(128,128,128,.28); }
.rm-group .rm-count { font-weight:600; letter-spacing:0; opacity:.7; }
.rm-card { box-sizing:border-box !important;
display:block !important;
width:100% !important; max-width:100% !important;
@@ -105,6 +115,8 @@
padding:14px 14px 15px !important;
border-bottom:1px solid rgba(128,128,128,.28) !important; }
.rm-card:active { background:rgba(128,128,128,.14); }
.rm-card.rm-forum { border-left:3px solid rgba(120,170,255,.7);
background:rgba(120,170,255,.07); }
.rm-main { box-sizing:border-box !important;
display:block !important;
width:100% !important; max-width:100% !important;
@@ -303,9 +315,9 @@
// Karten teilen sich Titel, Zahlenzeile und Fusszeile; nur die Quellen
// dafuer unterscheiden sich zwischen Thema und Forum.
function card(titleA, badgeable) {
function card(titleA, badgeable, kind) {
var el = document.createElement('div');
el.className = 'rm-card';
el.className = 'rm-card' + (kind === 'forum' ? ' rm-forum' : '');
var main = document.createElement('a');
main.className = 'rm-main';
@@ -375,7 +387,7 @@
}
});
var el = card(titleA, true);
var el = card(titleA, true, 'thema');
var meta = metaRow([author,
nums[0] ? nums[0] + ' Antworten' : '',
nums[1] ? nums[1] + ' Views' : '']);
@@ -403,7 +415,7 @@
}
});
var el = card(titleA, false);
var el = card(titleA, false, 'forum');
// Beschreibung, Moderatoren und Unterforen benutzen denselben Absatztyp.
// Die beiden letzten sind nur an ihrer Einleitung zu erkennen.
@@ -481,6 +493,22 @@
return el;
}
// Kopf ueber einem Block gleichartiger Karten. Die Originalseite trennt Foren
// und Themen ueber zwei Tabellen mit eigenem Kopf; im Kartenstrom geht diese
// Grenze verloren.
function groupHead(kind, n) {
var el = document.createElement('div');
el.className = 'rm-group';
var t = document.createElement('span');
t.textContent = kind === 'forum' ? 'Foren' : 'Themen';
el.appendChild(t);
var c = document.createElement('span');
c.className = 'rm-count';
c.textContent = n;
el.appendChild(c);
return el;
}
// Welche Karte eine Zeile ergibt, entscheidet der erste verwertbare Link
// darin. Beiwerk wie die Brotkrumen oder "Mark topics read" verlinkt
// ebenfalls auf viewforum.php, steht aber in keiner Zeile, die eine Karte
@@ -533,17 +561,34 @@
var root = document.createElement('div');
root.className = 'rm-root';
var built = 0;
// Erst alle Karten bauen, dann ausgeben: der Gruppenkopf nennt die Zahl der
// Karten unter sich, und die steht erst fest, wenn die Zeilen durch sind,
// von denen manche keine Karte hergeben.
var items = [];
rows.forEach(function (r) {
try {
var c = r.kind === 'thema' ? convertTopic(r.tr)
: r.kind === 'forum' ? convertForum(r.tr)
: section(r.a);
if (!c) return;
root.appendChild(c);
if (r.kind !== 'sektion') built++;
if (c) items.push({ kind: r.kind, el: c });
} catch (e) { log.push('convert: ' + e.message); }
});
var built = 0, last = '';
items.forEach(function (it, i) {
// Eine Kategoriezeile leitet die Foren darunter bereits ein — auf der
// Forenwurzel wuerde ein Gruppenkopf sie nur doppeln.
if (it.kind !== 'sektion') {
if (it.kind !== last && last !== 'sektion') {
var n = 0;
while (i + n < items.length && items[i + n].kind === it.kind) n++;
root.appendChild(groupHead(it.kind, n));
}
built++;
}
last = it.kind;
root.appendChild(it.el);
});
log.push('karten=' + built);
if (!built) return;
@@ -946,7 +991,7 @@
if (DEBUG) {
var d = document.createElement('div');
d.className = 'rm-dbg';
d.textContent = 'RIN Mobile v3.2\n' + log.join('\n');
d.textContent = 'RIN Mobile v3.3\n' + log.join('\n');
document.body.insertBefore(d, document.body.firstChild);
}
}