feat: add search access to the crumbs bar for logged-in users

The mobile view hides the whole original body behind replaceBody(),
which removed every path back to phpBB's search: the header icon and,
inside a thread, the per-topic "Search this topic..." form. Without
this there was no way to search at all from the rebuilt view.

The crumbs bar has no room for a third element next to the breadcrumb
trail and the login pill, so the new search button only shows once a
session exists and shares the pill's existing right-aligned group
instead of claiming separate space. On viewtopic it reveals a second
bar that reuses the original per-topic search form in place, keeping
its hidden topic-id and scope fields intact rather than reconstructing
them and risking a silently broken query.
This commit is contained in:
Andre
2026-08-03 08:02:14 +02:00
parent 0d2731eaa9
commit 21820b88d0
+104 -4
View File
@@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name RIN Mobile // @name RIN Mobile
// @description Mobile Ansicht fuer cs.rin.ru: Themenlisten als Karten, Threads als Beitragsstrom // @description Mobile Ansicht fuer cs.rin.ru: Themenlisten als Karten, Threads als Beitragsstrom
// @version 3.8 // @version 3.9
// @match *://cs.rin.ru/forum/* // @match *://cs.rin.ru/forum/*
// @run-at document-start // @run-at document-start
// ==/UserScript== // ==/UserScript==
@@ -86,10 +86,21 @@
color:#eee !important; text-decoration:none !important; } color:#eee !important; text-decoration:none !important; }
.rm-crumbs a:last-of-type { font-weight:650; } .rm-crumbs a:last-of-type { font-weight:650; }
.rm-crumbs .rm-sep { flex:none; font-size:13px; color:#eee; opacity:.45; } .rm-crumbs .rm-sep { flex:none; font-size:13px; color:#eee; opacity:.45; }
.rm-crumbs a.rm-auth { flex:none; margin-left:auto; padding:6px 12px !important; /* Traegt die Lupe und die Login/Logout-Pille zusammen als eine Einheit
rechts — nur eine gemeinsame margin-left:auto, statt jedes Element
einzeln an den Rand zu schieben, sonst klafft zwischen beiden eine
Luecke statt "direkt links neben der Pille". */
.rm-crumbs .rm-auth-group { flex:none; margin-left:auto;
display:flex; align-items:center; gap:6px; }
.rm-crumbs a.rm-auth { flex:none; padding:6px 12px !important;
font-size:13px !important; border-radius:99px; font-size:13px !important; border-radius:99px;
background:rgba(128,128,128,.18); background:rgba(128,128,128,.18);
border:1px solid rgba(160,160,160,.4); } border:1px solid rgba(160,160,160,.4); }
.rm-crumbs a.rm-search { flex:none; min-width:44px; height:29px;
display:flex; align-items:center; justify-content:center;
padding:0 16px !important; font-size:14px; border-radius:99px;
background:rgba(128,128,128,.18);
border:1px solid rgba(160,160,160,.4); }
/* Nur gesetzt, wenn die Leiste wirklich gebaut wurde — ohne Brotkrumen /* Nur gesetzt, wenn die Leiste wirklich gebaut wurde — ohne Brotkrumen
im Original-DOM bleibt der Platz sonst leer reserviert. */ im Original-DOM bleibt der Platz sonst leer reserviert. */
body.rm-crumbed .rm-root { body.rm-crumbed .rm-root {
@@ -97,6 +108,34 @@
body.rm-crumbed .rm-dbg { body.rm-crumbed .rm-dbg {
margin-top:calc(45px + env(safe-area-inset-top)); } margin-top:calc(45px + env(safe-area-inset-top)); }
/* Zweite Leiste unter den Brotkrumen, nur im Thread: Ersatz fuer
"Search this topic..." der Originalseite. Das dortige Formular wird
unveraendert hierher verschoben statt neu gebaut, wie das
Login-Formular in .rm-login form. */
.rm-search-bar { box-sizing:border-box;
position:fixed; left:0; right:0; z-index:9997;
top:calc(44px + env(safe-area-inset-top));
display:flex; align-items:center;
padding:8px 12px;
background:rgba(28,28,30,.96);
-webkit-backdrop-filter:blur(12px);
backdrop-filter:blur(12px);
border-bottom:1px solid rgba(128,128,128,.3);
transform:translateY(-110%);
transition:transform .18s ease; }
.rm-search-bar.rm-open { transform:translateY(0); }
.rm-search-bar form { flex:1; min-width:0;
display:flex; align-items:center; gap:8px; }
.rm-search-bar input[type="text"] {
flex:1; min-width:0; box-sizing:border-box;
font-size:16px; padding:9px 12px; border-radius:10px;
color:#eee; background:rgba(120,120,120,.18);
border:1px solid rgba(160,160,160,.35); }
.rm-search-bar input[type="submit"] {
flex:none; font-size:14px; font-weight:650; padding:9px 16px;
border-radius:10px; color:#fff; border:0;
background:rgba(120,170,255,.85); }
/* === Themen- und Forenliste === */ /* === Themen- und Forenliste === */
.rm-sec { padding:18px 14px 6px; font-size:12px; font-weight:700; .rm-sec { padding:18px 14px 6px; font-size:12px; font-weight:700;
@@ -388,11 +427,31 @@
if (!n) return; if (!n) return;
var st = loginState(); var st = loginState();
var group = document.createElement('div');
group.className = 'rm-auth-group';
// Lupe nur bei bestehender Sitzung. Ausserhalb von viewtopic fuehrt sie
// direkt auf search.php, im Thread blendet sie stattdessen die zweite
// Leiste ein — Ersatz fuer "Search this topic...", das mit dem
// Original-DOM ausgeblendet wurde.
if (st.in) {
var search = document.createElement('a');
search.className = 'rm-search';
search.href = 'https://cs.rin.ru/forum/search.php';
search.textContent = '🔍';
search.setAttribute('aria-label', 'Suche');
search.addEventListener('click', function (e) {
if (view === 'thread') { e.preventDefault(); toggleThreadSearch(); }
});
group.appendChild(search);
}
var auth = document.createElement('a'); var auth = document.createElement('a');
auth.className = 'rm-auth'; auth.className = 'rm-auth';
auth.href = st.href; auth.href = st.href;
auth.textContent = st.in ? (st.name || 'Logout') : 'Login'; auth.textContent = st.in ? (st.name || 'Logout') : 'Login';
bar.appendChild(auth); group.appendChild(auth);
bar.appendChild(group);
document.body.appendChild(bar); document.body.appendChild(bar);
document.body.classList.add('rm-crumbed'); document.body.classList.add('rm-crumbed');
@@ -1032,6 +1091,47 @@
// Thread // Thread
// ========================================================================== // ==========================================================================
// "Search this topic..." steht dreifach identisch im Original-DOM (Kopf,
// Fuss, ueber der Beitragsliste), samt versteckter Felder fuer Themen-Id
// und Scope (sf=msgonly). replaceBody() versteckt das nur per Klasse, das
// erste Formular bleibt im DOM erreichbar und wird beim ersten Antippen
// der Lupe unveraendert in die zweite Leiste verschoben statt neu gebaut —
// wie das Login-Formular in buildLogin().
var threadSearchBar = null;
function buildThreadSearch() {
var form = document.querySelector('#topic-search');
if (!form) return null;
// Die Originalseite emuliert einen Platzhalter per onclick/onblur statt
// per placeholder-Attribut.
var inp = form.querySelector('input[name="keywords"]');
if (inp) {
inp.removeAttribute('onclick');
inp.removeAttribute('onblur');
if (inp.value === 'Search this topic…') inp.value = '';
inp.placeholder = 'In diesem Thema suchen';
}
var submit = form.querySelector('input[type="submit"]');
if (submit) submit.value = 'Suchen';
var bar = document.createElement('div');
bar.className = 'rm-search-bar';
bar.appendChild(form);
document.body.appendChild(bar);
return bar;
}
function toggleThreadSearch() {
if (!threadSearchBar) threadSearchBar = buildThreadSearch();
if (!threadSearchBar) return;
var open = threadSearchBar.classList.toggle('rm-open');
if (open) {
var inp = threadSearchBar.querySelector('input[type="text"]');
if (inp) inp.focus();
}
}
// Der Beitragstext liegt in einer verschachtelten Tabelle. closest('tr') // Der Beitragstext liegt in einer verschachtelten Tabelle. closest('tr')
// trifft deshalb die innere Zeile, der Autor- und Profilspalte fehlen. // trifft deshalb die innere Zeile, der Autor- und Profilspalte fehlen.
// Aufsteigen, bis die Zeile eine Profil- oder Autorenspalte enthaelt. // Aufsteigen, bis die Zeile eine Profil- oder Autorenspalte enthaelt.
@@ -1287,7 +1387,7 @@
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.8\n' + log.join('\n'); d.textContent = 'RIN Mobile v3.9\n' + log.join('\n');
document.body.insertBefore(d, document.body.firstChild); document.body.insertBefore(d, document.body.firstChild);
} }
} }