OASIS_MOBILE/GUIA_DE_DESARROLLO.md
hacklab a85aa24b82 fichas de Opiniones en su rejilla, avisos abajo, nombres cortos en la barra y pantallas de dentro
- Opiniones y Tendencias: las cuatro primeras fichas se montaban en una columna de
  122px; cada ficha es ya una casilla de la rejilla (display: contents en sus columnas)
- avisos de version y sugerencia fijos abajo, encima de la barra, como el del pub;
  se esconden con el teclado, el menu y la barra del pub; arriba en el WebView viejo
- barra de abajo: nombre corto (bbShort_* en i18n_fork) donde el del dev no cabe,
  medido en los 13 idiomas a 412 y 360px; el entero queda como aria-label
- parlamento, banca, etiquetas, habitantes, fediverso y blogs: letra y zonas tactiles
2026-10-23 20:39:33 +02:00

20 KiB

Guía de desarrollo

Notas para quien vaya a meter mano en la rama del móvil. Leedlas antes de empezar, que nos ahorramos disgustos.

Esta rama va encima de Oasis, que es de epsylon. Él saca versión casi cada día (39 entre la 1.0.1 y la 1.3.3, en siete semanas) y cada versión llega en un solo commit. Si metemos cosas en sus ficheros, en cada integración hay que volver a pelearse con ellas. Por eso la idea es sencilla: lo de Oasis lo cambia él; nosotros cambiamos cómo se ve y se usa en el móvil, y lo hacemos en ficheros nuestros.

Los números y de dónde salen están en docs/FRONTERA_UPSTREAM.md.

La estrategia: una capa encima

Lo del dev entra tal cual y lo nuestro va encima, en ficheros nuestros: hojas de estilo, vistas y un router propio que va delante del suyo. Se eligió así frente a las otras salidas:

  • Un fork que copie sus vistas y siga por libre se queda viejo en semanas (39 versiones en siete semanas).
  • Una app propia que hable con su backend obliga a rehacer toda la interfaz, y Oasis no tiene API: devuelve HTML.
  • Reescribir su HTML o sus respuestas al vuelo se rompe sin avisar con cualquier cambio suyo. Se probó y se quitó el 20/10/2026.

Las reglas de la capa:

  1. Lo del dev no se cambia: ni su código ni lo que contesta (HTML, redirecciones, cabeceras). Nuestro código no mira sus respuestas.
  2. El aspecto, con CSS en nuestras hojas.
  3. Otro HTML en una pantalla suya: función en mobile_ui.js y una línea en su vista.
  4. Una pantalla o una ruta nueva: en fork_routes.js; lo que no es nuestro pasa al dev con next().
  5. Si una pantalla del dev ya hace algo (editar el perfil, escribir, guardar los módulos), se enlaza a ella o se envía a su ruta y se acepta a dónde vuelve. No se copia su lógica.
  6. Se pueden usar sus funciones (getConfig, saveConfig, leer de sus modelos). Reescribirlas, no.
  7. Si algo no se puede hacer con estas reglas, se le pide al dev.

Dónde va cada cosa:

Quiero... Va en
Cambiar colores, tamaños, márgenes styles/mobile_ux.css (piezas) o styles/activista.css (lanzador y barras)
Cambiar los colores de serie o las paletas Variables --a26-* de themes/Activista.css; las paletas, en mobile_settings.js
La barra de unirse a un pub views/mobile_pubbar.js
Otro HTML en una pantalla del dev Función en views/mobile_ui.js + una línea en su vista
Una pantalla nueva Vista propia en views/mobile_*.js + ruta en fork_routes.js
Algo en Ajustes del móvil views/mobile_settings.js
Un texto nuevo translations/i18n_fork.js, en los 13 idiomas
Un icono views/mobile_icons.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

Cómo seguir modificando, paso a paso:

  1. Arrancar en local (ver «Probar en local») y localizar en el inspector la clase o la pantalla.
  2. Decidir con la tabla dónde va. Si la respuesta es un fichero del dev, parar y releer las reglas.
  3. Hacer el cambio.
  4. Pasar «Antes de hacer commit».
  5. Commit en castellano y subir la rama PRUEBAS a forgejo.
  6. Montar la APK con android/scripts/sobre_oficial.sh y probarla en el emulador Oasis_Pruebas.
  7. Si entra un fichero o un mecanismo nuevo, apuntarlo en esta guía en el mismo commit.

Lo que no se toca

  • src/backend/backend.js. Cambia en 34 de cada 39 versiones. Ni rutas nuevas, ni middleware, ni envolver funciones suyas como checkMod.
  • La cadena de middleware del final de backend.js. Crece en cada versión.
  • Los modelos de src/models/, salvo el nuestro (fork_workflows.js). Ahí se decide qué se publica en la red y cómo se cuenta. Si lo cambiamos, nuestro móvil cuenta distinto que el escritorio de al lado. Un ejemplo real: quien crea una votación no puede votar en ella. No nos gusta, pero es una regla del modelo, así que se explica en pantalla y punto.
  • src/server/ (arranque de SSB, ssb_config.js, package.json).
  • src/backend/request_guards.js, que lleva la CSP. Nada de style="" ni de <script> en la página. Desde la 1.3.5 es script-src 'none': tampoco valen ficheros .js propios. Lo que haga falta, con enlaces, formularios y CSS.
  • Las traducciones del dev, translations/oasis_*.js. Se reescriben casi en cada versión.
  • styles/style.css y styles/mobile.css.
  • Los temas del dev: Dark, Clear, Purple, Matrix y también OasisMobile.css, que aunque parezca nuestro es suyo (lo toca en 21 de 39 versiones).

Las vistas del dev: una línea y ya

src/views/*_view.js y main_views.js son del dev y las reescribe a menudo (tribes_view.js en 23 versiones, main_views.js en 31). Si en una pantalla suya hace falta otro HTML en el móvil, el código va en src/views/mobile_ui.js y en la vista solo queda la llamada:

const mobileUi = require('./mobile_ui');
// ...
if (mobileUi.isMobile()) return mobileUi.tribeTabs(tribe, section, sections);

Cuando el dev reescribe la vista, se vuelve a poner esa línea y listo. En escritorio 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, 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

La rama tuvo un módulo de salas y llamadas propio (Karvan). Se quitó el 19/10/2026 porque el dev ya trae Teléfono y Salas. En Android el sonido y la cámara pasan por un puente nativo de la app del dev (.audio_bridge; los ficheros src/server/phone_*_android.js también son suyos). Por eso la APK se monta sobre la oficial con android/scripts/sobre_oficial.sh: su app tal cual, nuestro backend dentro y paquete propio. Si falta algo en las llamadas, se le pide al dev, no se monta otro módulo.

Ojo al comparar con el dev: para el móvil la referencia es el nodejs-project de su APK oficial, no su repositorio git. Hay ficheros, como SSB_server.js o phone_module.js, cuya versión de móvil solo está en la APK.

Lo mismo vale para cualquier módulo: antes de hacer uno propio, mirad si el dev ya lo tiene o lo está haciendo.

Navegación

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). La abre el ancla #oasis-menu y la pinta :target: abrirla deja una entrada en el historial, así que el gesto atrás la cierra sin cambiar de pantalla. La X, tocar fuera o volver a tocar Menú van a #menu-cerrado, un ancla que no existe, para que la página no salte arriba. 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.

Lo que es nuestro

Aquí se puede hacer lo que haga falta.

  • src/client/assets/styles/mobile_base.css: la maqueta del móvil (lanzador, barras, tarjetas, formularios). Se carga siempre en el móvil, antes del skin.
  • src/client/assets/styles/mobile_ux.css: márgenes, letra, botones y todas las piezas nuevas. Vale para los dos skins de móvil.
  • src/client/assets/themes/Activista.css y styles/activista.css: el skin Activista, el único del móvil (Acampada y el OasisMobile del dev se quitaron del selector el 20/10/2026). Lo más simple posible: letra del sistema, bordes finos y sin sombras. El skin quita lo que sobra; los colores los pone cada cual.
  • src/views/mobile_pubbar.js: la barra fija de unirse a un pub (y de restaurar una copia), encima de la barra de abajo. Solo sale si hay algo que contar y se pone al día al cambiar de pantalla (sin JS); el estado sale de backupModel.restoreStatus(), que backend.js le pasa a fork_routes.js en la línea que lo monta.
  • src/views/mobile_ui.js: lo que se enchufa en vistas del dev.
  • 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. 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. También deja abiertos los comentarios de las fichas con la opción del dev (comments_view.setCommentsOpen), salvo en el parlamento.
  • 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. Las claves bbShort_<modulo> son el nombre corto de la barra de abajo cuando el del dev no cabe en una de las cinco pestañas (medido a 412 y 360 px en los 13 idiomas); sin clave se usa el nombre entero, que queda siempre como nombre accesible. Si un perfil nuevo mete otro módulo en la barra, medirlo.
  • Los avisos del dev (versión nueva y sugerencia, .apk-banners .update-banner) van fijos abajo, encima de la barra, como la del pub: mobile_ux.css, sin tocar su HTML. Se esconden con el teclado, con el menú y con la barra del pub; en el WebView viejo se quedan arriba.
  • src/client/assets/images/ux-*.svg: nuestras imágenes.
  • src/client/assets/images/mobile-*.svg: iconos de línea que mobile_ux.css pinta con mask en sitios del dev que llevan emoji o un carácter (avisos de arriba, fichas de visibilidad, Compartir, estado del teléfono, responder y enviar en chats). Se esconde el carácter con font-size: 0 y el icono toma el color del texto. Mismo trazo para todos: 24x24, línea de 2, puntas redondas. Los del menú y la barra de abajo están en views/mobile_icons.js y no se tocan desde aquí. Nada de emoji ni de logotipos (tampoco el robot de las sugerencias del dev).
  • android/scripts/sobre_oficial.sh: monta la APK sobre la oficial del dev. El resto de android/ (el proyecto Gradle propio) queda como estaba, sin uso.
  • android/icono/: el icono adaptativo (la isla del logo de Oasis sobre su fondo). sobre_oficial.sh lo copia encima del de la APK oficial, que solo trae un PNG cuadrado y el lanzador lo encoge dentro de un círculo blanco.

Cómo hacer cada cosa

Desde la 1.3.5 el dev monta en el móvil una cabecera por módulo (apkModbar en main_views.js): se lleva a su barra el título, la primera caja de fichas, el buscador y los contadores, y pone los avisos en .apk-banners. Su CSS está en OasisMobile.css, que con el skin Activista no se carga, así que su estilo va en mobile_ux.css (bloque «cabecera de modulo de la 1.3.5»). Las fichas, en rejilla de tres columnas: en el móvil no se desliza de lado. Filtrar de Actividad es una casilla con su etiqueta dentro de la propia caja de fichas, para que viaje con ella a la cabecera.

Los colores de serie (paleta Estándar) son los de la APK oficial, medidos con el inspector sobre su backend: si el dev los cambia, se vuelven a medir y se ponen en PALETTES (mobile_settings.js). Los botones son los nuestros.

Cambiar cómo se ve algo. Se busca la clase en el HTML (servidor local e inspector) y se escribe la regla en mobile_ux.css. Para los colores usad las variables --ux-* (--ux-bg, --ux-fg, --ux-accent, --ux-muted, --ux-line, --ux-danger), que tiran de las --a26-* del skin. Si la regla no gana, es que mobile.css o Activista.css mandan con !important y selectores largos: hay que subir la especificidad y poner !important también. Ojo con una trampa: Activista.css quita fondo, borde y sombra a todos los div, así que para ponérselo a uno hace falta .main-column div.la-clase.

Huecos de las barras del sistema: nada de env(safe-area-inset-*). El contenedor de la app del dev ya se aparta de la barra de estado y de la de gestos, y si se suma en el CSS el hueco sale dos veces. Se usan var(--inset-top) y var(--inset-bottom), que valen 0 y están en mobile_base.css.

Botones de solo icono: debajo llevan su nombre en letra de 12 px, sacado de su title con attr(title) en CSS (en el móvil no hay hover). El texto es el del dev, ya traducido. Si un botón nuevo del dev no se entiende y no trae title, se le pide al dev.

Zonas táctiles: 44 px como mínimo para botones, fichas y casillas (con su etiqueta); 24 px para los enlaces que van dentro de una línea de texto (nombres, etiquetas).

Letra: Anton para títulos y para el botón negro principal de cada pantalla (.create-button). Lo demás, letra del sistema en negrita.

Márgenes: 14 px a cada lado y ya. Los contenedores de en medio sin relleno, que antes se iban sumando y una ficha perdía 74 px por lado.

Cambiar el HTML de una pantalla del dev. Función en mobile_ui.js y una línea en la vista, como arriba.

Una pantalla o una ruta nueva. En fork_routes.js. Lo que no atiende nuestro router pasa al del dev con next():

.get('/modules', async (ctx, next) => {
  if (!isMobile()) return next();   // escritorio: la del dev
  ctx.body = mobileModulesView({ ... });
})

Retocar lo que contesta el dev: no se hace (regla 1). Antes había un wrapUpstream que miraba sus redirecciones para el aviso de sección apagada, ?saved=1 al guardar módulos y la vuelta a Ajustes tras guardar el perfil; se quitó el 20/10/2026 porque cualquier cambio suyo lo rompía sin avisar. Ahora Ajustes enlaza a /profile/edit y /feed/create, y guardar los módulos vuelve a donde decide el dev.

Textos. En i18n_fork.js y en los 13 idiomas (en, es, ca, gl, fr, eu, de, it, pt, zh, ar, hi, ru). Un idioma que falte en i18n_fork.js coge el bloque en inglés entero y pisa las claves que el dev sí tenía traducidas (pasó con catalán y gallego hasta el 22/10). Antes, mirad que la clave no exista ya en oasis_en.js, porque si existe la estaríais cambiando también en escritorio. En el código siempre con texto de reserva: i18n.miClave || 'My text'.

Un workflow. En fork_workflows.js, que lo mete en las listas que exporta el modelo del dev. No se toca workflows_model.js.

Un icono. En mobile_icons.js, trazo de 2 px sobre rejilla de 24 y currentColor. El nombre es el de la ruta: /tribes es tribes.

Antes de hacer commit

  • Que git diff --stat no toque nada de la lista de lo que no se toca. En las vistas del dev, solo líneas de enganche.
  • node --check en los .js que hayáis cambiado.
  • Arrancar en local y ver que /activity, /tribes, /modules, /settings, /votes, /phone, /rooms e /inbox cargan.
  • Mirarlo a 412 px de ancho, y a 360 si es algo ancho.
  • Si es CSS nuevo, mirarlo también en un WebView viejo (Android 9 trae el 69): no hay :has, ni gap en flex, ni inset, ni dvh. Lo que dependa de eso va con alternativa; hay un bloque @supports not (inset: 0) al final de mobile_ux.css. En emulador x86 la APK no arranca por debajo de Android 12 (el traductor ARM no sabe ejecutar el node del dev), así que el viejo se prueba con el servidor local y el navegador de pruebas del WebView.
  • Los textos nuevos, en los 13 idiomas. node TESTS/idiomas/run.mjs recorre todas las pantallas en todos los idiomas buscando scroll de lado, filas que se deslizan y textos rotos o sin traducir (está en TESTS/, que no se sube).
  • Nada en línea, que la CSP lo bloquea.
  • Commit en castellano, sin coautorías de herramientas.
  • Sin claves, contraseñas ni nada de .ssb.

Cuando sale versión nueva del dev

  1. Lo suyo se coge tal cual, y para los ficheros con versión de móvil, la de su APK oficial (assets/nodejs-project.zip), no la de su git.
  2. En sus vistas se vuelven a poner los enganches. El grep -n mobileUi sobre la versión anterior de la rama dice dónde iban.
  3. Se repite la medición de docs/FRONTERA_UPSTREAM.md: qué ha tocado y si ha desaparecido alguna clase que usen nuestras hojas.
  4. Se repasan a 412 px las pantallas de la lista de arriba.
  5. Se monta la APK sobre la oficial de esa misma versión: OASIS_VERSION=x.y.z android/scripts/sobre_oficial.sh.
  6. Con REA se mira otra vez cómo extrae y cómo usa la WebView su APK (copyNodeProjectIfNeeded, configureWebView y el manifiesto). Si cambia, sobre_oficial.sh puede tener que cambiar. Los comandos, en docs/ARQUITECTURA_APK.md.

Probar en local

HOME=/tmp/oasis-prueba OASIS_NETWORK_PAUSED=1 node main.js

Y en el navegador http://localhost:3000 con el inspector en modo móvil a 412x915. Va con una identidad de usar y tirar y con la red parada.

Cosas que pasan:

  • src/server/node_modules no está en git. Sirve el de la APK base.
  • Si al reiniciar sale "Another Oasis instance is already running", el anterior sigue vivo y estáis viendo código viejo. Matadlo primero.
  • Al arrancar desaparecen src/configs/banking-eco-history.json y fediverse-accounts.json. Antes del commit, git checkout -- src/configs/.

En el emulador, la APK de depuración deja inspeccionar la WebView desde chrome://inspect. El Pixel_9_API_36 de Android Studio está casi lleno; para instalar la APK va mejor Oasis_Pruebas (12 GB, puerto 5556).

La APK y la extracción del backend

La app del dev lleva nuestro código dentro de assets/nodejs-project.zip y al abrirse lo descomprime en su carpeta de datos. Solo lo vuelve a descomprimir si cambia versionName.versionCode (lo guarda en nodejs-project/.version). Si no cambia, arranca con el código de la vez anterior aunque la APK sea nueva, y parece que se han perdido los cambios (el CSS, por ejemplo). Por eso sobre_oficial.sh pone en el versionName una huella del código (1.3.3-hacklab.<huella>): cada APK distinta se descomprime de nuevo. La config de cada cual (src/configs) se guarda aparte y se conserva.

Cómo está hecha la APK del dev por dentro (sacado con REA): docs/ARQUITECTURA_APK.md.

Lo que todavía está mal

Para el móvil, la referencia es el nodejs-project de la APK oficial del dev, no su git: él mete cambios de móvil (en backend.js, SSB_server.js, phone_module.js...) que solo están en la APK. Comparado con eso, la rama cambia 15 ficheros suyos, 516 líneas (20/10/2026, contra el nodejs-project de la APK 1.3.3). Por tamaño:

  • backend/blobHandler.js (190): limpiar los metadatos de las fotos también en Android. Es una función nuestra metida en su fichero; habría que proponérsela al dev.
  • configs/oasis-config.json (87) y configs/config-manager.js (18): la config de serie del móvil (skin Activista, perfil Activismo, barra de abajo).
  • views/main_views.js (64), settings_view.js (33), welcome_view.js (20), tribes_view.js (9), vote_view.js (7): enganches a mobile_ui.js y el orden de carga de las hojas. Es lo que la guía permite, pero hay que revisarlo en cada versión.
  • main.js (45): DNS del sistema primero, para respetar la VPN.
  • server/ssb_config.js (30): varias identidades en el mismo móvil.
  • models/workflows_model.js (17): la lógica de skins del móvil (themeOf, sameTheme). settings_view.js coge currentWorkflow al cargar y no se puede envolver desde fuera.
  • styles/mobile.css (14), bookmark_view.js (13), forum_view.js (7), translations/i18n.js (5, la mezcla con i18n_fork.js): arreglos sueltos de antes.
  • backend/backend.js (2): la línea que monta nuestro router.

Cuando el dev saque versión, se repite esta comparación con su APK nueva.