diff --git a/GUIA_DE_DESARROLLO.md b/GUIA_DE_DESARROLLO.md index 392cc6c..094bafb 100644 --- a/GUIA_DE_DESARROLLO.md +++ b/GUIA_DE_DESARROLLO.md @@ -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 diff --git a/src/backend/fork_routes.js b/src/backend/fork_routes.js index af05afc..1da58d3 100644 --- a/src/backend/fork_routes.js +++ b/src/backend/fork_routes.js @@ -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'); }) diff --git a/src/client/assets/styles/mobile_ux.css b/src/client/assets/styles/mobile_ux.css index 430bc19..0f971d8 100644 --- a/src/client/assets/styles/mobile_ux.css +++ b/src/client/assets/styles/mobile_ux.css @@ -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; +} diff --git a/src/client/assets/translations/i18n_fork.js b/src/client/assets/translations/i18n_fork.js index 8b1d33e..1b32cf2 100644 --- a/src/client/assets/translations/i18n_fork.js +++ b/src/client/assets/translations/i18n_fork.js @@ -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 diff --git a/src/configs/oasis-config.json b/src/configs/oasis-config.json index a0514d2..e73e009 100644 --- a/src/configs/oasis-config.json +++ b/src/configs/oasis-config.json @@ -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": [], diff --git a/src/models/fork_workflows.js b/src/models/fork_workflows.js index eb99b79..cba82e5 100644 --- a/src/models/fork_workflows.js +++ b/src/models/fork_workflows.js @@ -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 }; diff --git a/src/views/activity_view.js b/src/views/activity_view.js index 842979a..2e852fc 100644 --- a/src/views/activity_view.js +++ b/src/views/activity_view.js @@ -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') : '', diff --git a/src/views/hive_views.js b/src/views/hive_views.js index 651f3d0..59becac 100644 --- a/src/views/hive_views.js +++ b/src/views/hive_views.js @@ -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); diff --git a/src/views/mobile_settings.js b/src/views/mobile_settings.js index d5864e3..3312944 100644 --- a/src/views/mobile_settings.js +++ b/src/views/mobile_settings.js @@ -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_) 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"; diff --git a/src/views/mobile_ui.js b/src/views/mobile_ui.js index fdd6373..c073464 100644 --- a/src/views/mobile_ui.js +++ b/src/views/mobile_ui.js @@ -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
. 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 }; diff --git a/src/views/settings_view.js b/src/views/settings_view.js index 6ce4758..6e1f6f0 100644 --- a/src/views/settings_view.js +++ b/src/views/settings_view.js @@ -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)) );