interfaz: lanzador de modulos en lugar de los hexagonos
La portada ordena los modulos por secciones en una rejilla de iconos, como el cajon de apps del movil. Solo salen los modulos activos y las secciones que tienen alguno; Personal y Social de la topbar parten el lanzador en dos. Fuera los enlaces que ya no existen en 1.3.1 (/legacy, /public/latest/*) y dentro los modulos nuevos: wiki, rooms, emergencias, mailing, campanas... 1.3.1 trae en mobile.css su propio chrome movil (cabecera fija y cajones); se apaga desde el tema para que no se monte encima del de la rama.
This commit is contained in:
parent
a11a730c26
commit
5a04113330
2 changed files with 152 additions and 166 deletions
|
|
@ -42,7 +42,7 @@ body { overflow-x: clip; overflow-y: visible; }
|
||||||
|
|
||||||
body { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }
|
body { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }
|
||||||
|
|
||||||
/* topbar FIJA arriba: [logo] [Personal] [Community] [avatar]; el hive scrollea por debajo */
|
/* topbar FIJA arriba: [logo] [Personal] [Community] [avatar]; el lanzador scrollea por debajo */
|
||||||
.oasis-mobile-topbar {
|
.oasis-mobile-topbar {
|
||||||
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
|
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
|
||||||
display: flex; align-items: center; gap: 8px;
|
display: flex; align-items: center; gap: 8px;
|
||||||
|
|
@ -80,8 +80,8 @@ body { padding-top: 84px; background: #121212; }
|
||||||
|
|
||||||
/* ANULAR el "card" global de style.css `div{background:#222;border-radius:10px;box-shadow;padding:20px;margin-bottom:20px}`
|
/* ANULAR el "card" global de style.css `div{background:#222;border-radius:10px;box-shadow;padding:20px;margin-bottom:20px}`
|
||||||
en nuestro chrome móvil propio: era el 2º color (caja mas clara) detras de los botones,
|
en nuestro chrome móvil propio: era el 2º color (caja mas clara) detras de los botones,
|
||||||
la caja redondeada de la topbar y el fondo #222 detras de los hexagonos. */
|
la caja redondeada de la topbar y el fondo #222 detras del lanzador. */
|
||||||
.header, .hive-nav, .hive-grid, .hive-cats, .hive-row,
|
.header, .launcher, .ln-group, .ln-grid,
|
||||||
.oasis-mobile-topbar, .oasis-mobile-topbar .omt-menus {
|
.oasis-mobile-topbar, .oasis-mobile-topbar .omt-menus {
|
||||||
background-color: transparent; box-shadow: none; border-radius: 0;
|
background-color: transparent; box-shadow: none; border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +209,7 @@ body { overscroll-behavior: none; }
|
||||||
|
|
||||||
.main-content, .main-column, .header { overflow: visible; }
|
.main-content, .main-column, .header { overflow: visible; }
|
||||||
|
|
||||||
/* === Usabilidad 0.9.1: Personal/Community filtran el hive server-side (enlaces ?hive=) + desplegable FILTER === */
|
/* === Usabilidad 0.9.1: Personal/Community filtran el lanzador server-side (enlaces ?hive=) + desplegable FILTER === */
|
||||||
|
|
||||||
/* desplegable FILTER de la ristra de filtros de Activity (oculto por defecto) */
|
/* desplegable FILTER de la ristra de filtros de Activity (oculto por defecto) */
|
||||||
.activity-filter-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; margin: 0; }
|
.activity-filter-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; margin: 0; }
|
||||||
|
|
@ -252,77 +252,36 @@ body { overscroll-behavior: none; }
|
||||||
margin-top: 16px; min-height: 48px; line-height: 48px;
|
margin-top: 16px; min-height: 48px; line-height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hive-nav { --hx: min(64px, calc((100vw - 40px) / 4)); --hxm: min(58px, calc((100vw - 36px) / 5)); margin: 8px 0 16px; overflow: visible; background: transparent; padding: 0; border: 0; box-shadow: none; }
|
/* Lanzador de modulos de la home (sustituye a los hexagonos): secciones con un
|
||||||
.hive-radio { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
|
rotulo discreto y una rejilla de baldosas, como el cajon de apps del movil */
|
||||||
.hive-grid { display: flex; flex-direction: column; align-items: center; overflow: visible; background: transparent; padding: 0; margin: 0; box-shadow: none; }
|
.launcher { margin: 6px 0 20px; padding: 0; border: 0; }
|
||||||
.hive-row { display: flex; justify-content: center; gap: 3px; overflow: visible; background: transparent; padding: 0; margin: 0; box-shadow: none; }
|
.ln-group { margin: 0; padding: 0; border: 0; }
|
||||||
.hive-cats .hive-row + .hive-row { margin-top: calc(var(--hx) * -0.30); }
|
.ln-group + .ln-group { margin-top: 20px; }
|
||||||
.hex-cat, .hex-mod {
|
.ln-title {
|
||||||
position: relative;
|
margin: 0 2px 10px; padding: 0; border: 0;
|
||||||
-webkit-clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
|
font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
|
||||||
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
|
color: var(--c-muted);
|
||||||
display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
|
|
||||||
text-decoration: none; cursor: pointer; box-sizing: border-box;
|
|
||||||
background: #FFD700;
|
|
||||||
filter: drop-shadow(0 1px 2px rgba(0,0,0,.6));
|
|
||||||
}
|
}
|
||||||
.hex-cat::before, .hex-mod::before {
|
.ln-grid {
|
||||||
content: ''; position: absolute; inset: 1.5px; z-index: 0;
|
display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
-webkit-clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
|
gap: 14px 8px; margin: 0; padding: 0;
|
||||||
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
|
}
|
||||||
background: #161616;
|
.ln-app {
|
||||||
|
display: flex; flex-direction: column; align-items: center; gap: 6px;
|
||||||
|
min-width: 0; text-decoration: none; -webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
.ln-ico {
|
||||||
|
width: 54px; height: 54px; box-sizing: border-box;
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
border-radius: 16px; background: #1c1c1c; border: 1px solid #333;
|
||||||
|
color: #FFD700; font-size: 22px; line-height: 1;
|
||||||
|
transition: background-color .12s, border-color .12s;
|
||||||
|
}
|
||||||
|
.ln-app:active .ln-ico, .ln-app:focus-visible .ln-ico { background: #2a2412; border-color: #FFD700; }
|
||||||
|
.ln-lbl {
|
||||||
|
max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||||
|
font-size: 11px; line-height: 1.2; text-align: center; color: #e6e6e6;
|
||||||
}
|
}
|
||||||
.hex-cat { width: var(--hx); height: calc(var(--hx) * 1.15); }
|
|
||||||
.hex-mod { width: var(--hxm); height: calc(var(--hxm) * 1.15); }
|
|
||||||
.hex-cat .hx-ico, .hex-mod .hx-ico { color: #FFD700; line-height: 1; position: relative; z-index: 1; }
|
|
||||||
.hex-cat .hx-ico { font-size: 17px; }
|
|
||||||
.hex-mod .hx-ico { font-size: 16px; }
|
|
||||||
.hex-cat .hx-lbl, .hex-mod .hx-lbl { color: #FFD700; text-align: center; line-height: 1; font-weight: bold; overflow: hidden; position: relative; z-index: 1; }
|
|
||||||
.hex-cat .hx-lbl { font-size: 8px; max-width: 88%; }
|
|
||||||
.hex-mod .hx-lbl { font-size: 8px; max-width: 92%; }
|
|
||||||
.hex-cat:active::before, .hex-mod:active::before { background: #242424; }
|
|
||||||
#hive-personal:checked ~ .hive-grid .hex-cat[for="hive-personal"],
|
|
||||||
#hive-governance:checked ~ .hive-grid .hex-cat[for="hive-governance"],
|
|
||||||
#hive-office:checked ~ .hive-grid .hex-cat[for="hive-office"],
|
|
||||||
#hive-economy:checked ~ .hive-grid .hex-cat[for="hive-economy"],
|
|
||||||
#hive-tools:checked ~ .hive-grid .hex-cat[for="hive-tools"],
|
|
||||||
#hive-network:checked ~ .hive-grid .hex-cat[for="hive-network"],
|
|
||||||
#hive-blogs:checked ~ .hive-grid .hex-cat[for="hive-blogs"],
|
|
||||||
#hive-creative:checked ~ .hive-grid .hex-cat[for="hive-creative"],
|
|
||||||
#hive-media:checked ~ .hive-grid .hex-cat[for="hive-media"],
|
|
||||||
#hive-fediverse:checked ~ .hive-grid .hex-cat[for="hive-fediverse"] { background: #FFD700; }
|
|
||||||
#hive-personal:checked ~ .hive-grid .hex-cat[for="hive-personal"]::before,
|
|
||||||
#hive-governance:checked ~ .hive-grid .hex-cat[for="hive-governance"]::before,
|
|
||||||
#hive-office:checked ~ .hive-grid .hex-cat[for="hive-office"]::before,
|
|
||||||
#hive-economy:checked ~ .hive-grid .hex-cat[for="hive-economy"]::before,
|
|
||||||
#hive-tools:checked ~ .hive-grid .hex-cat[for="hive-tools"]::before,
|
|
||||||
#hive-network:checked ~ .hive-grid .hex-cat[for="hive-network"]::before,
|
|
||||||
#hive-blogs:checked ~ .hive-grid .hex-cat[for="hive-blogs"]::before,
|
|
||||||
#hive-creative:checked ~ .hive-grid .hex-cat[for="hive-creative"]::before,
|
|
||||||
#hive-media:checked ~ .hive-grid .hex-cat[for="hive-media"]::before,
|
|
||||||
#hive-fediverse:checked ~ .hive-grid .hex-cat[for="hive-fediverse"]::before { background: #FFD700; }
|
|
||||||
#hive-personal:checked ~ .hive-grid .hex-cat[for="hive-personal"] :is(.hx-ico,.hx-lbl),
|
|
||||||
#hive-governance:checked ~ .hive-grid .hex-cat[for="hive-governance"] :is(.hx-ico,.hx-lbl),
|
|
||||||
#hive-office:checked ~ .hive-grid .hex-cat[for="hive-office"] :is(.hx-ico,.hx-lbl),
|
|
||||||
#hive-economy:checked ~ .hive-grid .hex-cat[for="hive-economy"] :is(.hx-ico,.hx-lbl),
|
|
||||||
#hive-tools:checked ~ .hive-grid .hex-cat[for="hive-tools"] :is(.hx-ico,.hx-lbl),
|
|
||||||
#hive-network:checked ~ .hive-grid .hex-cat[for="hive-network"] :is(.hx-ico,.hx-lbl),
|
|
||||||
#hive-blogs:checked ~ .hive-grid .hex-cat[for="hive-blogs"] :is(.hx-ico,.hx-lbl),
|
|
||||||
#hive-creative:checked ~ .hive-grid .hex-cat[for="hive-creative"] :is(.hx-ico,.hx-lbl),
|
|
||||||
#hive-media:checked ~ .hive-grid .hex-cat[for="hive-media"] :is(.hx-ico,.hx-lbl),
|
|
||||||
#hive-fediverse:checked ~ .hive-grid .hex-cat[for="hive-fediverse"] :is(.hx-ico,.hx-lbl) { color: #121212; }
|
|
||||||
.hive-panel { display: none; margin: 12px auto 0; max-width: 340px; background: #101010; border: 1px solid #242424; border-radius: 16px; padding: 12px 8px; overflow: visible; box-shadow: none; }
|
|
||||||
#hive-personal:checked ~ #hive-panel-personal,
|
|
||||||
#hive-governance:checked ~ #hive-panel-governance,
|
|
||||||
#hive-office:checked ~ #hive-panel-office,
|
|
||||||
#hive-economy:checked ~ #hive-panel-economy,
|
|
||||||
#hive-tools:checked ~ #hive-panel-tools,
|
|
||||||
#hive-network:checked ~ #hive-panel-network,
|
|
||||||
#hive-blogs:checked ~ #hive-panel-blogs,
|
|
||||||
#hive-creative:checked ~ #hive-panel-creative,
|
|
||||||
#hive-media:checked ~ #hive-panel-media,
|
|
||||||
#hive-fediverse:checked ~ #hive-panel-fediverse { display: block; }
|
|
||||||
.hive-mods { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; margin: 0; padding: 0; background: transparent; overflow: visible; }
|
|
||||||
|
|
||||||
.header .top-bar-left nav,
|
.header .top-bar-left nav,
|
||||||
.header .top-bar-right nav { display: none; }
|
.header .top-bar-right nav { display: none; }
|
||||||
|
|
@ -909,33 +868,6 @@ button, input[type="submit"], input[type="button"],
|
||||||
padding: 8px 12px; font-size: 13px; margin: 0 0 6px;
|
padding: 8px 12px; font-size: 13px; margin: 0 0 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- #3: al desplegar una categoría, sus módulos son BOTONES CUADRADOS redondeados (no hexágonos),
|
|
||||||
en rejilla 2×2 (2 y 2) y grandes: cada cuadrado llena su columna --- */
|
|
||||||
.hive-mods {
|
|
||||||
display: grid; grid-template-columns: repeat(2, 1fr);
|
|
||||||
justify-items: stretch; align-content: center;
|
|
||||||
gap: 12px; padding: 8px 4px;
|
|
||||||
}
|
|
||||||
.hex-mod {
|
|
||||||
clip-path: none; -webkit-clip-path: none;
|
|
||||||
width: 100%; height: auto; aspect-ratio: 1 / 1; min-height: 120px;
|
|
||||||
border-radius: 18px; padding: 8px; gap: 7px;
|
|
||||||
}
|
|
||||||
.hex-mod::before { clip-path: none; -webkit-clip-path: none; inset: 2px; border-radius: 16px; }
|
|
||||||
.hex-mod .hx-ico { font-size: 36px; }
|
|
||||||
.hex-mod .hx-lbl { font-size: 12.5px; max-width: 94%; }
|
|
||||||
/* si el nº de módulos es IMPAR, el último (solo en su fila) se CENTRA en vez de pegarse a la izquierda;
|
|
||||||
abarca las 2 columnas pero conserva el ancho de una sola (gap 12 → mitad 6) */
|
|
||||||
.hex-mod:last-child:nth-child(odd) {
|
|
||||||
grid-column: 1 / -1; justify-self: center; width: calc(50% - 6px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- #2: el hexágono "Personal" muestra tu avatar (diferencia del filtro "Personal" del header) --- */
|
|
||||||
.hex-cat .hx-avatar {
|
|
||||||
width: 58%; height: 58%; border-radius: 50%; object-fit: cover;
|
|
||||||
position: relative; z-index: 1; border: 1px solid rgba(255,215,0,.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- #1: chat estilo Signal — compose ABAJO + mensajes arriba (el reply deja de "saltar") --- */
|
/* --- #1: chat estilo Signal — compose ABAJO + mensajes arriba (el reply deja de "saltar") --- */
|
||||||
.tribe-main.chat-full-width { display: flex; flex-direction: column-reverse; }
|
.tribe-main.chat-full-width { display: flex; flex-direction: column-reverse; }
|
||||||
#chatbox { scroll-margin-top: 8px; scroll-margin-bottom: 8px; }
|
#chatbox { scroll-margin-top: 8px; scroll-margin-bottom: 8px; }
|
||||||
|
|
@ -1032,17 +964,17 @@ button, input[type="submit"], input[type="button"],
|
||||||
========================================================================== */
|
========================================================================== */
|
||||||
|
|
||||||
/* --- fuente única en todo el UI móvil (quitar el lío monospace/sans) --- */
|
/* --- fuente única en todo el UI móvil (quitar el lío monospace/sans) --- */
|
||||||
.oasis-mobile-topbar, .oasis-mobile-menus, .hive-nav, .oasis-bottombar, .main-column,
|
.oasis-mobile-topbar, .oasis-mobile-menus, .launcher, .oasis-bottombar, .main-column,
|
||||||
.oasis-mobile-topbar input, .main-column input, .main-column textarea, .main-column select, button {
|
.oasis-mobile-topbar input, .main-column input, .main-column textarea, .main-column select, button {
|
||||||
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (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) */
|
||||||
|
|
||||||
/* --- hive ahora global en el header (debajo de los 2 botones) --- */
|
/* --- el lanzador va en el header (debajo de los 2 botones), solo en la home --- */
|
||||||
.header .hive-nav { margin: 34px auto 10px; }
|
.header .launcher { width: 100%; max-width: 440px; box-sizing: border-box; margin: 34px auto 10px; padding: 0 14px; }
|
||||||
|
|
||||||
/* holgura bajo la topbar fija (el hive va en el header, solo en la home) */
|
/* holgura bajo la topbar fija */
|
||||||
body { padding-top: 84px; }
|
body { padding-top: 84px; }
|
||||||
|
|
||||||
/* ==========================================================================
|
/* ==========================================================================
|
||||||
|
|
@ -1113,3 +1045,22 @@ body { padding-top: 84px; }
|
||||||
.kc-btn-start { font-weight: 600; }
|
.kc-btn-start { font-weight: 600; }
|
||||||
.kc-btn-stop { background: #241414; border-color: #5a2a2a; }
|
.kc-btn-stop { background: #241414; border-color: #5a2a2a; }
|
||||||
.kc-status { font-size: 12px; color: #FFDD44; margin-top: 6px; min-height: 14px; }
|
.kc-status { font-size: 12px; color: #FFDD44; margin-top: 6px; min-height: 14px; }
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
1.3.x: upstream trae en mobile.css su propio chrome movil (cabecera fija, cajones
|
||||||
|
laterales y botones Personal/Community que los abren). La rama ya tiene el suyo
|
||||||
|
(topbar, lanzador y barra inferior), asi que aqui se apaga el de upstream sin
|
||||||
|
tocar mobile.css. Va con !important porque las reglas que anula lo llevan.
|
||||||
|
========================================================================== */
|
||||||
|
.oasis-nav-side-toggle ~ .header {
|
||||||
|
position: static !important;
|
||||||
|
display: flex !important; flex-direction: column !important; flex-wrap: nowrap !important;
|
||||||
|
align-items: stretch !important;
|
||||||
|
min-height: 0 !important; padding: 0 !important; gap: 0 !important;
|
||||||
|
z-index: auto !important;
|
||||||
|
}
|
||||||
|
body:has(.oasis-nav-side-toggle) { padding-top: 84px !important; }
|
||||||
|
.oasis-nav-side-toggle ~ .header .oasis-mobile-menus,
|
||||||
|
.oasis-nav-side-toggle ~ .header .top-bar-left nav,
|
||||||
|
.oasis-nav-side-toggle ~ .header .top-bar-right nav,
|
||||||
|
.oasis-nav-side-toggle ~ .header .top-bar-left a.logo-icon { display: none !important; }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
// Navegacion propia de la rama experimental para movil: topbar, barra inferior
|
// Navegacion propia de la rama experimental para movil: topbar, barra inferior
|
||||||
// personalizable y rejilla de hexagonos.
|
// personalizable y lanzador de modulos.
|
||||||
//
|
//
|
||||||
// Vive fuera de main_views.js a proposito: upstream reescribe ese fichero en cada
|
// Vive fuera de main_views.js a proposito: upstream reescribe ese fichero en cada
|
||||||
// release (de 0.9.1 a 0.9.5 movio +256/-502 lineas) y esta interfaz se perdia en
|
// release (de 0.9.1 a 0.9.5 movio +256/-502 lineas) y esta interfaz se perdia en
|
||||||
|
|
@ -12,7 +12,7 @@ const { getConfig } = require("../configs/config-manager.js");
|
||||||
const sharedState = require("../configs/shared-state");
|
const sharedState = require("../configs/shared-state");
|
||||||
|
|
||||||
module.exports = ({ i18n }) => {
|
module.exports = ({ i18n }) => {
|
||||||
// === Oasis UX (portado de 0.8.7_UX): topbar + bottombar + hive ===
|
// === 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)
|
||||||
const renderMobileTopbar = () => {
|
const renderMobileTopbar = () => {
|
||||||
// solo en movil: en escritorio manda la cabecera de upstream
|
// solo en movil: en escritorio manda la cabecera de upstream
|
||||||
|
|
@ -39,6 +39,8 @@ module.exports = ({ i18n }) => {
|
||||||
{ key: 'tribes', href: '/tribes', glyph: 'ꖥ', labelKey: 'tribesTitle', mod: 'tribesMod' },
|
{ key: 'tribes', href: '/tribes', glyph: 'ꖥ', labelKey: 'tribesTitle', mod: 'tribesMod' },
|
||||||
{ key: 'chats', href: '/chats', glyph: 'ꖒ', labelKey: 'chatsTitle', mod: 'chatsMod' },
|
{ key: 'chats', href: '/chats', glyph: 'ꖒ', labelKey: 'chatsTitle', mod: 'chatsMod' },
|
||||||
{ key: 'karvan', href: '/karvan', glyph: '⧗', labelKey: 'karvanTitle', mod: 'karvanMod' },
|
{ key: 'karvan', href: '/karvan', glyph: '⧗', labelKey: 'karvanTitle', mod: 'karvanMod' },
|
||||||
|
{ key: 'rooms', href: '/rooms', glyph: 'ꕢ', labelKey: 'roomsTitle', mod: 'roomsMod' },
|
||||||
|
{ key: 'wiki', href: '/wiki', glyph: 'ꖿ', labelKey: 'wikiTitle', mod: 'wikiMod' },
|
||||||
{ key: 'polls', href: '/polls', glyph: 'ꖙ', labelKey: 'pollsTitle', mod: 'pollsMod' },
|
{ key: 'polls', href: '/polls', glyph: 'ꖙ', labelKey: 'pollsTitle', mod: 'pollsMod' },
|
||||||
{ key: 'blogs', href: '/blogs', glyph: 'ꔫ', labelKey: 'blogTitle', mod: 'blogsMod' },
|
{ key: 'blogs', href: '/blogs', glyph: 'ꔫ', labelKey: 'blogTitle', mod: 'blogsMod' },
|
||||||
{ key: 'data', href: '/data', glyph: 'ꘑ', labelKey: 'dataTitle', mod: 'dataMod' },
|
{ key: 'data', href: '/data', glyph: 'ꘑ', labelKey: 'dataTitle', mod: 'dataMod' },
|
||||||
|
|
@ -119,71 +121,104 @@ module.exports = ({ i18n }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Lanzador de modulos de la home: secciones con una rejilla de iconos, como el
|
||||||
|
// cajon de apps del movil. Solo salen los modulos activos y las secciones que
|
||||||
|
// tienen alguno, asi que con un workflow corto (activistas) cabe en una pantalla.
|
||||||
|
const GROUPS = [
|
||||||
|
{ id: 'community', titleKey: 'menuNetwork', side: 'community', mods: [
|
||||||
|
{ href: '/activity', glyph: 'ꔙ', labelKey: 'activityTitle', mod: null },
|
||||||
|
{ href: '/feed', glyph: 'ꕿ', labelKey: 'feedTitle', mod: 'feedMod' },
|
||||||
|
{ href: '/chats', glyph: 'ꖒ', labelKey: 'chatsTitle', mod: 'chatsMod' },
|
||||||
|
{ href: '/karvan', glyph: '⧗', labelKey: 'karvanTitle', mod: 'karvanMod' },
|
||||||
|
{ href: '/rooms', glyph: 'ꕢ', labelKey: 'roomsTitle', mod: 'roomsMod' },
|
||||||
|
{ href: '/forum', glyph: 'ꕒ', labelKey: 'forumTitle', mod: 'forumMod' },
|
||||||
|
{ href: '/pads', glyph: 'ꔗ', labelKey: 'padsTitle', mod: 'padsMod' },
|
||||||
|
{ href: '/wiki', glyph: 'ꖿ', labelKey: 'wikiTitle', mod: 'wikiMod' },
|
||||||
|
{ href: '/blogs', glyph: 'ꔫ', labelKey: 'blogTitle', mod: 'blogsMod' },
|
||||||
|
{ href: '/opinions', glyph: 'ꔍ', labelKey: 'opinionsTitle', mod: 'opinionsMod' },
|
||||||
|
{ href: '/mentions', glyph: '✺', labelKey: 'mentions', mod: null },
|
||||||
|
{ href: '/tags', glyph: 'ꖶ', labelKey: 'tagsLabel', mod: 'tagsMod' },
|
||||||
|
{ href: '/trending', glyph: 'ꗝ', labelKey: 'trendingLabel', mod: 'trendingMod' },
|
||||||
|
{ href: '/maps', glyph: 'ꔌ', labelKey: 'mapsLabel', mod: 'mapsMod' },
|
||||||
|
{ href: '/graphos', glyph: '⌬', labelKey: 'modulesGraphosLabel', mod: 'graphosMod' },
|
||||||
|
{ href: '/inhabitants', glyph: 'ꖘ', labelKey: 'inhabitantsLabel', mod: null },
|
||||||
|
{ href: '/fediverse', glyph: 'ꗵ', labelKey: 'fediverseTimeline', mod: 'fediverseMod' } ] },
|
||||||
|
{ id: 'media', titleKey: 'menuMedia', side: 'community', mods: [
|
||||||
|
{ href: '/images', glyph: 'ꕥ', labelKey: 'imagesLabel', mod: 'imagesMod' },
|
||||||
|
{ href: '/videos', glyph: 'ꗟ', labelKey: 'videosLabel', mod: 'videosMod' },
|
||||||
|
{ href: '/audios', glyph: 'ꔿ', labelKey: 'audiosLabel', mod: 'audiosMod' },
|
||||||
|
{ href: '/podcasts', glyph: '◉', labelKey: 'podcastsTitle', mod: 'podcastsMod' },
|
||||||
|
{ href: '/documents', glyph: 'ꕨ', labelKey: 'docsLabel', mod: 'docsMod' },
|
||||||
|
{ href: '/files', glyph: 'ꖃ', labelKey: 'filesTitle', mod: 'filesMod' },
|
||||||
|
{ href: '/bookmarks', glyph: 'ꔪ', labelKey: 'bookmarksLabel', mod: 'bookmarksMod' },
|
||||||
|
{ href: '/torrents', glyph: 'ꖅ', labelKey: 'torrentsLabel', mod: 'torrentsMod' } ] },
|
||||||
|
{ id: 'creative', titleKey: 'menuCreative', side: 'community', mods: [
|
||||||
|
{ href: '/games', glyph: 'ꕇ', labelKey: 'gamesTitle', mod: 'gamesMod' },
|
||||||
|
{ href: '/pixelia', glyph: 'ꔘ', labelKey: 'pixeliaTitle', mod: 'pixeliaMod' },
|
||||||
|
{ href: '/melody', glyph: '♪', labelKey: 'melodyTitle', mod: 'melodyMod' } ] },
|
||||||
|
{ id: 'office', titleKey: 'menuOffice', side: 'personal', mods: [
|
||||||
|
{ href: '/events', glyph: 'ꕆ', labelKey: 'eventsLabel', mod: 'eventsMod' },
|
||||||
|
{ href: '/calendars', glyph: 'ꖯ', labelKey: 'calendarsTitle', mod: 'calendarsMod' },
|
||||||
|
{ href: '/tasks', glyph: 'ꖧ', labelKey: 'tasksTitle', mod: 'tasksMod' },
|
||||||
|
{ href: '/campaigns', glyph: '⚑', labelKey: 'campaignsTitle', mod: 'campaignsMod' },
|
||||||
|
{ href: '/mailing', glyph: '✉', labelKey: 'mailingTitle', mod: 'mailingMod' },
|
||||||
|
{ href: '/votes', glyph: 'ꔰ', labelKey: 'votationsTitle', mod: 'votesMod' },
|
||||||
|
{ href: '/polls', glyph: 'ꖙ', labelKey: 'pollsTitle', mod: 'pollsMod' },
|
||||||
|
{ href: '/reports', glyph: 'ꕤ', labelKey: 'reportsTitle', mod: 'reportsMod' } ] },
|
||||||
|
{ id: 'governance', titleKey: 'menuGovernance', side: 'personal', mods: [
|
||||||
|
{ href: '/tribes', glyph: 'ꖥ', labelKey: 'tribesTitle', mod: 'tribesMod' },
|
||||||
|
{ href: '/emergencies', glyph: '✚', labelKey: 'emergenciesTitle', mod: 'emergenciesMod' },
|
||||||
|
{ href: '/school', glyph: 'ꗳ', labelKey: 'schoolTitle', mod: 'schoolMod' },
|
||||||
|
{ href: '/larp', glyph: '✦', labelKey: 'larpTitle', mod: 'larpMod' },
|
||||||
|
{ href: '/parliament', glyph: 'ꗞ', labelKey: 'parliamentTitle', mod: 'parliamentMod' },
|
||||||
|
{ href: '/courts', glyph: 'ꖻ', labelKey: 'courtsTitle', mod: 'courtsMod' } ] },
|
||||||
|
{ id: 'economy', titleKey: 'menuEconomy', side: 'personal', mods: [
|
||||||
|
{ href: '/market', glyph: 'ꕻ', labelKey: 'marketTitle', mod: 'marketMod' },
|
||||||
|
{ href: '/shops', glyph: 'ꔜ', labelKey: 'shopsTitle', mod: 'shopsMod' },
|
||||||
|
{ href: '/jobs', glyph: 'ꗒ', labelKey: 'jobsTitle', mod: 'jobsMod' },
|
||||||
|
{ href: '/projects', glyph: 'ꕧ', labelKey: 'projectsTitle', mod: 'projectsMod' },
|
||||||
|
{ href: '/housing', glyph: '⌂', labelKey: 'housingTitle', mod: 'housingMod' },
|
||||||
|
{ href: '/logistics', glyph: '⇄', labelKey: 'logisticsTitle', mod: 'logisticsMod' },
|
||||||
|
{ href: '/banking', glyph: 'ꗴ', labelKey: 'bankingTitle', mod: 'bankingMod' },
|
||||||
|
{ href: '/transfers', glyph: 'ꘉ', labelKey: 'transfersTitle', mod: 'transfersMod' } ] },
|
||||||
|
{ id: 'personal', titleKey: 'menuPersonal', side: 'personal', mods: [
|
||||||
|
{ href: '/profile', glyph: '⚉', labelKey: 'profile', mod: null },
|
||||||
|
{ href: '/agenda', glyph: 'ꗤ', labelKey: 'agendaTitle', mod: 'agendaMod' },
|
||||||
|
{ href: '/favorites', glyph: 'ꘝ', labelKey: 'favoritesTitle', mod: 'favoritesMod' },
|
||||||
|
{ href: '/phone', glyph: '☏', labelKey: 'phoneTitle', mod: 'phoneMod' },
|
||||||
|
{ href: '/cv', glyph: 'ꕛ', labelKey: 'cvTitle', mod: null },
|
||||||
|
{ href: '/wallet', glyph: '❄', labelKey: 'wallet', mod: 'walletMod' },
|
||||||
|
{ href: '/logs', glyph: 'ꗯ', labelKey: 'logsTitle', mod: 'logsMod' } ] },
|
||||||
|
{ id: 'tools', titleKey: 'menuTools', side: 'personal', mods: [
|
||||||
|
{ href: '/invites', glyph: 'ꔹ', labelKey: 'invites', mod: 'invitesMod' },
|
||||||
|
{ href: '/backup', glyph: 'ꖤ', labelKey: 'backupTitle', mod: 'backupMod' },
|
||||||
|
{ href: '/cipher', glyph: 'ꗄ', labelKey: 'cipher', mod: 'cipherMod' },
|
||||||
|
{ href: '/ai', glyph: 'ꘜ', labelKey: 'ai', mod: 'aiMod' },
|
||||||
|
{ href: '/stats', glyph: 'ꕷ', labelKey: 'statistics', mod: null },
|
||||||
|
{ href: '/blockexplorer', glyph: 'ꖸ', labelKey: 'blockchain', mod: null },
|
||||||
|
{ href: '/modules', glyph: 'ꗣ', labelKey: 'modules', mod: null },
|
||||||
|
{ href: '/settings', glyph: '⚙', labelKey: 'settings', mod: null } ] },
|
||||||
|
];
|
||||||
|
|
||||||
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 CATS = [
|
// Personal/Social de la topbar (lo pone el middleware desde ?hive=) parte el lanzador en dos
|
||||||
{ id: 'personal', emoji: '⚉', title: i18n.menuPersonal, mods: [
|
|
||||||
{ href: '/profile', glyph: '⚉', labelKey: 'profile', mod: null }, { href: '/cv', glyph: 'ꕛ', labelKey: 'cvTitle', mod: null },
|
|
||||||
{ href: '/agenda', glyph: 'ꗤ', labelKey: 'agendaTitle', mod: 'agendaMod' }, { href: '/favorites', glyph: 'ꘝ', labelKey: 'favoritesTitle', mod: 'favoritesMod' },
|
|
||||||
{ href: '/logs', glyph: 'ꗯ', labelKey: 'logsTitle', mod: 'logsMod' }, { href: '/wallet', glyph: '❄', labelKey: 'wallet', mod: 'walletMod' },
|
|
||||||
{ href: '/modules', glyph: 'ꗣ', labelKey: 'modules', mod: null }, { href: '/settings', glyph: '⚙', labelKey: 'settings', mod: null } ] },
|
|
||||||
{ id: 'governance', emoji: '⚖', title: i18n.menuGovernance, mods: [
|
|
||||||
{ href: '/inhabitants', glyph: 'ꖘ', labelKey: 'inhabitantsLabel', mod: null }, { href: '/tribes', glyph: 'ꖥ', labelKey: 'tribesTitle', mod: 'tribesMod' },
|
|
||||||
{ href: '/larp', glyph: '✦', labelKey: 'larpTitle', mod: 'larpMod' }, { href: '/parliament', glyph: 'ꗞ', labelKey: 'parliamentTitle', mod: 'parliamentMod' },
|
|
||||||
{ href: '/courts', glyph: 'ꖻ', labelKey: 'courtsTitle', mod: 'courtsMod' } ] },
|
|
||||||
{ id: 'office', emoji: '⌂', title: i18n.menuOffice, mods: [
|
|
||||||
{ href: '/votes', glyph: 'ꔰ', labelKey: 'votationsTitle', mod: 'votesMod' }, { href: '/polls', glyph: 'ꖙ', labelKey: 'pollsTitle', mod: 'pollsMod' }, { href: '/events', glyph: 'ꕆ', labelKey: 'eventsLabel', mod: 'eventsMod' },
|
|
||||||
{ href: '/calendars', glyph: 'ꖯ', labelKey: 'calendarsTitle', mod: 'calendarsMod' }, { href: '/tasks', glyph: 'ꖧ', labelKey: 'tasksTitle', mod: 'tasksMod' },
|
|
||||||
{ href: '/reports', glyph: 'ꕥ', labelKey: 'reportsTitle', mod: 'reportsMod' } ] },
|
|
||||||
{ id: 'economy', emoji: '¤', title: i18n.menuEconomy, mods: [
|
|
||||||
{ href: '/banking', glyph: 'ꗴ', labelKey: 'bankingTitle', mod: 'bankingMod' }, { href: '/market', glyph: 'ꕻ', labelKey: 'marketTitle', mod: 'marketMod' },
|
|
||||||
{ href: '/projects', glyph: 'ꕧ', labelKey: 'projectsTitle', mod: 'projectsMod' }, { href: '/jobs', glyph: 'ꗒ', labelKey: 'jobsTitle', mod: 'jobsMod' },
|
|
||||||
{ href: '/shops', glyph: 'ꔜ', labelKey: 'shopsTitle', mod: 'shopsMod' }, { href: '/transfers', glyph: 'ꘉ', labelKey: 'transfersTitle', mod: 'transfersMod' } ] },
|
|
||||||
{ id: 'tools', emoji: '⚒', title: i18n.menuTools, mods: [
|
|
||||||
{ href: '/ai', glyph: 'ꘜ', labelKey: 'ai', mod: 'aiMod' }, { href: '/blockexplorer', glyph: 'ꖸ', labelKey: 'blockchain', mod: null },
|
|
||||||
{ href: '/cipher', glyph: 'ꗄ', labelKey: 'cipher', mod: 'cipherMod' }, { href: '/invites', glyph: 'ꔹ', labelKey: 'invites', mod: 'invitesMod' },
|
|
||||||
{ href: '/legacy', glyph: 'ꖤ', labelKey: 'legacy', mod: 'legacyMod' }, { href: '/stats', glyph: 'ꕷ', labelKey: 'statistics', mod: null },
|
|
||||||
{ href: '/data', glyph: 'ꘑ', labelKey: 'dataTitle', mod: 'dataMod' } ] },
|
|
||||||
{ id: 'network', emoji: '☍', title: i18n.menuNetwork, mods: [
|
|
||||||
{ href: '/activity', glyph: 'ꔙ', labelKey: 'activityTitle', mod: null }, { href: '/tags', glyph: 'ꖶ', labelKey: 'tagsLabel', mod: 'tagsMod' },
|
|
||||||
{ href: '/trending', glyph: 'ꗝ', labelKey: 'trendingLabel', mod: 'trendingMod' }, { href: '/opinions', glyph: 'ꔍ', labelKey: 'opinionsTitle', mod: 'opinionsMod' },
|
|
||||||
{ href: '/pads', glyph: 'ꔗ', labelKey: 'padsTitle', mod: 'padsMod' }, { href: '/forum', glyph: 'ꕒ', labelKey: 'forumTitle', mod: 'forumMod' },
|
|
||||||
{ href: '/maps', glyph: 'ꔌ', labelKey: 'mapsLabel', mod: 'mapsMod' }, { href: '/chats', glyph: 'ꖒ', labelKey: 'chatsTitle', mod: 'chatsMod' },
|
|
||||||
{ href: '/karvan', glyph: '⧗', labelKey: 'karvanTitle', mod: 'karvanMod' } ] },
|
|
||||||
{ id: 'blogs', emoji: '✦', title: i18n.menuBlogs, mods: [
|
|
||||||
{ href: '/blogs', glyph: 'ꔫ', labelKey: 'blogTitle', mod: 'blogsMod' }, { href: '/mentions', glyph: '✺', labelKey: 'mentions', mod: null }, { href: '/public/latest', glyph: '☄', labelKey: 'latest', mod: 'latestMod' },
|
|
||||||
{ href: '/public/latest/threads', glyph: '♺', labelKey: 'threads', mod: 'threadsMod' }, { href: '/public/latest/topics', glyph: 'ϟ', labelKey: 'topics', mod: 'topicsMod' },
|
|
||||||
{ href: '/public/latest/summaries', glyph: '※', labelKey: 'summaries', mod: 'summariesMod' }, { href: '/public/popular/day', glyph: '⌘', labelKey: 'popular', mod: 'popularMod' },
|
|
||||||
{ href: '/public/latest/extended', glyph: '∞', labelKey: 'multiverse', mod: 'multiverseMod' } ] },
|
|
||||||
{ id: 'creative', emoji: '✎', title: i18n.menuCreative, mods: [
|
|
||||||
{ href: '/feed', glyph: 'ꕿ', labelKey: 'feedTitle', mod: 'feedMod' }, { href: '/games', glyph: 'ꕇ', labelKey: 'gamesTitle', mod: 'gamesMod' },
|
|
||||||
{ href: '/pixelia', glyph: 'ꔘ', labelKey: 'pixeliaTitle', mod: 'pixeliaMod' }, { href: '/melody', glyph: '♪', labelKey: 'melodyTitle', mod: 'melodyMod' } ] },
|
|
||||||
{ id: 'media', emoji: '▤', title: i18n.menuMedia, mods: [
|
|
||||||
{ href: '/audios', glyph: 'ꔿ', labelKey: 'audiosLabel', mod: 'audiosMod' }, { href: '/bookmarks', glyph: 'ꔪ', labelKey: 'bookmarksLabel', mod: 'bookmarksMod' },
|
|
||||||
{ href: '/documents', glyph: 'ꕨ', labelKey: 'docsLabel', mod: 'docsMod' }, { href: '/images', glyph: 'ꕥ', labelKey: 'imagesLabel', mod: 'imagesMod' },
|
|
||||||
{ href: '/torrents', glyph: 'ꖅ', labelKey: 'torrentsLabel', mod: 'torrentsMod' }, { href: '/videos', glyph: 'ꗟ', labelKey: 'videosLabel', mod: 'videosMod' } ] },
|
|
||||||
{ id: 'fediverse', emoji: '⌬', title: i18n.fediverse, mods: [
|
|
||||||
{ href: '/fediverse', glyph: 'ꗵ', labelKey: 'fediverseTimeline', mod: 'fediverseMod' } ] },
|
|
||||||
];
|
|
||||||
// filtro server-side (lo pone el middleware desde ?hive=): personal = CATS[0..4], community = CATS[5..9], vacío = las 10
|
|
||||||
const hiveFilter = (typeof global !== "undefined" && global.__OASIS_HIVE_FILTER__) || "";
|
const hiveFilter = (typeof global !== "undefined" && global.__OASIS_HIVE_FILTER__) || "";
|
||||||
const shown = hiveFilter === "personal" ? CATS.slice(0, 5) : hiveFilter === "community" ? CATS.slice(5) : CATS;
|
const app = (m) => a({ class: 'ln-app', href: m.href },
|
||||||
const rowSizes = shown.length <= 5 ? [3, 2] : [3, 4, 3];
|
span({ class: 'ln-ico', 'aria-hidden': 'true' }, m.glyph),
|
||||||
const catHex = (c) => label({ for: `hive-${c.id}`, class: 'hex-cat' },
|
span({ class: 'ln-lbl' }, i18n[m.labelKey] || m.href.slice(1)));
|
||||||
span({ class: 'hx-ico' }, c.emoji), span({ class: 'hx-lbl' }, c.title));
|
const groups = GROUPS
|
||||||
const modHex = (m) => a({ class: 'hex-mod', href: m.href },
|
.filter(g => !hiveFilter || g.side === hiveFilter)
|
||||||
span({ class: 'hx-ico' }, m.glyph), span({ class: 'hx-lbl' }, i18n[m.labelKey] || ''));
|
.map(g => ({ g, mods: g.mods.filter(m => modOn(m.mod)) }))
|
||||||
const radios = shown.map(c => input({ type: 'radio', name: 'hive-cat', id: `hive-${c.id}`, class: 'hive-radio' }));
|
.filter(x => x.mods.length);
|
||||||
const catRows = [];
|
return nav({ class: 'launcher', 'aria-label': i18n.modules || 'Modules' },
|
||||||
let idx = 0;
|
...groups.map(({ g, mods }) => div({ class: 'ln-group' },
|
||||||
for (const size of rowSizes) { catRows.push(div({ class: 'hive-row' }, ...shown.slice(idx, idx + size).map(catHex))); idx += size; }
|
h3({ class: 'ln-title' }, i18n[g.titleKey] || g.id),
|
||||||
const grid = div({ class: 'hive-grid hive-cats' }, ...catRows);
|
div({ class: 'ln-grid' }, ...mods.map(app))
|
||||||
const panels = shown.map(c => div({ class: 'hive-panel', id: `hive-panel-${c.id}` },
|
))
|
||||||
div({ class: 'hive-mods' }, ...c.mods.filter(m => modOn(m.mod)).map(modHex))
|
);
|
||||||
));
|
|
||||||
return div({ class: 'hive-nav' }, ...radios, grid, ...panels);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue