mirror of
https://github.com/Andre-Bzk/rin-mobile-userscript.git
synced 2026-11-15 09:33:08 +01:00
fix: resolve author and avatar detection in thread view
The forum nests each post body inside its own table, so ascending to the nearest enclosing row stopped within that inner table rather than at the actual post row. The author and profile columns were never in scope, and every post silently degraded to the placeholder name and the generated initial avatar instead of the real ones. Author lookup additionally keyed on a profile link attribute this forum does not emit at all, so even a correct row would have yielded nothing. Both conditions failed quietly, which made the result look like a styling problem rather than a broken DOM traversal.
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
// ==UserScript==
|
||||
// @name RIN Mobile
|
||||
// @description Mobile Karten-Ansicht fuer cs.rin.ru
|
||||
// @version 1.4
|
||||
// @match *://cs.rin.ru/forum/*
|
||||
// @run-at document-start
|
||||
// ==/UserScript==
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var DEBUG = true;
|
||||
var log = [];
|
||||
|
||||
function h() { return document.head || document.documentElement; }
|
||||
|
||||
if (!document.querySelector('meta[name="viewport"][data-rm]')) {
|
||||
var m = document.createElement('meta');
|
||||
m.name = 'viewport';
|
||||
m.content = 'width=device-width, initial-scale=1, viewport-fit=cover';
|
||||
m.setAttribute('data-rm', '1');
|
||||
h().appendChild(m);
|
||||
}
|
||||
|
||||
var st = document.createElement('style');
|
||||
st.textContent = `
|
||||
html, body { max-width:100% !important; overflow-x:hidden !important;
|
||||
margin:0 !important; padding:0 !important; }
|
||||
body { font-size:16px !important;
|
||||
-webkit-text-size-adjust:100% !important; }
|
||||
img { max-width:100% !important; height:auto !important; }
|
||||
|
||||
.rm-dbg { background:#222; color:#0f0; font:12px/1.45 monospace;
|
||||
padding:8px 10px; white-space:pre-wrap;
|
||||
border-bottom:2px solid #0f0; }
|
||||
|
||||
.rm-root { box-sizing:border-box !important;
|
||||
display:block !important;
|
||||
width:100vw !important; max-width:100vw !important;
|
||||
margin:0 !important; padding:0 !important;
|
||||
overflow:hidden !important; }
|
||||
.rm-card { box-sizing:border-box !important;
|
||||
display:block !important;
|
||||
width:100% !important; max-width:100% !important;
|
||||
margin:0 !important;
|
||||
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-main { box-sizing:border-box !important;
|
||||
display:block !important;
|
||||
width:100% !important; max-width:100% !important;
|
||||
text-decoration:none !important; color:inherit !important;
|
||||
font-size:20px !important; font-weight:600 !important;
|
||||
line-height:1.32 !important;
|
||||
white-space:normal !important;
|
||||
word-break:normal !important;
|
||||
overflow-wrap:break-word !important;
|
||||
hyphens:none !important; }
|
||||
.rm-badge { display:inline; font-size:11px; font-weight:700;
|
||||
text-transform:uppercase; letter-spacing:.04em;
|
||||
padding:2px 6px; margin-right:6px; border-radius:4px;
|
||||
background:rgba(200,60,60,.18); color:#e06a6a;
|
||||
white-space:nowrap; vertical-align:2px; }
|
||||
.rm-meta { margin-top:8px; font-size:13px; opacity:.7;
|
||||
overflow-wrap:break-word; }
|
||||
.rm-meta span + span::before { content:" · "; opacity:.55; }
|
||||
.rm-foot { margin-top:5px; display:flex; align-items:center;
|
||||
justify-content:space-between; gap:10px; }
|
||||
.rm-last { font-size:13px; opacity:.55; min-width:0;
|
||||
overflow-wrap:break-word; }
|
||||
.rm-jump { flex:none; font-size:12px; padding:5px 10px;
|
||||
border:1px solid rgba(128,128,128,.4); border-radius:99px;
|
||||
text-decoration:none !important; color:inherit !important;
|
||||
white-space:nowrap; }
|
||||
.rm-pages { padding:14px; display:flex; flex-wrap:wrap; gap:8px; }
|
||||
.rm-pages a { padding:6px 11px; border-radius:8px;
|
||||
border:1px solid rgba(128,128,128,.35);
|
||||
text-decoration:none !important; color:inherit !important; }
|
||||
.rm-hidden { display:none !important; }
|
||||
`;
|
||||
h().appendChild(st);
|
||||
|
||||
function txt(el) { return (el.textContent || '').replace(/\s+/g, ' ').trim(); }
|
||||
|
||||
function breakable(s) {
|
||||
return s.replace(/([|\/\\,;:>\]\)])/g, '$1\u200B');
|
||||
}
|
||||
|
||||
function convert(tr) {
|
||||
var titleA = tr.querySelector('a.topictitle') ||
|
||||
tr.querySelector('a[href*="viewtopic.php"]');
|
||||
if (!titleA) return null;
|
||||
|
||||
var titleCell = titleA.closest('td');
|
||||
var nums = [], author = '', last = '', jump = null;
|
||||
|
||||
Array.prototype.forEach.call(tr.children, function (td) {
|
||||
if (td === titleCell) return;
|
||||
var t = txt(td);
|
||||
if (/^\d+$/.test(t)) { nums.push(t); return; }
|
||||
var pa = td.querySelector('a[href*="profile.php"],a[href*="memberlist.php"]');
|
||||
if (pa && t.length < 40 && !/\d{4}/.test(t)) { author = t; return; }
|
||||
if (t) {
|
||||
last = t;
|
||||
jump = td.querySelector('a[href*="#p"]') ||
|
||||
td.querySelector('a[href*="viewtopic.php"]');
|
||||
}
|
||||
});
|
||||
|
||||
var card = document.createElement('div');
|
||||
card.className = 'rm-card';
|
||||
|
||||
var main = document.createElement('a');
|
||||
main.className = 'rm-main';
|
||||
main.href = titleA.href;
|
||||
|
||||
var raw = txt(titleA);
|
||||
var badge = (raw.match(/^\[([^\]]{1,20})\]/) || [])[1];
|
||||
if (badge) {
|
||||
var b = document.createElement('span');
|
||||
b.className = 'rm-badge';
|
||||
b.textContent = badge;
|
||||
main.appendChild(b);
|
||||
raw = raw.replace(/^\[[^\]]{1,20}\]\s*/, '');
|
||||
}
|
||||
main.appendChild(document.createTextNode(breakable(raw)));
|
||||
card.appendChild(main);
|
||||
|
||||
var meta = document.createElement('div');
|
||||
meta.className = 'rm-meta';
|
||||
function add(s) {
|
||||
var e = document.createElement('span');
|
||||
e.textContent = s;
|
||||
meta.appendChild(e);
|
||||
}
|
||||
if (author) add(author);
|
||||
if (nums[0]) add(nums[0] + ' Antworten');
|
||||
if (nums[1]) add(nums[1] + ' Views');
|
||||
if (meta.children.length) card.appendChild(meta);
|
||||
|
||||
var foot = document.createElement('div');
|
||||
foot.className = 'rm-foot';
|
||||
var l = document.createElement('div');
|
||||
l.className = 'rm-last';
|
||||
l.textContent = last;
|
||||
foot.appendChild(l);
|
||||
if (jump) {
|
||||
var j = document.createElement('a');
|
||||
j.className = 'rm-jump';
|
||||
j.href = jump.href;
|
||||
j.textContent = 'Neueste ↓';
|
||||
foot.appendChild(j);
|
||||
}
|
||||
card.appendChild(foot);
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
function build() {
|
||||
var onList = /viewforum\.php|search\.php/
|
||||
.test(location.pathname + location.search) ||
|
||||
location.pathname === '/forum/';
|
||||
log.push('listenseite=' + onList);
|
||||
if (!onList) return;
|
||||
|
||||
var links = document.querySelectorAll(
|
||||
'a.topictitle,a[href*="viewtopic.php"]');
|
||||
log.push('themenlinks=' + links.length);
|
||||
if (!links.length) return;
|
||||
|
||||
var root = document.createElement('div');
|
||||
root.className = 'rm-root';
|
||||
|
||||
var rows = [], tables = new Set();
|
||||
links.forEach(function (a) {
|
||||
var tr = a.closest('tr');
|
||||
if (!tr || tr.dataset.rm) return;
|
||||
var tbl = tr.closest('table');
|
||||
if (!tbl) return;
|
||||
tr.dataset.rm = '1';
|
||||
rows.push(tr);
|
||||
tables.add(tbl);
|
||||
});
|
||||
|
||||
var built = 0;
|
||||
rows.forEach(function (tr) {
|
||||
try {
|
||||
var c = convert(tr);
|
||||
if (c) { root.appendChild(c); built++; }
|
||||
} catch (e) { log.push('convert: ' + e.message); }
|
||||
});
|
||||
log.push('karten=' + built);
|
||||
if (!built) return;
|
||||
|
||||
var seen = {}, pages = document.createElement('div');
|
||||
pages.className = 'rm-pages';
|
||||
document.querySelectorAll('a[href*="start="]').forEach(function (a) {
|
||||
var t = txt(a);
|
||||
if (!t || t.length > 4 || seen[t]) return;
|
||||
seen[t] = 1;
|
||||
var n = document.createElement('a');
|
||||
n.href = a.href;
|
||||
n.textContent = t;
|
||||
pages.appendChild(n);
|
||||
});
|
||||
if (pages.children.length) root.appendChild(pages);
|
||||
|
||||
// Originalinhalt ausblenden, Liste als direktes body-Kind einhaengen
|
||||
Array.prototype.forEach.call(document.body.children, function (el) {
|
||||
if (el !== root) el.classList.add('rm-hidden');
|
||||
});
|
||||
document.body.appendChild(root);
|
||||
|
||||
if (DEBUG) {
|
||||
var c0 = root.querySelector('.rm-card');
|
||||
log.push('fenster=' + window.innerWidth +
|
||||
' body=' + document.body.scrollWidth +
|
||||
' karte=' + (c0 ? Math.round(c0.getBoundingClientRect().width) : '?'));
|
||||
}
|
||||
}
|
||||
|
||||
function run() {
|
||||
try { build(); } catch (e) { log.push('build: ' + e.message); }
|
||||
if (DEBUG) {
|
||||
var d = document.createElement('div');
|
||||
d.className = 'rm-dbg';
|
||||
d.textContent = 'RIN Mobile v1.4\n' + log.join('\n');
|
||||
document.body.insertBefore(d, document.body.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading')
|
||||
document.addEventListener('DOMContentLoaded', run);
|
||||
else
|
||||
run();
|
||||
})();
|
||||
Reference in New Issue
Block a user