activistas: workflow por defecto, lanzador compacto y barra de 4 atajos

Con el workflow activistas caben todos los modulos en una pantalla: se
quitan el filtro Personal/Social y los accesos de usuario avanzado
(menciones, habitantes, perfil, CV, estadisticas, blockexplorer,
modulos). Peers y la edicion de la barra pasan a Herramientas; la barra
inferior se queda en los 4 atajos. La config de serie arranca ya con
los modulos de activistas.
This commit is contained in:
oasis-bot 2026-10-18 23:54:54 +02:00
parent e01f718c1c
commit ab9bfab09a
4 changed files with 68 additions and 64 deletions

View file

@ -50,7 +50,7 @@ body { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }
background: #121212; background: #121212;
border-bottom: 1px solid #333; border-bottom: 1px solid #333;
} }
body { padding-top: 84px; background: #121212; } body { padding-top: 74px; background: #121212; }
.oasis-mobile-topbar .omt-logo, .oasis-mobile-topbar .omt-avatar { flex: 0 0 auto; } .oasis-mobile-topbar .omt-logo, .oasis-mobile-topbar .omt-avatar { flex: 0 0 auto; }
.oasis-mobile-topbar .omt-logo img, .oasis-mobile-topbar .omt-logo img,
@ -972,10 +972,10 @@ button, input[type="submit"], input[type="button"],
/* (topbar sin barra de búsqueda: vuelve el título "OASIS" — CSS .omt-title más arriba) */ /* (topbar sin barra de búsqueda: vuelve el título "OASIS" — CSS .omt-title más arriba) */
/* --- el lanzador va en el header (debajo de los 2 botones), solo en la home --- */ /* --- el lanzador va en el header (debajo de los 2 botones), solo en la home --- */
.header .launcher { width: 100%; max-width: 440px; box-sizing: border-box; margin: 34px auto 10px; padding: 0 14px; } .header .launcher { width: 100%; max-width: 440px; box-sizing: border-box; margin: 4px auto 10px; padding: 0 14px; }
/* holgura bajo la topbar fija */ /* holgura bajo la topbar fija */
body { padding-top: 84px; } body { padding-top: 74px; }
/* ========================================================================== /* ==========================================================================
FORK_IA_UX · Módulo KARVAN (mensajes temporales + WebRTC) — chat estilo burbujas FORK_IA_UX · Módulo KARVAN (mensajes temporales + WebRTC) — chat estilo burbujas

View file

@ -7,63 +7,63 @@
}, },
"modules": { "modules": {
"blogsMod": "on", "blogsMod": "on",
"pollsMod": "on", "pollsMod": "off",
"fediverseMod": "on", "fediverseMod": "off",
"invitesMod": "on", "invitesMod": "on",
"walletMod": "off", "walletMod": "off",
"devMod": "off", "devMod": "off",
"cipherMod": "on", "cipherMod": "off",
"bookmarksMod": "on", "bookmarksMod": "off",
"videosMod": "on", "videosMod": "on",
"docsMod": "off", "docsMod": "off",
"audiosMod": "on", "audiosMod": "off",
"tagsMod": "on", "tagsMod": "off",
"imagesMod": "on", "imagesMod": "on",
"trendingMod": "on", "trendingMod": "off",
"eventsMod": "on", "eventsMod": "off",
"tasksMod": "on", "tasksMod": "off",
"marketMod": "on", "marketMod": "off",
"votesMod": "on", "votesMod": "off",
"tribesMod": "on", "tribesMod": "off",
"reportsMod": "on", "reportsMod": "off",
"opinionsMod": "on", "opinionsMod": "off",
"padsMod": "on", "padsMod": "on",
"karvanMod": "on", "karvanMod": "on",
"calendarsMod": "on", "calendarsMod": "off",
"transfersMod": "off", "transfersMod": "off",
"feedMod": "on", "feedMod": "on",
"pixeliaMod": "off", "pixeliaMod": "off",
"melodyMod": "on", "melodyMod": "off",
"agendaMod": "on", "agendaMod": "off",
"aiMod": "off", "aiMod": "off",
"aiNavMod": "off", "aiNavMod": "off",
"forumMod": "on", "forumMod": "on",
"gamesMod": "off", "gamesMod": "off",
"housingMod": "on", "housingMod": "off",
"jobsMod": "on", "jobsMod": "off",
"shopsMod": "on", "shopsMod": "off",
"projectsMod": "on", "projectsMod": "off",
"industryMod": "on", "industryMod": "off",
"bankingMod": "off", "bankingMod": "off",
"schoolMod": "on", "schoolMod": "off",
"parliamentMod": "on", "parliamentMod": "off",
"courtsMod": "off", "courtsMod": "off",
"favoritesMod": "on", "favoritesMod": "off",
"logsMod": "off", "logsMod": "off",
"mapsMod": "off", "mapsMod": "off",
"chatsMod": "on", "chatsMod": "on",
"torrentsMod": "off", "torrentsMod": "off",
"filesMod": "on", "filesMod": "off",
"phoneMod": "on", "phoneMod": "off",
"roomsMod": "on", "roomsMod": "off",
"graphosMod": "on", "graphosMod": "off",
"larpMod": "on", "larpMod": "off",
"backupMod": "on", "backupMod": "on",
"campaignsMod": "on", "campaignsMod": "off",
"emergenciesMod": "on", "emergenciesMod": "off",
"logisticsMod": "on", "logisticsMod": "off",
"mailingMod": "on", "mailingMod": "off",
"podcastsMod": "on", "podcastsMod": "off",
"wikiMod": "on" "wikiMod": "on"
}, },
"wallet": { "wallet": {
@ -96,10 +96,10 @@
"pubMaxMB": 0 "pubMaxMB": 0
}, },
"bottomBarPins": [ "bottomBarPins": [
"search", "activity",
"inbox", "chats",
"publish", "publish",
"activity" "inbox"
], ],
"rtc": { "rtc": {
"stun": [], "stun": [],

View file

@ -120,7 +120,7 @@ const applyWorkflow = (cfg, workflow) => {
const FULL_WORKFLOW = { key: 'full', modules: ALL_MODULES }; const FULL_WORKFLOW = { key: 'full', modules: ALL_MODULES };
const WIZARD_WORKFLOWS = ['full', 'social', 'activists', 'kids', 'night', 'jobs', 'business', 'mobile']; const WIZARD_WORKFLOWS = ['activists', 'full', 'social', 'kids', 'night', 'jobs', 'business', 'mobile'];
const wizardWorkflow = (key) => { const wizardWorkflow = (key) => {
const k = String(key || ''); const k = String(key || '');

View file

@ -11,6 +11,10 @@ const { a, button, div, form, h2, h3, img, input, label, nav, p, section, span }
const { getConfig } = require("../configs/config-manager.js"); const { getConfig } = require("../configs/config-manager.js");
const sharedState = require("../configs/shared-state"); const sharedState = require("../configs/shared-state");
// con pocos modulos activos (el workflow activistas) todo cabe en una pantalla:
// sobran el filtro Personal/Social y los accesos de usuario avanzado
const COMPACT_MAX = 16;
module.exports = ({ i18n }) => { module.exports = ({ i18n }) => {
// === Oasis UX (portado de 0.8.7_UX): topbar + bottombar + lanzador === // === Oasis UX (portado de 0.8.7_UX): topbar + bottombar + lanzador ===
// topbar fija arriba: [logo] [Personal] [Community] [avatar] en una línea (sin título OASIS) // topbar fija arriba: [logo] [Personal] [Community] [avatar] en una línea (sin título OASIS)
@ -23,7 +27,7 @@ module.exports = ({ i18n }) => {
return div( return div(
{ class: "oasis-mobile-topbar" }, { class: "oasis-mobile-topbar" },
a({ class: "omt-logo", href: "/" }, img({ src: "/assets/images/snh-oasis.jpg", alt: "Oasis" })), a({ class: "omt-logo", href: "/" }, img({ src: "/assets/images/snh-oasis.jpg", alt: "Oasis" })),
div({ class: "omt-menus" }, isCompact() ? div({ class: "omt-menus" }) : div({ class: "omt-menus" },
a({ class: hiveFilter === "personal" ? "oasis-menu-btn active" : "oasis-menu-btn", href: hiveFilter === "personal" ? "/activity" : "/activity?hive=personal" }, span(i18n.menuPersonal || "Personal")), a({ class: hiveFilter === "personal" ? "oasis-menu-btn active" : "oasis-menu-btn", href: hiveFilter === "personal" ? "/activity" : "/activity?hive=personal" }, span(i18n.menuPersonal || "Personal")),
a({ class: hiveFilter === "community" ? "oasis-menu-btn active" : "oasis-menu-btn", href: hiveFilter === "community" ? "/activity" : "/activity?hive=community" }, span(i18n.menuSocial || "Social")) a({ class: hiveFilter === "community" ? "oasis-menu-btn active" : "oasis-menu-btn", href: hiveFilter === "community" ? "/activity" : "/activity?hive=community" }, span(i18n.menuSocial || "Social"))
), ),
@ -96,8 +100,8 @@ module.exports = ({ i18n }) => {
(badge && badge > 0) ? span({ class: "bb-badge" }, String(badge)) : "", (badge && badge > 0) ? span({ class: "bb-badge" }, String(badge)) : "",
span({ class: "bb-lbl" }, label) span({ class: "bb-lbl" }, label)
); );
// FORK_IA_UX v4: barra PERSONALIZABLE (pins) + lápiz ✎ para editar (/settings/bottombar) // barra PERSONALIZABLE: solo los pins (max 4). Editarla y Peers estan en el
// + par FIJO Peers/Invites a la derecha. Sin FAB "+". (restaurada de la versión que gustaba) // lanzador (Herramientas): 7 botones abajo eran demasiados para un pulgar.
const MAX = 4; const MAX = 4;
const pins = (cfg.bottomBarPins || []) const pins = (cfg.bottomBarPins || [])
.map(key => PINNABLE_MODULES.find(m => m.key === key)) .map(key => PINNABLE_MODULES.find(m => m.key === key))
@ -106,18 +110,9 @@ module.exports = ({ i18n }) => {
const slots = pins.map(m => bbLink( const slots = pins.map(m => bbLink(
m.href, m.glyph, i18n[m.labelKey] || m.key, m.key === 'inbox' ? inboxN : 0 m.href, m.glyph, i18n[m.labelKey] || m.key, m.key === 'inbox' ? inboxN : 0
)); ));
const editSlot = a(
{ class: "bb-item bb-add", href: "/settings/bottombar" },
span({ class: "bb-ico" }, "✎"),
span({ class: "bb-lbl" }, i18n.bbManage || "Edit")
);
const pair = [ bbLink("/peers", "⧖", i18n.peers || "Peers") ];
if (modOn('invitesMod')) pair.push(bbLink("/invites", "ꔮ", i18n.invites || "Invites"));
return nav( return nav(
{ class: "oasis-bottombar", attrs: { "aria-label": i18n.bbQuickActions || "Quick actions" } }, { class: "oasis-bottombar", attrs: { "aria-label": i18n.bbQuickActions || "Quick actions" } },
...slots, ...slots
editSlot,
div({ class: "bb-pair" }, ...pair)
); );
}; };
@ -136,12 +131,12 @@ module.exports = ({ i18n }) => {
{ href: '/wiki', glyph: 'ꖿ', labelKey: 'wikiTitle', mod: 'wikiMod' }, { href: '/wiki', glyph: 'ꖿ', labelKey: 'wikiTitle', mod: 'wikiMod' },
{ href: '/blogs', glyph: 'ꔫ', labelKey: 'blogTitle', mod: 'blogsMod' }, { href: '/blogs', glyph: 'ꔫ', labelKey: 'blogTitle', mod: 'blogsMod' },
{ href: '/opinions', glyph: 'ꔍ', labelKey: 'opinionsTitle', mod: 'opinionsMod' }, { href: '/opinions', glyph: 'ꔍ', labelKey: 'opinionsTitle', mod: 'opinionsMod' },
{ href: '/mentions', glyph: '✺', labelKey: 'mentions', mod: null }, { href: '/mentions', glyph: '✺', labelKey: 'mentions', mod: null, extra: true },
{ href: '/tags', glyph: 'ꖶ', labelKey: 'tagsLabel', mod: 'tagsMod' }, { href: '/tags', glyph: 'ꖶ', labelKey: 'tagsLabel', mod: 'tagsMod' },
{ href: '/trending', glyph: 'ꗝ', labelKey: 'trendingLabel', mod: 'trendingMod' }, { href: '/trending', glyph: 'ꗝ', labelKey: 'trendingLabel', mod: 'trendingMod' },
{ href: '/maps', glyph: 'ꔌ', labelKey: 'mapsLabel', mod: 'mapsMod' }, { href: '/maps', glyph: 'ꔌ', labelKey: 'mapsLabel', mod: 'mapsMod' },
{ href: '/graphos', glyph: '⌬', labelKey: 'modulesGraphosLabel', mod: 'graphosMod' }, { href: '/graphos', glyph: '⌬', labelKey: 'modulesGraphosLabel', mod: 'graphosMod' },
{ href: '/inhabitants', glyph: 'ꖘ', labelKey: 'inhabitantsLabel', mod: null }, { href: '/inhabitants', glyph: 'ꖘ', labelKey: 'inhabitantsLabel', mod: null, extra: true },
{ href: '/fediverse', glyph: 'ꗵ', labelKey: 'fediverseTimeline', mod: 'fediverseMod' } ] }, { href: '/fediverse', glyph: 'ꗵ', labelKey: 'fediverseTimeline', mod: 'fediverseMod' } ] },
{ id: 'media', titleKey: 'menuMedia', side: 'community', mods: [ { id: 'media', titleKey: 'menuMedia', side: 'community', mods: [
{ href: '/images', glyph: 'ꕥ', labelKey: 'imagesLabel', mod: 'imagesMod' }, { href: '/images', glyph: 'ꕥ', labelKey: 'imagesLabel', mod: 'imagesMod' },
@ -182,36 +177,45 @@ module.exports = ({ i18n }) => {
{ href: '/banking', glyph: 'ꗴ', labelKey: 'bankingTitle', mod: 'bankingMod' }, { href: '/banking', glyph: 'ꗴ', labelKey: 'bankingTitle', mod: 'bankingMod' },
{ href: '/transfers', glyph: 'ꘉ', labelKey: 'transfersTitle', mod: 'transfersMod' } ] }, { href: '/transfers', glyph: 'ꘉ', labelKey: 'transfersTitle', mod: 'transfersMod' } ] },
{ id: 'personal', titleKey: 'menuPersonal', side: 'personal', mods: [ { id: 'personal', titleKey: 'menuPersonal', side: 'personal', mods: [
{ href: '/profile', glyph: '⚉', labelKey: 'profile', mod: null }, { href: '/profile', glyph: '⚉', labelKey: 'profile', mod: null, extra: true },
{ href: '/agenda', glyph: 'ꗤ', labelKey: 'agendaTitle', mod: 'agendaMod' }, { href: '/agenda', glyph: 'ꗤ', labelKey: 'agendaTitle', mod: 'agendaMod' },
{ href: '/favorites', glyph: 'ꘝ', labelKey: 'favoritesTitle', mod: 'favoritesMod' }, { href: '/favorites', glyph: 'ꘝ', labelKey: 'favoritesTitle', mod: 'favoritesMod' },
{ href: '/phone', glyph: '☏', labelKey: 'phoneTitle', mod: 'phoneMod' }, { href: '/phone', glyph: '☏', labelKey: 'phoneTitle', mod: 'phoneMod' },
{ href: '/cv', glyph: 'ꕛ', labelKey: 'cvTitle', mod: null }, { href: '/cv', glyph: 'ꕛ', labelKey: 'cvTitle', mod: null, extra: true },
{ href: '/wallet', glyph: '❄', labelKey: 'wallet', mod: 'walletMod' }, { href: '/wallet', glyph: '❄', labelKey: 'wallet', mod: 'walletMod' },
{ href: '/logs', glyph: 'ꗯ', labelKey: 'logsTitle', mod: 'logsMod' } ] }, { href: '/logs', glyph: 'ꗯ', labelKey: 'logsTitle', mod: 'logsMod' } ] },
{ id: 'tools', titleKey: 'menuTools', side: 'personal', mods: [ { id: 'tools', titleKey: 'menuTools', side: 'personal', mods: [
{ href: '/invites', glyph: 'ꔹ', labelKey: 'invites', mod: 'invitesMod' }, { href: '/invites', glyph: 'ꔹ', labelKey: 'invites', mod: 'invitesMod' },
{ href: '/peers', glyph: '⧖', labelKey: 'peers', mod: null },
{ href: '/settings/bottombar', glyph: '✎', labelKey: 'bbYourBar', mod: null },
{ href: '/backup', glyph: 'ꖤ', labelKey: 'backupTitle', mod: 'backupMod' }, { href: '/backup', glyph: 'ꖤ', labelKey: 'backupTitle', mod: 'backupMod' },
{ href: '/cipher', glyph: 'ꗄ', labelKey: 'cipher', mod: 'cipherMod' }, { href: '/cipher', glyph: 'ꗄ', labelKey: 'cipher', mod: 'cipherMod' },
{ href: '/ai', glyph: 'ꘜ', labelKey: 'ai', mod: 'aiMod' }, { href: '/ai', glyph: 'ꘜ', labelKey: 'ai', mod: 'aiMod' },
{ href: '/stats', glyph: 'ꕷ', labelKey: 'statistics', mod: null }, { href: '/stats', glyph: 'ꕷ', labelKey: 'statistics', mod: null, extra: true },
{ href: '/blockexplorer', glyph: 'ꖸ', labelKey: 'blockchain', mod: null }, { href: '/blockexplorer', glyph: 'ꖸ', labelKey: 'blockchain', mod: null, extra: true },
{ href: '/modules', glyph: 'ꗣ', labelKey: 'modules', mod: null }, { href: '/modules', glyph: 'ꗣ', labelKey: 'modules', mod: null, extra: true },
{ href: '/settings', glyph: '⚙', labelKey: 'settings', mod: null } ] }, { href: '/settings', glyph: '⚙', labelKey: 'settings', mod: null } ] },
]; ];
const isCompact = () => {
const cfg = getConfig();
const on = (m) => m && cfg.modules[m] === 'on';
return GROUPS.reduce((n, g) => n + g.mods.filter(x => on(x.mod)).length, 0) <= COMPACT_MAX;
};
const renderHiveNav = () => { const renderHiveNav = () => {
if (process.env.OASIS_MOBILE !== '1') return ""; if (process.env.OASIS_MOBILE !== '1') return "";
const cfg = getConfig(); const cfg = getConfig();
const modOn = (m) => !m || cfg.modules[m] === 'on' || cfg.modules[m] === undefined; const modOn = (m) => !m || cfg.modules[m] === 'on' || cfg.modules[m] === undefined;
const compact = isCompact();
// Personal/Social de la topbar (lo pone el middleware desde ?hive=) parte el lanzador en dos // Personal/Social de la topbar (lo pone el middleware desde ?hive=) parte el lanzador en dos
const hiveFilter = (typeof global !== "undefined" && global.__OASIS_HIVE_FILTER__) || ""; const hiveFilter = compact ? "" : ((typeof global !== "undefined" && global.__OASIS_HIVE_FILTER__) || "");
const app = (m) => a({ class: 'ln-app', href: m.href }, const app = (m) => a({ class: 'ln-app', href: m.href },
span({ class: 'ln-ico', 'aria-hidden': 'true' }, m.glyph), span({ class: 'ln-ico', 'aria-hidden': 'true' }, m.glyph),
span({ class: 'ln-lbl' }, i18n[m.labelKey] || m.href.slice(1))); span({ class: 'ln-lbl' }, i18n[m.labelKey] || m.href.slice(1)));
const groups = GROUPS const groups = GROUPS
.filter(g => !hiveFilter || g.side === hiveFilter) .filter(g => !hiveFilter || g.side === hiveFilter)
.map(g => ({ g, mods: g.mods.filter(m => modOn(m.mod)) })) .map(g => ({ g, mods: g.mods.filter(m => modOn(m.mod) && !(compact && m.extra)) }))
.filter(x => x.mods.length); .filter(x => x.mods.length);
return nav({ class: 'launcher', 'aria-label': i18n.modules || 'Modules' }, return nav({ class: 'launcher', 'aria-label': i18n.modules || 'Modules' },
...groups.map(({ g, mods }) => div({ class: 'ln-group' }, ...groups.map(({ g, mods }) => div({ class: 'ln-group' },