mirror of
https://github.com/Andre-Bzk/rin-mobile-userscript.git
synced 2026-11-15 09:33:08 +01:00
feat: add a mobile login view and a login/logout status pill
The script previously had no way to log in or tell whether a session was already active, since ucp.php fell outside the view switch and rendered in the desktop layout. Session state is only visible in the forum's own menu bar link (mode=login vs mode=logout), so every view now surfaces it as a pill in the breadcrumb bar instead of leaving the user to dig for it. The login form itself is moved into the new layout rather than rebuilt from scratch, keeping the hidden sid/redirect fields and the autologin/viewonline checkboxes intact without the script having to reimplement the session handshake. As the first short, unscrollable view in the project, it also exposed a WebKit quirk that longer views never triggered: without enough scroll headroom, Safari's own partially-retracted toolbar has nothing to scroll away and permanently covers the submit button. The generous bottom padding on the form works around that, separately from the safe-area inset that only accounts for the home indicator.
This commit is contained in:
+124
-4
@@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name RIN Mobile
|
||||
// @description Mobile Ansicht fuer cs.rin.ru: Themenlisten als Karten, Threads als Beitragsstrom
|
||||
// @version 3.5
|
||||
// @version 3.6
|
||||
// @match *://cs.rin.ru/forum/*
|
||||
// @run-at document-start
|
||||
// ==/UserScript==
|
||||
@@ -26,6 +26,7 @@
|
||||
var view = /viewtopic\.php/.test(here) ? 'thread'
|
||||
: /viewforum\.php|search\.php/.test(here) ||
|
||||
location.pathname === '/forum/' ? 'liste'
|
||||
: /ucp\.php/.test(here) && /mode=login/.test(here) ? 'login'
|
||||
: '';
|
||||
log.push('ansicht=' + (view || 'keine'));
|
||||
|
||||
@@ -40,7 +41,7 @@
|
||||
if (view) {
|
||||
var st = document.createElement('style');
|
||||
st.textContent = `
|
||||
/* === Grundlage, beide Ansichten === */
|
||||
/* === Grundlage, alle Ansichten === */
|
||||
|
||||
html, body { max-width:100% !important; overflow-x:hidden !important;
|
||||
margin:0 !important; padding:0 !important; }
|
||||
@@ -61,7 +62,7 @@
|
||||
Leiste selbst, damit ohne sie kein leerer Streifen bleibt. */
|
||||
.rm-root.rm-paged { padding-bottom:64px !important; }
|
||||
|
||||
/* Brotkrumen, beide Ansichten. Fixiert statt sticky: .rm-root traegt
|
||||
/* Brotkrumen, alle Ansichten. Fixiert statt sticky: .rm-root traegt
|
||||
overflow:hidden und wuerde als Scrollport einer sticky-Leiste dienen,
|
||||
die darin nie klebt. Fixierte Nachfahren klammert es nicht, weil der
|
||||
Root keinen eigenen Containing Block aufspannt. */
|
||||
@@ -80,6 +81,10 @@
|
||||
color:#eee !important; text-decoration:none !important; }
|
||||
.rm-crumbs a:last-of-type { font-weight:650; }
|
||||
.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;
|
||||
font-size:13px !important; 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
|
||||
im Original-DOM bleibt der Platz sonst leer reserviert. */
|
||||
body.rm-crumbed .rm-root {
|
||||
@@ -200,6 +205,49 @@
|
||||
.rm-sig { margin-top:12px; font-size:13px; opacity:.5; }
|
||||
.rm-sig summary { cursor:pointer; opacity:.8; }
|
||||
|
||||
/* === Login === */
|
||||
|
||||
.rm-login-title { padding:16px 14px 6px; font-size:21px;
|
||||
font-weight:650; line-height:1.3; }
|
||||
.rm-login-note { margin:8px 14px 4px; padding:10px 12px;
|
||||
font-size:13px; opacity:.75; border-radius:10px;
|
||||
background:rgba(128,128,128,.14);
|
||||
overflow-wrap:break-word; }
|
||||
.rm-login-note summary { cursor:pointer; font-weight:650; opacity:.9; }
|
||||
.rm-login-note[open] summary { margin-bottom:8px; }
|
||||
|
||||
/* Das Original-Formular ist tabellenbasiert und wird fuer den gestapelten
|
||||
Kartenstil komplett auf Block-Elemente umgelegt — derselbe Trick wie bei
|
||||
.rm-body table im Thread. Ohne Paginierung fehlt hier die .rm-nav, die
|
||||
sonst per .rm-root.rm-paged den unteren Rand freihaelt. Der grosse
|
||||
Bodensatz ist kein Stilmittel, sondern erzwingt genug Seitenhoehe zum
|
||||
Scrollen: ist die Seite so kurz wie der Viewport, bleibt Safaris eigene,
|
||||
nur teilweise eingefahrene Werkzeugleiste unten stehen und verdeckt den
|
||||
Button dauerhaft, weil nichts mehr zu scrollen ist, um sie wegzuschieben. */
|
||||
.rm-login form { display:block;
|
||||
padding:4px 14px calc(140px + env(safe-area-inset-bottom)); }
|
||||
.rm-login form table, .rm-login form tbody,
|
||||
.rm-login form tr, .rm-login form td {
|
||||
display:block !important; width:100% !important; }
|
||||
.rm-login form th { display:none !important; }
|
||||
.rm-login form td { padding:0 !important; }
|
||||
.rm-login form b.gensmall { display:block; margin:16px 0 6px;
|
||||
font-size:13px; font-weight:650; opacity:.8; }
|
||||
.rm-login form input[type="text"],
|
||||
.rm-login form input[type="password"] {
|
||||
box-sizing:border-box; width:100%; font-size:16px; padding:11px 12px;
|
||||
border-radius:10px; color:#eee; background:rgba(120,120,120,.18);
|
||||
border:1px solid rgba(160,160,160,.35); }
|
||||
.rm-login form span.gensmall, .rm-login form a.gensmall {
|
||||
display:inline-block; margin-top:6px; font-size:12px; opacity:.6;
|
||||
text-decoration:none !important; color:inherit !important; }
|
||||
.rm-login form input[type="checkbox"] { width:18px; height:18px;
|
||||
vertical-align:middle; margin-right:8px; }
|
||||
.rm-login form input[type="submit"] {
|
||||
width:100%; font-size:16px; font-weight:650; padding:13px;
|
||||
margin-top:20px; border-radius:10px; color:#fff; border:0;
|
||||
background:rgba(120,170,255,.85); }
|
||||
|
||||
/* === Seitennavigation, beide Ansichten === */
|
||||
|
||||
.rm-nav { position:fixed; left:0; right:0; bottom:0; z-index:9999;
|
||||
@@ -277,6 +325,21 @@
|
||||
document.body.appendChild(root);
|
||||
}
|
||||
|
||||
// Ob eine Sitzung besteht, verraet nur der Menuebalken der Originalseite:
|
||||
// ausgeloggt verlinkt er ucp.php?mode=login, eingeloggt stattdessen
|
||||
// mode=logout, ueblicherweise als "Logout [ Name ]". Das Namensmuster ist
|
||||
// ungetestet, da dem Projekt keine eingeloggte Fixture vorliegt — schlaegt
|
||||
// es fehl, bleibt die Pille ohne Namen stehen statt zu reissen.
|
||||
function loginState() {
|
||||
var out = document.querySelector('a[href*="mode=logout"]');
|
||||
if (out) {
|
||||
var m = txt(out).match(/\[\s*(.+?)\s*\]/);
|
||||
return { in: true, href: out.href, name: m ? m[1] : '' };
|
||||
}
|
||||
var into = document.querySelector('a[href*="mode=login"]');
|
||||
return { in: false, href: into ? into.href : './ucp.php?mode=login' };
|
||||
}
|
||||
|
||||
// Ohne die Brotkrumen fuehrt aus der neuen Ansicht kein Weg zurueck: das
|
||||
// Original-DOM ist ausgeblendet, und phpBB verlinkt das Elternforum nirgends
|
||||
// sonst. Muss nach replaceBody() laufen, weil die Leiste an body haengt.
|
||||
@@ -308,6 +371,14 @@
|
||||
|
||||
log.push('krumen=' + n);
|
||||
if (!n) return;
|
||||
|
||||
var st = loginState();
|
||||
var auth = document.createElement('a');
|
||||
auth.className = 'rm-auth';
|
||||
auth.href = st.href;
|
||||
auth.textContent = st.in ? (st.name || 'Logout') : 'Login';
|
||||
bar.appendChild(auth);
|
||||
|
||||
document.body.appendChild(bar);
|
||||
document.body.classList.add('rm-crumbed');
|
||||
}
|
||||
@@ -1099,18 +1170,67 @@
|
||||
addCrumbs();
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Login
|
||||
// ==========================================================================
|
||||
|
||||
// Das Original-Formular wird unveraendert wiederverwendet statt neu gebaut
|
||||
// — wie der Beitragstext im Thread. So bleiben versteckte Felder (sid,
|
||||
// redirect) und die serverseitige Validierung erhalten; das Script muss
|
||||
// weder Sitzungs- noch Fehlerzustaende selbst nachbilden.
|
||||
function buildLogin() {
|
||||
var userInput = document.querySelector('input[name="username"]');
|
||||
var form = userInput && userInput.closest('form');
|
||||
if (!form) { log.push('login: kein Formular'); return; }
|
||||
|
||||
var root = document.createElement('div');
|
||||
root.className = 'rm-root rm-login';
|
||||
|
||||
var th = form.querySelector('th');
|
||||
var title = document.createElement('div');
|
||||
title.className = 'rm-login-title';
|
||||
title.textContent = txt(th) || 'Login';
|
||||
root.appendChild(title);
|
||||
|
||||
// Der Regeltext steckt als einziger Inhalt in td.row1 und wird separat als
|
||||
// aufklappbarer Kasten gefuehrt statt mitten im Formular zu stehen.
|
||||
var note = form.querySelector('.postbody');
|
||||
if (note && txt(note)) {
|
||||
var det = document.createElement('details');
|
||||
det.className = 'rm-login-note';
|
||||
var sm = document.createElement('summary');
|
||||
sm.textContent = 'Regeln';
|
||||
det.appendChild(sm);
|
||||
det.appendChild(note);
|
||||
root.appendChild(det);
|
||||
}
|
||||
|
||||
// Zellen ohne Element-Kinder und ohne Text sind reine Layout-Fuellzellen
|
||||
// (blosses " " als Platzhalter neben Checkboxen) — im gestapelten
|
||||
// Formular bleiben sie sonst als leere Zeilen stehen.
|
||||
Array.prototype.forEach.call(form.querySelectorAll('td'), function (td) {
|
||||
if (!td.children.length && !txt(td)) td.classList.add('rm-hidden');
|
||||
});
|
||||
|
||||
root.appendChild(form);
|
||||
replaceBody(root);
|
||||
addCrumbs();
|
||||
log.push('login=formular');
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
function run() {
|
||||
try {
|
||||
if (view === 'liste') buildList();
|
||||
else if (view === 'thread') buildThread();
|
||||
else if (view === 'login') buildLogin();
|
||||
} catch (e) { log.push('build: ' + e.message); }
|
||||
|
||||
if (DEBUG) {
|
||||
var d = document.createElement('div');
|
||||
d.className = 'rm-dbg';
|
||||
d.textContent = 'RIN Mobile v3.5\n' + log.join('\n');
|
||||
d.textContent = 'RIN Mobile v3.6\n' + log.join('\n');
|
||||
document.body.insertBefore(d, document.body.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user