perfiles de menos a más con su barra, EMPEZAR, paletas con nombre y Filtrar

- Perfil Activista (acción directa: chats, teléfono, eventos, emergencias,
  invitaciones y copia), 6 módulos, de serie. Acampada 16 y los del dev detrás,
  ordenados por número de módulos; cada tarjeta dice cuántos y enseña su barra.
  El activists del dev se llama Movimiento en el móvil.
- Cada perfil trae su barra de abajo (BARS en fork_workflows.js); al editarla se
  guarda para ese perfil (bottomBarBySkin).
- Aviso de bienvenida de la portada: un botón EMPEZAR grande y la X discreta.
  Los botones de cada paso de la bienvenida, a todo lo ancho.
- Colores: la paleta de serie, Estándar, son los del dev (negro y oro). El resto:
  Plaza, Madrugada, Huerto, Violeta, Hoguera, Fanzine y Pancarta.
- Actividad: las fichas de tipo van plegadas tras un botón Filtrar; por defecto
  se ve todo y con filtro el botón dice cuál (enganche en activity_view.js).
This commit is contained in:
hacklab 2026-10-22 11:55:37 +02:00
parent 438ecba47b
commit ff91ef938c
11 changed files with 404 additions and 205 deletions

View file

@ -52,7 +52,7 @@ Dónde va cada cosa:
| Algo en Ajustes del móvil | `views/mobile_settings.js` |
| Un texto nuevo | `translations/i18n_fork.js`, en los 11 idiomas |
| Un icono | `views/mobile_icons.js` |
| Un workflow | `models/fork_workflows.js` |
| Un workflow (perfil) o la barra de abajo de un perfil | `models/fork_workflows.js` (`FORK_WORKFLOWS` y `BARS`) |
| Algo de la APK | `android/scripts/sobre_oficial.sh` o `android/icono/` |
| Algo que la capa no deja | Pedírselo al dev |
@ -106,7 +106,8 @@ Cuando el dev reescribe la vista, se vuelve a poner esa línea y listo. En escri
no cambia nada porque la bandera `OASIS_MOBILE` solo la pone `main.js` en el móvil.
Ahora mismo hay enganches en `main_views.js`, `tribes_view.js`, `vote_view.js`,
`settings_view.js` y `welcome_view.js`. Para verlos: `grep -n mobileUi src/views/*.js`.
`settings_view.js`, `welcome_view.js` y `activity_view.js` (el botón Filtrar, que
pliega las fichas de tipo de actividad). Para verlos: `grep -n mobileUi src/views/*.js`.
## Llamadas: las del dev
@ -132,7 +133,9 @@ tiene o lo está haciendo.
Al abrir se ve la actividad. Los módulos están en la quinta pestaña de abajo, Menú,
que abre una hoja con el lanzador (`hive_views.js`: una casilla y CSS). Un script
mínimo, `public/js/mobile_menu.js`, hace que el botón atrás de Android cierre la hoja;
sin él el menú funciona igual. La barra tiene siempre cuatro atajos elegidos por cada cual más Menú. Por qué
sin él el menú funciona igual. La barra tiene cuatro atajos más Menú. Cada perfil trae los suyos (`BARS` en
`fork_workflows.js`) y quien la cambia desde «Tu barra» la cambia solo para ese perfil
(`bottomBarBySkin` en la config; sin perfil reconocido, `bottomBarPins`). Por qué
así: `docs/ESTUDIO_NAVEGACION.md`. Si se cambia, que sea con una prueba que lo
justifique, no por gusto.
@ -158,14 +161,22 @@ Aquí se puede hacer lo que haga falta.
- `src/views/mobile_settings.js`: los seis accesos de arriba de Ajustes (identidad,
perfil, portada, colores, comunidad y saludo) y los colores. Los colores se guardan
en la config (`mobileColors`) y salen en `/mobile-colors.css`, la última hoja; son
las variables `--a26-*` del skin Activista.
las variables `--a26-*` del skin Activista. La paleta de serie, Estándar, son los
colores del dev (negro y oro de su OasisMobile); las demás llevan nombre propio
(Plaza, Madrugada, Huerto, Violeta, Hoguera, Fanzine, Pancarta).
- `src/views/mobile_modules_view.js`, `identities_view.js`: pantallas propias.
- `src/views/hive_views.js`: lanzador y barras de arriba y abajo.
- `src/views/mobile_icons.js`: los iconos.
- `src/backend/fork_routes.js`: nuestro router. Va justo delante del del dev.
- `src/backend/mobile_layer.js`: lo que nuestra interfaz necesita del backend
(avatar, filtro y lanzador de la barra de arriba). La monta `fork_routes.js`.
- `src/models/fork_workflows.js`: nuestros workflows.
- `src/models/fork_workflows.js`: nuestros workflows, que en el móvil hacen de skins:
cada uno enciende unos módulos y trae su barra de abajo. Activista (acción directa,
6 módulos) es el de serie, después Acampada (16) y los del dev; en Ajustes y en la
bienvenida salen de menos a más módulos, con el número y los iconos de su barra.
Ojo: `backend.js` apaga a la fuerza en el móvil `ai`, `aiNav`, `dev`, `games`, `logs`,
`maps` y `pixelia`. Un perfil que encienda alguno de esos no se reconoce nunca como
puesto (le pasa a Movimiento, el `activists` del dev, y a Por defecto).
- `src/client/assets/translations/i18n_fork.js`: nuestros textos.
- `src/client/assets/images/ux-*.svg`: nuestras imágenes.
- `android/scripts/sobre_oficial.sh`: monta la APK sobre la oficial del dev. El resto

View file

@ -84,7 +84,9 @@ const mobileLayer = require('./mobile_layer')({ getViewerId, about });
const action = String(body.action || '').trim();
const key = String(body.key || '').trim();
const catalog = require("../views/main_views").PINNABLE_MODULES || [];
let pins = Array.isArray(cfg.bottomBarPins) ? cfg.bottomBarPins.slice() : [];
// cada skin tiene su barra (fork_workflows.js): se cambia la del skin puesto
const bars = require("../models/fork_workflows");
let pins = bars.barFor(cfg).slice();
if (action === 'add') {
if (key && catalog.some(m => m.key === key) && !pins.includes(key) && pins.length < MAX) pins.push(key);
} else if (action === 'remove') {
@ -92,7 +94,7 @@ const mobileLayer = require('./mobile_layer')({ getViewerId, about });
} else if (action === 'clear') {
pins = [];
}
cfg.bottomBarPins = pins.slice(0, MAX);
bars.saveBar(cfg, pins.slice(0, MAX));
saveConfig(cfg);
ctx.redirect('/settings/bottombar');
})

View file

@ -86,19 +86,29 @@
body { padding-bottom: 0 !important; }
}
/* ---------- aviso de bienvenida: una linea, no un bloque ---------- */
.welcome-banner {
display: flex !important; align-items: center !important; gap: 10px !important;
padding: 8px 8px 8px 14px !important; min-height: 0 !important;
/* ---------- aviso de bienvenida: un boton EMPEZAR que no se pueda pasar por alto ----------
la X queda pequeña en la esquina: cerrar tiene que costar mas que empezar */
.main-column .welcome-banner, .welcome-banner {
display: block !important; position: relative !important; text-align: center !important;
padding: 14px 14px 16px !important; min-height: 0 !important;
}
.welcome-banner .update-banner-icon { display: none !important; }
.welcome-banner .update-banner-text { flex: 1 1 auto; font-size: 15px !important; line-height: 1.3 !important; margin: 0 !important; }
.welcome-banner .welcome-banner-start {
flex: 0 0 auto; font-size: 16px !important; min-height: 40px !important;
padding: 6px 14px !important; margin: 0 !important; width: auto !important;
.welcome-banner .update-banner-text {
display: block !important; font-size: 15px !important; line-height: 1.3 !important;
margin: 0 28px 12px !important;
}
.welcome-banner a.welcome-banner-start {
display: block !important; width: auto !important; margin: 0 !important;
min-height: 72px !important; line-height: 72px !important; padding: 0 16px !important;
font-family: var(--a26-tit, inherit) !important; font-size: 34px !important; font-weight: 900 !important;
letter-spacing: 2px !important; text-transform: uppercase !important; text-align: center !important;
border-radius: var(--a26-radius, 12px) !important;
}
.welcome-banner .welcome-banner-close { position: absolute !important; top: 0 !important; right: 0 !important; margin: 0 !important; }
.welcome-banner .welcome-banner-close-btn {
min-height: 44px !important; height: 44px !important; width: 44px !important; padding: 0 !important; margin: 0 !important;
font-size: 16px !important; color: var(--ux-muted) !important;
}
.welcome-banner .welcome-banner-close { margin: 0 !important; flex: 0 0 auto; }
.welcome-banner .welcome-banner-close-btn { min-height: 40px !important; width: 36px !important; margin: 0 !important; }
/* ---------- pie de una linea ---------- */
.oasis-footer.oasis-footer-mobile {
@ -603,6 +613,11 @@ body:has(#oasis-menu-toggle:checked) form.oasis-phone-state { display: none !imp
.main-column .ux-pick-text .ux-pick-label { display: block; }
.main-column .ux-pick-sub { display: block; margin-top: 2px; font-size: 13px; font-weight: 400; line-height: 1.3; opacity: .8; }
.main-column .wf-pick button.ux-pick-card { padding: 10px 14px !important; }
/* skins: cuantos modulos y los iconos de su barra de abajo */
.main-column .wf-pick .wf-count { display: inline-block; margin-top: 6px; font-size: 13px; font-weight: 700; }
.main-column .wf-pick .wf-bar { display: inline-block; margin: 6px 0 0 10px; vertical-align: middle; opacity: .85; }
.main-column .wf-pick .wf-bar-ico { display: inline-block; width: 18px; height: 18px; margin-right: 6px; vertical-align: middle; font-size: 15px; line-height: 18px; }
.main-column .wf-pick .wf-bar-ico svg { width: 18px; height: 18px; }
.main-column .wf-pick .ux-pick-grid { display: block !important; }
@media (min-width: 700px) {
.main-column .ux-pick-grid { display: grid !important; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-gap: 12px; }
@ -649,6 +664,9 @@ body:has(#oasis-menu-toggle:checked) form.oasis-phone-state { display: none !imp
.main-column button.pal-card.is-current { border-width: 3px !important; box-shadow: 0 0 0 3px var(--ux-accent) !important; }
.main-column button.pal-card { justify-content: flex-start !important; }
.main-column .pal-card .pal-name { flex: 1 1 auto; min-width: 0; text-align: left; font-size: 15px; font-weight: 700; line-height: 1.15; }
/* nombres como Madrugada no se parten por la mitad a 360px */
.main-column .pal-card .pal-name { overflow-wrap: normal !important; word-break: normal !important; hyphens: auto; }
@media (max-width: 380px) { .main-column .pal-card .pal-name { font-size: 14px; } }
.main-column .pal-card .ux-pick-now { display: none; }
.pal-swatch { display: inline-flex; flex: 0 0 auto; width: 42px; height: 30px; margin-right: 10px; border-radius: 8px; overflow: hidden; border: 1px solid var(--ux-line); }
.pal-swatch .pal-bg { flex: 2 1 0; }
@ -677,6 +695,23 @@ body:has(#oasis-menu-toggle:checked) form.oasis-phone-state { display: none !imp
width: auto !important; min-width: 0; min-height: 44px !important; margin: 0 !important; padding: 4px 6px !important;
font-size: 14px !important; line-height: 1.15 !important; overflow-wrap: anywhere;
}
/* las fichas van plegadas tras un boton Filtrar (mobile_ui.activityFilter); por
defecto se ve todo y con un filtro puesto el boton dice cual */
.main-column details.activity-filter { margin: 0 0 12px !important; }
.main-column details.activity-filter > summary.activity-filter-toggle {
display: flex; align-items: center; justify-content: center; min-height: 48px; list-style: none; cursor: pointer;
border: 1px solid var(--ux-line); border-radius: var(--a26-radius, 12px);
font-weight: 700; font-size: 16px; text-transform: uppercase; letter-spacing: 1px;
}
.main-column details.activity-filter > summary::-webkit-details-marker { display: none; }
.main-column details.activity-filter > summary::after { content: "\25BE"; margin-left: 8px; font-size: 16px; }
.main-column details.activity-filter[open] > summary { margin-bottom: 10px; }
.main-column details.activity-filter[open] > summary::after { content: "\25B4"; }
.main-column details.activity-filter.is-filtered > summary { background: var(--ux-accent); color: var(--ux-on-accent); border-color: var(--ux-accent); }
.main-column .activity-filter-now { margin-left: 8px; font-weight: 400; text-transform: none; letter-spacing: 0; }
.main-column .activity-filter-now::before { content: "\00B7"; margin-right: 8px; }
.main-column details.activity-filter div.activity-filter-chips:not(.activity-toolbar-row) { margin: 0 !important; }
/* cabecera de cada tarjeta: los botones en una fila arriba a la derecha y la etiqueta
(FEEDS, SALAS...) debajo a la izquierda; antes compartian fila y la X caia sola */
.main-column div.card-header.activity-card-header { display: flex !important; flex-direction: column !important; align-items: stretch !important; padding: 0 !important; margin: 0 0 8px !important; }
@ -767,3 +802,11 @@ body .oasis-mobile-topbar .omt-logo img, body .oasis-mobile-topbar .omt-avatar i
/* sticky dentro de un fixed se pintaba en blanco */
.menu-sheet-head { position: relative !important; top: 0 !important; }
}
/* ---------- bienvenida: el boton de cada paso a todo lo ancho y con el resalte ----------
seguir tiene que ser lo facil; "Ahora no" se queda discreto al final */
.main-column details.welcome-step .welcome-action button[type="submit"]:not(.welcome-skip-btn) {
display: block !important; width: 100% !important; min-height: 52px !important; margin: 8px 0 0 !important;
background: var(--ux-accent) !important; color: var(--ux-on-accent) !important; border-color: var(--ux-accent) !important;
font-weight: 700 !important;
}

View file

@ -59,14 +59,14 @@ module.exports = {
colorsApply: "Apply",
colorsFixed: "The text could not be read on that background, so it was set to black or white.",
colorsKeep: "Keep these",
palette_acampada: "Light",
palette_noche: "Night",
palette_oro: "Gold",
palette_bosque: "Forest",
palette_lila: "Lilac",
palette_brasa: "Ember",
palette_papel: "Paper",
palette_contraste: "High contrast",
palette_oasis: "Standard",
palette_acampada: "Square",
palette_noche: "Late night",
palette_bosque: "Garden",
palette_lila: "Violet",
palette_brasa: "Bonfire",
palette_papel: "Fanzine",
palette_contraste: "Placard",
welcomeStepUseMobile: "Profile",
welcomeHintUseMobile: "What you use Oasis for. It turns on the modules you need.",
wfHint_activists: "Assemblies, tribes, votes, forums and shared documents",
@ -80,6 +80,11 @@ module.exports = {
wfHint_business: "Economy, banking, office and documents",
wfHint_mobile: "The basics for a phone",
workflow_acampada: "Camp",
workflow_activista: "Activist",
wfHint_activista: "Direct action: call out, coordinate, phone and alert",
wfNameMobile_activists: "Movement",
wfModuleCount: "{n} modules",
activityFilter: "Filter",
tribeSectionsMore: "More",
tribeSectionsLabel: "Sections",
voteYes: "Yes",
@ -98,8 +103,8 @@ module.exports = {
voteKindHint_scale: "From 1 (cold) to 5 (hot)",
deleteConfirmQuestion: "Delete it for good?",
deleteConfirmYes: "Yes, delete",
welcomeBannerTextMobile: "Add your name and photo so people know it is you.",
welcomeBannerActionMobile: "Set up",
welcomeBannerTextMobile: "Set up Oasis in a minute.",
welcomeBannerActionMobile: "Start",
footerPeersNone: "Not syncing with anyone yet",
footerPeersSome: "Syncing with {n}",
tribeMapUrlLabel: "Map link (optional)",
@ -108,7 +113,7 @@ module.exports = {
modulesOnCount: "{on} of {total} sections on",
// 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.",
workflowsDescriptionMobile: "Each profile turns on some modules and brings its own bottom bar. From fewer to more; change it whenever you like.",
// 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.",
// Identidades
@ -195,14 +200,14 @@ module.exports = {
colorsApply: "Aplicar",
colorsFixed: "El texto no se leía sobre ese fondo, así que se ha puesto en negro o blanco.",
colorsKeep: "Dejar estos",
palette_acampada: "Claro",
palette_noche: "Noche",
palette_oro: "Oro",
palette_bosque: "Bosque",
palette_lila: "Lila",
palette_brasa: "Brasa",
palette_papel: "Papel",
palette_contraste: "Alto contraste",
palette_oasis: "Estándar",
palette_acampada: "Plaza",
palette_noche: "Madrugada",
palette_bosque: "Huerto",
palette_lila: "Violeta",
palette_brasa: "Hoguera",
palette_papel: "Fanzine",
palette_contraste: "Pancarta",
welcomeStepUseMobile: "Perfil",
welcomeHintUseMobile: "Para qué usas Oasis. Enciende los módulos que hacen falta.",
wfHint_activists: "Asambleas, tribus, votaciones, foros y documentos compartidos",
@ -216,6 +221,11 @@ module.exports = {
wfHint_business: "Economía, banca, oficina y documentos",
wfHint_mobile: "Lo básico para el móvil",
workflow_acampada: "Acampada",
workflow_activista: "Activista",
wfHint_activista: "Acción directa: convocar, coordinarse, llamar y avisar",
wfNameMobile_activists: "Movimiento",
wfModuleCount: "{n} módulos",
activityFilter: "Filtrar",
tribeSectionsMore: "Más",
tribeSectionsLabel: "Secciones",
voteYes: "Sí",
@ -234,8 +244,8 @@ module.exports = {
voteKindHint_scale: "Del 1 (frío) al 5 (caliente)",
deleteConfirmQuestion: "¿Borrar para siempre?",
deleteConfirmYes: "Sí, borrar",
welcomeBannerTextMobile: "Pon tu nombre y tu foto para que te reconozcan.",
welcomeBannerActionMobile: "Ponerlos",
welcomeBannerTextMobile: "Prepara Oasis en un minuto.",
welcomeBannerActionMobile: "Empezar",
footerPeersNone: "Aún no sincronizas con nadie",
footerPeersSome: "Sincronizando con {n}",
tribeMapUrlLabel: "Enlace del mapa (opcional)",
@ -244,7 +254,7 @@ module.exports = {
modulesOnCount: "{on} de {total} secciones activas",
// 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á.",
workflowsDescriptionMobile: "Cada perfil enciende unos módulos y trae su barra de abajo. Van de menos a más; cámbialo cuando quieras.",
// 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.",
// Identidades
@ -337,14 +347,14 @@ module.exports = {
colorsApply: "Appliquer",
colorsFixed: "Le texte n'était pas lisible sur ce fond, il a été mis en noir ou en blanc.",
colorsKeep: "Garder celles-ci",
palette_acampada: "Clair",
palette_noche: "Nuit",
palette_oro: "Or",
palette_bosque: "Forêt",
palette_lila: "Lilas",
palette_brasa: "Braise",
palette_papel: "Papier",
palette_contraste: "Contraste élevé",
palette_oasis: "Standard",
palette_acampada: "Place",
palette_noche: "Nuit blanche",
palette_bosque: "Potager",
palette_lila: "Violette",
palette_brasa: "Feu de camp",
palette_papel: "Fanzine",
palette_contraste: "Pancarte",
welcomeStepUseMobile: "Profil",
welcomeHintUseMobile: "À quoi vous sert Oasis. Active les modules nécessaires.",
wfHint_activists: "Assemblées, tribus, votes, forums et documents partagés",
@ -358,6 +368,11 @@ module.exports = {
wfHint_business: "Économie, banque, bureau et documents",
wfHint_mobile: "L'essentiel pour le téléphone",
workflow_acampada: "Campement",
workflow_activista: "Activiste",
wfHint_activista: "Action directe : appeler, se coordonner, téléphoner et alerter",
wfNameMobile_activists: "Mouvement",
wfModuleCount: "{n} modules",
activityFilter: "Filtrer",
tribeSectionsMore: "Plus",
tribeSectionsLabel: "Sections",
voteYes: "Oui",
@ -376,8 +391,8 @@ module.exports = {
voteKindHint_scale: "De 1 (froid) à 5 (chaud)",
deleteConfirmQuestion: "Supprimer définitivement ?",
deleteConfirmYes: "Oui, supprimer",
welcomeBannerTextMobile: "Ajoutez votre nom et votre photo pour qu'on vous reconnaisse.",
welcomeBannerActionMobile: "Ajouter",
welcomeBannerTextMobile: "Préparez Oasis en une minute.",
welcomeBannerActionMobile: "Commencer",
footerPeersNone: "Aucune synchronisation pour l'instant",
footerPeersSome: "Synchronisé avec {n}",
tribeMapUrlLabel: "Lien de la carte (facultatif)",
@ -386,7 +401,7 @@ module.exports = {
modulesOnCount: "{on} sections actives sur {total}",
// 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.",
workflowsDescriptionMobile: "Chaque profil active des modules et apporte sa barre du bas. Du plus simple au plus complet ; changez quand vous voulez.",
// 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.",
// Identidades
@ -473,14 +488,14 @@ module.exports = {
colorsApply: "Aplikatu",
colorsFixed: "Testua ez zen irakurtzen hondo horretan, beltzez edo zuriz jarri da.",
colorsKeep: "Hauek utzi",
palette_acampada: "Argia",
palette_noche: "Gaua",
palette_oro: "Urrea",
palette_bosque: "Basoa",
palette_lila: "Lila",
palette_brasa: "Txingarra",
palette_papel: "Papera",
palette_contraste: "Kontraste handia",
palette_oasis: "Estandarra",
palette_acampada: "Plaza",
palette_noche: "Goizaldea",
palette_bosque: "Baratzea",
palette_lila: "Morea",
palette_brasa: "Sua",
palette_papel: "Fanzinea",
palette_contraste: "Pankarta",
welcomeStepUseMobile: "Profila",
welcomeHintUseMobile: "Oasis zertarako erabiltzen duzun. Behar diren moduluak pizten ditu.",
wfHint_activists: "Batzarrak, tribuak, bozketak, foroak eta dokumentu partekatuak",
@ -494,6 +509,11 @@ module.exports = {
wfHint_business: "Ekonomia, banka, bulegoa eta dokumentuak",
wfHint_mobile: "Mugikorrerako oinarrizkoa",
workflow_acampada: "Kanpaldia",
workflow_activista: "Aktibista",
wfHint_activista: "Ekintza zuzena: deitu, koordinatu, telefonoz hitz egin eta abisatu",
wfNameMobile_activists: "Mugimendua",
wfModuleCount: "{n} modulu",
activityFilter: "Iragazi",
tribeSectionsMore: "Gehiago",
tribeSectionsLabel: "Atalak",
voteYes: "Bai",
@ -512,8 +532,8 @@ module.exports = {
voteKindHint_scale: "1etik (hotza) 5era (beroa)",
deleteConfirmQuestion: "Betiko ezabatu?",
deleteConfirmYes: "Bai, ezabatu",
welcomeBannerTextMobile: "Jarri zure izena eta argazkia ezagutu zaitzaten.",
welcomeBannerActionMobile: "Jarri",
welcomeBannerTextMobile: "Prestatu Oasis minutu batean.",
welcomeBannerActionMobile: "Hasi",
footerPeersNone: "Oraindik ez zaude inorekin sinkronizatzen",
footerPeersSome: "{n}-rekin sinkronizatzen",
tribeMapUrlLabel: "Maparen esteka (aukerakoa)",
@ -522,7 +542,7 @@ module.exports = {
modulesOnCount: "{total} ataletatik {on} aktibo",
// 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.",
workflowsDescriptionMobile: "Profil bakoitzak modulu batzuk pizten ditu eta beheko barra propioa dakar. Gutxitik gehiagora; aldatu nahi duzunean.",
// 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.",
// Identidades
@ -609,14 +629,14 @@ module.exports = {
colorsApply: "Anwenden",
colorsFixed: "Der Text war auf diesem Hintergrund nicht lesbar, daher wurde er schwarz oder weiß gesetzt.",
colorsKeep: "Diese behalten",
palette_acampada: "Hell",
palette_noche: "Nacht",
palette_oro: "Gold",
palette_bosque: "Wald",
palette_lila: "Flieder",
palette_brasa: "Glut",
palette_papel: "Papier",
palette_contraste: "Hoher Kontrast",
palette_oasis: "Standard",
palette_acampada: "Platz",
palette_noche: "Spät nachts",
palette_bosque: "Garten",
palette_lila: "Violett",
palette_brasa: "Lagerfeuer",
palette_papel: "Fanzine",
palette_contraste: "Transparent",
welcomeStepUseMobile: "Profil",
welcomeHintUseMobile: "Wofür du Oasis nutzt. Schaltet die nötigen Module ein.",
wfHint_activists: "Versammlungen, Stämme, Abstimmungen, Foren und gemeinsame Dokumente",
@ -630,6 +650,11 @@ module.exports = {
wfHint_business: "Wirtschaft, Bank, Büro und Dokumente",
wfHint_mobile: "Das Wichtigste fürs Handy",
workflow_acampada: "Camp",
workflow_activista: "Aktivist*in",
wfHint_activista: "Direkte Aktion: aufrufen, koordinieren, telefonieren und warnen",
wfNameMobile_activists: "Bewegung",
wfModuleCount: "{n} Module",
activityFilter: "Filtern",
tribeSectionsMore: "Mehr",
tribeSectionsLabel: "Bereiche",
voteYes: "Ja",
@ -648,8 +673,8 @@ module.exports = {
voteKindHint_scale: "Von 1 (kalt) bis 5 (heiß)",
deleteConfirmQuestion: "Endgültig löschen?",
deleteConfirmYes: "Ja, löschen",
welcomeBannerTextMobile: "Füge deinen Namen und dein Foto hinzu, damit man dich erkennt.",
welcomeBannerActionMobile: "Einrichten",
welcomeBannerTextMobile: "Richte Oasis in einer Minute ein.",
welcomeBannerActionMobile: "Los geht's",
footerPeersNone: "Noch mit niemandem synchronisiert",
footerPeersSome: "Synchronisiert mit {n}",
tribeMapUrlLabel: "Kartenlink (optional)",
@ -658,7 +683,7 @@ module.exports = {
modulesOnCount: "{on} von {total} Bereichen aktiv",
// 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.",
workflowsDescriptionMobile: "Jedes Profil schaltet einige Module ein und bringt seine eigene untere Leiste mit. Von wenig zu viel; jederzeit änderbar.",
// 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.",
// Identidades
@ -745,14 +770,14 @@ module.exports = {
colorsApply: "Applica",
colorsFixed: "Il testo non si leggeva su quello sfondo, quindi è stato messo nero o bianco.",
colorsKeep: "Tieni questi",
palette_acampada: "Chiaro",
palette_noche: "Notte",
palette_oro: "Oro",
palette_bosque: "Bosco",
palette_lila: "Lilla",
palette_brasa: "Brace",
palette_papel: "Carta",
palette_contraste: "Alto contrasto",
palette_oasis: "Standard",
palette_acampada: "Piazza",
palette_noche: "Notte fonda",
palette_bosque: "Orto",
palette_lila: "Viola",
palette_brasa: "Falò",
palette_papel: "Fanzine",
palette_contraste: "Striscione",
welcomeStepUseMobile: "Profilo",
welcomeHintUseMobile: "A cosa ti serve Oasis. Attiva i moduli necessari.",
wfHint_activists: "Assemblee, tribù, votazioni, forum e documenti condivisi",
@ -766,6 +791,11 @@ module.exports = {
wfHint_business: "Economia, banca, ufficio e documenti",
wfHint_mobile: "L'essenziale per il telefono",
workflow_acampada: "Accampata",
workflow_activista: "Attivista",
wfHint_activista: "Azione diretta: convocare, coordinarsi, chiamare e avvisare",
wfNameMobile_activists: "Movimento",
wfModuleCount: "{n} moduli",
activityFilter: "Filtra",
tribeSectionsMore: "Altro",
tribeSectionsLabel: "Sezioni",
voteYes: "Sì",
@ -784,8 +814,8 @@ module.exports = {
voteKindHint_scale: "Da 1 (freddo) a 5 (caldo)",
deleteConfirmQuestion: "Eliminare per sempre?",
deleteConfirmYes: "Sì, elimina",
welcomeBannerTextMobile: "Aggiungi nome e foto perché ti riconoscano.",
welcomeBannerActionMobile: "Aggiungi",
welcomeBannerTextMobile: "Prepara Oasis in un minuto.",
welcomeBannerActionMobile: "Inizia",
footerPeersNone: "Non sincronizzi ancora con nessuno",
footerPeersSome: "In sincronia con {n}",
tribeMapUrlLabel: "Link della mappa (facoltativo)",
@ -794,7 +824,7 @@ module.exports = {
modulesOnCount: "{on} sezioni attive su {total}",
// 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'è.",
workflowsDescriptionMobile: "Ogni profilo attiva alcuni moduli e porta la sua barra in basso. Da meno a più; cambialo quando vuoi.",
// 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.",
// Identidades
@ -881,14 +911,14 @@ module.exports = {
colorsApply: "Aplicar",
colorsFixed: "O texto não se lia nesse fundo, por isso ficou preto ou branco.",
colorsKeep: "Manter estas",
palette_acampada: "Claro",
palette_noche: "Noite",
palette_oro: "Ouro",
palette_bosque: "Floresta",
palette_lila: "Lilás",
palette_brasa: "Brasa",
palette_papel: "Papel",
palette_contraste: "Alto contraste",
palette_oasis: "Padrão",
palette_acampada: "Praça",
palette_noche: "Madrugada",
palette_bosque: "Horta",
palette_lila: "Violeta",
palette_brasa: "Fogueira",
palette_papel: "Fanzine",
palette_contraste: "Faixa",
welcomeStepUseMobile: "Perfil",
welcomeHintUseMobile: "Para que usa o Oasis. Liga os módulos necessários.",
wfHint_activists: "Assembleias, tribos, votações, fóruns e documentos partilhados",
@ -902,6 +932,11 @@ module.exports = {
wfHint_business: "Economia, banca, escritório e documentos",
wfHint_mobile: "O básico para o telemóvel",
workflow_acampada: "Acampada",
workflow_activista: "Ativista",
wfHint_activista: "Ação direta: convocar, coordenar, ligar e avisar",
wfNameMobile_activists: "Movimento",
wfModuleCount: "{n} módulos",
activityFilter: "Filtrar",
tribeSectionsMore: "Mais",
tribeSectionsLabel: "Secções",
voteYes: "Sim",
@ -920,8 +955,8 @@ module.exports = {
voteKindHint_scale: "De 1 (frio) a 5 (quente)",
deleteConfirmQuestion: "Apagar para sempre?",
deleteConfirmYes: "Sim, apagar",
welcomeBannerTextMobile: "Põe o teu nome e a tua foto para que te reconheçam.",
welcomeBannerActionMobile: "Pôr",
welcomeBannerTextMobile: "Prepare o Oasis num minuto.",
welcomeBannerActionMobile: "Começar",
footerPeersNone: "Ainda não sincronizas com ninguém",
footerPeersSome: "A sincronizar com {n}",
tribeMapUrlLabel: "Ligação do mapa (opcional)",
@ -930,7 +965,7 @@ module.exports = {
modulesOnCount: "{on} de {total} secções ativas",
// 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á.",
workflowsDescriptionMobile: "Cada perfil liga alguns módulos e traz a sua barra de baixo. De menos para mais; muda quando quiseres.",
// 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.",
// Identidades
@ -1017,14 +1052,14 @@ module.exports = {
colorsApply: "应用",
colorsFixed: "文字在该背景上看不清,已改为黑色或白色。",
colorsKeep: "保留这些",
palette_acampada: "浅色",
palette_noche: "夜晚",
palette_oro: "金色",
palette_bosque: "森林",
palette_lila: "丁香",
palette_brasa: "余烬",
palette_papel: "纸张",
palette_contraste: "高对比度",
palette_oasis: "标准",
palette_acampada: "广场",
palette_noche: "深夜",
palette_bosque: "菜园",
palette_lila: "紫罗兰",
palette_brasa: "篝火",
palette_papel: "小志",
palette_contraste: "横幅",
welcomeStepUseMobile: "用途",
welcomeHintUseMobile: "你用 Oasis 做什么。会打开需要的模块。",
wfHint_activists: "集会、部落、投票、论坛和共享文档",
@ -1038,6 +1073,11 @@ module.exports = {
wfHint_business: "经济、银行、办公和文档",
wfHint_mobile: "手机基本功能",
workflow_acampada: "营地",
workflow_activista: "活动者",
wfHint_activista: "直接行动:召集、协调、通话和预警",
wfNameMobile_activists: "运动",
wfModuleCount: "{n} 个模块",
activityFilter: "筛选",
tribeSectionsMore: "更多",
tribeSectionsLabel: "板块",
voteYes: "赞成",
@ -1056,8 +1096,8 @@ module.exports = {
voteKindHint_scale: "从 1(冷)到 5(热)",
deleteConfirmQuestion: "永久删除?",
deleteConfirmYes: "是,删除",
welcomeBannerTextMobile: "添加你的名字和照片,让大家认出你。",
welcomeBannerActionMobile: "设置",
welcomeBannerTextMobile: "一分钟设置好 Oasis。",
welcomeBannerActionMobile: "开始",
footerPeersNone: "尚未与任何人同步",
footerPeersSome: "正在与 {n} 个节点同步",
tribeMapUrlLabel: "地图链接(可选)",
@ -1066,7 +1106,7 @@ module.exports = {
modulesOnCount: "已开启 {on}/{total} 个板块",
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "选择 Oasis 在手机上的外观。点一下就会生效。",
workflowsDescriptionMobile: "工作流决定启用哪些模块。在手机上,你的外观保持不变。",
workflowsDescriptionMobile: "每个配置会开启一些模块,并带有自己的底部栏。从少到多,随时可以更改。",
// fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "无法清除这张图片的元数据(位置、相机等),因此没有上传。请另存为 JPEG 或 PNG 后重试。",
// Identidades
@ -1153,14 +1193,14 @@ module.exports = {
colorsApply: "تطبيق",
colorsFixed: "لم يكن النص مقروءًا على تلك الخلفية، فجُعل أسود أو أبيض.",
colorsKeep: "الإبقاء على هذه",
palette_acampada: "فاتح",
palette_noche: "ليل",
palette_oro: "ذهب",
palette_bosque: "غابة",
palette_lila: "ليلكي",
palette_brasa: "جمر",
palette_papel: "ورق",
palette_contraste: "تباين عالٍ",
palette_oasis: "قياسي",
palette_acampada: "الساحة",
palette_noche: "آخر الليل",
palette_bosque: "البستان",
palette_lila: "بنفسجي",
palette_brasa: "نار المخيم",
palette_papel: "فانزين",
palette_contraste: "لافتة",
welcomeStepUseMobile: "الملف",
welcomeHintUseMobile: "لماذا تستخدم Oasis. يفعّل الوحدات التي تحتاجها.",
wfHint_activists: "جمعيات وقبائل وتصويت ومنتديات ووثائق مشتركة",
@ -1174,6 +1214,11 @@ module.exports = {
wfHint_business: "اقتصاد ومصرف ومكتب ووثائق",
wfHint_mobile: "الأساسيات للهاتف",
workflow_acampada: "مخيم",
workflow_activista: "ناشط",
wfHint_activista: "عمل مباشر: دعوة وتنسيق واتصال وتنبيه",
wfNameMobile_activists: "الحركة",
wfModuleCount: "{n} وحدات",
activityFilter: "تصفية",
tribeSectionsMore: "المزيد",
tribeSectionsLabel: "الأقسام",
voteYes: "نعم",
@ -1192,8 +1237,8 @@ module.exports = {
voteKindHint_scale: "من 1 (بارد) إلى 5 (ساخن)",
deleteConfirmQuestion: "حذف نهائيًا؟",
deleteConfirmYes: "نعم، احذف",
welcomeBannerTextMobile: "أضف اسمك وصورتك ليتعرّف عليك الآخرون.",
welcomeBannerActionMobile: "إضافة",
welcomeBannerTextMobile: "جهّز Oasis في دقيقة.",
welcomeBannerActionMobile: "ابدأ",
footerPeersNone: "لا مزامنة مع أحد بعد",
footerPeersSome: "مزامنة مع {n}",
tribeMapUrlLabel: "رابط الخريطة (اختياري)",
@ -1202,7 +1247,7 @@ module.exports = {
modulesOnCount: "{on} من {total} أقسام مفعّلة",
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "اختر مظهر Oasis على هاتفك. يُطبَّق بمجرد اللمس.",
workflowsDescriptionMobile: "يحدد سير العمل الوحدات المفعّلة. على الهاتف يبقى مظهرك كما هو.",
workflowsDescriptionMobile: "كل ملف يشغّل بعض الوحدات ويأتي بشريطه السفلي. من الأقل إلى الأكثر؛ غيّره متى شئت.",
// fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "تعذّر إزالة البيانات الوصفية من هذه الصورة (الموقع، الكاميرا…)، لذلك لم تُرفع. احفظها بصيغة JPEG أو PNG وحاول مجددًا.",
// Identidades
@ -1289,14 +1334,14 @@ module.exports = {
colorsApply: "लागू करें",
colorsFixed: "उस पृष्ठभूमि पर टेक्स्ट पढ़ा नहीं जा रहा था, इसलिए काला या सफ़ेद कर दिया गया।",
colorsKeep: "इन्हें रखें",
palette_acampada: "हल्का",
palette_noche: "रात",
palette_oro: "सोना",
palette_bosque: "जंगल",
palette_lila: "बकाइन",
palette_brasa: "अंगार",
palette_papel: "काग़ज़",
palette_contraste: "उच्च कंट्रास्ट",
palette_oasis: "मानक",
palette_acampada: "चौक",
palette_noche: "देर रात",
palette_bosque: "बगीचा",
palette_lila: "बैंगनी",
palette_brasa: "अलाव",
palette_papel: "फ़ैनज़ीन",
palette_contraste: "बैनर",
welcomeStepUseMobile: "प्रोफ़ाइल",
welcomeHintUseMobile: "आप Oasis किस लिए इस्तेमाल करते हैं। ज़रूरी मॉड्यूल चालू करता है।",
wfHint_activists: "सभाएँ, ट्राइब, मतदान, फ़ोरम और साझा दस्तावेज़",
@ -1310,6 +1355,11 @@ module.exports = {
wfHint_business: "अर्थव्यवस्था, बैंकिंग, दफ़्तर और दस्तावेज़",
wfHint_mobile: "फ़ोन के लिए बुनियादी",
workflow_acampada: "शिविर",
workflow_activista: "कार्यकर्ता",
wfHint_activista: "सीधी कार्रवाई: बुलाना, तालमेल, फ़ोन और चेतावनी",
wfNameMobile_activists: "आंदोलन",
wfModuleCount: "{n} मॉड्यूल",
activityFilter: "फ़िल्टर",
tribeSectionsMore: "और",
tribeSectionsLabel: "खंड",
voteYes: "हाँ",
@ -1328,8 +1378,8 @@ module.exports = {
voteKindHint_scale: "1 (ठंडा) से 5 (गरम) तक",
deleteConfirmQuestion: "हमेशा के लिए हटाएँ?",
deleteConfirmYes: "हाँ, हटाएँ",
welcomeBannerTextMobile: "अपना नाम और फ़ोटो जोड़ें ताकि लोग आपको पहचानें।",
welcomeBannerActionMobile: "जोड़ें",
welcomeBannerTextMobile: "एक मिनट में Oasis तैयार करें।",
welcomeBannerActionMobile: "शुरू करें",
footerPeersNone: "अभी किसी से सिंक नहीं",
footerPeersSome: "{n} से सिंक हो रहा है",
tribeMapUrlLabel: "नक्शे का लिंक (वैकल्पिक)",
@ -1338,7 +1388,7 @@ module.exports = {
modulesOnCount: "{total} में से {on} खंड चालू",
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "चुनें कि आपके फ़ोन पर Oasis कैसा दिखे। छूते ही लागू हो जाता है।",
workflowsDescriptionMobile: "वर्कफ़्लो तय करता है कि कौन-से मॉड्यूल चालू हैं। फ़ोन पर आपकी स्किन वैसी ही रहती है।",
workflowsDescriptionMobile: "हर प्रोफ़ाइल कुछ मॉड्यूल चालू करती है और अपनी निचली पट्टी लाती है। कम से ज़्यादा की ओर; जब चाहें बदलें।",
// fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "इस छवि का मेटाडेटा (स्थान, कैमरा…) हटाया नहीं जा सका, इसलिए इसे अपलोड नहीं किया गया। इसे JPEG या PNG के रूप में सहेजें और फिर कोशिश करें।",
// Identidades
@ -1425,14 +1475,14 @@ module.exports = {
colorsApply: "Применить",
colorsFixed: "Текст не читался на этом фоне, поэтому он стал чёрным или белым.",
colorsKeep: "Оставить эти",
palette_acampada: "Светлая",
palette_noche: "Ночь",
palette_oro: "Золото",
palette_bosque: "Лес",
palette_lila: "Сирень",
palette_brasa: "Угли",
palette_papel: "Бумага",
palette_contraste: "Высокий контраст",
palette_oasis: "Стандарт",
palette_acampada: "Площадь",
palette_noche: "Глубокая ночь",
palette_bosque: "Огород",
palette_lila: "Фиалка",
palette_brasa: "Костёр",
palette_papel: "Фэнзин",
palette_contraste: "Плакат",
welcomeStepUseMobile: "Профиль",
welcomeHintUseMobile: "Для чего вам Oasis. Включает нужные модули.",
wfHint_activists: "Собрания, племена, голосования, форумы и общие документы",
@ -1446,6 +1496,11 @@ module.exports = {
wfHint_business: "Экономика, банк, офис и документы",
wfHint_mobile: "Основное для телефона",
workflow_acampada: "Лагерь",
workflow_activista: "Активист",
wfHint_activista: "Прямое действие: созвать, координировать, звонить и предупреждать",
wfNameMobile_activists: "Движение",
wfModuleCount: "{n} модулей",
activityFilter: "Фильтр",
tribeSectionsMore: "Ещё",
tribeSectionsLabel: "Разделы",
voteYes: "Да",
@ -1464,8 +1519,8 @@ module.exports = {
voteKindHint_scale: "От 1 (холодно) до 5 (горячо)",
deleteConfirmQuestion: "Удалить навсегда?",
deleteConfirmYes: "Да, удалить",
welcomeBannerTextMobile: "Добавьте имя и фото, чтобы вас узнавали.",
welcomeBannerActionMobile: "Добавить",
welcomeBannerTextMobile: "Настройте Oasis за минуту.",
welcomeBannerActionMobile: "Начать",
footerPeersNone: "Пока ни с кем не синхронизировано",
footerPeersSome: "Синхронизация с {n}",
tribeMapUrlLabel: "Ссылка на карту (необязательно)",
@ -1474,7 +1529,7 @@ module.exports = {
modulesOnCount: "Включено {on} из {total} разделов",
// skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Выберите, как Oasis выглядит на телефоне. Применяется сразу по нажатию.",
workflowsDescriptionMobile: "Рабочий процесс задаёт, какие модули включены. На телефоне ваше оформление не меняется.",
workflowsDescriptionMobile: "Каждый профиль включает несколько модулей и приносит свою нижнюю панель. От меньшего к большему; меняйте когда угодно.",
// fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Не удалось удалить метаданные этого изображения (местоположение, камера…), поэтому оно не загружено. Сохраните его как JPEG или PNG и попробуйте снова.",
// Identidades

View file

@ -6,64 +6,64 @@
"current": "blocks"
},
"modules": {
"blogsMod": "on",
"pollsMod": "on",
"fediverseMod": "on",
"blogsMod": "off",
"pollsMod": "off",
"fediverseMod": "off",
"invitesMod": "on",
"walletMod": "off",
"devMod": "off",
"cipherMod": "on",
"bookmarksMod": "on",
"videosMod": "on",
"docsMod": "on",
"audiosMod": "on",
"tagsMod": "on",
"imagesMod": "on",
"trendingMod": "on",
"cipherMod": "off",
"bookmarksMod": "off",
"videosMod": "off",
"docsMod": "off",
"audiosMod": "off",
"tagsMod": "off",
"imagesMod": "off",
"trendingMod": "off",
"eventsMod": "on",
"tasksMod": "on",
"tasksMod": "off",
"marketMod": "off",
"votesMod": "on",
"tribesMod": "on",
"reportsMod": "on",
"opinionsMod": "on",
"padsMod": "on",
"calendarsMod": "on",
"votesMod": "off",
"tribesMod": "off",
"reportsMod": "off",
"opinionsMod": "off",
"padsMod": "off",
"calendarsMod": "off",
"transfersMod": "off",
"feedMod": "on",
"feedMod": "off",
"pixeliaMod": "off",
"melodyMod": "on",
"agendaMod": "on",
"melodyMod": "off",
"agendaMod": "off",
"aiMod": "off",
"aiNavMod": "off",
"forumMod": "on",
"forumMod": "off",
"gamesMod": "off",
"housingMod": "off",
"jobsMod": "off",
"shopsMod": "off",
"projectsMod": "on",
"projectsMod": "off",
"industryMod": "off",
"bankingMod": "off",
"schoolMod": "on",
"parliamentMod": "on",
"courtsMod": "on",
"favoritesMod": "on",
"logsMod": "on",
"mapsMod": "on",
"schoolMod": "off",
"parliamentMod": "off",
"courtsMod": "off",
"favoritesMod": "off",
"logsMod": "off",
"mapsMod": "off",
"chatsMod": "on",
"torrentsMod": "on",
"filesMod": "on",
"torrentsMod": "off",
"filesMod": "off",
"phoneMod": "on",
"roomsMod": "on",
"graphosMod": "on",
"larpMod": "on",
"roomsMod": "off",
"graphosMod": "off",
"larpMod": "off",
"backupMod": "on",
"campaignsMod": "on",
"campaignsMod": "off",
"emergenciesMod": "on",
"logisticsMod": "on",
"mailingMod": "on",
"podcastsMod": "on",
"wikiMod": "on"
"logisticsMod": "off",
"mailingMod": "off",
"podcastsMod": "off",
"wikiMod": "off"
},
"wallet": {
"url": "http://127.0.0.1:7474",
@ -97,8 +97,8 @@
"bottomBarPins": [
"activity",
"chats",
"publish",
"inbox"
"events",
"phone"
],
"rtc": {
"stun": [],

View file

@ -6,10 +6,23 @@
// los suyos empujandolos a los arrays que ese fichero exporta; getWorkflow,
// currentWorkflow y el asistente de bienvenida los leen de ahi.
// Ver docs/FRONTERA_UPSTREAM.md.
//
// En el movil los workflows son los skins: cada uno enciende unos modulos y trae su
// barra de abajo. Van de menos a mas: Activista (accion directa, lo minimo),
// Acampada, y despues los del dev por numero de modulos.
const wf = require('./workflows_model');
const FORK_WORKFLOWS = [
{
// accion directa: convocar, coordinarse, llamar y avisar. Lo minimo para salir a
// la calle; lo demas se enciende con otro skin
key: 'activista',
theme: 'Activista',
homePage: 'activity',
// (sin mapas: backend.js los apaga a la fuerza en el movil)
modules: ['chats', 'phone', 'events', 'emergencies', 'invites', 'backup']
},
{
// una acampada: hablar (chats, telefono y salas de voz del dev), escribir juntos,
// compartir lo que pasa y decidir (tribus = comisiones, parlamento y votaciones)
@ -21,6 +34,22 @@ const FORK_WORKFLOWS = [
}
];
// barra de abajo de cada skin: los cuatro atajos de lo que mas se usa en el (claves
// de PINNABLE_MODULES en hive_views.js). Quien la cambia, la cambia para ese skin
const BARS = {
activista: ['activity', 'chats', 'events', 'phone'],
acampada: ['activity', 'chats', 'tribes', 'votes'],
activists: ['activity', 'tribes', 'votes', 'forum'],
social: ['activity', 'feed', 'images', 'chats'],
night: ['feed', 'blogs', 'audios', 'chats'],
kids: ['activity', 'games', 'images', 'chats'],
jobs: ['activity', 'jobs', 'projects', 'tasks'],
business: ['activity', 'market', 'projects', 'banking'],
mobile: ['activity', 'chats', 'events', 'inbox'],
default: ['activity', 'chats', 'publish', 'inbox'],
full: ['activity', 'chats', 'publish', 'inbox']
};
let done = false;
const register = () => {
if (done) return;
@ -29,11 +58,35 @@ const register = () => {
if (wf.WORKFLOWS.some(x => x.key === w.key)) continue;
wf.WORKFLOWS.push(w);
wf.WORKFLOW_KEYS.push(w.key);
// en el asistente, detras de activistas (en el movil mobile_ui.workflowPick pone
// Activismo y Acampada las primeras)
// en el asistente, detras de activistas (en el movil mobile_ui.workflowPick los
// ordena por numero de modulos)
const at = wf.WIZARD_WORKFLOWS.indexOf('activists');
wf.WIZARD_WORKFLOWS.splice(at === -1 ? wf.WIZARD_WORKFLOWS.length : at + 1, 0, w.key);
}
};
module.exports = { FORK_WORKFLOWS, register };
// cuantos modulos enciende un skin ('full' no esta en WORKFLOWS)
const moduleCount = (key) => {
const w = key === 'full' ? { modules: wf.ALL_MODULES } : wf.getWorkflow(key);
return w ? wf.modulesOf(w).length : 0;
};
// la barra que toca: la que cada cual se hizo para ese skin, si no la del skin, y con
// los modulos a mano (sin skin) la de siempre, bottomBarPins
const barFor = (cfg) => {
register();
const key = wf.currentWorkflow(cfg);
const own = key && cfg.bottomBarBySkin && Array.isArray(cfg.bottomBarBySkin[key]) ? cfg.bottomBarBySkin[key] : null;
return (own || (key && BARS[key]) || cfg.bottomBarPins || []).slice(0, 4);
};
// guarda la barra en el skin puesto (o en bottomBarPins si no hay ninguno)
const saveBar = (cfg, pins) => {
register();
const key = wf.currentWorkflow(cfg);
if (!key) { cfg.bottomBarPins = pins; return cfg; }
cfg.bottomBarBySkin = Object.assign({}, cfg.bottomBarBySkin, { [key]: pins });
return cfg;
};
module.exports = { FORK_WORKFLOWS, BARS, register, moduleCount, barFor, saveBar };

View file

@ -3,6 +3,7 @@ const RAW_HTML = Symbol.for('oasis.rawHtml');
const { template, i18n, paged, userLink, userLinkLabel, renderStateChip, renderPhoneChip, renderSpreadButton, renderContentActions, renderVotesSummary, renderModuleStats, renderCardMetaRow, renderTorrentDownload, renderTorrentSourceDownload, renderFileDownloads, torrentDownloadHref, CONTENT_FAV_KIND, CONTENT_SPREADABLE, CONTENT_TORRENTABLE, contentDeleteAction } = require('./main_views');
const opinionCategories = require('../backend/opinion_categories');
const { roomNumberOf } = require('../models/phone_number');
const mobileUi = require("./mobile_ui");
const OPINION_TYPES = new Set(['bookmark','votes','feed','image','audio','video','document','torrent','file']);
const TORRENTABLE_TYPES = CONTENT_TORRENTABLE;
@ -2288,7 +2289,7 @@ exports.activityView = (actions, filter, userId, q = '', extras = {}) => {
h2(i18n.activityList),
p(desc)
),
emptyAct ? null : div({ class: 'activity-filter-chips' },
emptyAct ? null : mobileUi.activityFilter(filter, activityTypes, div({ class: 'activity-filter-chips' },
(() => {
const ORDER = [
'all', 'recent', 'mine', 'top',
@ -2314,7 +2315,7 @@ exports.activityView = (actions, filter, userId, q = '', extras = {}) => {
}, label)
);
})()
),
)),
emptyAct ? null : div({ class: 'activity-filter-chips activity-toolbar-row' },
renderModuleStats(filteredActions.length, [], null, { showInhabitants: true, showTribes: true }),
sub ? span({ class: 'activity-subchip-label' }, '\u21b3') : '',

View file

@ -47,6 +47,8 @@ module.exports = ({ i18n }) => {
{ key: 'data', href: '/data', glyph: 'ꘑ', labelKey: 'dataTitle', mod: 'dataMod' },
{ key: 'market', href: '/market', glyph: 'ꕻ', labelKey: 'marketTitle', mod: 'marketMod' },
{ key: 'events', href: '/events', glyph: 'ꕆ', labelKey: 'eventsLabel', mod: 'eventsMod' },
{ key: 'phone', href: '/phone', glyph: '☏', labelKey: 'phoneTitle', mod: 'phoneMod' },
{ key: 'emergencies', href: '/emergencies', glyph: '✚', labelKey: 'emergenciesTitle', mod: 'emergenciesMod' },
{ key: 'calendars', href: '/calendars', glyph: 'ꖯ', labelKey: 'calendarsTitle', mod: 'calendarsMod' },
{ key: 'banking', href: '/banking', glyph: 'ꗴ', labelKey: 'bankingTitle', mod: 'bankingMod' },
{ key: 'forum', href: '/forum', glyph: 'ꕒ', labelKey: 'forumTitle', mod: 'forumMod' },
@ -104,7 +106,7 @@ module.exports = ({ i18n }) => {
// barra PERSONALIZABLE: solo los pins (max 4). Editarla y Peers estan en el
// lanzador (Herramientas): 7 botones abajo eran demasiados para un pulgar.
const MAX = 4;
const pins = (cfg.bottomBarPins || [])
const pins = require('../models/fork_workflows').barFor(cfg)
.map(key => PINNABLE_MODULES.find(m => m.key === key))
.filter(m => m && modOn(m.mod))
.slice(0, MAX);
@ -253,7 +255,7 @@ module.exports = ({ i18n }) => {
const cfg = getConfig();
const modOn = (m) => !m || cfg.modules[m] === 'on' || cfg.modules[m] === undefined;
const MAX = 4;
const pinnedKeys = cfg.bottomBarPins || [];
const pinnedKeys = require('../models/fork_workflows').barFor(cfg);
const pinned = pinnedKeys
.map(key => PINNABLE_MODULES.find(m => m.key === key))
.filter(Boolean);

View file

@ -10,8 +10,9 @@
// /feed/create): no se reenvia nada a sus rutas ni se toca lo que contestan. Colores
// es propio: /settings/colors y la hoja /mobile-colors.css, que va la ultima.
//
// Los colores son las variables --a26-* del skin Activista, el unico del movil: el
// skin quita lo que sobra y los colores lo dejan a gusto de cada cual.
// Los colores son las variables --a26-* del skin Activista. Los skins (workflows)
// quitan lo que sobra y los colores lo dejan a gusto de cada cual; los de serie son
// los del dev.
const crypto = require("crypto");
const { a, button, details, div, form, img, input, label, p, section, span, summary, h2 } = require("../server/node_modules/hyperaxe");
@ -22,17 +23,20 @@ const cfgNow = () => { try { return require("../configs/config-manager.js").getC
// ---------- colores ----------
// [clave, fondo, texto, acento]; la primera es la de serie
// [clave, fondo, texto, acento]; la primera es la de serie y son los colores del dev
// (negro y oro de su tema OasisMobile). Los nombres, en i18n_fork (palette_<clave>)
const PALETTES = [
["oasis", "#121212", "#f2f2f2", "#ffd700"],
["acampada", "#ffffff", "#000000", "#00e5ff"],
["noche", "#101114", "#f2f2f2", "#00e5ff"],
["oro", "#121212", "#f2f2f2", "#ffd700"],
["bosque", "#f3f7ef", "#13231a", "#3ccf7e"],
["lila", "#faf7ff", "#1d1430", "#b48cff"],
["brasa", "#fff8f2", "#1a0f0a", "#ff6a2b"],
["papel", "#f5efe3", "#2a2420", "#ff4f8b"],
["contraste", "#000000", "#ffffff", "#ffff00"]
];
// claves de antes que ahora se llaman de otra forma
const RENAMED = { oro: "oasis" };
const DEFAULT = PALETTES[0];
const HEX = /^#[0-9a-f]{6}$/i;
@ -53,7 +57,8 @@ const colorState = (cfg) => {
if (!c || typeof c !== "object" || ![c.bg, c.fg, c.accent].every(v => HEX.test(String(v || "")))) {
return { preset: DEFAULT[0], bg: DEFAULT[1], fg: DEFAULT[2], accent: DEFAULT[3], chosen: false, fixed: false };
}
const preset = c.preset === "custom" || PALETTES.some(x => x[0] === c.preset) ? c.preset : "custom";
const key = RENAMED[c.preset] || c.preset;
const preset = key === "custom" || PALETTES.some(x => x[0] === key) ? key : "custom";
return { preset, bg: c.bg.toLowerCase(), fg: c.fg.toLowerCase(), accent: c.accent.toLowerCase(), chosen: true, fixed: c.fixed === true };
};
@ -79,7 +84,8 @@ const PREVIEW_CSS = PALETTES.map(([k, bg, fg, ac]) =>
// muestras de las paletas (la CSP no deja estilos en linea)
const colorsCss = (cfg) => {
const c = colorState(cfg);
const vars = c.chosen ? [
// sin nada guardado tambien: la de serie son los colores del dev, no los de Activista.css
const vars = [
`--a26-bg:${c.bg}`, `--a26-fg:${c.fg}`, `--a26-neon:${c.accent}`,
`--a26-on-neon:${readableOn(c.accent)}`,
`--a26-soft:${mix(c.bg, c.fg, 0.06)}`,
@ -90,9 +96,9 @@ const colorsCss = (cfg) => {
// rojo de texto (borrar): el de serie si se lee sobre el fondo; si no, uno claro
`--a26-danger-text:${contrast(c.bg, "#c4003b") >= 4.5 ? "#c4003b" : "#ff6b86"}`,
`color-scheme:${lum(c.bg) < 0.2 ? "dark" : "light"}`
] : [];
];
const custom = `.pal-custom .pal-bg{background:${c.bg}!important}.pal-custom .pal-fg{background:${c.fg}!important}.pal-custom .pal-ac{background:${c.accent}!important}`;
return (vars.length ? `:root{${vars.join(";")}}\n` : "") + PREVIEW_CSS + "\n" + custom + "\n";
return `:root{${vars.join(";")}}\n` + PREVIEW_CSS + "\n" + custom + "\n";
};
const colorsVersion = (cfg) => crypto.createHash("sha1").update(colorsCss(cfg)).digest("hex").slice(0, 10);
const colorsLink = () => require("../server/node_modules/hyperaxe").link({ rel: "stylesheet", href: `/mobile-colors.css?v=${colorsVersion()}` });
@ -150,7 +156,7 @@ const quickValue = (id, cfg) => {
if (id === "identity") return global.__OASIS_SELF_NAME__ || "";
if (id === "workflows") {
const wf = (() => { try { return require("../models/workflows_model").currentWorkflow(cfg); } catch (_) { return null; } })();
return wf ? (i18n[`workflow_${wf}`] || wf) : "";
return wf ? require("./mobile_ui").workflowName(wf) : "";
}
if (id === "ux") {
const ux = (cfg.ux || {}).current || "blocks";

View file

@ -11,7 +11,7 @@
// antes que el).
const { a, button, details, div, form, img, input, label, nav, p, progress, span, summary } = require("../server/node_modules/hyperaxe");
const { iconNode } = require("./mobile_icons");
const { iconNode, iconKeyOf } = require("./mobile_icons");
const isMobile = () => process.env.OASIS_MOBILE === '1';
const t = () => require('./main_views').i18n;
@ -152,20 +152,29 @@ const uxPick = (action, cfg, withHint) => {
);
};
// perfil de uso (workflow): igual, un boton por opcion con una linea de para que
// sirve. Activismo (el de serie) y Acampada primero; el resto en el orden del dev
const WORKFLOW_FIRST = ['activists', 'acampada'];
// perfil de uso (workflow), que en el movil es el skin: un boton por opcion con
// para que sirve, cuantos modulos enciende y su barra de abajo. Van de menos a mas
// modulos: Activista (accion directa) el primero
const workflowName = (k) => {
const i18n = t();
if (k === 'full') return i18n.welcomeWorkflow_full || k;
return i18n[`wfNameMobile_${k}`] || i18n[`workflow_${k}`] || k;
};
const workflowPick = (action, current, keys, withHint) => {
const i18n = t();
const list = WORKFLOW_FIRST.filter(k => keys.includes(k)).concat(keys.filter(k => !WORKFLOW_FIRST.includes(k)));
const name = (k) => k === 'full' ? (i18n.welcomeWorkflow_full || k) : (i18n[`workflow_${k}`] || k);
const fw = require('../models/fork_workflows');
const { PINNABLE_MODULES } = require('./main_views');
const list = keys.slice().sort((x, y) => fw.moduleCount(x) - fw.moduleCount(y));
const barOf = (k) => (fw.BARS[k] || []).map(key => (PINNABLE_MODULES || []).find(m => m.key === key)).filter(Boolean);
return form({ method: 'POST', action, class: 'ux-pick wf-pick' },
withHint ? p({ class: 'ux-pick-hint' }, i18n.uxPickHint || 'Tap one and it is saved. You can change it any time in Settings.') : null,
div({ class: 'ux-pick-grid' },
...list.map(k => button(Object.assign({ type: 'submit', name: 'workflow', value: k, class: k === current ? 'ux-pick-card is-current' : 'ux-pick-card' }, k === current ? { 'aria-current': 'true' } : {}),
span({ class: 'ux-pick-text' },
span({ class: 'ux-pick-label' }, name(k)),
i18n[`wfHint_${k}`] ? span({ class: 'ux-pick-sub' }, i18n[`wfHint_${k}`]) : null),
span({ class: 'ux-pick-label' }, workflowName(k)),
i18n[`wfHint_${k}`] ? span({ class: 'ux-pick-sub' }, i18n[`wfHint_${k}`]) : null,
span({ class: 'wf-count' }, String(i18n.wfModuleCount || '{n} modules').replace('{n}', String(fw.moduleCount(k)))),
barOf(k).length ? span({ class: 'wf-bar', 'aria-hidden': 'true' }, ...barOf(k).map(m => iconNode('wf-bar-ico', iconKeyOf(m.href), m.glyph))) : null),
k === current ? span({ class: 'ux-pick-now' }, i18n.uxPickCurrent || 'In use') : null
))
)
@ -184,6 +193,23 @@ const welcomeSteps = (usable) => {
return require('./mobile_settings').welcomeWithColors(out);
};
// ---------- actividad ----------
// las fichas de tipo de actividad (de tres en tres, varias filas antes de la primera
// tarjeta) van plegadas tras un boton Filtrar; por defecto se ve todo. Con un filtro
// puesto, el boton dice cual. Sin JS, con <details>. En escritorio, las fichas tal cual
const activityFilter = (filter, types, chips) => {
if (!isMobile()) return chips;
const i18n = t();
const cur = filter && filter !== 'all' ? ((types || []).find(x => x.type === filter) || {}).label : null;
return details({ class: cur ? 'activity-filter is-filtered' : 'activity-filter' },
summary({ class: 'activity-filter-toggle' },
span({ class: 'activity-filter-name' }, i18n.activityFilter || 'Filter'),
cur ? span({ class: 'activity-filter-now' }, cur) : null),
chips
);
};
// ---------- acciones de tarjeta ----------
// borrar pide un segundo toque: la X abre "¿Borrar? Si, borrar" y solo ese boton
@ -234,6 +260,6 @@ const welcomeDone = (steps) => require('./mobile_settings').welcomeDone(steps);
module.exports = {
colorsLink, colorsPick, welcomeDone,
isMobile, VOTE_KINDS, voteKindPicker, voteBars, voteOwnNote, tribeRow, tribeTabs,
settingsOrder, languagePick, uxPick, workflowPick, welcomeSteps, deleteConfirm, footerLine,
settingsOrder, languagePick, uxPick, workflowPick, workflowName, activityFilter, welcomeSteps, deleteConfirm, footerLine,
welcomeBannerHere, welcomeBannerText, welcomeBannerAction
};

View file

@ -71,7 +71,7 @@ const settingsView = (params) => {
)
);
const workflowPicker = () => section({ id: "workflows" },
div({ class: "tags-header" }, h2(i18n.workflowsTitle), p(i18n.workflowsDescriptionMobile)),
div({ class: "tags-header" }, h2(i18n.welcomeStepUseMobile || i18n.workflowsTitle), p(i18n.workflowsDescriptionMobile)),
mobileUi.workflowPick("/settings/workflow", activeWorkflow, WORKFLOWS.map(w => w.key))
);