Nachrichten: Design-Label, server-seitige Präferenz, mobiler Leerraum fix
This commit is contained in:
@@ -246,6 +246,11 @@ if (msgCols2.length && !msgCols2.includes('read_by_recipient')) {
|
||||
db.exec("ALTER TABLE messages ADD COLUMN read_by_recipient INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
|
||||
// User-Preferences (JSON-Blob)
|
||||
const userCols2 = db.prepare("PRAGMA table_info(users)").all().map(r => r.name);
|
||||
if (!userCols2.includes('preferences'))
|
||||
db.exec("ALTER TABLE users ADD COLUMN preferences TEXT DEFAULT NULL");
|
||||
|
||||
// ── Login-Sicherheit ──────────────────────────────────────────────────────────
|
||||
// Spalten für Account-Lockout in users-Tabelle
|
||||
const userCols = db.prepare("PRAGMA table_info(users)").all().map(r => r.name);
|
||||
|
||||
@@ -150,4 +150,20 @@ router.delete('/account', authenticate, (req, res) => {
|
||||
res.json({ success: true });
|
||||
});
|
||||
|
||||
// ── GET/PUT /api/auth/preferences ─────────────────────────────────────────────
|
||||
router.get('/preferences', authenticate, (req, res) => {
|
||||
const user = db.prepare('SELECT preferences FROM users WHERE id=?').get(req.user.id);
|
||||
try { res.json(JSON.parse(user?.preferences || '{}')); }
|
||||
catch { res.json({}); }
|
||||
});
|
||||
|
||||
router.put('/preferences', authenticate, (req, res) => {
|
||||
const user = db.prepare('SELECT preferences FROM users WHERE id=?').get(req.user.id);
|
||||
let current = {};
|
||||
try { current = JSON.parse(user?.preferences || '{}'); } catch {}
|
||||
const merged = { ...current, ...req.body };
|
||||
db.prepare('UPDATE users SET preferences=? WHERE id=?').run(JSON.stringify(merged), req.user.id);
|
||||
res.json(merged);
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -1660,7 +1660,7 @@ export default function App() {
|
||||
const activeTool = TOOLS.find(t=>t.id===active);
|
||||
|
||||
// Mobile padding bottom für fixed nav
|
||||
const mainStyle = { flex:1, overflowY:'auto', ...(mobile ? { paddingBottom:'calc(56px + env(safe-area-inset-bottom, 0px))' } : {}) };
|
||||
const mainStyle = { flex:1, overflowY:'auto', ...(mobile ? { paddingBottom: active==='nachrichten' ? 0 : 'calc(56px + env(safe-area-inset-bottom, 0px))' } : {}) };
|
||||
|
||||
return(
|
||||
<>
|
||||
|
||||
@@ -82,8 +82,16 @@ export default function Nachrichten({ toast, mobile }) {
|
||||
const [text, setText] = useState('');
|
||||
const [sending, setSending] = useState(false);
|
||||
const [showPicker, setShowPicker] = useState(false);
|
||||
const [mirc, setMirc] = useState(() => localStorage.getItem('dd_chat_design') === 'mirc');
|
||||
const toggleDesign = () => setMirc(v => { const n = !v; localStorage.setItem('dd_chat_design', n ? 'mirc' : 'modern'); return n; });
|
||||
const [mirc, setMirc] = useState(false);
|
||||
// Preference vom Server laden
|
||||
useEffect(() => {
|
||||
api('/auth/preferences').then(p => { if (p.chat_design === 'mirc') setMirc(true); }).catch(()=>{});
|
||||
}, []);
|
||||
const toggleDesign = () => setMirc(v => {
|
||||
const next = !v;
|
||||
api('/auth/preferences', { method:'PUT', body:{ chat_design: next ? 'mirc' : 'modern' } }).catch(()=>{});
|
||||
return next;
|
||||
});
|
||||
const bottomRef = useRef(null);
|
||||
const pollRef = useRef(null);
|
||||
const pickerRef = useRef(null);
|
||||
@@ -247,12 +255,12 @@ export default function Nachrichten({ toast, mobile }) {
|
||||
display:'flex', alignItems:'center', justifyContent:'space-between' }}>
|
||||
<div style={{ ...S.head, marginBottom:0 }}>NACHRICHTEN</div>
|
||||
<div style={{ display:'flex', gap:5 }}>
|
||||
<button onClick={toggleDesign} title={mirc ? 'Modern' : 'mIRC-Stil'}
|
||||
style={{ background: mirc ? 'rgba(78,205,196,0.12)' : 'transparent',
|
||||
border:`1px solid ${mirc ? 'rgba(78,205,196,0.3)' : 'rgba(255,255,255,0.1)'}`,
|
||||
borderRadius:7, color: mirc ? '#4ecdc4' : 'rgba(255,255,255,0.35)',
|
||||
cursor:'pointer', padding:'3px 7px', fontSize:10, fontFamily:'monospace', lineHeight:1 }}>
|
||||
{mirc ? '◈ mIRC' : '◈'}
|
||||
<button onClick={toggleDesign} title={mirc ? 'Zu Modern wechseln' : 'Zu mIRC wechseln'}
|
||||
style={{ background: 'rgba(255,255,255,0.05)',
|
||||
border:'1px solid rgba(255,255,255,0.1)',
|
||||
borderRadius:7, color:'rgba(255,255,255,0.55)',
|
||||
cursor:'pointer', padding:'3px 8px', fontSize:10, fontFamily:'monospace', lineHeight:1 }}>
|
||||
{mirc ? '◈ mIRC' : '◈ Modern'}
|
||||
</button>
|
||||
<button onClick={() => { loadUsers(); if (activeUser) loadMessages(activeUser.id); }} title="Neu laden"
|
||||
style={{ background:'transparent', border:'1px solid rgba(255,255,255,0.1)', borderRadius:7,
|
||||
|
||||
Reference in New Issue
Block a user