Commit graph

87 commits

Author SHA1 Message Date
oasis-bot
2e3ff1e79f tema Acampada: letra y botones mas grandes
Lanzador (iconos de 64px, etiquetas de 13px en negrita que solo parten entre
palabras), barra de abajo, fichas de filtro de 46px, iconos de las tarjetas
de 44px, reacciones del chat, formularios y textos de cabecera.
2026-10-19 02:17:12 +02:00
oasis-bot
0baf85faa9 skins: elegir el aspecto en el movil con tarjetas de un toque
En Ajustes del movil, Tema y Flujos de trabajo dejan de ser desplegables:
cada skin es una tarjeta con su miniatura y cada workflow un boton grande,
y se aplican al tocarlos. Solo se ofrecen los skins que tienen maqueta de
movil (Acampada y Oasis Mobile); el servidor rechaza un tema de escritorio,
que dejaba la app sin maqueta. La bienvenida tambien ofrece elegir skin.

Aplicar un workflow ya no cambia el skin: se queda el que haya elegido cada
cual.

OasisMobile.css se carga con su propio <link> versionado antes de
Acampada.css, en vez de con @import: el @import sin ?v= se quedaba en la
cache del WebView y tras actualizar se veia la maqueta vieja.
2026-10-19 02:17:12 +02:00
oasis-bot
ac921c9d56 readme: capturas con el tema Acampada
Las ocho capturas, la portada y el esquema de la interfaz rehechos sobre la
1.3.3 con el tema Acampada. generar_portada.py compone la portada a partir
de las capturas y dibuja el esquema; el texto vive en el script. Novedades:
tema, fotos que no se pueden limpiar y DNS.
2026-10-19 02:06:05 +02:00
oasis-bot
9a4ca6b2b3 tema Acampada: Karvan y respuestas del chat en blanco y negro
karvan.css trae su paleta amarilla sin !important: las salas activas salian
en negro con la letra oscura. Ahora tarjetas con marco negro, burbujas como
las del chat y los botones de llamada en blanco.
2026-10-19 02:06:05 +02:00
oasis-bot
b64dcf9b7a fotos: si no se pueden limpiar, no se suben
Si quitar los metadatos fallaba, blobHandler subia la foto original, con el
GPS. Ahora se para con un 400 y un aviso (imageMetadataUnsafe, en los 11
idiomas): HEIC/HEIF/AVIF y TIFF, que pueden llevar EXIF y aqui no se saben
limpiar, y JPEG/PNG/WebP que no se dejan recorrer. Un JPEG cortado ya no
sube como una imagen vacia. Formatos sin EXIF (BMP, SVG...) pasan igual.

Es el cambio del 10 de octubre, llevado a la copia de la limpieza que vive
ahora en blobHandler.js.
2026-10-19 02:02:16 +02:00
hacklab
ed77a13c85 dns: primero el resolutor del sistema, los publicos de respaldo
main.js preguntaba siempre a 8.8.8.8/1.1.1.1. Las VPN que evitan fugas de DNS
(Mullvad) y las redes que bloquean DNS externos los rechazan, y entonces no se
encontraba ningun pub por nombre: unirse a uno no hacia nada y no decia nada.

Ahora va primero getaddrinfo, que respeta la VPN y el DNS privado de Android;
a los 5 s, o si falla, tambien los publicos. Probado en Android 15 detras de
Mullvad: antes no resolvia hacklab.laenre.net y ahora si.
2026-10-19 02:00:56 +02:00
oasis-bot
b3172ed1c3 android: release --public, version de package.json y libnode comprimida
Lo del 10 de octubre que sigue valiendo sobre la base 1.3.3:
- con un tag v* el workflow publica la APK; a mano sigue en borrador
- el workflow trae el APK oficial de la misma version: de ahi salen
  node_modules y libnode.so (prepare.sh ya lo usaba, pero el runner no lo tenia)
- versionName sale de package.json en vez de ir escrito a mano
- libnode.so comprimida, como en la oficial (unos 35 MB menos por descarga)
- release.sh: JAVA_HOME en el PATH, no deja salir una release debuggable,
  exige CHANGE_WIFI_MULTICAST_STATE y avisa si la APK pasa de 80 MB

Se queda fuera la poda de prepare.sh y la sha256 de la APK 1.2.5: ahora el
node_modules viene ya podado del APK oficial.
2026-10-19 02:00:40 +02:00
hacklab
99e5d766e9 android: pantalla completa con margenes, teclado y descargas
El contenedor deja sitio a las barras del sistema y al teclado (Android 15
obliga con targetSdk 35). Las descargas van al gestor de Android. Fondo
blanco e iconos oscuros, como el tema Acampada.
2026-10-19 01:59:39 +02:00
hacklab
ba057f0092 android: permisos y MulticastLock para ver moviles en la misma wifi
El anuncio LAN de SSB va por UDP broadcast y Android lo filtra sin un
MulticastLock. La oficial declara ACCESS_WIFI_STATE y
CHANGE_WIFI_MULTICAST_STATE; esta no, asi que dos moviles en la misma red no
se encontraban.
2026-10-19 01:59:13 +02:00
hacklab
de5e8fba20 android: un script deja el proyecto listo para Android Studio
Clona el Oasis oficial en su commit, descarga su APK de la misma version y
lanza prepare.sh. Despues basta con abrir android/ y darle a Build APK.
2026-10-19 01:59:13 +02:00
oasis-bot
101bdfe4e8 tema Acampada: blanco, negro y cian sobre el lanzador de la 1.3.3
Trae el tema del 10 de octubre (que se quedo fuera de PRUEBAS) y lo pone
por defecto en el movil. Acampada.css importa OasisMobile.css, asi que el
lanzador, la barra de 4 atajos y el workflow de activistas siguen igual;
hive_acampada.css va detras del tema y repinta lanzador, fichas de filtro,
hilos del foro, burbujas del chat, iconos de las tarjetas e identidades.

Quien ya tenia OasisMobile conserva su workflow reconocido.
2026-10-19 01:59:04 +02:00
oasis-bot
7d281902fb readme: capturas de la 1.3.3 nada mas entrar
Some checks are pending
APK / build (push) Waiting to run
Portada con cuatro pantallas, enlace de descarga y novedades arriba del
todo. Capturas nuevas de la interfaz y de Karvan, y el esquema de la
interfaz redibujado: ya no hay hexagonos ni Peers/Invites en la barra.
Las imagenes viven en docs/capturas, en el propio repo.
2026-10-19 00:44:06 +02:00
oasis-bot
cfe0b6cca1 karvan: tus mensajes a la derecha tambien al recargar la sala
karvan.js solo marcaba como propios los que llegaban despues de abrir
la sala; los que pintaba el servidor salian todos como de otra persona.
2026-10-19 00:44:06 +02:00
oasis-bot
5f5c1d6d0a interfaz: filtros en fichas y tarjetas sin cajas de mas
- Los filtros de chats, feed, foros, pads... heredaban el estilo de boton
  grande (48px, ancho completo): en el foro las categorias llenaban la
  pantalla. Ahora van en fila como los de Actividad; Crear sigue grande.
- La regla de tarjetas ([class*=-card]) pillaba tambien -card-header y
  -card-hero-image, que salian como cajas con fondo y borde. Se limita a
  las clases acabadas en -card.
- Acciones de la tarjeta (borrar, fijar, enlace, abrir) en una sola fila
  de iconos redondos; '.main-column form' las ponia a ancho completo.
- Se ocultan las cajas de filtros vacias del foro.
2026-10-19 00:44:06 +02:00
oasis-bot
948b6460d9 upstream: integrar Oasis 1.3.3
Diferencia 1.3.1 -> 1.3.3 del codigo de la APK oficial aplicada a tres
bandas encima de la rama: karma en el perfil, salas con directo, fotos
selladas, visibilidad de menciones, telefono por stream en Android y
las traducciones nuevas. Sin dependencias nuevas.

OasisMobile.css sigue siendo el del fork; del oficial solo se traen al
final las reglas de las piezas nuevas (karma, directo a pantalla
completa, salas en vivo, graphos).
2026-10-19 00:30:25 +02:00
oasis-bot
bc64565e9c android: gradle toma el JDK de JAVA_HOME
La ruta fija a /opt/android-studio/jbr rompia la compilacion en cualquier
otra maquina y en el runner, que pasa su propio JAVA_HOME.
2026-10-19 00:28:51 +02:00
oasis-bot
ab9bfab09a activistas: workflow por defecto, lanzador compacto y barra de 4 atajos
Con el workflow activistas caben todos los modulos en una pantalla: se
quitan el filtro Personal/Social y los accesos de usuario avanzado
(menciones, habitantes, perfil, CV, estadisticas, blockexplorer,
modulos). Peers y la edicion de la barra pasan a Herramientas; la barra
inferior se queda en los 4 atajos. La config de serie arranca ya con
los modulos de activistas.
2026-10-18 23:54:54 +02:00
oasis-bot
e01f718c1c docs: base 1.3.1, lanzador y workflows; la APK base ha de ser la 1.3.1 2026-10-18 02:52:17 +02:00
oasis-bot
5a04113330 interfaz: lanzador de modulos en lugar de los hexagonos
La portada ordena los modulos por secciones en una rejilla de iconos, como el
cajon de apps del movil. Solo salen los modulos activos y las secciones que
tienen alguno; Personal y Social de la topbar parten el lanzador en dos.

Fuera los enlaces que ya no existen en 1.3.1 (/legacy, /public/latest/*) y
dentro los modulos nuevos: wiki, rooms, emergencias, mailing, campanas...

1.3.1 trae en mobile.css su propio chrome movil (cabecera fija y cajones); se
apaga desde el tema para que no se monte encima del de la rama.
2026-10-18 02:52:17 +02:00
oasis-bot
a11a730c26 workflows: activistas con lo justo para organizarse
Chats, Karvan, pads, foro, imagenes, videos, wiki y blogs, mas feed,
invitaciones y copia de seguridad. Karvan entra en la lista de modulos para que
los workflows lo enciendan y apaguen como al resto.

En movil un workflow cambia los modulos y no el tema: se queda OasisMobile.
2026-10-18 02:52:17 +02:00
oasis-bot
c332afd6ea upstream: integrar Oasis 1.3.1
Base del merge a tres bandas: git 0.9.5 de epsylon, esta rama y el src de la
APK oficial 1.3.1 (la variante movil: OASIS_MOBILE, regex sin \p{}, audio y
video de Android). Corre en el mismo nodejs-mobile 18.20.4 que ya usabamos.

Se conserva de la rama: Karvan, identidades y multicuenta, topbar y barra
inferior, borrado de EXIF sin sharp, filtro hot del foro, RTC sin STUN y los
modulos apagados en movil (wallet, banking, torrents).

Se toma de upstream lo que ya hace de serie: respuesta citada en chats, ssb-lan
en movil, configuracion en ~/.ssb/oasis (sobrevive a reinstalar el backend).
El asistente de bienvenida deja elegir workflow tambien en movil.
2026-10-18 02:52:17 +02:00
s1to
8d838dd8b1 readme: la portada del repositorio, con esquemas y capturas
Al entrar en el repositorio se veia el aviso de rama experimental y, debajo,
el README entero de upstream copiado: 350 lineas contando lo que ya cuenta el
proyecto oficial, y mejor.

Ahora la portada ensena lo que hay aqui: la tabla de que anade esta rama frente
al oficial, Oasis explicado en cuatro dibujos, Karvan, las videollamadas, las
identidades y como empezar desde cero, todo con esquemas propios y capturas
reales.

El aviso de que esto NO es Oasis oficial se mantiene arriba del todo y completo.
Y al final, los enlaces al proyecto de epsylon, que es de donde sale todo.

Las imagenes se enlazan a la wiki en vez de duplicarse en el repositorio, que
es lo que hace tambien upstream con las suyas.

El fichero se sigue leyendo al arrancar el backend (readFileSync sin try/catch),
asi que lo importante es que exista: comprobado que arranca.
2026-08-20 08:32:22 +02:00
s1to
923bb0ef9d blobs: las fotos ya no suben con la ubicacion dentro
stripImageMetadata dependia de sharp, y cuando no esta devolvia la imagen
intacta. En Android sharp no se empaqueta —lleva binarios nativos y el bundle
del movil va sin ninguno— asi que las fotos subian con su EXIF entero: marca,
modelo, numero de serie, fecha y coordenadas GPS. Y sin sharp instalado,
tambien en escritorio.

Ahora hay un limpiador que no depende de nada: recorre el contenedor y tira los
bloques de metadatos sin decodificar ni recomprimir, asi que los pixeles quedan
byte a byte como estaban.

  JPEG   fuera APP1 (Exif y XMP), APP13 (IPTC), APP14, COM y demas.
         Se quedan JFIF y el perfil de color, que afectan a como se ve.
  PNG    fuera tEXt, zTXt, iTXt, eXIf, tIME, dSIG.
  WebP   fuera los bloques EXIF y XMP del contenedor RIFF.

De la orientacion se guarda solo eso: sin sharp no se pueden girar los pixeles,
y tirar la etiqueta dejaria tumbadas las fotos verticales. Se reconstruye un
bloque EXIF de 32 bytes con esa unica etiqueta, que no dice nada de quien hizo
la foto ni donde. Si sharp esta, se sigue prefiriendo su camino, que ademas gira
la imagen de verdad.

Comprobado con una foto que llevaba GPS, marca, modelo, numero de serie y fecha:

  - En el movil y en escritorio, el blob guardado queda con 32 bytes de EXIF
    (solo la orientacion, que sobrevive) y cero rastros de lo demas.
  - Los pixeles son identicos antes y despues, en JPEG, PNG y WebP.
  - El perfil de color ICC se conserva.
  - Sin metadatos, progresivo, GIF, fichero corrupto, fichero vacio y algo que
    no es una imagen: se devuelven tal cual, sin excepciones.
2026-08-19 21:07:02 +02:00
s1to
da2ad8e1c6 android: la pantalla de espera, con tilde y sin asustar
Decia "Preparando la aplicacion" sin tilde y "puede tardar unos minutos", que
para un primer arranque de quince segundos suena a que algo va mal. Ahora dice
lo que hace y cuanto: descomprime el servidor, tarda un minuto, no hay que
hacer nada.
2026-08-19 20:48:38 +02:00
s1to
5c769a5a10 estructura: los ficheros de la rama, donde los pondria el dev
Upstream no usa ni un solo subdirectorio en src/views, src/backend, src/models,
src/client/assets/styles ni translations: todo plano. La rama habia creado dos
(views/fork/ y translations/fork/), que es lo que mas se separaba de su forma de
organizar el codigo. Se deshacen, y los ficheros pasan a llamarse como los suyos:

  views/fork/hive_nav.js          -> views/hive_views.js      (como main_views.js)
  views/fork/identities.js        -> views/identities_view.js (como *_view.js)
  translations/fork/i18n_fork.js  -> translations/i18n_fork.js (junto a i18n.js)
  backend/fork_routes.js          -> backend/karvan_routes.js (familia karvan_*)

Ademas se retira una ruta duplicada: /legacy/export estaba declarada dos veces,
en backend.js (la del dev) y en el fichero de rutas de la rama, con el mismo
cuerpo salvo un && defensivo. Nacio cuando el formulario se paso a GET; al
devolverlo a POST quedo como copia exacta. Con ella se van legacyModel y
onboardingModel, que ya no hacia falta inyectar.

La cabecera del fichero de rutas explica ahora por que sigue existiendo, con los
datos medidos y no de memoria: backend.js concentra 625 rutas y se reescribe en
cada release (+833/-286 en la 0.9.2, +266/-31 en la 0.9.1), asi que una ruta
anadida en medio entra en conflicto cada vez.

Quedan diez ficheros propios, todos siguiendo la convencion de upstream, y
+247 lineas repartidas en 21 ficheros suyos (sin contar OasisMobile.css, que es
el tema de la rama).

Comprobado tras mover: arranque, las siete rutas principales, el selector de
identidades con sus siete entradas y su aviso, crear sala y enviar mensaje en
Karvan, y la exportacion de identidad por la ruta del dev.
2026-08-19 20:38:26 +02:00
s1to
e0ff70c138 android: rotar la pantalla rompia la app
Al girar el movil aparecia ERR_CONNECTION_REFUSED y ahi se quedaba. La lista de
configChanges estaba incompleta —faltaba smallestScreenSize, que es justo lo que
cambia al rotar—, asi que Android destruia y recreaba la Activity: el WebView se
perdia y volvia a cargar la URL, a veces antes de que el backend escuchara.

Con la lista completa, rotar ya no recrea nada y ademas no se pierde lo que
estuvieras escribiendo.

Y se anade una red de seguridad que no habia: onReceivedError vuelve a esperar
al backend y recarga la ultima pagina que si cargo, en vez de dejar el error de
Chromium en pantalla. Cubre tres casos mas, todos comprobados en el emulador:

- Matar el proceso :node con la app abierta (lo que hace Android cuando necesita
  memoria): antes se quedaba muerta, ahora vuelve sola en unos 19 segundos.
- Cambiar de identidad, que reinicia el backend a proposito.
- Arranques lentos en moviles con poca memoria.

Un guard evita que se acumulen hilos esperando al mismo puerto, porque
onReceivedError se dispara una vez por recurso que falle.

Probado ademas: boton atras, modo avion, trim-memory RUNNING_CRITICAL y
am kill con reapertura. Todo eso ya iba bien.
2026-08-19 19:34:06 +02:00
s1to
728f10beb0 i18n: los nombres de las categorias vuelven a ser los de epsylon
El overlay pisaba menuNetwork, menuMedia y fediverse para dejarlos en Network,
Media y Fediverse. Se quitan: la rama no deberia separarse de upstream en algo
tan visible, y ahora movil y escritorio dicen lo mismo (Community, Library,
Multiverse).

Eso obliga a renombrar el filtro de la topbar: se llamaba Community y ahora ese
nombre es el de una categoria, asi que en la misma pantalla habria dos. Pasa a
ser Social, que es del fork y no choca con nada de epsylon.

Y las traducciones dejan de estar a medias: las 56 claves de la rama estan
completas en los 11 idiomas, ninguna cae al ingles. Antes solo el castellano
estaba entero y los otros nueve mostraban el texto en ingles.
2026-08-19 19:24:29 +02:00
s1to
161d636f17 legacy: la contraseña de la copia deja de viajar en la direccion
El formulario de exportacion se habia pasado a GET, asi que la contraseña que
cifra la copia de la identidad acababa en el historial del navegador, en el
registro del servidor y en el Referer de lo siguiente que se cargara. Vuelve a
POST, como en upstream, y la ruta la lee del cuerpo.

Comprobado: la exportacion sigue descargando el fichero, y la direccion con la
contraseña ya no responde.
2026-08-19 11:23:19 +02:00
s1to
e84a9f84da forum: quitar el campo subtopic, que no lo lee nadie
Resto del intento de subtemas propios que se descarto: se copiaba a cada
respuesta pero ninguna vista lo mira. Los subtemas de verdad son los de
upstream, con sus rutas y sus vistas.
2026-08-19 11:21:25 +02:00
s1to
d843d47374 identidades: enlace a exportar e importar
Sacar o meter una identidad ya existente lo hace el modulo legacy, que es quien
sabe cifrar el secret con una contraseña. Se enlaza desde la lista para que
este donde se busca.
2026-08-19 11:18:55 +02:00
s1to
f465fb2288 android: script de publicacion y workflow para la APK
release.sh hace el ciclo entero y siempre igual, se lance a mano o desde un
runner: empaqueta el backend, compila, verifica y publica la release en gitea.

Las verificaciones no son decorativas, son las que han cazado fallos reales en
esta rama: una APK puede compilar, instalar y arrancar sin el backend dentro, o
haber perdido los permisos de camara y quedarse sin videollamadas. Se comprueba
que estan el backend y libnode.so, los dos permisos, y la firma.

El versionCode sale del numero de commits, que sube solo; el versionName, de
package.json, que es de donde lo saca tambien el backend, para que la version
que muestra la aplicacion no pueda discrepar de la de la APK. Los dos se pasan
por entorno a Gradle en vez de editarlos a mano.

La release se crea como borrador a proposito: publicar una APK firmada sin que
nadie la mire no deberia poder pasar por descuido.

El workflow de gitea no se dispara con cada commit (la APK son mas de 100 MB) y
necesita un runner con el SDK de Android; queda documentado en su cabecera.
2026-08-19 11:16:25 +02:00
s1to
a22e4a49d4 identidades: selector en los ajustes, con reinicio en movil
La base de multicuenta ya estaba en el arranque (OASIS_ACCOUNT), pero solo se
podia elegir por linea de comandos. Ahora hay una seccion en los ajustes que
lista las identidades, marca cual esta en uso y permite crear una.

Como funciona:

- accounts.js encuentra las identidades buscando directorios ~/.<algo> con un
  secret dentro, y lee de el su @id. En Android ese HOME es el almacenamiento
  privado de la app, asi que quedan aisladas del resto del sistema.
- El selector anota la elegida en src/configs/active-account; ssb_config.js la
  usa al arrancar si no hay OASIS_ACCOUNT (que sigue mandando).
- Crear una identidad solo anota el nombre: el secret lo genera ssb-config al
  arrancar con esa cuenta.

En movil hay ademas un boton de reinicio, porque aqui cerrar la app no basta:
el backend vive en un servicio en primer plano que sobrevive. La ruta responde
la pagina y luego termina el proceso; el servicio se recrea y node arranca con
la identidad nueva. No se puede levantar el runtime dos veces en el mismo
proceso, de ahi salir en vez de reiniciar por dentro.

Comprobado en el emulador: al reiniciar, el feed pasa a ser el de la otra
identidad y la anterior sigue intacta.

Dos carpetas pueden tener el mismo secret copiado, y publicar desde las dos
parte el registro sin arreglo posible. La lista lo detecta comparando los @id
y lo avisa en rojo en las dos filas.
2026-08-19 11:08:55 +02:00
s1to
37937e8363 assets: recuperar las tres imagenes de UX que faltaban
La pantalla de ajustes y el asistente de bienvenida piden ux-blocks.png,
ux-chats.png y ux-ainav.png para el selector de modo de interfaz. No se
copiaron al integrar 0.9.5, asi que el selector salia con tres imagenes rotas.

De paso se retira media-favorites.js con su JSON: es de una version anterior
de la rama y ya no lo requiere nadie, upstream lo resuelve con
content_favorites.js.
2026-08-19 10:35:26 +02:00
s1to
48cafbbe59 android: selector de ficheros, espera del backend y re-extraccion
Cuatro arreglos del envoltorio, todos vistos al probarlo en el emulador:

- onShowFileChooser: sin el, el navegador interno no abre nada al pulsar
  "Choose File", asi que no se podia subir ninguna imagen. El APK oficial si
  lo implementa; era una regresion frente a el.

- La marca de re-extraccion del backend era el versionName. Al reconstruir la
  APK sin subir version, la app se quedaba con el backend anterior y ningun
  cambio se aplicaba. Pasa a ser lastUpdateTime del paquete, que cambia en
  cada instalacion. (openFd sobre el asset no vale: va comprimido dentro del
  APK y no admite descriptor.)

- La espera del backend sondeaba con HEAD, que el backend rechaza con 400.
  Ahora abre un socket TCP contra 127.0.0.1:3000, que es lo unico que hay que
  saber, y espera hasta cinco minutos en vez de uno: descomprimir 231 MB y
  levantar SSB tarda mas en un movil lento. Mientras, pinta una pantalla de
  estado con los segundos transcurridos, en vez de dejar el WebView en blanco.

- targetUrl/onNewIntent para poder abrir una ruta concreta desde un intent.

network_security_config.xml tenia base-config detras de domain-config, que el
esquema no admite. Corregido el orden y restaurada la referencia en el
manifiesto, que se habia sustituido por usesCleartextTraffic=true al depurar:
eso abria texto en claro hacia cualquier host, no solo hacia loopback.
2026-08-19 10:30:37 +02:00
s1to
5bfbe2d6c8 modules: karvan en su sitio alfabetico
La lista de modulos va ordenada por nombre; karvan estaba detras de polls,
que es de donde se copio el patron. Pasa a estar entre jobs y larp.
2026-08-19 10:30:37 +02:00
s1to
cb892579f5 karvan: el panel de llamada no tenia estilos
Un comentario sin cerrar en karvan.css se comia la llave de la regla que
neutraliza el div{background:#222;padding:20px} global, y con ella todo el
bloque de la videollamada. El resultado eran dos cajas vacias enormes y unos
botones cuadrados en vez del panel.

Ademas:

- La hoja del modulo se cargaba antes que el tema, asi que el tema ganaba por
  cascada. Pasa a cargarse despues, que es lo que decia su propio comentario.
- Las opciones de duracion (30m / 2h / 8h) se partian letra a letra en
  escritorio; les faltaba white-space: nowrap.
- Clear-SNH usa !important en casi todo, asi que ninguna hoja posterior puede
  ganarle. Se resuelve como lo resuelve Oasis: es el tema el que pinta el
  modulo. Sin ese bloque las burbujas salian negras sobre blanco y el texto
  secundario en amarillo palido, ilegible.

Comprobado con los cuatro temas en escritorio y en el emulador.
2026-08-19 10:30:16 +02:00
s1to
2203b54917 chats: la respuesta citada se guardaba pero no se pintaba
buildMessage no copiaba replyTo del contenido del mensaje, asi que la vista
nunca encontraba a quien se respondia y la burbuja salia sin cita. El campo
estaba puesto por error en buildChat, donde no significa nada: un chat no
responde a ningun mensaje.

Se ve al responder a un mensaje y recargar el hilo.
2026-08-19 10:30:00 +02:00
SITO
0bf4a8fcb9 fix: la app no arrancaba en Android por una expresion regular de 0.9.5
Diagnosticado en el emulador. El backend moria al cargar backend.js:

  SyntaxError: Invalid regular expression: /^#([\p{L}\p{N}_-]+)/:
  Invalid property name in character class

libnode.so de nodejs-mobile viene sin ICU completo, asi que las propiedades Unicode
en expresiones regulares no existen y el fichero ni siquiera compila. La rama ya lo
habia resuelto con un rango explicito; al integrar 0.9.5 se reintrodujo la forma de
upstream y con ella el fallo. Afectaba a backend.js y a data_model.js.

Tras el arreglo el emulador arranca: 'Backend started on port 3000', 991 modulos,
285 ms de warmup.

Y se devuelven al overlay los nombres de tres categorias. Upstream los renombro en
0.9.5 (Network -> Community, Media -> Library, Fediverse -> Multiverse) y al
restaurar los ficheros de traduccion se colaron los suyos, cambiando las etiquetas
de los hexagonos. Lo destapo una captura de pantalla del usuario, no el codigo.
2026-08-19 08:24:12 +02:00
SITO
f354069af7 ssb: base de multicuenta y arreglo de las rutas fijas a ~/.ssb
ssb_config pasa a derivar la cuenta de OASIS_ACCOUNT. Como ssb-config construye la
ruta desde el appname y gui.js saca el socket de config.path, cambiar ese literal
arrastra de forma coherente el almacen, la base de datos, los blobs, el secret y el
socket. Sin la variable se usa 'ssb', asi que las instalaciones existentes siguen en
~/.ssb y no notan nada.

El nombre se valida contra [a-zA-Z0-9][a-zA-Z0-9_-]{0,31} y cae a 'ssb' si no encaja.
No es de adorno: acaba en rutas de fichero y hay operaciones destructivas detras.
Comprobado que OASIS_ACCOUNT=../../etc no sale de sitio.

statePath separa tambien por cuenta cuando se usa OASIS_STATE_DIR. Sin eso, dos
identidades compartirian el estado que 0.9.5 empezo a guardar ahi, que es justo el
camino a partir el registro.

Y el arreglo que importa: doce sitios construian la ruta como os.homedir() + '/.ssb'
en vez de usar la de la cuenta. El peor era panicmode_model, que con varias
identidades habria borrado la equivocada; tambien exportmode y legacy_model, que
habrian exportado o restaurado la identidad de otra cuenta. Los de lectura
—main_models, stats_model y backend.js con gossip.json y ebt— habrian mirado siempre
la cuenta por defecto.

Falta la parte visible: el selector de identidad y el reinicio del proceso al
cambiar. Esta base es la que hacia falta para que eso no sea peligroso.

Verificado: con OASIS_ACCOUNT sin definir la ruta sigue siendo ~/.ssb; con 'trabajo'
pasa a ~/.trabajo; con un valor con .. o espacios se rechaza. Diez rutas OK con la
app en marcha, incluidas /peers y /stats, que son las que leen esos ficheros.
2026-08-19 00:44:23 +02:00
SITO
f80b2e04f0 docs: aviso de rama experimental en el README y version al dia
El README abria con 'Oasis Mobile 0.9.1' y describia mejoras sobre 0.9.0, sin decir
en ningun sitio que esto no es el Oasis oficial. Ahora lo primero que se lee es que
es una rama experimental sin afiliacion, con enlace al repositorio de epsylon, la
indicacion de que los fallos se reportan aqui y el enlace a la wiki.

El package.json de la raiz seguia en 0.9.1 mientras el de src/server ya estaba en
0.9.5. Alineados.

Nota: backend.js sirve este README en la interfaz, asi que el aviso se ve tambien
desde dentro de la aplicacion.
2026-08-19 00:41:25 +02:00
SITO
f3330e3d0e views: la topbar de movil solo en movil
renderMobileTopbar era la unica de las tres piezas de interfaz de la rama sin gate,
asi que en escritorio se dibujaba encima de la cabecera de upstream. Los hexagonos y
la barra inferior si lo tenian.

Detectado al arrancar el arbol sin OASIS_MOBILE para preparar la version de
escritorio.
2026-08-19 00:35:49 +02:00
SITO
736b528b99 karvan: darle sitio en el escritorio siguiendo el patron del dev
Karvan solo existia en la rejilla de hexagonos, que es de movil. En escritorio no
habia forma de llegar salvo escribiendo la URL.

Se anade renderKarvanLink en main_views, calcado de renderPollsLink —misma forma,
mismo checkMod por getConfig().modules, mismo navLink— y se invoca en el grupo
social junto a renderChatsLink. Entra tambien en modules_view y en la lista de
/modules de backend.js, para poder apagarlo como cualquier otro modulo, con sus
etiquetas en el overlay.

Los estilos del modulo pasan a src/client/assets/styles/karvan.css. Estaban dentro
de OasisMobile.css, que en escritorio no se carga, asi que las salas se habrian
visto sin formato. Va como hoja propia siguiendo el patron de highlight.css, que
tampoco pertenece a ningun tema: asi el modulo se ve igual con cualquier tema y en
las dos plataformas.

Verificado: karvan.css sirve 200 y se carga en las dos plantillas, el enlace aparece
en el menu lateral, y en movil la rejilla de hexagonos sigue igual.
2026-08-19 00:30:55 +02:00
SITO
841acf2a7a karvan: quitar el STUN de Google y servir la configuracion ICE del propio nodo
El cliente tenia stun.l.google.com fijo en el codigo. Un servidor STUN aprende la
IP publica y el momento de cada consulta, asi que tal cual estaba cada llamada le
avisaba a Google de que ese usuario esta llamando. En un proyecto con esta postura
sobre privacidad no se sostiene.

Por defecto ya no hay ningun servidor ICE: solo candidatos host, que funcionan en
la misma red y con NAT amable. Es mas honesto degradar a nada que degradar a un
tercero.

Se anade turnCredentials.js, siguiendo el estilo de los helpers de src/backend/:
genera credenciales efimeras con el mecanismo REST de coturn (use-auth-secret),
username = caducidad:identificador y credential = HMAC-SHA1 en base64. El feed id
hace de identificador, que es lo que distingue a quien llama en Oasis. Como coturn
valida el HMAC, las credenciales se emiten sin hablar con el servidor y caducan
solas.

La ruta GET /karvan/ice las sirve solo a loopback —la credencial va firmada con el
secreto del nodo y no debe salir de la maquina— y el cliente la pide ANTES de crear
ninguna RTCPeerConnection, porque la configuracion ICE de una conexion ya creada no
se puede cambiar de forma fiable. Con dos segundos de espera maxima y respaldo a
candidatos host.

La configuracion vive en oasis-config.json bajo rtc, vacia de fabrica, y admite tres
formas: STUN propio, TURN con secreto compartido, o credenciales estaticas. Con
relayOnly se fuerza iceTransportPolicy relay para que ningun par vea la IP del otro.

Verificado: sin configuracion devuelve iceServers vacio; con secreto emite credencial
reproducible y con caducidad; cero referencias a Google en el codigo.
2026-08-19 00:16:50 +02:00
SITO
c3a1c841e6 fix: cerrar la integracion 0.9.5 — recursos que faltaban y regresiones
Una revision a fondo del arbol contra 0.9.5 saco varios fallos, unos heredados y
otros que introdujo la propia integracion. Verificados uno a uno antes de tocar.

Recursos referenciados que no existian (los introduje al adoptar vistas de 0.9.5
que los usan, mientras la rama los habia borrado):
- Los cuatro temas *-SNH.css. settings_view ofrece Dark, Clear, Matrix y Purple,
  pero solo estaba OasisMobile: elegir cualquiera daba 404 y la app se quedaba sin
  estilos. Ahora los cuatro responden 200.
- pdf.min.mjs, pdf.worker.min.mjs y pdf-viewer.js, referenciados desde seis vistas.

Regresiones revertidas a 0.9.5 verbatim en catorce ficheros. Las de fondo:
- larp_model perdio getGoverningPeriodId, que backend.js llama: el anuncio de
  gobierno no salia nunca, con el TypeError tragado por un catch.
- courts_view y search_view tenian selected: false, que hyperscript SI serializa
  como atributo y HTML interpreta como seleccionado. La forma de upstream, el
  spread condicional, es la correcta.
- pm_model perdio includeDeleted, projects_model la validacion de deadline pasado,
  jobs_model el desempate por timestamp, middleware el flag de debug HTTP.

forum_view pasa a 0.9.5 conservando el filtro hot. Esto arregla un fallo activo: la
vista de la rama declaraba un cuarto parametro topic y backend.js llama con cinco
argumentos, asi que al abrir una respuesta el %clave del hilo se colaba como tema y
el hilo salia VACIO. Upstream pasa los mismos cinco argumentos a una firma de tres y
JS los ignora, que es lo correcto.

chats_view pasa a 0.9.5 y se implementa replyTo de verdad. Estaba muerto de punta a
punta: backend.js no leia ctx.query.replyTo ni pasaba el cuarto argumento a
sendMessage, asi que ningun mensaje llegaba a tener replyTo y la cita no se
renderizaba jamas. Ahora la cadena esta completa —modelo, GET, POST y vista— con
indice msgById armado antes de mezclar con las encuestas, y sin gate de movil:
responder a un mensaje no es una funcion de movil.

aria-label: encontrada la causa. No es que hyperaxe lo ignore, es que hyperscript
solo asigna como propiedad y html-element solo serializa atributos de su tabla, en
la que aria-* no esta; data-* si tiene rama propia, por eso las tablas responsive
funcionaban. Se arregla con el escape hatch attrs:{}, sin tocar node_modules.

prepare.sh copia README.md y falla si no esta: backend.js lo lee con readFileSync
sin try/catch, de modo que sin el fichero el backend muere con ENOENT al arrancar.

Verificado con la app en marcha: 17 rutas OK, los cuatro recursos que faltaban
sirviendo 200, aria-label emitido en el HTML, e interfaz intacta (10 categorias,
50 modulos, 7 accesos rapidos, 0 etiquetas vacias).
2026-08-18 23:48:14 +02:00
SITO
7459644a73 android: fijar HOME y reutilizar el node_modules podado del APK base
main.js resuelve el directorio de datos con process.env.HOME || resolve(__dirname,
'..','..'). En Android HOME suele llegar como "/", que no es escribible, asi que el
servicio lo fija explicitamente con Os.setenv al almacenamiento privado de la app:
ahi cuelga ~/.ssb. Tambien fija TMPDIR.

prepare.sh deja de pedir un npm install: saca el node_modules del APK base, que
viene podado —137 MB frente a los 1,4 GB de una instalacion de escritorio— y
sustituye solo el codigo. Es seguro porque las 98 dependencias son identicas entre
0.9.1 y 0.9.5: ninguna nueva, ninguna quitada, ninguna con version distinta.
El zip se comprime; sin comprimir el backend son 145 MB y la APK se iria por encima
de 200.

APK generada y verificada: 78 MB, net.laenre.oasis, versionName 0.9.5, targetSdk 35,
con libnode.so y el backend de 32 MB dentro.
2026-08-18 23:35:19 +02:00
SITO
32f6d2269c android: wrapper propio, con los permisos que faltaban para las videollamadas
Hasta ahora la APK salia re-firmando la de epsylon, y su classes.dex no implementa
WebChromeClient.onPermissionRequest. Sin ese metodo el WebView deniega por defecto
todo getUserMedia, asi que las videollamadas de Karvan no podian funcionar por mucho
que se parchease el manifest: la lista de permisos es estatica y se fija al compilar.

El wrapper cierra las dos puertas. Declara CAMERA, RECORD_AUDIO y
MODIFY_AUDIO_SETTINGS, pero no se conceden al instalar: son permisos peligrosos y se
piden en tiempo de ejecucion la primera vez que se pulsa Llamar. Si nadie llama, no
se pide nada. uses-feature required=false evita excluir dispositivos sin camara.

Reutiliza las tres librerias nativas tal cual: libnode.so es nodejs-mobile v18.20.4
oficial y libnative-lib.so son 6,8 KB con un unico simbolo JNI. De ahi que el
namespace sea com.solarnethub.oasis —JNI resuelve por nombre— mientras el
applicationId es net.laenre.oasis, que permite instalarla junto a la oficial. No
hace falta NDK ni compilar Node.

De paso corrige cosas del APK actual: targetSdk 35, trafico en claro permitido solo
hacia loopback en vez de usesCleartextTraffic global, allowBackup a false para que
adb backup no saque el .ssb, y el backend en un servicio en primer plano en el
proceso :node, que ademas es lo que permitira reiniciarlo limpio para el cambio de
identidad. El APK actual declara FOREGROUND_SERVICE pero no registra ningun servicio,
de modo que el backend muere al pasar a segundo plano.

Los binarios no se versionan: scripts/prepare.sh extrae las librerias y empaqueta el
backend. La keystore se pasa por entorno.

Verificado: ./gradlew assembleDebug construye una APK de 52 MB con las tres librerias,
targetSdk 35 y los permisos declarados; su DEX contiene onPermissionRequest,
PermissionRequest, CAMERA y RECORD_AUDIO, donde el APK actual tiene cero de los cuatro.
Falta probarla en un dispositivo real.
2026-08-18 23:13:03 +02:00
SITO
ace175cca3 karvan: refrescar la sala sin JavaScript
Sin JS el chat ya funcionaba —el formulario publica y el mensaje sale en el HTML—
pero no llegaban los mensajes de los demas hasta recargar a mano.

La pagina de sala anade <noscript><meta http-equiv=refresh content=10>: solo actua
cuando no hay JavaScript, asi que con JS el data-channel sigue mandando y no hay
recargas encima del chat en vivo. Es el mismo recurso que usa upstream en
indexing_view.

Comprobado ademas sobre el modelo, con TTL acortado: la sala se autodestruye al
vencer y no deja mensajes, el anillo respeta el tope de 250 conservando los mas
recientes, se rechaza la senalizacion de mas de 16 KiB, el tope de 100 salas se
aplica, y postear en una sala inexistente devuelve null en vez de reventar.

El identificador de sala son 72 bits de entropia: no es adivinable, y es la unica
credencial de acceso — quien tiene el enlace, entra. Es el modelo previsto, pero
conviene tenerlo escrito.
2026-08-18 23:04:41 +02:00
SITO
ad2d5c8f62 nav: dar entrada en la interfaz a los modulos nuevos del dev
polls, blogs y data tenian modelo, vista y rutas desde la integracion de 0.9.5,
pero no aparecian en ningun sitio: habia que llegar por URL.

Entran en los hexagonos por categoria — blogs junto a menciones y publicaciones,
encuestas junto a votaciones, coincidencias en herramientas — y en la lista de
modulos fijables en la barra inferior. La rejilla se autogestiona, asi que no hace
falta tocar CSS.

Sus etiquetas ya existian en el i18n de upstream (pollsTitle, blogTitle, dataTitle),
de modo que salen traducidas sin anadir claves al overlay.

Verificado: 10 categorias y 50 modulos (antes 47), los tres enlaces presentes en la
home, 0 etiquetas vacias y las cuatro rutas respondiendo 200.
2026-08-18 23:01:38 +02:00
SITO
7b90fa8211 backend: backend.js a 0.9.5, con lo que faltaba para los modulos nuevos
backend.js pasa a la version de 0.9.5 y baja de 1549 a 16 lineas de divergencia.
Sin esto los modulos que el dev ha anadido estaban portados pero inaccesibles: no
tenian rutas. Ahora /polls, /blogs y /mentions responden.

Reinyectado de la rama: el enganche de fork_routes, los tres gates de movil (no
abrir navegador al arrancar, no matar el sbot al borrar la cadena), el selector de
chats de la barra lateral movil, y los globals de la interfaz — el filtro
Personal/Community, la visibilidad de los hexagonos y el avatar de la topbar.
Esos globals no aparecian al clasificar el diff y su perdida dejaba la home sin
hexagonos; detectado al comparar el HTML servido.

bottomBarPickerView (la pantalla de personalizar la barra) vivia en main_views y se
perdia al adoptar 0.9.5. Pasa a fork/hive_nav.js, junto al resto de la interfaz de
la rama, y main_views la reexporta en una linea.

housing se porta pero apagado (housingMod off). Mantenerlo fuera obligaba a editar
83 referencias de backend.js en cada release; asi el fichero queda igual que
upstream y el modulo no aparece en la interfaz. Se portan tambien contentPdf,
housing_model y housing_view para cerrar los requires.

Verificado con la app en marcha: 29 rutas OK, hexagonos 10/47 con los filtros
Personal y Community dando 5 y 5, topbar con avatar, 7 accesos rapidos, orden de
hojas correcto, y Karvan creando sala y sirviendo el panel de videollamada.
2026-08-18 22:57:33 +02:00
SITO
7eeac8b004 upstream: integrar 0.9.5 en style.css y las vistas grandes
style.css pasa a 0.9.5: lo unico que la rama le habia hecho era borrar reglas de
housing, y su estilo propio vive en OasisMobile.css, que carga despues y gana igual.

Se adopta 0.9.5 en tags_view (anade busqueda y filtros mine/recent), vote_view,
market_view y activity_view, donde la rama solo arrastraba la version anterior:
renderContentActions de dos parametros, comentarios de mercado propios y un import
muerto de renderHiveNav que no se llegaba a llamar.

Quedan a proposito en la version de la rama forum_view y chats_view: llevan
funcionalidad movil propia (la tira de temas del foro y la interfaz de responder
mensajes, que acompana al replyTo del modelo) entrelazada con estructuras que 0.9.5
ha reescrito. Integrarlas pide rehacer esa funcionalidad sobre la forma nueva, y no
es un cambio que convenga colar entre otros veinte.

Verificado con la app en marcha: 21 rutas OK, 0 claves i18n rotas, 0 requires rotos,
interfaz intacta y orden de hojas correcto (style.css, mobile.css, OasisMobile.css).
2026-08-18 22:49:21 +02:00