From 0e031959d9bdf369cbf5aa1dc816d32a3e746b0b Mon Sep 17 00:00:00 2001 From: joaohortsenado <100957576+joaohortsenado@users.noreply.github.com> Date: Thu, 24 Sep 2026 18:12:24 -0300 Subject: [PATCH] Permite ajustar e persistir o tamanho da letra no editor de textos articulados (#3862) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Permite ajustar e persistir o tamanho da letra no editor de textos articulados Os botões a/A da leitura alteravam o font-size de cada dispositivo via jQuery, sem persistir, e não existiam na tela de edição. Com isso, a única forma de aumentar a letra era formatar o texto no TinyMCE, o que gravava o tamanho no conteúdo do dispositivo e valia apenas para ele. - Escala de leitura aplicada via variável CSS (--cp-font-scale) no container .cp, salva no localStorage (80% a 250%, passo de 10%) - Botões a/A também na tela de edição (text_edit) - Textarea do editor simples e corpo do TinyMCE acompanham a escala - Linha de vigências não é afetada pela escala - initTextRichEditor passa a retornar a promise do tinymce.init * Ajusta a escala de fonte conforme a revisão do PR - Agrupa as constantes no objeto congelado EscalaFonte, com o valor padrão em EscalaFonte.PADRAO. - Extrai o helper clamp() para limitar a escala ao intervalo permitido. - Separa, no log, a falha de acesso ao localStorage do valor salvo inválido, e registra também a falha ao salvar. - Renomeia aplicaEscalaFonte/salvaEscalaFonte para o infinitivo. --------- Co-authored-by: Edward <9326037+edwardoliveira@users.noreply.github.com> --- .../__apps/compilacao/js/old/compilacao.js | 70 ++++++++++++++++++- .../compilacao/js/old/compilacao_edit.js | 4 +- .../__apps/compilacao/scss/compilacao.scss | 9 +++ frontend/src/__global/js/tinymce/index.js | 2 +- sapl/templates/compilacao/text_edit.html | 10 ++- 5 files changed, 89 insertions(+), 6 deletions(-) diff --git a/frontend/src/__apps/compilacao/js/old/compilacao.js b/frontend/src/__apps/compilacao/js/old/compilacao.js index f7176c473..8853d6425 100644 --- a/frontend/src/__apps/compilacao/js/old/compilacao.js +++ b/frontend/src/__apps/compilacao/js/old/compilacao.js @@ -279,6 +279,69 @@ function DispositivoSearch (opts) { }) } +// Escala de leitura do texto articulado, preferência de cada navegador. +// Aplicada via variável CSS (--cp-font-scale) para não alterar o conteúdo +// dos dispositivos e para valer também nos que são recarregados via ajax. +const EscalaFonte = Object.freeze({ + CHAVE: 'compilacao_escala_fonte', + PADRAO: 1, + PASSO: 0.1, + MIN: 0.8, + MAX: 2.5 +}) +let escalaFonteAtual = null + +// Limita num ao intervalo [lower, upper]. +function clamp (num, lower, upper) { + return Math.max(lower, Math.min(num, upper)) +} + +function lerEscalaFonte () { + if (escalaFonteAtual !== null) { + return escalaFonteAtual + } + let valor = null + try { + valor = window.localStorage.getItem(EscalaFonte.CHAVE) + } catch (e) { + // localStorage indisponível (ex.: navegação privada bloqueada) + console.warn('Escala de fonte: não foi possível ler o localStorage.', e) + return EscalaFonte.PADRAO + } + if (valor === null) { + return EscalaFonte.PADRAO + } + const escala = parseFloat(valor) + if (!Number.isFinite(escala)) { + console.warn('Escala de fonte: valor inválido no localStorage, usando o padrão.', valor) + return EscalaFonte.PADRAO + } + return clamp(escala, EscalaFonte.MIN, EscalaFonte.MAX) +} + +function aplicarEscalaFonte (escala) { + document.documentElement.style.setProperty('--cp-font-scale', escala) + if (window.tinymce) { + window.tinymce.get().forEach(function (editor) { + if (editor.getBody()) { + editor.getBody().style.fontSize = (escala * 100) + '%' + } + }) + } +} + +function salvarEscalaFonte (escala) { + escala = Math.round(clamp(escala, EscalaFonte.MIN, EscalaFonte.MAX) * 10) / 10 + try { + window.localStorage.setItem(EscalaFonte.CHAVE, escala) + } catch (e) { + // localStorage indisponível: a escala vale apenas até recarregar a página + console.warn('Escala de fonte: não foi possível salvar no localStorage.', escala, e) + } + escalaFonteAtual = escala + aplicarEscalaFonte(escala) +} + function InitViewTAs () { setTimeout(function () { var href = location.href.split('#') @@ -297,11 +360,12 @@ function InitViewTAs () { } }, 100) + aplicarEscalaFonte(lerEscalaFonte()) $('#btn_font_menos').click(function () { - $('.dpt').css('font-size', '-=1') + salvarEscalaFonte(lerEscalaFonte() - EscalaFonte.PASSO) }) $('#btn_font_mais').click(function () { - $('.dpt').css('font-size', '+=1') + salvarEscalaFonte(lerEscalaFonte() + EscalaFonte.PASSO) }) $('.dpt.bloco_alteracao .dpt').each(function () { @@ -327,5 +391,7 @@ export default { ReadCookie, insertWaitAjax, InitViewTAs, + lerEscalaFonte, + aplicarEscalaFonte, DispositivoSearch } diff --git a/frontend/src/__apps/compilacao/js/old/compilacao_edit.js b/frontend/src/__apps/compilacao/js/old/compilacao_edit.js index ba651188b..27060135b 100644 --- a/frontend/src/__apps/compilacao/js/old/compilacao_edit.js +++ b/frontend/src/__apps/compilacao/js/old/compilacao_edit.js @@ -244,7 +244,9 @@ window.DispositivoEdit = function () { if (editortype !== 'construct') { dpt_form.html(data) if (editortype === 'tinymce') { - window.initTextRichEditor(null, false, false) + window.initTextRichEditor(null, false, false).then(function () { + window.aplicarEscalaFonte(window.lerEscalaFonte()) + }) } // OptionalCustomFrontEnd().init() } diff --git a/frontend/src/__apps/compilacao/scss/compilacao.scss b/frontend/src/__apps/compilacao/scss/compilacao.scss index 82c52f7f6..842436b24 100644 --- a/frontend/src/__apps/compilacao/scss/compilacao.scss +++ b/frontend/src/__apps/compilacao/scss/compilacao.scss @@ -164,12 +164,21 @@ a:link:after, a:visited:after { } .cp { + /* --cp-font-scale: escala de leitura escolhida pelo usuário (a/A) */ + font-size: calc(100% * var(--cp-font-scale, 1)); + + .dpt-form textarea.form-control { + font-size: calc(1rem * var(--cp-font-scale, 1)); + } + .vigencia-active { margin-top: 30px; display: block; } .cp-linha-vigencias { + /* navegação entre vigências não acompanha a escala de leitura */ + font-size: calc(100% / var(--cp-font-scale, 1)); display: flex; flex-direction: row; list-style: none; diff --git a/frontend/src/__global/js/tinymce/index.js b/frontend/src/__global/js/tinymce/index.js index 51eed1efa..3f3ca312e 100644 --- a/frontend/src/__global/js/tinymce/index.js +++ b/frontend/src/__global/js/tinymce/index.js @@ -31,5 +31,5 @@ window.initTextRichEditor = function (elements, readonly = false, paste_as_text configTinymce.menubar = false configTinymce.toolbar = false } - window.tinymce.init(configTinymce) + return window.tinymce.init(configTinymce) } diff --git a/sapl/templates/compilacao/text_edit.html b/sapl/templates/compilacao/text_edit.html index ada437934..ed7055e62 100644 --- a/sapl/templates/compilacao/text_edit.html +++ b/sapl/templates/compilacao/text_edit.html @@ -17,8 +17,14 @@ {% if object.editing_locked %}{% trans 'Desbloquear Edição' %}{%else%}{% trans 'Publicar Texto' %}{% endif %} {% endif %} -
{% if object.dispositivos_set.count == 1 %}