Add a Monospace messages toggle in Appearance settings
Message text goes back to the proportional UI font by default; the new switch renders it in a fixed-width font (via html[data-mono]) so ASCII art, tables and box-drawing line up on demand. Persisted per user and translated across all locales.
This commit is contained in:
parent
e2abcce3d9
commit
322505a5b5
14 changed files with 39 additions and 15 deletions
|
|
@ -2,7 +2,7 @@ import { useActiveChat } from '@/core/networks';
|
|||
|
||||
// One preference toggle row: icon · label/hint · switch. Shared by the
|
||||
// Appearance and Notifications sections.
|
||||
export function ToggleRow({ icon, label, hint, prefKey }: { icon: string; label: string; hint?: string; prefKey: 'sound' | 'hideJoinQuit' | 'compact' | 'linkPreviews' | 'hoverActions' | 'confirmClose' }) {
|
||||
export function ToggleRow({ icon, label, hint, prefKey }: { icon: string; label: string; hint?: string; prefKey: 'sound' | 'hideJoinQuit' | 'compact' | 'linkPreviews' | 'hoverActions' | 'confirmClose' | 'monoMessages' }) {
|
||||
const value = useActiveChat((s) => s.prefs[prefKey]);
|
||||
const setPref = useActiveChat((s) => s.setPref);
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ export function AppearanceSection() {
|
|||
</div>
|
||||
<ToggleRow icon="🗜️" label={t('settings.appearance.compact')} hint={t('settings.appearance.compactHint')} prefKey="compact" />
|
||||
<ToggleRow icon="🖱️" label={t('settings.appearance.hoverActions')} hint={t('settings.appearance.hoverActionsHint')} prefKey="hoverActions" />
|
||||
<ToggleRow icon="⌨️" label={t('settings.appearance.mono')} hint={t('settings.appearance.monoHint')} prefKey="monoMessages" />
|
||||
<div className="srow">
|
||||
<span className="srow__ic" aria-hidden>🕓</span>
|
||||
<div className="srow__txt"><div className="srow__label">{t('settings.appearance.timeFormat')}</div></div>
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@
|
|||
"textSize": "Textgröße",
|
||||
"compactHint": "Dichtere Nachrichten, mehr auf dem Bildschirm.",
|
||||
"hoverActions": "Aktionen beim Überfahren",
|
||||
"hoverActionsHint": "Reaktion, Antwort und Pin beim Überfahren einer Nachricht."
|
||||
"hoverActionsHint": "Reaktion, Antwort und Pin beim Überfahren einer Nachricht.",
|
||||
"mono": "Nachrichten in Monospace",
|
||||
"monoHint": "Feste Zeichenbreite, damit ASCII-Art und Tabellen ausgerichtet bleiben."
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "Browser-Benachrichtigungen",
|
||||
|
|
|
|||
|
|
@ -320,7 +320,9 @@
|
|||
"textSize": "Text size",
|
||||
"compactHint": "Denser messages, more on screen.",
|
||||
"hoverActions": "Hover actions",
|
||||
"hoverActionsHint": "Quick react, reply and pin buttons when you hover a message."
|
||||
"hoverActionsHint": "Quick react, reply and pin buttons when you hover a message.",
|
||||
"mono": "Monospace messages",
|
||||
"monoHint": "Fixed-width font so ASCII art and tables line up."
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "Browser notifications",
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@
|
|||
"textSize": "Tamaño de texto",
|
||||
"compactHint": "Mensajes más densos, más en pantalla.",
|
||||
"hoverActions": "Acciones al pasar el cursor",
|
||||
"hoverActionsHint": "Botones de reacción, respuesta y fijar al pasar el cursor por un mensaje."
|
||||
"hoverActionsHint": "Botones de reacción, respuesta y fijar al pasar el cursor por un mensaje.",
|
||||
"mono": "Mensajes monoespaciados",
|
||||
"monoHint": "Fuente de ancho fijo para alinear el arte ASCII y las tablas."
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "Notificaciones del navegador",
|
||||
|
|
|
|||
|
|
@ -320,7 +320,9 @@
|
|||
"textSize": "Taille du texte",
|
||||
"compactHint": "Messages plus denses, plus d’infos à l’écran.",
|
||||
"hoverActions": "Actions au survol",
|
||||
"hoverActionsHint": "Boutons de réaction, réponse et épingle au survol d'un message."
|
||||
"hoverActionsHint": "Boutons de réaction, réponse et épingle au survol d'un message.",
|
||||
"mono": "Messages à chasse fixe",
|
||||
"monoHint": "Police à largeur fixe pour aligner l'art ASCII et les tableaux."
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "Notifications navigateur",
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@
|
|||
"textSize": "Dimensione testo",
|
||||
"compactHint": "Messaggi più compatti, più contenuti a schermo.",
|
||||
"hoverActions": "Azioni al passaggio",
|
||||
"hoverActionsHint": "Pulsanti di reazione, risposta e fissaggio al passaggio su un messaggio."
|
||||
"hoverActionsHint": "Pulsanti di reazione, risposta e fissaggio al passaggio su un messaggio.",
|
||||
"mono": "Messaggi a spaziatura fissa",
|
||||
"monoHint": "Carattere a larghezza fissa per allineare ASCII art e tabelle."
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "Notifiche del browser",
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@
|
|||
"textSize": "पाठ आकार",
|
||||
"compactHint": "घना सन्देश, स्क्रिनमा बढी।",
|
||||
"hoverActions": "होभर कार्यहरू",
|
||||
"hoverActionsHint": "सन्देशमाथि माउस लैजाँदा द्रुत प्रतिक्रिया, जवाफ र पिन बटनहरू।"
|
||||
"hoverActionsHint": "सन्देशमाथि माउस लैजाँदा द्रुत प्रतिक्रिया, जवाफ र पिन बटनहरू।",
|
||||
"mono": "मोनोस्पेस सन्देशहरू",
|
||||
"monoHint": "ASCII कला र तालिकाहरू पङ्क्तिबद्ध हुन स्थिर-चौडाइको फन्ट।"
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "ब्राउजर सूचनाहरू",
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@
|
|||
"textSize": "Tamanho do texto",
|
||||
"compactHint": "Mensagens mais densas, mais na tela.",
|
||||
"hoverActions": "Ações ao passar o mouse",
|
||||
"hoverActionsHint": "Botões de reação, resposta e fixar ao passar o mouse sobre uma mensagem."
|
||||
"hoverActionsHint": "Botões de reação, resposta e fixar ao passar o mouse sobre uma mensagem.",
|
||||
"mono": "Mensagens monoespaçadas",
|
||||
"monoHint": "Fonte de largura fixa para alinhar arte ASCII e tabelas."
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "Notificações do navegador",
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@
|
|||
"textSize": "Tamanho do texto",
|
||||
"compactHint": "Mensagens mais densas, mais no ecrã.",
|
||||
"hoverActions": "Ações ao passar o rato",
|
||||
"hoverActionsHint": "Botões de reação, resposta e fixar ao passar o rato sobre uma mensagem."
|
||||
"hoverActionsHint": "Botões de reação, resposta e fixar ao passar o rato sobre uma mensagem.",
|
||||
"mono": "Mensagens monoespaçadas",
|
||||
"monoHint": "Tipo de letra de largura fixa para alinhar arte ASCII e tabelas."
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "Notificações do navegador",
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@
|
|||
"textSize": "Размер текста",
|
||||
"compactHint": "Более плотные сообщения, больше на экране.",
|
||||
"hoverActions": "Действия при наведении",
|
||||
"hoverActionsHint": "Кнопки реакции, ответа и закрепления при наведении на сообщение."
|
||||
"hoverActionsHint": "Кнопки реакции, ответа и закрепления при наведении на сообщение.",
|
||||
"mono": "Моноширинные сообщения",
|
||||
"monoHint": "Моноширинный шрифт, чтобы ASCII-арт и таблицы выравнивались."
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "Уведомления браузера",
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@
|
|||
"textSize": "Metin boyutu",
|
||||
"compactHint": "Daha sık mesajlar, ekranda daha fazlası.",
|
||||
"hoverActions": "Fareyle eylemler",
|
||||
"hoverActionsHint": "Bir mesajın üzerine gelince hızlı tepki, yanıt ve sabitleme düğmeleri."
|
||||
"hoverActionsHint": "Bir mesajın üzerine gelince hızlı tepki, yanıt ve sabitleme düğmeleri.",
|
||||
"mono": "Eş aralıklı mesajlar",
|
||||
"monoHint": "ASCII sanatı ve tabloların hizalanması için sabit genişlikli yazı tipi."
|
||||
},
|
||||
"notifications": {
|
||||
"browser": "Tarayıcı bildirimleri",
|
||||
|
|
|
|||
|
|
@ -531,9 +531,10 @@ input, textarea { font-family: inherit; }
|
|||
.group__nick { font-weight: 800; font-size: .94rem; }
|
||||
.group__time { font-size: .7rem; color: var(--faint); font-weight: 600; }
|
||||
.group--cont .group__avatar.group__time-rail { height: auto; }
|
||||
/* Monospace + the existing pre-wrap keeps ASCII art, tables and box-drawing
|
||||
aligned (every glyph one cell wide, spaces preserved). */
|
||||
.line { font-family: var(--mono); font-size: .92rem; line-height: 1.5; color: var(--ink-2); word-wrap: break-word; overflow-wrap: anywhere; white-space: pre-wrap; }
|
||||
.line { font-size: .96rem; line-height: 1.5; color: var(--ink-2); word-wrap: break-word; overflow-wrap: anywhere; white-space: pre-wrap; }
|
||||
/* "Monospace messages" pref: a fixed-width font + the existing pre-wrap keeps
|
||||
ASCII art, tables and box-drawing aligned (every glyph one cell wide). */
|
||||
html[data-mono="on"] .line { font-family: var(--mono); font-size: .92rem; }
|
||||
.line--action { font-style: italic; color: var(--accent-d); }
|
||||
.line--notice { color: var(--muted); }
|
||||
.line--notice::before { content: "-notice- "; font-weight: 700; opacity: .7; font-size: .82em; }
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ export interface Prefs {
|
|||
linkPreviews: boolean; // show OpenGraph link-preview cards (off = never fetch)
|
||||
hoverActions: boolean; // quick react/reply/pin toolbar on message hover (off = classic)
|
||||
confirmClose: boolean; // warn (beforeunload) before closing/reloading the tab while connected
|
||||
monoMessages: boolean; // render message text in a fixed-width font so ASCII art/tables line up
|
||||
}
|
||||
|
||||
const KEY = 'tchatou-prefs';
|
||||
|
|
@ -17,7 +18,7 @@ const KEY = 'tchatou-prefs';
|
|||
// Defaults come from config.json (so a deployment can preset compact/sound/etc.).
|
||||
function defaults(): Prefs {
|
||||
const d = getConfig().defaults;
|
||||
return { sound: d.sound, hideJoinQuit: d.hideJoinQuit, compact: d.compact, clock24: d.clock24, textScale: 1, linkPreviews: true, hoverActions: true, confirmClose: false };
|
||||
return { sound: d.sound, hideJoinQuit: d.hideJoinQuit, compact: d.compact, clock24: d.clock24, textScale: 1, linkPreviews: true, hoverActions: true, confirmClose: false, monoMessages: false };
|
||||
}
|
||||
|
||||
export function getPrefs(): Prefs {
|
||||
|
|
@ -38,6 +39,7 @@ export function savePrefs(p: Prefs): void {
|
|||
export function applyPrefs(p: Prefs): void {
|
||||
document.documentElement.dataset.density = p.compact ? 'compact' : 'comfortable';
|
||||
document.documentElement.dataset.actions = p.hoverActions ? 'on' : 'off';
|
||||
document.documentElement.dataset.mono = p.monoMessages ? 'on' : 'off';
|
||||
const scale = Math.min(1.4, Math.max(0.8, p.textScale || 1));
|
||||
document.documentElement.style.fontSize = Math.round(scale * 100) + '%';
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue