skins: elegir el aspecto en el movil con tarjetas de un toque

En Ajustes del movil, Tema y Flujos de trabajo dejan de ser desplegables:
cada skin es una tarjeta con su miniatura y cada workflow un boton grande,
y se aplican al tocarlos. Solo se ofrecen los skins que tienen maqueta de
movil (Acampada y Oasis Mobile); el servidor rechaza un tema de escritorio,
que dejaba la app sin maqueta. La bienvenida tambien ofrece elegir skin.

Aplicar un workflow ya no cambia el skin: se queda el que haya elegido cada
cual.

OasisMobile.css se carga con su propio <link> versionado antes de
Acampada.css, en vez de con @import: el @import sin ?v= se quedaba en la
cache del WebView y tras actualizar se veia la maqueta vieja.
This commit is contained in:
oasis-bot 2026-10-19 02:17:12 +02:00
parent ac921c9d56
commit 0baf85faa9
9 changed files with 103 additions and 17 deletions

View file

@ -8487,7 +8487,7 @@ router
profile: true, profile: true,
ux: true, ux: true,
workflow: isLoopbackRequest(ctx), workflow: isLoopbackRequest(ctx),
theme: process.env.OASIS_MOBILE !== '1', theme: true, // en el movil ofrece los skins de movil (WIZARD_THEMES)
community: checkMod(ctx, 'invitesMod'), community: checkMod(ctx, 'invitesMod'),
greeting: checkMod(ctx, 'feedMod') greeting: checkMod(ctx, 'feedMod')
}; };
@ -14669,6 +14669,8 @@ router
}) })
.post("/settings/theme", koaBody(), async (ctx) => { .post("/settings/theme", koaBody(), async (ctx) => {
const theme = String(ctx.request.body.theme || "").trim(), cfg = getConfig(); const theme = String(ctx.request.body.theme || "").trim(), cfg = getConfig();
// en el movil solo los skins de movil: un tema de escritorio deja la app sin maqueta
if (process.env.OASIS_MOBILE === '1' && !require('../views/main_views').MOBILE_THEMES.some(([value]) => value === theme)) { ctx.redirect("/settings#theme"); return; }
cfg.themes.current = theme || "Dark-SNH"; cfg.themes.current = theme || "Dark-SNH";
saveConfig(cfg); saveConfig(cfg);
ctx.cookies.set("theme", cfg.themes.current, { httpOnly: true, sameSite: 'strict', secure: ctx.secure }); ctx.cookies.set("theme", cfg.themes.current, { httpOnly: true, sameSite: 'strict', secure: ctx.secure });

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -3,12 +3,11 @@
* Los colores y las formas salen de acampada26s.net: bordes negros gruesos, * Los colores y las formas salen de acampada26s.net: bordes negros gruesos,
* botones con sombra solida que se hunden al pulsar y titulos en mayusculas. * botones con sombra solida que se hunden al pulsar y titulos en mayusculas.
* *
* La maqueta de movil es la de OasisMobile.css de upstream, que se importa entera; * La maqueta de movil es la de OasisMobile.css, que main_views.js carga justo antes
* aqui solo se cambian colores, letra y formas encima. Por eso casi todo lleva * con su propio <link> versionado (no con @import: se quedaba en la cache del
* WebView); aqui solo se cambian colores, letra y formas encima. Por eso casi todo lleva
* !important: OasisMobile.css tambien lo usa. Las piezas propias de la rama * !important: OasisMobile.css tambien lo usa. Las piezas propias de la rama
* (panal, barras) se ajustan en styles/hive_acampada.css. */ * (panal, barras) se ajustan en styles/hive_acampada.css. */
@import url("OasisMobile.css");
@font-face { @font-face {
font-family: "Anton"; font-family: "Anton";
src: url("../fonts/Anton-Regular.ttf") format("truetype"); src: url("../fonts/Anton-Regular.ttf") format("truetype");

View file

@ -1258,3 +1258,24 @@ body:has(.oasis-nav-side-toggle) { padding-top: 84px !important; }
align-items: center !important; align-items: center !important;
justify-content: center !important; justify-content: center !important;
} }
/* Skins y workflows en Ajustes (views/settings_view.js): tarjetas de un toque */
.skin-pick { display: grid !important; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin: 0; }
.skin-card {
display: flex !important; flex-direction: column; align-items: stretch; gap: 8px;
width: 100% !important; height: auto !important; min-height: 0 !important; margin: 0 !important; padding: 8px !important;
background: #1c1c1c !important; color: #e6e6e6 !important;
border: 1px solid #444 !important; border-radius: 16px !important; cursor: pointer;
}
.skin-card .skin-shot { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; object-position: top; border-radius: 10px; display: block; }
.skin-card .skin-name { font-size: 17px; font-weight: 700; text-align: center; }
.skin-card.is-current { border: 2px solid #FFD700 !important; background: #2a2412 !important; }
.skin-card.is-current .skin-name::after { content: " \2713"; }
.workflow-pick { display: flex !important; flex-direction: column; gap: 10px; margin: 0; }
.workflow-card {
width: 100% !important; min-height: 56px !important; margin: 0 !important; padding: 10px 16px !important;
font-size: 18px !important; text-align: left !important;
background: #1c1c1c !important; color: #e6e6e6 !important; border: 1px solid #444 !important; border-radius: 14px !important;
}
.workflow-card.is-current { border: 2px solid #FFD700 !important; background: #2a2412 !important; color: #FFD700 !important; }
.workflow-card.is-current::after { content: " \2713"; }

View file

@ -17,6 +17,9 @@
module.exports = { module.exports = {
en: { en: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Pick how Oasis looks on your phone. It applies as soon as you tap it.",
workflowsDescriptionMobile: "A workflow sets which modules are on. On the phone your skin stays as it is.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "This image could not be cleaned of its metadata (location, camera…), so it has not been uploaded. Save it as JPEG or PNG and try again.", imageMetadataUnsafe: "This image could not be cleaned of its metadata (location, camera…), so it has not been uploaded. Save it as JPEG or PNG and try again.",
// Karvan // Karvan
@ -82,6 +85,9 @@ module.exports = {
spreadMore: "more" spreadMore: "more"
}, },
es: { es: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Elige cómo se ve Oasis en tu móvil. Se aplica al tocarlo.",
workflowsDescriptionMobile: "Un workflow fija qué módulos están activos. En el móvil tu skin se queda como está.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "No se han podido quitar los metadatos de esta imagen (ubicación, cámara…), así que no se ha subido. Guárdala como JPEG o PNG y vuelve a intentarlo.", imageMetadataUnsafe: "No se han podido quitar los metadatos de esta imagen (ubicación, cámara…), así que no se ha subido. Guárdala como JPEG o PNG y vuelve a intentarlo.",
// Karvan // Karvan
@ -153,6 +159,9 @@ module.exports = {
totalspreads: "Réplicas totales" totalspreads: "Réplicas totales"
}, },
fr: { fr: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Choisis l'apparence d'Oasis sur ton téléphone. Elle s'applique dès que tu touches.",
workflowsDescriptionMobile: "Un workflow fixe les modules actifs. Sur le téléphone, ton thème ne change pas.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Impossible de retirer les métadonnées de cette image (position, appareil…), elle n'a donc pas été envoyée. Enregistrez-la en JPEG ou PNG et réessayez.", imageMetadataUnsafe: "Impossible de retirer les métadonnées de cette image (position, appareil…), elle n'a donc pas été envoyée. Enregistrez-la en JPEG ou PNG et réessayez.",
// Karvan // Karvan
@ -218,6 +227,9 @@ module.exports = {
spreadMore: "plus" spreadMore: "plus"
}, },
eu: { eu: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Aukeratu nolakoa den Oasis zure mugikorrean. Ukitu bezain laster aplikatzen da.",
workflowsDescriptionMobile: "Workflow batek zein modulu dauden aktibo finkatzen du. Mugikorrean zure itxura ez da aldatzen.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Ezin izan dira irudi honen metadatuak kendu (kokapena, kamera…), beraz ez da igo. Gorde JPEG edo PNG gisa eta saiatu berriro.", imageMetadataUnsafe: "Ezin izan dira irudi honen metadatuak kendu (kokapena, kamera…), beraz ez da igo. Gorde JPEG edo PNG gisa eta saiatu berriro.",
// Karvan // Karvan
@ -283,6 +295,9 @@ module.exports = {
spreadMore: "gehiago" spreadMore: "gehiago"
}, },
de: { de: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Wähle, wie Oasis auf deinem Handy aussieht. Es wird beim Antippen übernommen.",
workflowsDescriptionMobile: "Ein Workflow legt fest, welche Module aktiv sind. Auf dem Handy bleibt dein Skin, wie er ist.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Die Metadaten dieses Bildes (Standort, Kamera…) konnten nicht entfernt werden, daher wurde es nicht hochgeladen. Speichere es als JPEG oder PNG und versuche es erneut.", imageMetadataUnsafe: "Die Metadaten dieses Bildes (Standort, Kamera…) konnten nicht entfernt werden, daher wurde es nicht hochgeladen. Speichere es als JPEG oder PNG und versuche es erneut.",
// Karvan // Karvan
@ -348,6 +363,9 @@ module.exports = {
spreadMore: "mehr" spreadMore: "mehr"
}, },
it: { it: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Scegli come appare Oasis sul tuo telefono. Si applica appena lo tocchi.",
workflowsDescriptionMobile: "Un workflow stabilisce quali moduli sono attivi. Sul telefono la tua skin resta com'è.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Non è stato possibile rimuovere i metadati di questa immagine (posizione, fotocamera…), quindi non è stata caricata. Salvala come JPEG o PNG e riprova.", imageMetadataUnsafe: "Non è stato possibile rimuovere i metadati di questa immagine (posizione, fotocamera…), quindi non è stata caricata. Salvala come JPEG o PNG e riprova.",
// Karvan // Karvan
@ -413,6 +431,9 @@ module.exports = {
spreadMore: "altro" spreadMore: "altro"
}, },
pt: { pt: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Escolhe como o Oasis aparece no teu telemóvel. Aplica-se ao tocar.",
workflowsDescriptionMobile: "Um workflow define que módulos estão ativos. No telemóvel o teu tema fica como está.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Não foi possível remover os metadados desta imagem (localização, câmara…), por isso não foi enviada. Guarda-a como JPEG ou PNG e tenta de novo.", imageMetadataUnsafe: "Não foi possível remover os metadados desta imagem (localização, câmara…), por isso não foi enviada. Guarda-a como JPEG ou PNG e tenta de novo.",
// Karvan // Karvan
@ -478,6 +499,9 @@ module.exports = {
spreadMore: "mais" spreadMore: "mais"
}, },
zh: { zh: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "选择 Oasis 在手机上的外观。点一下就会生效。",
workflowsDescriptionMobile: "工作流决定启用哪些模块。在手机上,你的外观保持不变。",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "无法清除这张图片的元数据(位置、相机等),因此没有上传。请另存为 JPEG 或 PNG 后重试。", imageMetadataUnsafe: "无法清除这张图片的元数据(位置、相机等),因此没有上传。请另存为 JPEG 或 PNG 后重试。",
// Karvan // Karvan
@ -543,6 +567,9 @@ module.exports = {
spreadMore: "更多" spreadMore: "更多"
}, },
ar: { ar: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "اختر مظهر Oasis على هاتفك. يُطبَّق بمجرد اللمس.",
workflowsDescriptionMobile: "يحدد سير العمل الوحدات المفعّلة. على الهاتف يبقى مظهرك كما هو.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "تعذّر إزالة البيانات الوصفية من هذه الصورة (الموقع، الكاميرا…)، لذلك لم تُرفع. احفظها بصيغة JPEG أو PNG وحاول مجددًا.", imageMetadataUnsafe: "تعذّر إزالة البيانات الوصفية من هذه الصورة (الموقع، الكاميرا…)، لذلك لم تُرفع. احفظها بصيغة JPEG أو PNG وحاول مجددًا.",
// Karvan // Karvan
@ -608,6 +635,9 @@ module.exports = {
spreadMore: "المزيد" spreadMore: "المزيد"
}, },
hi: { hi: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "चुनें कि आपके फ़ोन पर Oasis कैसा दिखे। छूते ही लागू हो जाता है।",
workflowsDescriptionMobile: "वर्कफ़्लो तय करता है कि कौन-से मॉड्यूल चालू हैं। फ़ोन पर आपकी स्किन वैसी ही रहती है।",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "इस छवि का मेटाडेटा (स्थान, कैमरा…) हटाया नहीं जा सका, इसलिए इसे अपलोड नहीं किया गया। इसे JPEG या PNG के रूप में सहेजें और फिर कोशिश करें।", imageMetadataUnsafe: "इस छवि का मेटाडेटा (स्थान, कैमरा…) हटाया नहीं जा सका, इसलिए इसे अपलोड नहीं किया गया। इसे JPEG या PNG के रूप में सहेजें और फिर कोशिश करें।",
// Karvan // Karvan
@ -673,6 +703,9 @@ module.exports = {
spreadMore: "और" spreadMore: "और"
}, },
ru: { ru: {
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Выберите, как Oasis выглядит на телефоне. Применяется сразу по нажатию.",
workflowsDescriptionMobile: "Рабочий процесс задаёт, какие модули включены. На телефоне ваше оформление не меняется.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Не удалось удалить метаданные этого изображения (местоположение, камера…), поэтому оно не загружено. Сохраните его как JPEG или PNG и попробуйте снова.", imageMetadataUnsafe: "Не удалось удалить метаданные этого изображения (местоположение, камера…), поэтому оно не загружено. Сохраните его как JPEG или PNG и попробуйте снова.",
// Karvan // Karvan

View file

@ -89,10 +89,14 @@ const WORKFLOWS = [
const WORKFLOW_KEYS = WORKFLOWS.map(w => w.key); const WORKFLOW_KEYS = WORKFLOWS.map(w => w.key);
const isMobile = () => process.env.OASIS_MOBILE === '1'; const isMobile = () => process.env.OASIS_MOBILE === '1';
// en el movil todos los workflows llevan el tema Acampada; quien venga de OasisMobile // en el movil el workflow no toca el skin: se queda el que haya elegido cada cual
// sigue reconociendo su workflow (Acampada es OasisMobile con otros colores) // (Acampada u OasisMobile); si no hay ninguno de movil, Acampada
const MOBILE_THEMES = ['Acampada', 'OasisMobile']; const MOBILE_THEMES = ['Acampada', 'OasisMobile'];
const themeOf = (workflow) => (isMobile() ? 'Acampada' : workflow.theme); const mobileSkin = (cfg) => {
const cur = cfg && cfg.themes && cfg.themes.current;
return MOBILE_THEMES.includes(cur) ? cur : 'Acampada';
};
const themeOf = (workflow, cfg) => (isMobile() ? mobileSkin(cfg) : workflow.theme);
const sameTheme = (theme, workflow) => (isMobile() ? MOBILE_THEMES.includes(theme) : theme === workflow.theme); const sameTheme = (theme, workflow) => (isMobile() ? MOBILE_THEMES.includes(theme) : theme === workflow.theme);
const getWorkflow = (key) => WORKFLOWS.find(w => w.key === String(key || '')) || null; const getWorkflow = (key) => WORKFLOWS.find(w => w.key === String(key || '')) || null;
@ -117,7 +121,7 @@ const applyWorkflow = (cfg, workflow) => {
const enabled = new Set(modulesOf(workflow)); const enabled = new Set(modulesOf(workflow));
cfg.modules = cfg.modules || {}; cfg.modules = cfg.modules || {};
ALL_MODULES.forEach(mod => { cfg.modules[`${mod}Mod`] = enabled.has(mod) ? 'on' : 'off'; }); ALL_MODULES.forEach(mod => { cfg.modules[`${mod}Mod`] = enabled.has(mod) ? 'on' : 'off'; });
if (workflow.theme) cfg.themes = { ...(cfg.themes || {}), current: themeOf(workflow) }; if (workflow.theme) cfg.themes = { ...(cfg.themes || {}), current: themeOf(workflow, cfg) };
if (workflow.homePage) cfg.homePage = workflow.homePage; if (workflow.homePage) cfg.homePage = workflow.homePage;
return cfg; return cfg;
}; };

View file

@ -438,9 +438,17 @@ exports.CONTENT_SPREADABLE = CONTENT_SPREADABLE;
exports.CONTENT_TORRENTABLE = CONTENT_TORRENTABLE; exports.CONTENT_TORRENTABLE = CONTENT_TORRENTABLE;
exports.contentDeleteAction = contentDeleteAction; exports.contentDeleteAction = contentDeleteAction;
exports.THEMES = [['Acampada', 'Acampada'], ['Dark-SNH', 'Dark-SNH'], ['Clear-SNH', 'Clear-SNH'], ['Purple-SNH', 'Purple-SNH'], ['Matrix-SNH', 'Matrix-SNH'], ['OasisMobile', 'Oasis-Mobile']]; exports.THEMES = [['Acampada', 'Acampada'], ['Dark-SNH', 'Dark-SNH'], ['Clear-SNH', 'Clear-SNH'], ['Purple-SNH', 'Purple-SNH'], ['Matrix-SNH', 'Matrix-SNH'], ['OasisMobile', 'Oasis-Mobile']];
// Acampada importa la maqueta de OasisMobile.css: los dos son solo de movil // Acampada importa la maqueta de OasisMobile.css: los dos son solo de movil, y en el
exports.WIZARD_THEMES = exports.THEMES.filter(([value]) => value !== 'OasisMobile' && value !== 'Acampada'); // movil son los unicos que valen (los de escritorio no traen la maqueta)
// con el tema Acampada, hive_acampada.css va detras del tema: pinta lanzador, barras y tarjetas exports.MOBILE_THEMES = [['Acampada', 'Acampada'], ['OasisMobile', 'Oasis Mobile']];
exports.WIZARD_THEMES = process.env.OASIS_MOBILE === '1'
? exports.MOBILE_THEMES
: exports.THEMES.filter(([value]) => value !== 'OasisMobile' && value !== 'Acampada');
// el tema Acampada es la maqueta de OasisMobile.css con otros colores. OasisMobile.css va
// en su propio <link> versionado y no como @import dentro de Acampada.css: un @import sin
// ?v= se queda en la cache del WebView y tras actualizar se veia la maqueta vieja.
// hive_acampada.css va detras del tema: pinta lanzador, barras y tarjetas.
const acampadaBase = (theme) => theme === 'Acampada' ? link({ rel: "stylesheet", href: `/assets/themes/OasisMobile.css?v=${assetVersion()}` }) : null;
const acampadaLink = (theme) => theme === 'Acampada' ? link({ rel: "stylesheet", href: `/assets/styles/hive_acampada.css?v=${assetVersion()}` }) : null; const acampadaLink = (theme) => theme === 'Acampada' ? link({ rel: "stylesheet", href: `/assets/styles/hive_acampada.css?v=${assetVersion()}` }) : null;
const renderDocumentActions = (kind, id, leadingNodes = []) => { const renderDocumentActions = (kind, id, leadingNodes = []) => {
@ -2006,7 +2014,7 @@ const template = (titlePrefix, ...elements) => {
// movil: el tema va DESPUES de mobile.css para ganar por cascada sin !important; // movil: el tema va DESPUES de mobile.css para ganar por cascada sin !important;
// escritorio: orden original de epsylon // escritorio: orden original de epsylon
...(process.env.OASIS_MOBILE === '1' ...(process.env.OASIS_MOBILE === '1'
? [ link({ rel: "stylesheet", href: `/assets/styles/mobile.css?v=${assetVersion()}` }), themeLink, acampadaLink(theme) ] ? [ link({ rel: "stylesheet", href: `/assets/styles/mobile.css?v=${assetVersion()}` }), acampadaBase(theme), themeLink, acampadaLink(theme) ]
: [ themeLink, link({ rel: "stylesheet", href: `/assets/styles/mobile.css?v=${assetVersion()}`, media: "(max-width: 768px)" }) ]), : [ themeLink, link({ rel: "stylesheet", href: `/assets/styles/mobile.css?v=${assetVersion()}`, media: "(max-width: 768px)" }) ]),
// el modulo Karvan trae su propia hoja: asi se ve igual en cualquier tema // el modulo Karvan trae su propia hoja: asi se ve igual en cualquier tema
// y tambien en escritorio, donde no se carga OasisMobile.css // y tambien en escritorio, donde no se carga OasisMobile.css
@ -2395,7 +2403,7 @@ exports.ainavHomeView = ({ recentTags = [] } = {}) => {
// movil: el tema va DESPUES de mobile.css para ganar por cascada sin !important; // movil: el tema va DESPUES de mobile.css para ganar por cascada sin !important;
// escritorio: orden original de epsylon // escritorio: orden original de epsylon
...(process.env.OASIS_MOBILE === '1' ...(process.env.OASIS_MOBILE === '1'
? [ link({ rel: "stylesheet", href: `/assets/styles/mobile.css?v=${assetVersion()}` }), link({ rel: "stylesheet", href: `/assets/themes/${theme}.css?v=${assetVersion()}` }), acampadaLink(theme) ] ? [ link({ rel: "stylesheet", href: `/assets/styles/mobile.css?v=${assetVersion()}` }), acampadaBase(theme), link({ rel: "stylesheet", href: `/assets/themes/${theme}.css?v=${assetVersion()}` }), acampadaLink(theme) ]
: [ link({ rel: "stylesheet", href: `/assets/themes/${theme}.css?v=${assetVersion()}` }), link({ rel: "stylesheet", href: `/assets/styles/mobile.css?v=${assetVersion()}`, media: "(max-width: 768px)" }) ]), : [ link({ rel: "stylesheet", href: `/assets/themes/${theme}.css?v=${assetVersion()}` }), link({ rel: "stylesheet", href: `/assets/styles/mobile.css?v=${assetVersion()}`, media: "(max-width: 768px)" }) ]),
// el modulo Karvan trae su propia hoja: asi se ve igual en cualquier tema // el modulo Karvan trae su propia hoja: asi se ve igual en cualquier tema
// y tambien en escritorio, donde no se carga OasisMobile.css // y tambien en escritorio, donde no se carga OasisMobile.css

View file

@ -2,7 +2,7 @@ const { form, button, div, h2, h3, p, section, select, option, input, br, a, lab
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { getConfig } = require('../configs/config-manager.js'); const { getConfig } = require('../configs/config-manager.js');
const { template, selectedLanguage, i18n, setLanguage, INBOX_BOT_ORDER, inboxBotLabel, THEMES, userLink } = require('./main_views'); const { template, selectedLanguage, i18n, setLanguage, INBOX_BOT_ORDER, inboxBotLabel, THEMES, MOBILE_THEMES, userLink } = require('./main_views');
const i18nBase = require("../client/assets/translations/i18n"); const i18nBase = require("../client/assets/translations/i18n");
const moment = require("../server/node_modules/moment"); const moment = require("../server/node_modules/moment");
const { WORKFLOWS, currentWorkflow } = require('../models/workflows_model'); const { WORKFLOWS, currentWorkflow } = require('../models/workflows_model');
@ -58,7 +58,26 @@ const settingsView = (params) => {
const modOn = (name) => (currentConfig.modules || {})[`${name}Mod`] === 'on'; const modOn = (name) => (currentConfig.modules || {})[`${name}Mod`] === 'on';
const isMobile = process.env.OASIS_MOBILE === '1'; const isMobile = process.env.OASIS_MOBILE === '1';
const workflowSection = section({ id: "workflows" }, // movil: skins y workflows como tarjetas que se aplican al tocarlas (un boton
// de envio por opcion); el desplegable de escritorio quedaba enterrado y dejaba
// poner temas de escritorio, que en el movil se quedan sin maqueta
const skinPicker = () => section({ id: "theme" },
div({ class: "tags-header" }, h2(i18n.theme), p(i18n.skinIntroMobile)),
form({ action: "/settings/theme", method: "post", class: "skin-pick" },
...MOBILE_THEMES.map(([value, name]) => button({ type: "submit", name: "theme", value, class: theme === value ? "skin-card is-current" : "skin-card" },
img({ src: `/assets/images/theme-${value.toLowerCase()}.png`, alt: "", class: "skin-shot" }),
span({ class: "skin-name" }, name)))
)
);
const workflowPicker = () => section({ id: "workflows" },
div({ class: "tags-header" }, h2(i18n.workflowsTitle), p(i18n.workflowsDescriptionMobile)),
form({ action: "/settings/workflow", method: "POST", class: "workflow-pick" },
...WORKFLOWS.map(w => button({ type: "submit", name: "workflow", value: w.key, class: activeWorkflow === w.key ? "workflow-card is-current" : "workflow-card" },
i18n[`workflow_${w.key}`] || w.key))
)
);
const workflowSection = isMobile ? workflowPicker() : section({ id: "workflows" },
div({ class: "tags-header" }, div({ class: "tags-header" },
h2(i18n.workflowsTitle), h2(i18n.workflowsTitle),
p(i18n.workflowsDescription), p(i18n.workflowsDescription),
@ -181,7 +200,7 @@ const settingsView = (params) => {
) )
) )
), ),
section({ id: "theme" }, isMobile ? skinPicker() : section({ id: "theme" },
div({ class: "tags-header" }, div({ class: "tags-header" },
h2(i18n.theme), h2(i18n.theme),
p(i18n.themeIntro), p(i18n.themeIntro),