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` | | Algo en Ajustes del móvil | `views/mobile_settings.js` |
| Un texto nuevo | `translations/i18n_fork.js`, en los 11 idiomas | | Un texto nuevo | `translations/i18n_fork.js`, en los 11 idiomas |
| Un icono | `views/mobile_icons.js` | | 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 de la APK | `android/scripts/sobre_oficial.sh` o `android/icono/` |
| Algo que la capa no deja | Pedírselo al dev | | 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. 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`, 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 ## 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ú, 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 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; 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 así: `docs/ESTUDIO_NAVEGACION.md`. Si se cambia, que sea con una prueba que lo
justifique, no por gusto. 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, - `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 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 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/mobile_modules_view.js`, `identities_view.js`: pantallas propias.
- `src/views/hive_views.js`: lanzador y barras de arriba y abajo. - `src/views/hive_views.js`: lanzador y barras de arriba y abajo.
- `src/views/mobile_icons.js`: los iconos. - `src/views/mobile_icons.js`: los iconos.
- `src/backend/fork_routes.js`: nuestro router. Va justo delante del del dev. - `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 - `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`. (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/translations/i18n_fork.js`: nuestros textos.
- `src/client/assets/images/ux-*.svg`: nuestras imágenes. - `src/client/assets/images/ux-*.svg`: nuestras imágenes.
- `android/scripts/sobre_oficial.sh`: monta la APK sobre la oficial del dev. El resto - `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 action = String(body.action || '').trim();
const key = String(body.key || '').trim(); const key = String(body.key || '').trim();
const catalog = require("../views/main_views").PINNABLE_MODULES || []; 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 (action === 'add') {
if (key && catalog.some(m => m.key === key) && !pins.includes(key) && pins.length < MAX) pins.push(key); if (key && catalog.some(m => m.key === key) && !pins.includes(key) && pins.length < MAX) pins.push(key);
} else if (action === 'remove') { } else if (action === 'remove') {
@ -92,7 +94,7 @@ const mobileLayer = require('./mobile_layer')({ getViewerId, about });
} else if (action === 'clear') { } else if (action === 'clear') {
pins = []; pins = [];
} }
cfg.bottomBarPins = pins.slice(0, MAX); bars.saveBar(cfg, pins.slice(0, MAX));
saveConfig(cfg); saveConfig(cfg);
ctx.redirect('/settings/bottombar'); ctx.redirect('/settings/bottombar');
}) })

View file

@ -86,19 +86,29 @@
body { padding-bottom: 0 !important; } body { padding-bottom: 0 !important; }
} }
/* ---------- aviso de bienvenida: una linea, no un bloque ---------- */ /* ---------- aviso de bienvenida: un boton EMPEZAR que no se pueda pasar por alto ----------
.welcome-banner { la X queda pequeña en la esquina: cerrar tiene que costar mas que empezar */
display: flex !important; align-items: center !important; gap: 10px !important; .main-column .welcome-banner, .welcome-banner {
padding: 8px 8px 8px 14px !important; min-height: 0 !important; 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-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 .update-banner-text {
.welcome-banner .welcome-banner-start { display: block !important; font-size: 15px !important; line-height: 1.3 !important;
flex: 0 0 auto; font-size: 16px !important; min-height: 40px !important; margin: 0 28px 12px !important;
padding: 6px 14px !important; margin: 0 !important; width: auto !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 ---------- */ /* ---------- pie de una linea ---------- */
.oasis-footer.oasis-footer-mobile { .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-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 .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; } .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; } .main-column .wf-pick .ux-pick-grid { display: block !important; }
@media (min-width: 700px) { @media (min-width: 700px) {
.main-column .ux-pick-grid { display: grid !important; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-gap: 12px; } .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.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 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; } .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; } .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 { 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; } .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; 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; 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 /* 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 */ (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; } .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 */ /* sticky dentro de un fixed se pintaba en blanco */
.menu-sheet-head { position: relative !important; top: 0 !important; } .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", colorsApply: "Apply",
colorsFixed: "The text could not be read on that background, so it was set to black or white.", colorsFixed: "The text could not be read on that background, so it was set to black or white.",
colorsKeep: "Keep these", colorsKeep: "Keep these",
palette_acampada: "Light", palette_oasis: "Standard",
palette_noche: "Night", palette_acampada: "Square",
palette_oro: "Gold", palette_noche: "Late night",
palette_bosque: "Forest", palette_bosque: "Garden",
palette_lila: "Lilac", palette_lila: "Violet",
palette_brasa: "Ember", palette_brasa: "Bonfire",
palette_papel: "Paper", palette_papel: "Fanzine",
palette_contraste: "High contrast", palette_contraste: "Placard",
welcomeStepUseMobile: "Profile", welcomeStepUseMobile: "Profile",
welcomeHintUseMobile: "What you use Oasis for. It turns on the modules you need.", welcomeHintUseMobile: "What you use Oasis for. It turns on the modules you need.",
wfHint_activists: "Assemblies, tribes, votes, forums and shared documents", wfHint_activists: "Assemblies, tribes, votes, forums and shared documents",
@ -80,6 +80,11 @@ module.exports = {
wfHint_business: "Economy, banking, office and documents", wfHint_business: "Economy, banking, office and documents",
wfHint_mobile: "The basics for a phone", wfHint_mobile: "The basics for a phone",
workflow_acampada: "Camp", 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", tribeSectionsMore: "More",
tribeSectionsLabel: "Sections", tribeSectionsLabel: "Sections",
voteYes: "Yes", voteYes: "Yes",
@ -98,8 +103,8 @@ module.exports = {
voteKindHint_scale: "From 1 (cold) to 5 (hot)", voteKindHint_scale: "From 1 (cold) to 5 (hot)",
deleteConfirmQuestion: "Delete it for good?", deleteConfirmQuestion: "Delete it for good?",
deleteConfirmYes: "Yes, delete", deleteConfirmYes: "Yes, delete",
welcomeBannerTextMobile: "Add your name and photo so people know it is you.", welcomeBannerTextMobile: "Set up Oasis in a minute.",
welcomeBannerActionMobile: "Set up", welcomeBannerActionMobile: "Start",
footerPeersNone: "Not syncing with anyone yet", footerPeersNone: "Not syncing with anyone yet",
footerPeersSome: "Syncing with {n}", footerPeersSome: "Syncing with {n}",
tribeMapUrlLabel: "Map link (optional)", tribeMapUrlLabel: "Map link (optional)",
@ -108,7 +113,7 @@ module.exports = {
modulesOnCount: "{on} of {total} sections on", modulesOnCount: "{on} of {total} sections on",
// skins y workflows en el movil (settings_view.js) // 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.", 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) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "This image could not be cleaned of its metadata (location, camera…), so it has not been uploaded. Save it as JPEG or PNG and try again.", imageMetadataUnsafe: "This image could not be cleaned of its metadata (location, camera…), so it has not been uploaded. Save it as JPEG or PNG and try again.",
// Identidades // Identidades
@ -195,14 +200,14 @@ module.exports = {
colorsApply: "Aplicar", colorsApply: "Aplicar",
colorsFixed: "El texto no se leía sobre ese fondo, así que se ha puesto en negro o blanco.", colorsFixed: "El texto no se leía sobre ese fondo, así que se ha puesto en negro o blanco.",
colorsKeep: "Dejar estos", colorsKeep: "Dejar estos",
palette_acampada: "Claro", palette_oasis: "Estándar",
palette_noche: "Noche", palette_acampada: "Plaza",
palette_oro: "Oro", palette_noche: "Madrugada",
palette_bosque: "Bosque", palette_bosque: "Huerto",
palette_lila: "Lila", palette_lila: "Violeta",
palette_brasa: "Brasa", palette_brasa: "Hoguera",
palette_papel: "Papel", palette_papel: "Fanzine",
palette_contraste: "Alto contraste", palette_contraste: "Pancarta",
welcomeStepUseMobile: "Perfil", welcomeStepUseMobile: "Perfil",
welcomeHintUseMobile: "Para qué usas Oasis. Enciende los módulos que hacen falta.", welcomeHintUseMobile: "Para qué usas Oasis. Enciende los módulos que hacen falta.",
wfHint_activists: "Asambleas, tribus, votaciones, foros y documentos compartidos", wfHint_activists: "Asambleas, tribus, votaciones, foros y documentos compartidos",
@ -216,6 +221,11 @@ module.exports = {
wfHint_business: "Economía, banca, oficina y documentos", wfHint_business: "Economía, banca, oficina y documentos",
wfHint_mobile: "Lo básico para el móvil", wfHint_mobile: "Lo básico para el móvil",
workflow_acampada: "Acampada", 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", tribeSectionsMore: "Más",
tribeSectionsLabel: "Secciones", tribeSectionsLabel: "Secciones",
voteYes: "Sí", voteYes: "Sí",
@ -234,8 +244,8 @@ module.exports = {
voteKindHint_scale: "Del 1 (frío) al 5 (caliente)", voteKindHint_scale: "Del 1 (frío) al 5 (caliente)",
deleteConfirmQuestion: "¿Borrar para siempre?", deleteConfirmQuestion: "¿Borrar para siempre?",
deleteConfirmYes: "Sí, borrar", deleteConfirmYes: "Sí, borrar",
welcomeBannerTextMobile: "Pon tu nombre y tu foto para que te reconozcan.", welcomeBannerTextMobile: "Prepara Oasis en un minuto.",
welcomeBannerActionMobile: "Ponerlos", welcomeBannerActionMobile: "Empezar",
footerPeersNone: "Aún no sincronizas con nadie", footerPeersNone: "Aún no sincronizas con nadie",
footerPeersSome: "Sincronizando con {n}", footerPeersSome: "Sincronizando con {n}",
tribeMapUrlLabel: "Enlace del mapa (opcional)", tribeMapUrlLabel: "Enlace del mapa (opcional)",
@ -244,7 +254,7 @@ module.exports = {
modulesOnCount: "{on} de {total} secciones activas", modulesOnCount: "{on} de {total} secciones activas",
// skins y workflows en el movil (settings_view.js) // skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Elige cómo se ve Oasis en tu móvil. Se aplica al tocarlo.", 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) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "No se han podido quitar los metadatos de esta imagen (ubicación, cámara…), así que no se ha subido. Guárdala como JPEG o PNG y vuelve a intentarlo.", imageMetadataUnsafe: "No se han podido quitar los metadatos de esta imagen (ubicación, cámara…), así que no se ha subido. Guárdala como JPEG o PNG y vuelve a intentarlo.",
// Identidades // Identidades
@ -337,14 +347,14 @@ module.exports = {
colorsApply: "Appliquer", colorsApply: "Appliquer",
colorsFixed: "Le texte n'était pas lisible sur ce fond, il a été mis en noir ou en blanc.", colorsFixed: "Le texte n'était pas lisible sur ce fond, il a été mis en noir ou en blanc.",
colorsKeep: "Garder celles-ci", colorsKeep: "Garder celles-ci",
palette_acampada: "Clair", palette_oasis: "Standard",
palette_noche: "Nuit", palette_acampada: "Place",
palette_oro: "Or", palette_noche: "Nuit blanche",
palette_bosque: "Forêt", palette_bosque: "Potager",
palette_lila: "Lilas", palette_lila: "Violette",
palette_brasa: "Braise", palette_brasa: "Feu de camp",
palette_papel: "Papier", palette_papel: "Fanzine",
palette_contraste: "Contraste élevé", palette_contraste: "Pancarte",
welcomeStepUseMobile: "Profil", welcomeStepUseMobile: "Profil",
welcomeHintUseMobile: "À quoi vous sert Oasis. Active les modules nécessaires.", welcomeHintUseMobile: "À quoi vous sert Oasis. Active les modules nécessaires.",
wfHint_activists: "Assemblées, tribus, votes, forums et documents partagés", 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_business: "Économie, banque, bureau et documents",
wfHint_mobile: "L'essentiel pour le téléphone", wfHint_mobile: "L'essentiel pour le téléphone",
workflow_acampada: "Campement", 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", tribeSectionsMore: "Plus",
tribeSectionsLabel: "Sections", tribeSectionsLabel: "Sections",
voteYes: "Oui", voteYes: "Oui",
@ -376,8 +391,8 @@ module.exports = {
voteKindHint_scale: "De 1 (froid) à 5 (chaud)", voteKindHint_scale: "De 1 (froid) à 5 (chaud)",
deleteConfirmQuestion: "Supprimer définitivement ?", deleteConfirmQuestion: "Supprimer définitivement ?",
deleteConfirmYes: "Oui, supprimer", deleteConfirmYes: "Oui, supprimer",
welcomeBannerTextMobile: "Ajoutez votre nom et votre photo pour qu'on vous reconnaisse.", welcomeBannerTextMobile: "Préparez Oasis en une minute.",
welcomeBannerActionMobile: "Ajouter", welcomeBannerActionMobile: "Commencer",
footerPeersNone: "Aucune synchronisation pour l'instant", footerPeersNone: "Aucune synchronisation pour l'instant",
footerPeersSome: "Synchronisé avec {n}", footerPeersSome: "Synchronisé avec {n}",
tribeMapUrlLabel: "Lien de la carte (facultatif)", tribeMapUrlLabel: "Lien de la carte (facultatif)",
@ -386,7 +401,7 @@ module.exports = {
modulesOnCount: "{on} sections actives sur {total}", modulesOnCount: "{on} sections actives sur {total}",
// skins y workflows en el movil (settings_view.js) // 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.", 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) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Impossible de retirer les métadonnées de cette image (position, appareil…), elle n'a donc pas été envoyée. Enregistrez-la en JPEG ou PNG et réessayez.", imageMetadataUnsafe: "Impossible de retirer les métadonnées de cette image (position, appareil…), elle n'a donc pas été envoyée. Enregistrez-la en JPEG ou PNG et réessayez.",
// Identidades // Identidades
@ -473,14 +488,14 @@ module.exports = {
colorsApply: "Aplikatu", colorsApply: "Aplikatu",
colorsFixed: "Testua ez zen irakurtzen hondo horretan, beltzez edo zuriz jarri da.", colorsFixed: "Testua ez zen irakurtzen hondo horretan, beltzez edo zuriz jarri da.",
colorsKeep: "Hauek utzi", colorsKeep: "Hauek utzi",
palette_acampada: "Argia", palette_oasis: "Estandarra",
palette_noche: "Gaua", palette_acampada: "Plaza",
palette_oro: "Urrea", palette_noche: "Goizaldea",
palette_bosque: "Basoa", palette_bosque: "Baratzea",
palette_lila: "Lila", palette_lila: "Morea",
palette_brasa: "Txingarra", palette_brasa: "Sua",
palette_papel: "Papera", palette_papel: "Fanzinea",
palette_contraste: "Kontraste handia", palette_contraste: "Pankarta",
welcomeStepUseMobile: "Profila", welcomeStepUseMobile: "Profila",
welcomeHintUseMobile: "Oasis zertarako erabiltzen duzun. Behar diren moduluak pizten ditu.", welcomeHintUseMobile: "Oasis zertarako erabiltzen duzun. Behar diren moduluak pizten ditu.",
wfHint_activists: "Batzarrak, tribuak, bozketak, foroak eta dokumentu partekatuak", wfHint_activists: "Batzarrak, tribuak, bozketak, foroak eta dokumentu partekatuak",
@ -494,6 +509,11 @@ module.exports = {
wfHint_business: "Ekonomia, banka, bulegoa eta dokumentuak", wfHint_business: "Ekonomia, banka, bulegoa eta dokumentuak",
wfHint_mobile: "Mugikorrerako oinarrizkoa", wfHint_mobile: "Mugikorrerako oinarrizkoa",
workflow_acampada: "Kanpaldia", 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", tribeSectionsMore: "Gehiago",
tribeSectionsLabel: "Atalak", tribeSectionsLabel: "Atalak",
voteYes: "Bai", voteYes: "Bai",
@ -512,8 +532,8 @@ module.exports = {
voteKindHint_scale: "1etik (hotza) 5era (beroa)", voteKindHint_scale: "1etik (hotza) 5era (beroa)",
deleteConfirmQuestion: "Betiko ezabatu?", deleteConfirmQuestion: "Betiko ezabatu?",
deleteConfirmYes: "Bai, ezabatu", deleteConfirmYes: "Bai, ezabatu",
welcomeBannerTextMobile: "Jarri zure izena eta argazkia ezagutu zaitzaten.", welcomeBannerTextMobile: "Prestatu Oasis minutu batean.",
welcomeBannerActionMobile: "Jarri", welcomeBannerActionMobile: "Hasi",
footerPeersNone: "Oraindik ez zaude inorekin sinkronizatzen", footerPeersNone: "Oraindik ez zaude inorekin sinkronizatzen",
footerPeersSome: "{n}-rekin sinkronizatzen", footerPeersSome: "{n}-rekin sinkronizatzen",
tribeMapUrlLabel: "Maparen esteka (aukerakoa)", tribeMapUrlLabel: "Maparen esteka (aukerakoa)",
@ -522,7 +542,7 @@ module.exports = {
modulesOnCount: "{total} ataletatik {on} aktibo", modulesOnCount: "{total} ataletatik {on} aktibo",
// skins y workflows en el movil (settings_view.js) // skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Aukeratu nolakoa den Oasis zure mugikorrean. Ukitu bezain laster aplikatzen da.", 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) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Ezin izan dira irudi honen metadatuak kendu (kokapena, kamera…), beraz ez da igo. Gorde JPEG edo PNG gisa eta saiatu berriro.", imageMetadataUnsafe: "Ezin izan dira irudi honen metadatuak kendu (kokapena, kamera…), beraz ez da igo. Gorde JPEG edo PNG gisa eta saiatu berriro.",
// Identidades // Identidades
@ -609,14 +629,14 @@ module.exports = {
colorsApply: "Anwenden", colorsApply: "Anwenden",
colorsFixed: "Der Text war auf diesem Hintergrund nicht lesbar, daher wurde er schwarz oder weiß gesetzt.", colorsFixed: "Der Text war auf diesem Hintergrund nicht lesbar, daher wurde er schwarz oder weiß gesetzt.",
colorsKeep: "Diese behalten", colorsKeep: "Diese behalten",
palette_acampada: "Hell", palette_oasis: "Standard",
palette_noche: "Nacht", palette_acampada: "Platz",
palette_oro: "Gold", palette_noche: "Spät nachts",
palette_bosque: "Wald", palette_bosque: "Garten",
palette_lila: "Flieder", palette_lila: "Violett",
palette_brasa: "Glut", palette_brasa: "Lagerfeuer",
palette_papel: "Papier", palette_papel: "Fanzine",
palette_contraste: "Hoher Kontrast", palette_contraste: "Transparent",
welcomeStepUseMobile: "Profil", welcomeStepUseMobile: "Profil",
welcomeHintUseMobile: "Wofür du Oasis nutzt. Schaltet die nötigen Module ein.", welcomeHintUseMobile: "Wofür du Oasis nutzt. Schaltet die nötigen Module ein.",
wfHint_activists: "Versammlungen, Stämme, Abstimmungen, Foren und gemeinsame Dokumente", 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_business: "Wirtschaft, Bank, Büro und Dokumente",
wfHint_mobile: "Das Wichtigste fürs Handy", wfHint_mobile: "Das Wichtigste fürs Handy",
workflow_acampada: "Camp", 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", tribeSectionsMore: "Mehr",
tribeSectionsLabel: "Bereiche", tribeSectionsLabel: "Bereiche",
voteYes: "Ja", voteYes: "Ja",
@ -648,8 +673,8 @@ module.exports = {
voteKindHint_scale: "Von 1 (kalt) bis 5 (heiß)", voteKindHint_scale: "Von 1 (kalt) bis 5 (heiß)",
deleteConfirmQuestion: "Endgültig löschen?", deleteConfirmQuestion: "Endgültig löschen?",
deleteConfirmYes: "Ja, löschen", deleteConfirmYes: "Ja, löschen",
welcomeBannerTextMobile: "Füge deinen Namen und dein Foto hinzu, damit man dich erkennt.", welcomeBannerTextMobile: "Richte Oasis in einer Minute ein.",
welcomeBannerActionMobile: "Einrichten", welcomeBannerActionMobile: "Los geht's",
footerPeersNone: "Noch mit niemandem synchronisiert", footerPeersNone: "Noch mit niemandem synchronisiert",
footerPeersSome: "Synchronisiert mit {n}", footerPeersSome: "Synchronisiert mit {n}",
tribeMapUrlLabel: "Kartenlink (optional)", tribeMapUrlLabel: "Kartenlink (optional)",
@ -658,7 +683,7 @@ module.exports = {
modulesOnCount: "{on} von {total} Bereichen aktiv", modulesOnCount: "{on} von {total} Bereichen aktiv",
// skins y workflows en el movil (settings_view.js) // skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Wähle, wie Oasis auf deinem Handy aussieht. Es wird beim Antippen übernommen.", 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) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Die Metadaten dieses Bildes (Standort, Kamera…) konnten nicht entfernt werden, daher wurde es nicht hochgeladen. Speichere es als JPEG oder PNG und versuche es erneut.", imageMetadataUnsafe: "Die Metadaten dieses Bildes (Standort, Kamera…) konnten nicht entfernt werden, daher wurde es nicht hochgeladen. Speichere es als JPEG oder PNG und versuche es erneut.",
// Identidades // Identidades
@ -745,14 +770,14 @@ module.exports = {
colorsApply: "Applica", colorsApply: "Applica",
colorsFixed: "Il testo non si leggeva su quello sfondo, quindi è stato messo nero o bianco.", colorsFixed: "Il testo non si leggeva su quello sfondo, quindi è stato messo nero o bianco.",
colorsKeep: "Tieni questi", colorsKeep: "Tieni questi",
palette_acampada: "Chiaro", palette_oasis: "Standard",
palette_noche: "Notte", palette_acampada: "Piazza",
palette_oro: "Oro", palette_noche: "Notte fonda",
palette_bosque: "Bosco", palette_bosque: "Orto",
palette_lila: "Lilla", palette_lila: "Viola",
palette_brasa: "Brace", palette_brasa: "Falò",
palette_papel: "Carta", palette_papel: "Fanzine",
palette_contraste: "Alto contrasto", palette_contraste: "Striscione",
welcomeStepUseMobile: "Profilo", welcomeStepUseMobile: "Profilo",
welcomeHintUseMobile: "A cosa ti serve Oasis. Attiva i moduli necessari.", welcomeHintUseMobile: "A cosa ti serve Oasis. Attiva i moduli necessari.",
wfHint_activists: "Assemblee, tribù, votazioni, forum e documenti condivisi", wfHint_activists: "Assemblee, tribù, votazioni, forum e documenti condivisi",
@ -766,6 +791,11 @@ module.exports = {
wfHint_business: "Economia, banca, ufficio e documenti", wfHint_business: "Economia, banca, ufficio e documenti",
wfHint_mobile: "L'essenziale per il telefono", wfHint_mobile: "L'essenziale per il telefono",
workflow_acampada: "Accampata", 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", tribeSectionsMore: "Altro",
tribeSectionsLabel: "Sezioni", tribeSectionsLabel: "Sezioni",
voteYes: "Sì", voteYes: "Sì",
@ -784,8 +814,8 @@ module.exports = {
voteKindHint_scale: "Da 1 (freddo) a 5 (caldo)", voteKindHint_scale: "Da 1 (freddo) a 5 (caldo)",
deleteConfirmQuestion: "Eliminare per sempre?", deleteConfirmQuestion: "Eliminare per sempre?",
deleteConfirmYes: "Sì, elimina", deleteConfirmYes: "Sì, elimina",
welcomeBannerTextMobile: "Aggiungi nome e foto perché ti riconoscano.", welcomeBannerTextMobile: "Prepara Oasis in un minuto.",
welcomeBannerActionMobile: "Aggiungi", welcomeBannerActionMobile: "Inizia",
footerPeersNone: "Non sincronizzi ancora con nessuno", footerPeersNone: "Non sincronizzi ancora con nessuno",
footerPeersSome: "In sincronia con {n}", footerPeersSome: "In sincronia con {n}",
tribeMapUrlLabel: "Link della mappa (facoltativo)", tribeMapUrlLabel: "Link della mappa (facoltativo)",
@ -794,7 +824,7 @@ module.exports = {
modulesOnCount: "{on} sezioni attive su {total}", modulesOnCount: "{on} sezioni attive su {total}",
// skins y workflows en el movil (settings_view.js) // skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Scegli come appare Oasis sul tuo telefono. Si applica appena lo tocchi.", 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) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Non è stato possibile rimuovere i metadati di questa immagine (posizione, fotocamera…), quindi non è stata caricata. Salvala come JPEG o PNG e riprova.", imageMetadataUnsafe: "Non è stato possibile rimuovere i metadati di questa immagine (posizione, fotocamera…), quindi non è stata caricata. Salvala come JPEG o PNG e riprova.",
// Identidades // Identidades
@ -881,14 +911,14 @@ module.exports = {
colorsApply: "Aplicar", colorsApply: "Aplicar",
colorsFixed: "O texto não se lia nesse fundo, por isso ficou preto ou branco.", colorsFixed: "O texto não se lia nesse fundo, por isso ficou preto ou branco.",
colorsKeep: "Manter estas", colorsKeep: "Manter estas",
palette_acampada: "Claro", palette_oasis: "Padrão",
palette_noche: "Noite", palette_acampada: "Praça",
palette_oro: "Ouro", palette_noche: "Madrugada",
palette_bosque: "Floresta", palette_bosque: "Horta",
palette_lila: "Lilás", palette_lila: "Violeta",
palette_brasa: "Brasa", palette_brasa: "Fogueira",
palette_papel: "Papel", palette_papel: "Fanzine",
palette_contraste: "Alto contraste", palette_contraste: "Faixa",
welcomeStepUseMobile: "Perfil", welcomeStepUseMobile: "Perfil",
welcomeHintUseMobile: "Para que usa o Oasis. Liga os módulos necessários.", welcomeHintUseMobile: "Para que usa o Oasis. Liga os módulos necessários.",
wfHint_activists: "Assembleias, tribos, votações, fóruns e documentos partilhados", 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_business: "Economia, banca, escritório e documentos",
wfHint_mobile: "O básico para o telemóvel", wfHint_mobile: "O básico para o telemóvel",
workflow_acampada: "Acampada", 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", tribeSectionsMore: "Mais",
tribeSectionsLabel: "Secções", tribeSectionsLabel: "Secções",
voteYes: "Sim", voteYes: "Sim",
@ -920,8 +955,8 @@ module.exports = {
voteKindHint_scale: "De 1 (frio) a 5 (quente)", voteKindHint_scale: "De 1 (frio) a 5 (quente)",
deleteConfirmQuestion: "Apagar para sempre?", deleteConfirmQuestion: "Apagar para sempre?",
deleteConfirmYes: "Sim, apagar", deleteConfirmYes: "Sim, apagar",
welcomeBannerTextMobile: "Põe o teu nome e a tua foto para que te reconheçam.", welcomeBannerTextMobile: "Prepare o Oasis num minuto.",
welcomeBannerActionMobile: "Pôr", welcomeBannerActionMobile: "Começar",
footerPeersNone: "Ainda não sincronizas com ninguém", footerPeersNone: "Ainda não sincronizas com ninguém",
footerPeersSome: "A sincronizar com {n}", footerPeersSome: "A sincronizar com {n}",
tribeMapUrlLabel: "Ligação do mapa (opcional)", tribeMapUrlLabel: "Ligação do mapa (opcional)",
@ -930,7 +965,7 @@ module.exports = {
modulesOnCount: "{on} de {total} secções ativas", modulesOnCount: "{on} de {total} secções ativas",
// skins y workflows en el movil (settings_view.js) // skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Escolhe como o Oasis aparece no teu telemóvel. Aplica-se ao tocar.", 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) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Não foi possível remover os metadados desta imagem (localização, câmara…), por isso não foi enviada. Guarda-a como JPEG ou PNG e tenta de novo.", imageMetadataUnsafe: "Não foi possível remover os metadados desta imagem (localização, câmara…), por isso não foi enviada. Guarda-a como JPEG ou PNG e tenta de novo.",
// Identidades // Identidades
@ -1017,14 +1052,14 @@ module.exports = {
colorsApply: "应用", colorsApply: "应用",
colorsFixed: "文字在该背景上看不清,已改为黑色或白色。", colorsFixed: "文字在该背景上看不清,已改为黑色或白色。",
colorsKeep: "保留这些", colorsKeep: "保留这些",
palette_acampada: "浅色", palette_oasis: "标准",
palette_noche: "夜晚", palette_acampada: "广场",
palette_oro: "金色", palette_noche: "深夜",
palette_bosque: "森林", palette_bosque: "菜园",
palette_lila: "丁香", palette_lila: "紫罗兰",
palette_brasa: "余烬", palette_brasa: "篝火",
palette_papel: "纸张", palette_papel: "小志",
palette_contraste: "高对比度", palette_contraste: "横幅",
welcomeStepUseMobile: "用途", welcomeStepUseMobile: "用途",
welcomeHintUseMobile: "你用 Oasis 做什么。会打开需要的模块。", welcomeHintUseMobile: "你用 Oasis 做什么。会打开需要的模块。",
wfHint_activists: "集会、部落、投票、论坛和共享文档", wfHint_activists: "集会、部落、投票、论坛和共享文档",
@ -1038,6 +1073,11 @@ module.exports = {
wfHint_business: "经济、银行、办公和文档", wfHint_business: "经济、银行、办公和文档",
wfHint_mobile: "手机基本功能", wfHint_mobile: "手机基本功能",
workflow_acampada: "营地", workflow_acampada: "营地",
workflow_activista: "活动者",
wfHint_activista: "直接行动:召集、协调、通话和预警",
wfNameMobile_activists: "运动",
wfModuleCount: "{n} 个模块",
activityFilter: "筛选",
tribeSectionsMore: "更多", tribeSectionsMore: "更多",
tribeSectionsLabel: "板块", tribeSectionsLabel: "板块",
voteYes: "赞成", voteYes: "赞成",
@ -1056,8 +1096,8 @@ module.exports = {
voteKindHint_scale: "从 1(冷)到 5(热)", voteKindHint_scale: "从 1(冷)到 5(热)",
deleteConfirmQuestion: "永久删除?", deleteConfirmQuestion: "永久删除?",
deleteConfirmYes: "是,删除", deleteConfirmYes: "是,删除",
welcomeBannerTextMobile: "添加你的名字和照片,让大家认出你。", welcomeBannerTextMobile: "一分钟设置好 Oasis。",
welcomeBannerActionMobile: "设置", welcomeBannerActionMobile: "开始",
footerPeersNone: "尚未与任何人同步", footerPeersNone: "尚未与任何人同步",
footerPeersSome: "正在与 {n} 个节点同步", footerPeersSome: "正在与 {n} 个节点同步",
tribeMapUrlLabel: "地图链接(可选)", tribeMapUrlLabel: "地图链接(可选)",
@ -1066,7 +1106,7 @@ module.exports = {
modulesOnCount: "已开启 {on}/{total} 个板块", modulesOnCount: "已开启 {on}/{total} 个板块",
// skins y workflows en el movil (settings_view.js) // skins y workflows en el movil (settings_view.js)
skinIntroMobile: "选择 Oasis 在手机上的外观。点一下就会生效。", skinIntroMobile: "选择 Oasis 在手机上的外观。点一下就会生效。",
workflowsDescriptionMobile: "工作流决定启用哪些模块。在手机上,你的外观保持不变。", workflowsDescriptionMobile: "每个配置会开启一些模块,并带有自己的底部栏。从少到多,随时可以更改。",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "无法清除这张图片的元数据(位置、相机等),因此没有上传。请另存为 JPEG 或 PNG 后重试。", imageMetadataUnsafe: "无法清除这张图片的元数据(位置、相机等),因此没有上传。请另存为 JPEG 或 PNG 后重试。",
// Identidades // Identidades
@ -1153,14 +1193,14 @@ module.exports = {
colorsApply: "تطبيق", colorsApply: "تطبيق",
colorsFixed: "لم يكن النص مقروءًا على تلك الخلفية، فجُعل أسود أو أبيض.", colorsFixed: "لم يكن النص مقروءًا على تلك الخلفية، فجُعل أسود أو أبيض.",
colorsKeep: "الإبقاء على هذه", colorsKeep: "الإبقاء على هذه",
palette_acampada: "فاتح", palette_oasis: "قياسي",
palette_noche: "ليل", palette_acampada: "الساحة",
palette_oro: "ذهب", palette_noche: "آخر الليل",
palette_bosque: "غابة", palette_bosque: "البستان",
palette_lila: "ليلكي", palette_lila: "بنفسجي",
palette_brasa: "جمر", palette_brasa: "نار المخيم",
palette_papel: "ورق", palette_papel: "فانزين",
palette_contraste: "تباين عالٍ", palette_contraste: "لافتة",
welcomeStepUseMobile: "الملف", welcomeStepUseMobile: "الملف",
welcomeHintUseMobile: "لماذا تستخدم Oasis. يفعّل الوحدات التي تحتاجها.", welcomeHintUseMobile: "لماذا تستخدم Oasis. يفعّل الوحدات التي تحتاجها.",
wfHint_activists: "جمعيات وقبائل وتصويت ومنتديات ووثائق مشتركة", wfHint_activists: "جمعيات وقبائل وتصويت ومنتديات ووثائق مشتركة",
@ -1174,6 +1214,11 @@ module.exports = {
wfHint_business: "اقتصاد ومصرف ومكتب ووثائق", wfHint_business: "اقتصاد ومصرف ومكتب ووثائق",
wfHint_mobile: "الأساسيات للهاتف", wfHint_mobile: "الأساسيات للهاتف",
workflow_acampada: "مخيم", workflow_acampada: "مخيم",
workflow_activista: "ناشط",
wfHint_activista: "عمل مباشر: دعوة وتنسيق واتصال وتنبيه",
wfNameMobile_activists: "الحركة",
wfModuleCount: "{n} وحدات",
activityFilter: "تصفية",
tribeSectionsMore: "المزيد", tribeSectionsMore: "المزيد",
tribeSectionsLabel: "الأقسام", tribeSectionsLabel: "الأقسام",
voteYes: "نعم", voteYes: "نعم",
@ -1192,8 +1237,8 @@ module.exports = {
voteKindHint_scale: "من 1 (بارد) إلى 5 (ساخن)", voteKindHint_scale: "من 1 (بارد) إلى 5 (ساخن)",
deleteConfirmQuestion: "حذف نهائيًا؟", deleteConfirmQuestion: "حذف نهائيًا؟",
deleteConfirmYes: "نعم، احذف", deleteConfirmYes: "نعم، احذف",
welcomeBannerTextMobile: "أضف اسمك وصورتك ليتعرّف عليك الآخرون.", welcomeBannerTextMobile: "جهّز Oasis في دقيقة.",
welcomeBannerActionMobile: "إضافة", welcomeBannerActionMobile: "ابدأ",
footerPeersNone: "لا مزامنة مع أحد بعد", footerPeersNone: "لا مزامنة مع أحد بعد",
footerPeersSome: "مزامنة مع {n}", footerPeersSome: "مزامنة مع {n}",
tribeMapUrlLabel: "رابط الخريطة (اختياري)", tribeMapUrlLabel: "رابط الخريطة (اختياري)",
@ -1202,7 +1247,7 @@ module.exports = {
modulesOnCount: "{on} من {total} أقسام مفعّلة", modulesOnCount: "{on} من {total} أقسام مفعّلة",
// skins y workflows en el movil (settings_view.js) // skins y workflows en el movil (settings_view.js)
skinIntroMobile: "اختر مظهر Oasis على هاتفك. يُطبَّق بمجرد اللمس.", skinIntroMobile: "اختر مظهر Oasis على هاتفك. يُطبَّق بمجرد اللمس.",
workflowsDescriptionMobile: "يحدد سير العمل الوحدات المفعّلة. على الهاتف يبقى مظهرك كما هو.", workflowsDescriptionMobile: "كل ملف يشغّل بعض الوحدات ويأتي بشريطه السفلي. من الأقل إلى الأكثر؛ غيّره متى شئت.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "تعذّر إزالة البيانات الوصفية من هذه الصورة (الموقع، الكاميرا…)، لذلك لم تُرفع. احفظها بصيغة JPEG أو PNG وحاول مجددًا.", imageMetadataUnsafe: "تعذّر إزالة البيانات الوصفية من هذه الصورة (الموقع، الكاميرا…)، لذلك لم تُرفع. احفظها بصيغة JPEG أو PNG وحاول مجددًا.",
// Identidades // Identidades
@ -1289,14 +1334,14 @@ module.exports = {
colorsApply: "लागू करें", colorsApply: "लागू करें",
colorsFixed: "उस पृष्ठभूमि पर टेक्स्ट पढ़ा नहीं जा रहा था, इसलिए काला या सफ़ेद कर दिया गया।", colorsFixed: "उस पृष्ठभूमि पर टेक्स्ट पढ़ा नहीं जा रहा था, इसलिए काला या सफ़ेद कर दिया गया।",
colorsKeep: "इन्हें रखें", colorsKeep: "इन्हें रखें",
palette_acampada: "हल्का", palette_oasis: "मानक",
palette_noche: "रात", palette_acampada: "चौक",
palette_oro: "सोना", palette_noche: "देर रात",
palette_bosque: "जंगल", palette_bosque: "बगीचा",
palette_lila: "बकाइन", palette_lila: "बैंगनी",
palette_brasa: "अंगार", palette_brasa: "अलाव",
palette_papel: "काग़ज़", palette_papel: "फ़ैनज़ीन",
palette_contraste: "उच्च कंट्रास्ट", palette_contraste: "बैनर",
welcomeStepUseMobile: "प्रोफ़ाइल", welcomeStepUseMobile: "प्रोफ़ाइल",
welcomeHintUseMobile: "आप Oasis किस लिए इस्तेमाल करते हैं। ज़रूरी मॉड्यूल चालू करता है।", welcomeHintUseMobile: "आप Oasis किस लिए इस्तेमाल करते हैं। ज़रूरी मॉड्यूल चालू करता है।",
wfHint_activists: "सभाएँ, ट्राइब, मतदान, फ़ोरम और साझा दस्तावेज़", wfHint_activists: "सभाएँ, ट्राइब, मतदान, फ़ोरम और साझा दस्तावेज़",
@ -1310,6 +1355,11 @@ module.exports = {
wfHint_business: "अर्थव्यवस्था, बैंकिंग, दफ़्तर और दस्तावेज़", wfHint_business: "अर्थव्यवस्था, बैंकिंग, दफ़्तर और दस्तावेज़",
wfHint_mobile: "फ़ोन के लिए बुनियादी", wfHint_mobile: "फ़ोन के लिए बुनियादी",
workflow_acampada: "शिविर", workflow_acampada: "शिविर",
workflow_activista: "कार्यकर्ता",
wfHint_activista: "सीधी कार्रवाई: बुलाना, तालमेल, फ़ोन और चेतावनी",
wfNameMobile_activists: "आंदोलन",
wfModuleCount: "{n} मॉड्यूल",
activityFilter: "फ़िल्टर",
tribeSectionsMore: "और", tribeSectionsMore: "और",
tribeSectionsLabel: "खंड", tribeSectionsLabel: "खंड",
voteYes: "हाँ", voteYes: "हाँ",
@ -1328,8 +1378,8 @@ module.exports = {
voteKindHint_scale: "1 (ठंडा) से 5 (गरम) तक", voteKindHint_scale: "1 (ठंडा) से 5 (गरम) तक",
deleteConfirmQuestion: "हमेशा के लिए हटाएँ?", deleteConfirmQuestion: "हमेशा के लिए हटाएँ?",
deleteConfirmYes: "हाँ, हटाएँ", deleteConfirmYes: "हाँ, हटाएँ",
welcomeBannerTextMobile: "अपना नाम और फ़ोटो जोड़ें ताकि लोग आपको पहचानें।", welcomeBannerTextMobile: "एक मिनट में Oasis तैयार करें।",
welcomeBannerActionMobile: "जोड़ें", welcomeBannerActionMobile: "शुरू करें",
footerPeersNone: "अभी किसी से सिंक नहीं", footerPeersNone: "अभी किसी से सिंक नहीं",
footerPeersSome: "{n} से सिंक हो रहा है", footerPeersSome: "{n} से सिंक हो रहा है",
tribeMapUrlLabel: "नक्शे का लिंक (वैकल्पिक)", tribeMapUrlLabel: "नक्शे का लिंक (वैकल्पिक)",
@ -1338,7 +1388,7 @@ module.exports = {
modulesOnCount: "{total} में से {on} खंड चालू", modulesOnCount: "{total} में से {on} खंड चालू",
// skins y workflows en el movil (settings_view.js) // skins y workflows en el movil (settings_view.js)
skinIntroMobile: "चुनें कि आपके फ़ोन पर Oasis कैसा दिखे। छूते ही लागू हो जाता है।", skinIntroMobile: "चुनें कि आपके फ़ोन पर Oasis कैसा दिखे। छूते ही लागू हो जाता है।",
workflowsDescriptionMobile: "वर्कफ़्लो तय करता है कि कौन-से मॉड्यूल चालू हैं। फ़ोन पर आपकी स्किन वैसी ही रहती है।", workflowsDescriptionMobile: "हर प्रोफ़ाइल कुछ मॉड्यूल चालू करती है और अपनी निचली पट्टी लाती है। कम से ज़्यादा की ओर; जब चाहें बदलें।",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "इस छवि का मेटाडेटा (स्थान, कैमरा…) हटाया नहीं जा सका, इसलिए इसे अपलोड नहीं किया गया। इसे JPEG या PNG के रूप में सहेजें और फिर कोशिश करें।", imageMetadataUnsafe: "इस छवि का मेटाडेटा (स्थान, कैमरा…) हटाया नहीं जा सका, इसलिए इसे अपलोड नहीं किया गया। इसे JPEG या PNG के रूप में सहेजें और फिर कोशिश करें।",
// Identidades // Identidades
@ -1425,14 +1475,14 @@ module.exports = {
colorsApply: "Применить", colorsApply: "Применить",
colorsFixed: "Текст не читался на этом фоне, поэтому он стал чёрным или белым.", colorsFixed: "Текст не читался на этом фоне, поэтому он стал чёрным или белым.",
colorsKeep: "Оставить эти", colorsKeep: "Оставить эти",
palette_acampada: "Светлая", palette_oasis: "Стандарт",
palette_noche: "Ночь", palette_acampada: "Площадь",
palette_oro: "Золото", palette_noche: "Глубокая ночь",
palette_bosque: "Лес", palette_bosque: "Огород",
palette_lila: "Сирень", palette_lila: "Фиалка",
palette_brasa: "Угли", palette_brasa: "Костёр",
palette_papel: "Бумага", palette_papel: "Фэнзин",
palette_contraste: "Высокий контраст", palette_contraste: "Плакат",
welcomeStepUseMobile: "Профиль", welcomeStepUseMobile: "Профиль",
welcomeHintUseMobile: "Для чего вам Oasis. Включает нужные модули.", welcomeHintUseMobile: "Для чего вам Oasis. Включает нужные модули.",
wfHint_activists: "Собрания, племена, голосования, форумы и общие документы", wfHint_activists: "Собрания, племена, голосования, форумы и общие документы",
@ -1446,6 +1496,11 @@ module.exports = {
wfHint_business: "Экономика, банк, офис и документы", wfHint_business: "Экономика, банк, офис и документы",
wfHint_mobile: "Основное для телефона", wfHint_mobile: "Основное для телефона",
workflow_acampada: "Лагерь", workflow_acampada: "Лагерь",
workflow_activista: "Активист",
wfHint_activista: "Прямое действие: созвать, координировать, звонить и предупреждать",
wfNameMobile_activists: "Движение",
wfModuleCount: "{n} модулей",
activityFilter: "Фильтр",
tribeSectionsMore: "Ещё", tribeSectionsMore: "Ещё",
tribeSectionsLabel: "Разделы", tribeSectionsLabel: "Разделы",
voteYes: "Да", voteYes: "Да",
@ -1464,8 +1519,8 @@ module.exports = {
voteKindHint_scale: "От 1 (холодно) до 5 (горячо)", voteKindHint_scale: "От 1 (холодно) до 5 (горячо)",
deleteConfirmQuestion: "Удалить навсегда?", deleteConfirmQuestion: "Удалить навсегда?",
deleteConfirmYes: "Да, удалить", deleteConfirmYes: "Да, удалить",
welcomeBannerTextMobile: "Добавьте имя и фото, чтобы вас узнавали.", welcomeBannerTextMobile: "Настройте Oasis за минуту.",
welcomeBannerActionMobile: "Добавить", welcomeBannerActionMobile: "Начать",
footerPeersNone: "Пока ни с кем не синхронизировано", footerPeersNone: "Пока ни с кем не синхронизировано",
footerPeersSome: "Синхронизация с {n}", footerPeersSome: "Синхронизация с {n}",
tribeMapUrlLabel: "Ссылка на карту (необязательно)", tribeMapUrlLabel: "Ссылка на карту (необязательно)",
@ -1474,7 +1529,7 @@ module.exports = {
modulesOnCount: "Включено {on} из {total} разделов", modulesOnCount: "Включено {on} из {total} разделов",
// skins y workflows en el movil (settings_view.js) // skins y workflows en el movil (settings_view.js)
skinIntroMobile: "Выберите, как Oasis выглядит на телефоне. Применяется сразу по нажатию.", skinIntroMobile: "Выберите, как Oasis выглядит на телефоне. Применяется сразу по нажатию.",
workflowsDescriptionMobile: "Рабочий процесс задаёт, какие модули включены. На телефоне ваше оформление не меняется.", workflowsDescriptionMobile: "Каждый профиль включает несколько модулей и приносит свою нижнюю панель. От меньшего к большему; меняйте когда угодно.",
// fotos que no se pueden limpiar (blobHandler.js) // fotos que no se pueden limpiar (blobHandler.js)
imageMetadataUnsafe: "Не удалось удалить метаданные этого изображения (местоположение, камера…), поэтому оно не загружено. Сохраните его как JPEG или PNG и попробуйте снова.", imageMetadataUnsafe: "Не удалось удалить метаданные этого изображения (местоположение, камера…), поэтому оно не загружено. Сохраните его как JPEG или PNG и попробуйте снова.",
// Identidades // Identidades

View file

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

View file

@ -6,10 +6,23 @@
// los suyos empujandolos a los arrays que ese fichero exporta; getWorkflow, // los suyos empujandolos a los arrays que ese fichero exporta; getWorkflow,
// currentWorkflow y el asistente de bienvenida los leen de ahi. // currentWorkflow y el asistente de bienvenida los leen de ahi.
// Ver docs/FRONTERA_UPSTREAM.md. // 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 wf = require('./workflows_model');
const FORK_WORKFLOWS = [ 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, // una acampada: hablar (chats, telefono y salas de voz del dev), escribir juntos,
// compartir lo que pasa y decidir (tribus = comisiones, parlamento y votaciones) // 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; let done = false;
const register = () => { const register = () => {
if (done) return; if (done) return;
@ -29,11 +58,35 @@ const register = () => {
if (wf.WORKFLOWS.some(x => x.key === w.key)) continue; if (wf.WORKFLOWS.some(x => x.key === w.key)) continue;
wf.WORKFLOWS.push(w); wf.WORKFLOWS.push(w);
wf.WORKFLOW_KEYS.push(w.key); wf.WORKFLOW_KEYS.push(w.key);
// en el asistente, detras de activistas (en el movil mobile_ui.workflowPick pone // en el asistente, detras de activistas (en el movil mobile_ui.workflowPick los
// Activismo y Acampada las primeras) // ordena por numero de modulos)
const at = wf.WIZARD_WORKFLOWS.indexOf('activists'); const at = wf.WIZARD_WORKFLOWS.indexOf('activists');
wf.WIZARD_WORKFLOWS.splice(at === -1 ? wf.WIZARD_WORKFLOWS.length : at + 1, 0, w.key); 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 { 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 opinionCategories = require('../backend/opinion_categories');
const { roomNumberOf } = require('../models/phone_number'); 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 OPINION_TYPES = new Set(['bookmark','votes','feed','image','audio','video','document','torrent','file']);
const TORRENTABLE_TYPES = CONTENT_TORRENTABLE; const TORRENTABLE_TYPES = CONTENT_TORRENTABLE;
@ -2288,7 +2289,7 @@ exports.activityView = (actions, filter, userId, q = '', extras = {}) => {
h2(i18n.activityList), h2(i18n.activityList),
p(desc) p(desc)
), ),
emptyAct ? null : div({ class: 'activity-filter-chips' }, emptyAct ? null : mobileUi.activityFilter(filter, activityTypes, div({ class: 'activity-filter-chips' },
(() => { (() => {
const ORDER = [ const ORDER = [
'all', 'recent', 'mine', 'top', 'all', 'recent', 'mine', 'top',
@ -2314,7 +2315,7 @@ exports.activityView = (actions, filter, userId, q = '', extras = {}) => {
}, label) }, label)
); );
})() })()
), )),
emptyAct ? null : div({ class: 'activity-filter-chips activity-toolbar-row' }, emptyAct ? null : div({ class: 'activity-filter-chips activity-toolbar-row' },
renderModuleStats(filteredActions.length, [], null, { showInhabitants: true, showTribes: true }), renderModuleStats(filteredActions.length, [], null, { showInhabitants: true, showTribes: true }),
sub ? span({ class: 'activity-subchip-label' }, '\u21b3') : '', 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: 'data', href: '/data', glyph: 'ꘑ', labelKey: 'dataTitle', mod: 'dataMod' },
{ key: 'market', href: '/market', glyph: 'ꕻ', labelKey: 'marketTitle', mod: 'marketMod' }, { key: 'market', href: '/market', glyph: 'ꕻ', labelKey: 'marketTitle', mod: 'marketMod' },
{ key: 'events', href: '/events', glyph: 'ꕆ', labelKey: 'eventsLabel', mod: 'eventsMod' }, { 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: 'calendars', href: '/calendars', glyph: 'ꖯ', labelKey: 'calendarsTitle', mod: 'calendarsMod' },
{ key: 'banking', href: '/banking', glyph: 'ꗴ', labelKey: 'bankingTitle', mod: 'bankingMod' }, { key: 'banking', href: '/banking', glyph: 'ꗴ', labelKey: 'bankingTitle', mod: 'bankingMod' },
{ key: 'forum', href: '/forum', glyph: 'ꕒ', labelKey: 'forumTitle', mod: 'forumMod' }, { 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 // barra PERSONALIZABLE: solo los pins (max 4). Editarla y Peers estan en el
// lanzador (Herramientas): 7 botones abajo eran demasiados para un pulgar. // lanzador (Herramientas): 7 botones abajo eran demasiados para un pulgar.
const MAX = 4; const MAX = 4;
const pins = (cfg.bottomBarPins || []) const pins = require('../models/fork_workflows').barFor(cfg)
.map(key => PINNABLE_MODULES.find(m => m.key === key)) .map(key => PINNABLE_MODULES.find(m => m.key === key))
.filter(m => m && modOn(m.mod)) .filter(m => m && modOn(m.mod))
.slice(0, MAX); .slice(0, MAX);
@ -253,7 +255,7 @@ module.exports = ({ i18n }) => {
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 MAX = 4; const MAX = 4;
const pinnedKeys = cfg.bottomBarPins || []; const pinnedKeys = require('../models/fork_workflows').barFor(cfg);
const pinned = pinnedKeys const pinned = pinnedKeys
.map(key => PINNABLE_MODULES.find(m => m.key === key)) .map(key => PINNABLE_MODULES.find(m => m.key === key))
.filter(Boolean); .filter(Boolean);

View file

@ -10,8 +10,9 @@
// /feed/create): no se reenvia nada a sus rutas ni se toca lo que contestan. Colores // /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. // 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 // Los colores son las variables --a26-* del skin Activista. Los skins (workflows)
// skin quita lo que sobra y los colores lo dejan a gusto de cada cual. // 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 crypto = require("crypto");
const { a, button, details, div, form, img, input, label, p, section, span, summary, h2 } = require("../server/node_modules/hyperaxe"); 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 ---------- // ---------- 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 = [ const PALETTES = [
["oasis", "#121212", "#f2f2f2", "#ffd700"],
["acampada", "#ffffff", "#000000", "#00e5ff"], ["acampada", "#ffffff", "#000000", "#00e5ff"],
["noche", "#101114", "#f2f2f2", "#00e5ff"], ["noche", "#101114", "#f2f2f2", "#00e5ff"],
["oro", "#121212", "#f2f2f2", "#ffd700"],
["bosque", "#f3f7ef", "#13231a", "#3ccf7e"], ["bosque", "#f3f7ef", "#13231a", "#3ccf7e"],
["lila", "#faf7ff", "#1d1430", "#b48cff"], ["lila", "#faf7ff", "#1d1430", "#b48cff"],
["brasa", "#fff8f2", "#1a0f0a", "#ff6a2b"], ["brasa", "#fff8f2", "#1a0f0a", "#ff6a2b"],
["papel", "#f5efe3", "#2a2420", "#ff4f8b"], ["papel", "#f5efe3", "#2a2420", "#ff4f8b"],
["contraste", "#000000", "#ffffff", "#ffff00"] ["contraste", "#000000", "#ffffff", "#ffff00"]
]; ];
// claves de antes que ahora se llaman de otra forma
const RENAMED = { oro: "oasis" };
const DEFAULT = PALETTES[0]; const DEFAULT = PALETTES[0];
const HEX = /^#[0-9a-f]{6}$/i; 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 || "")))) { 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 }; 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 }; 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) // muestras de las paletas (la CSP no deja estilos en linea)
const colorsCss = (cfg) => { const colorsCss = (cfg) => {
const c = colorState(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-bg:${c.bg}`, `--a26-fg:${c.fg}`, `--a26-neon:${c.accent}`,
`--a26-on-neon:${readableOn(c.accent)}`, `--a26-on-neon:${readableOn(c.accent)}`,
`--a26-soft:${mix(c.bg, c.fg, 0.06)}`, `--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 // 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"}`, `--a26-danger-text:${contrast(c.bg, "#c4003b") >= 4.5 ? "#c4003b" : "#ff6b86"}`,
`color-scheme:${lum(c.bg) < 0.2 ? "dark" : "light"}` `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}`; 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 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()}` }); 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 === "identity") return global.__OASIS_SELF_NAME__ || "";
if (id === "workflows") { if (id === "workflows") {
const wf = (() => { try { return require("../models/workflows_model").currentWorkflow(cfg); } catch (_) { return null; } })(); 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") { if (id === "ux") {
const ux = (cfg.ux || {}).current || "blocks"; const ux = (cfg.ux || {}).current || "blocks";

View file

@ -11,7 +11,7 @@
// antes que el). // antes que el).
const { a, button, details, div, form, img, input, label, nav, p, progress, span, summary } = require("../server/node_modules/hyperaxe"); 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 isMobile = () => process.env.OASIS_MOBILE === '1';
const t = () => require('./main_views').i18n; 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 // perfil de uso (workflow), que en el movil es el skin: un boton por opcion con
// sirve. Activismo (el de serie) y Acampada primero; el resto en el orden del dev // para que sirve, cuantos modulos enciende y su barra de abajo. Van de menos a mas
const WORKFLOW_FIRST = ['activists', 'acampada']; // 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 workflowPick = (action, current, keys, withHint) => {
const i18n = t(); const i18n = t();
const list = WORKFLOW_FIRST.filter(k => keys.includes(k)).concat(keys.filter(k => !WORKFLOW_FIRST.includes(k))); const fw = require('../models/fork_workflows');
const name = (k) => k === 'full' ? (i18n.welcomeWorkflow_full || k) : (i18n[`workflow_${k}`] || k); 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' }, 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, 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' }, 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' } : {}), ...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-text' },
span({ class: 'ux-pick-label' }, name(k)), span({ class: 'ux-pick-label' }, workflowName(k)),
i18n[`wfHint_${k}`] ? span({ class: 'ux-pick-sub' }, i18n[`wfHint_${k}`]) : null), 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 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); 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 ---------- // ---------- acciones de tarjeta ----------
// borrar pide un segundo toque: la X abre "¿Borrar? Si, borrar" y solo ese boton // 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 = { module.exports = {
colorsLink, colorsPick, welcomeDone, colorsLink, colorsPick, welcomeDone,
isMobile, VOTE_KINDS, voteKindPicker, voteBars, voteOwnNote, tribeRow, tribeTabs, 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 welcomeBannerHere, welcomeBannerText, welcomeBannerAction
}; };

View file

@ -71,7 +71,7 @@ const settingsView = (params) => {
) )
); );
const workflowPicker = () => section({ id: "workflows" }, 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)) mobileUi.workflowPick("/settings/workflow", activeWorkflow, WORKFLOWS.map(w => w.key))
); );