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
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
// 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
|
||||
// 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");
|
||||
|
||||
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)
|
||||
const renderMobileTopbar = () => {
|
||||
// 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: 'chats', href: '/chats', glyph: 'ꖒ', labelKey: 'chatsTitle', mod: 'chatsMod' },
|
||||
{ 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: 'blogs', href: '/blogs', glyph: 'ꔫ', labelKey: 'blogTitle', mod: 'blogsMod' },
|
||||
{ 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 = () => {
|
||||
if (process.env.OASIS_MOBILE !== '1') return "";
|
||||
const cfg = getConfig();
|
||||
const modOn = (m) => !m || cfg.modules[m] === 'on' || cfg.modules[m] === undefined;
|
||||
const CATS = [
|
||||
{ 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
|
||||
// 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 shown = hiveFilter === "personal" ? CATS.slice(0, 5) : hiveFilter === "community" ? CATS.slice(5) : CATS;
|
||||
const rowSizes = shown.length <= 5 ? [3, 2] : [3, 4, 3];
|
||||
const catHex = (c) => label({ for: `hive-${c.id}`, class: 'hex-cat' },
|
||||
span({ class: 'hx-ico' }, c.emoji), span({ class: 'hx-lbl' }, c.title));
|
||||
const modHex = (m) => a({ class: 'hex-mod', href: m.href },
|
||||
span({ class: 'hx-ico' }, m.glyph), span({ class: 'hx-lbl' }, i18n[m.labelKey] || ''));
|
||||
const radios = shown.map(c => input({ type: 'radio', name: 'hive-cat', id: `hive-${c.id}`, class: 'hive-radio' }));
|
||||
const catRows = [];
|
||||
let idx = 0;
|
||||
for (const size of rowSizes) { catRows.push(div({ class: 'hive-row' }, ...shown.slice(idx, idx + size).map(catHex))); idx += size; }
|
||||
const grid = div({ class: 'hive-grid hive-cats' }, ...catRows);
|
||||
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);
|
||||
const app = (m) => a({ class: 'ln-app', href: m.href },
|
||||
span({ class: 'ln-ico', 'aria-hidden': 'true' }, m.glyph),
|
||||
span({ class: 'ln-lbl' }, i18n[m.labelKey] || m.href.slice(1)));
|
||||
const groups = GROUPS
|
||||
.filter(g => !hiveFilter || g.side === hiveFilter)
|
||||
.map(g => ({ g, mods: g.mods.filter(m => modOn(m.mod)) }))
|
||||
.filter(x => x.mods.length);
|
||||
return nav({ class: 'launcher', 'aria-label': i18n.modules || 'Modules' },
|
||||
...groups.map(({ g, mods }) => div({ class: 'ln-group' },
|
||||
h3({ class: 'ln-title' }, i18n[g.titleKey] || g.id),
|
||||
div({ class: 'ln-grid' }, ...mods.map(app))
|
||||
))
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue