quitar el proyecto Gradle propio y lo que dependia de el
La APK se monta sobre la oficial con sobre_oficial.sh; el proyecto Gradle, sus scripts, el workflow de gitea, la guia en PDF y el pad de usabilidad ya no se usan.
This commit is contained in:
parent
e4bbbc23f2
commit
2d79e6779c
30 changed files with 17 additions and 2330 deletions
|
|
@ -1,254 +0,0 @@
|
|||
Prueba de usabilidad - Oasis Mobile 1.3.3 (rama PRUEBAS, tema Acampada)
|
||||
19/10/2026 - emulador Pixel 9, Android 16, 1080x2424; tambien 720x1280 y letra al 130 %
|
||||
Escenario: alguien de la acampada que entra, cambia a castellano, activa tribus
|
||||
y parlamento, crea tribus, vota y abre una sala de voz.
|
||||
|
||||
=================================
|
||||
Botones complejos de interpretar
|
||||
=================================
|
||||
|
||||
- Los iconos del lanzador son letras del alfabeto vai (ꔙ ꕿ ꖒ ꕒ ꔗ...). No dicen
|
||||
nada de lo que hacen: hay que leer siempre la etiqueta de debajo.
|
||||
- Karvan (⧗) y Nodos (⧖) llevan casi el mismo reloj de arena.
|
||||
Videos lleva algo que parece un simbolo de dolar.
|
||||
- En la sala de voz los botones 🎤 🎥 ⛔ no tienen texto ni descripcion.
|
||||
⛔ no se sabe si es colgar, silenciar o salir.
|
||||
- En cada tarjeta de tribu el primer boton es una ✕ roja: es BORRAR TRIBU y
|
||||
borra con un solo toque, sin preguntar. Probado: la tribu desaparece.
|
||||
- En "Crear tribu" el texto CREAR TRIBU sale tres veces (boton de arriba,
|
||||
titulo y boton de enviar). El de arriba recarga la pagina y borra lo escrito.
|
||||
- Dos campos seguidos se llaman "Ubicacion" (lugar y enlace de mapa).
|
||||
- "Estado: Privada/Publica" y "Modo: Estricto/Abierta" no explican que
|
||||
significan. Por defecto sale Privada + Estricto.
|
||||
- Votacion: las opciones salen mezcladas en ingles y castellano
|
||||
(YES, NO, ABSTENTION, CONFUNDIDO, SEGUIR MAYORIA, SIN INTERES), partidas por
|
||||
silabas y la tabla se corta por la derecha.
|
||||
- Jerga a la vista: "server relay", "Synced-peers", "HcT/HcH", "TASA ECO",
|
||||
la clave @...ed25519 completa en el pie y en el buzon.
|
||||
|
||||
=================================
|
||||
Inicio intuitivo "empezar"
|
||||
=================================
|
||||
|
||||
- El aviso "Tu avatar aun no esta configurado - EMPEZAR" sale arriba en TODAS
|
||||
las paginas. En pantalla pequena se come casi una quinta parte. EMPEZAR no
|
||||
dice que va a pasar (es poner foto y nombre).
|
||||
- En Bienvenida el primer boton, el mas grande, es "AHORA NO". Lo facil es
|
||||
saltarse todo.
|
||||
- El nombre viene relleno con un trozo de la clave (jlYELyx4). Parece un nombre
|
||||
ya puesto y no lo es.
|
||||
- El idioma sale en el del movil la primera vez (el emulador estaba en ingles).
|
||||
Cambiarlo despues costaba: Ajustes, bajar a la segunda pantalla, desplegable,
|
||||
Espanol y boton "Establecer idioma".
|
||||
- La pantalla de carga si sale en castellano y tarda unos 10 s: bien.
|
||||
- Ajustes mide unas 7 pantallas. Lo que mas se toca (idioma, aspecto) queda
|
||||
debajo de Identidades, que es lo mas tecnico.
|
||||
- Al abrir una seccion apagada (p. ej. Tribus) te manda sin avisar a la tabla
|
||||
de Modulos. Deberia decir "Tribus esta apagado - Activar".
|
||||
- Invitar a una sala pide el @feed-id de la otra persona. Nadie lo sabe de
|
||||
memoria: hace falta elegir de los contactos o compartir un enlace / QR.
|
||||
|
||||
=================================
|
||||
Reduccion de funcionalidades
|
||||
"skin activistas"
|
||||
=================================
|
||||
|
||||
- El flujo "activistas" NO activa tribus, parlamento ni votaciones. Para una
|
||||
acampada con 12 tribus es justo lo que falta. Propuesta: anadir tribes,
|
||||
parliament y votes al flujo activistas (o hacer un flujo "acampada").
|
||||
- Activar un modulo a mano: la pagina Modulos son 52 filas, unas 11 pantallas.
|
||||
Tribus esta a 7800 px de altura y la casilla mide 16x16 px (lo minimo
|
||||
recomendable son 48). El boton Guardar esta al final del todo.
|
||||
- Propuesta: en movil, Modulos como interruptores grandes agrupados
|
||||
(Hablar / Organizarse / Compartir) y guardado al tocar.
|
||||
- Cada tribu que creas te manda a ti mismo un mensaje del POLITICALBOT
|
||||
("Ha comenzado un nuevo ciclo de gobierno... Anarchy"). 12 tribus = 12 avisos
|
||||
en el buzon. En movil sobra o deberia agruparse.
|
||||
|
||||
=================================
|
||||
Voz y turnos de palabra
|
||||
=================================
|
||||
|
||||
- LLAMAR en Karvan pide primero la CAMARA aunque solo quieras hablar. Si dices
|
||||
que no a la camara la llamada no arranca, aunque des el micro. Sale el aviso
|
||||
"pendiente del wrapper", que es una nota interna.
|
||||
Arreglo sencillo: LLAMAR empieza solo con audio y 🎥 anade video.
|
||||
(src/client/public/js/karvan.js, funcion startCall)
|
||||
- Solo el boton 🎤 suelto funciona con audio.
|
||||
- La llamada de Karvan se corta al cambiar de pagina (probado: el micro se para
|
||||
al entrar en Parlamento). La sala que sigue viva al navegar es la de Mumble,
|
||||
que va en otra app.
|
||||
- Propuesta: en Parlamento y en cada tribu, boton "Entrar a la sala de voz" que
|
||||
abra mumble://mumble.acampada26s.net/<canal de la tribu>.
|
||||
- Turnos de palabra con tiempo: no existe. Encaja como cola de "pido palabra"
|
||||
dentro de la sala (lista + cronometro visible para todas).
|
||||
|
||||
=================================
|
||||
Listado de tribus
|
||||
=================================
|
||||
|
||||
- Confirmado: cada tribu ocupa casi una pantalla porque todas repiten la misma
|
||||
imagen generica grande. 12 tribus = 10 pantallas de scroll.
|
||||
- Propuesta: lista compacta (nombre + miembros + publica/privada, una linea por
|
||||
tribu), imagen solo si la tribu tiene una propia, y el buscador arriba fijo.
|
||||
|
||||
=================================
|
||||
Votaciones: semaforo / termometro
|
||||
=================================
|
||||
|
||||
- El servidor ya acepta opciones propias (campo "options" separado por comas),
|
||||
pero el formulario no lo ofrece: siempre salen las 6 opciones fijas.
|
||||
- Propuesta: al crear, elegir tipo: Si/No - Semaforo (verde, amarillo, rojo) -
|
||||
Termometro (1 a 5). Sale casi gratis.
|
||||
- Quien crea la votacion no puede votar en ella y la pantalla no lo explica.
|
||||
En una asamblea, quien facilita se queda sin voto.
|
||||
- El selector de fecha es el nativo de Android y propone una semana: bien.
|
||||
|
||||
=================================
|
||||
Lo que va bien
|
||||
=================================
|
||||
|
||||
- Sin desbordes horizontales en 1080 ni en 720 de ancho (salvo tablas).
|
||||
- Tema Acampada legible, botones grandes, buen contraste.
|
||||
- La barra de abajo (Actividad, Chats, Publicar, Buzon) se entiende sola.
|
||||
- Actualizar encima de la 0.9.5 no pierde la identidad ni los datos.
|
||||
|
||||
Pendiente de probar: primer arranque en limpio (instalacion nueva), dos moviles
|
||||
en la misma sala, y la barra de abajo que tapa media pantalla con el teclado
|
||||
abierto (visto en Crear tribu).
|
||||
|
||||
=================================
|
||||
Arreglado en PRUEBAS (19/10/2026)
|
||||
=================================
|
||||
|
||||
- Borrar pide confirmacion ("¿Borrar para siempre? Si, borrar") y la X va la
|
||||
ultima de la fila. Vale para tribus y para todo el contenido.
|
||||
- Karvan: Llamar empieza solo con voz y la camara se anade con su boton.
|
||||
Botones con icono y nombre (Llamar, Micro, Camara, Colgar). Sin el recuadro
|
||||
gris en llamadas de voz. Ayuda para invitar. Textos en los 11 idiomas.
|
||||
- Votaciones: al crear se elige Si/No, Semaforo (verde, amarillo, rojo) o
|
||||
Termometro (1 a 5). Resultados en barras. Aviso a quien la crea.
|
||||
- Flujo activistas con tribus, parlamento, votaciones y eventos.
|
||||
- Abrir una seccion apagada dice cual es y ofrece "Activar" de un toque.
|
||||
- Modulos: agrupados como el lanzador, interruptores grandes, Guardar fijo.
|
||||
- Tribus en filas compactas (12 tribus: de 10 pantallas a unas 3). Dentro de
|
||||
una tribu, las 25 secciones en una tira de fichas + "Mas".
|
||||
- Iconos del lanzador y de la barra: dibujos claros en vez de letras vai.
|
||||
La barra de abajo marca la seccion abierta y se esconde con el teclado.
|
||||
- Ajustes empieza por idioma y aspecto; los idiomas se eligen de un toque.
|
||||
- Aviso del avatar solo en la portada y en una linea. "Ahora no" al final de
|
||||
la bienvenida.
|
||||
- Pie de una linea: "Aun no sincronizas con nadie" / "Sincronizando con N".
|
||||
- Fuera la jerga: tasa ECO, HcT/HcH, "server relay".
|
||||
- Espacio: un solo margen de 14px (las fichas perdian 74px por lado).
|
||||
Letra: Anton solo en titulos y en el boton principal.
|
||||
|
||||
=================================
|
||||
Sigue pendiente
|
||||
=================================
|
||||
|
||||
- Invitar a una sala o mandar un privado eligiendo de los contactos, no
|
||||
pegando el @id.
|
||||
- Turnos de palabra con tiempo en la sala de voz.
|
||||
- Boton "Entrar a la sala de voz" (Mumble) en Parlamento y en cada tribu.
|
||||
- Quien crea una votacion sigue sin poder votar (regla de upstream: cambiarla
|
||||
haria que los nodos contaran distinto).
|
||||
- Probar un primer arranque en limpio y dos moviles en la misma sala.
|
||||
|
||||
=================================
|
||||
Segunda ronda (19/10/2026, tarde)
|
||||
=================================
|
||||
|
||||
Desde ahora cada arreglo respeta docs/FRONTERA_UPSTREAM.md: primero CSS propio;
|
||||
si hace falta HTML, una funcion propia y una linea en la vista del dev; nada en
|
||||
backend, middleware ni modelos del dev.
|
||||
|
||||
- Boton principal de cada modulo (Crear chat, foro, pad, feed, evento...): el
|
||||
mismo en todos. Antes unos a todo lo ancho, otros estrechos, otros con otra
|
||||
letra. [CSS]
|
||||
- Listas vacias: icono, texto centrado y recuadro discontinuo, en vez de una
|
||||
linea suelta ("No se encontraron chats."). [CSS]
|
||||
- El pie se queda abajo aunque la pagina sea corta. [CSS]
|
||||
- Buzon: cada mensaje en pocas lineas (remitente y fecha arriba, el aviso, el
|
||||
titulo y tres lineas de texto). Fuera Para (eres tu), Tasa ECO y Cifrado, que
|
||||
eran iguales en todos. Antes un aviso ocupaba una pantalla. [CSS]
|
||||
- Busqueda: primero el campo de buscar; las fechas y el ID despues. [CSS]
|
||||
- Nodos: Refrescar, Quitar inactivos y Exportar en rejilla. [CSS]
|
||||
- Workflow propio "Acampada" (chats, Karvan, pads, foros, wiki, tribus,
|
||||
parlamento, votaciones, eventos...) en Ajustes y en la bienvenida, sin tocar
|
||||
el "Activismo" del dev. [fichero propio]
|
||||
|
||||
Visto y pendiente de esta ronda:
|
||||
- Buzon: Marcar como leido / Archivar / Borrar siguen uno debajo de otro.
|
||||
- Buzon: los avisos del PoliticalBot de las tribus propias siguen llegando
|
||||
(es upstream; se puede agrupar en la vista, no quitar).
|
||||
- Los ID @...ed25519 siguen a la vista en perfil, buzon y nodos: falta mostrar
|
||||
el nombre y dejar el ID para "copiar".
|
||||
|
||||
=================================
|
||||
Tercera ronda: emulador limpio (19/10/2026, noche)
|
||||
=================================
|
||||
|
||||
Emulador nuevo (Pixel 9, Android 16, 12 GB) para probar una instalacion desde
|
||||
cero con la APK sin Karvan (codigo 102).
|
||||
|
||||
- Primer arranque: 18 segundos hasta la portada. Bien.
|
||||
- Quien entra por primera vez no ve por donde empezar: el lanzador ocupa toda la
|
||||
pantalla y el aviso "pon tu nombre y tu foto" quedaba a 1.300 px, abajo del
|
||||
todo. Arreglado: el aviso va encima del lanzador. [CSS]
|
||||
- El boton No molestar del Telefono ocupaba una fila entera arriba de cada
|
||||
pagina. Arreglado: va en la barra de arriba, junto al avatar. [CSS]
|
||||
- Ajustes marcaba English aunque se hubiera elegido otro idioma. Arreglado. [vista propia]
|
||||
- LLAMADAS: en esta APK el Telefono dice "las llamadas no estan disponibles". La
|
||||
APK oficial del dev trae un puente nativo de audio y camara (.audio_bridge) y
|
||||
la nuestra no. Hay que escribirlo en la app Android o construir sobre la APK
|
||||
oficial. Mientras tanto, en la rama no hay llamadas.
|
||||
- El avatar por defecto (una calavera con gafas) asusta un poco para quien
|
||||
empieza. Es del dev; se puede cambiar solo en el skin.
|
||||
|
||||
Con la APK montada sobre la oficial (1.3.3-hacklab, mismo emulador):
|
||||
- Llamadas: ahora SI. El Telefono ofrece "Nueva llamada" y en una sala el micro
|
||||
graba de verdad (comprobado en Android: VOICE_COMMUNICATION activo) y se corta
|
||||
al salir.
|
||||
- Turnos de palabra: las Salas del dev ya tienen "Levantar la mano". Es la base de
|
||||
lo que pedia el pad; falta el cronometro.
|
||||
- Dentro de una sala, los controles (silenciar, camara, levantar la mano, salir)
|
||||
quedan muy abajo, debajo de la ficha de la sala. Habria que tenerlos a mano
|
||||
mientras se esta dentro. [pendiente, CSS]
|
||||
- La app del dev pide el permiso de camara nada mas abrirse, antes de ensenar
|
||||
nada. Es su app; no se toca.
|
||||
- El boton de crear sala se tapa con el teclado al escribir el titulo: hay que
|
||||
cerrar el teclado para verlo.
|
||||
|
||||
=================================
|
||||
Cuarta ronda: tamaños y sistemas (19/10/2026)
|
||||
=================================
|
||||
|
||||
Con la navegación nueva (portada = actividad, pestaña Menú abajo).
|
||||
|
||||
- Android 16, Pixel 9 (APK real): menú, atrás con gesto y con tres botones, ir a un
|
||||
módulo desde la hoja y volver. Bien.
|
||||
- Fallaba: volver atrás desde un módulo abierto desde la hoja dejaba la portada con
|
||||
la hoja abierta. Arreglado. [script propio]
|
||||
- Android 9 (WebView 69, el que trae sin actualizar): fichas pegadas, hoja del menú
|
||||
sin pintar, grupos montados y No molestar encima de la hoja. Arreglado. [CSS]
|
||||
- Android 11 a 360 dp (motor 83): nueve pantallas sin desbordar, sin textos de
|
||||
menos de 12 px ni botones de menos de 40 px. La barra de cinco cabe (70 dp cada una).
|
||||
- En emulador, Android 9 y 11 no arrancan la APK (ni la nuestra ni la oficial): el
|
||||
node arm64 no corre en el traductor ARM de x86. En un móvil de verdad no pasa; falta
|
||||
probarlo en uno físico con Android 9-11.
|
||||
- Tableta y letra al 130 %: bien.
|
||||
- Bienvenida, paso Tipo: había que elegir una tarjeta y bajar seis tarjetas grandes
|
||||
hasta Guardar. Ahora cada opción es un botón: un toque y queda guardado, el paso se
|
||||
marca y se abre el siguiente. Una fila por opción con miniatura (en rejilla de tres,
|
||||
"Conversaciones" se partía a 360 px). En Ajustes, lo mismo, y la sección va justo
|
||||
después del idioma para encontrarla fácil. [vista propia + una línea en welcome_view
|
||||
y settings_view]
|
||||
- Bienvenida: faltaba elegir para qué se usa Oasis (el backend del dev quita ese paso
|
||||
en el móvil). Vuelve como paso "Perfil", el segundo, justo después de la identidad:
|
||||
Activismo primero, luego Acampada y el resto, cada uno con una línea de para qué
|
||||
sirve. Un toque y guardado. En Ajustes, la misma lista. [vista propia + una línea
|
||||
en welcome_view y settings_view]
|
||||
- Con el perfil Activismo (45 módulos) los botones Personal/Social de la barra de
|
||||
arriba no cabían a 360 px y tapaban el logo. Ya no hacían falta (filtraban el
|
||||
lanzador, que ahora está en la hoja del menú): quitados. [vista propia]
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Portada y esquemas del README.
|
||||
|
||||
Las capturas de movil (01..06) se hacen aparte, con la app arrancada en un nodo de
|
||||
pruebas a 412x915 y escala 2, en español y con lo que trae de serie (perfil Minimo y
|
||||
colores del dev; 03 a 06 con el perfil Activista). Este script compone 00-portada.png
|
||||
a partir de ellas, con los colores de serie, y dibuja esquema-interfaz.png,
|
||||
esquema-rama.png y esquema-llamadas.png (estos aun con la paleta de Acampada).
|
||||
El texto vive aqui: se cambia y se relanza, nunca se retocan los PNG a mano.
|
||||
|
||||
python3 docs/capturas/generar_portada.py
|
||||
"""
|
||||
import math
|
||||
from pathlib import Path
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
ANTON = HERE.parents[1] / "src/client/assets/fonts/Anton-Regular.ttf"
|
||||
SANS = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
|
||||
|
||||
BG, FG, NEON, MUTED = "#ffffff", "#000000", "#00e5ff", "#555555"
|
||||
# colores de serie del movil (los de la APK oficial del dev)
|
||||
DEV_BG, DEV_CARD, DEV_FG, DEV_ACCENT, DEV_MUTED = "#121212", "#1e1e1e", "#ffd700", "#ffa300", "#bbbbbb"
|
||||
SANS_BOLD = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
|
||||
|
||||
|
||||
def font(path, size):
|
||||
return ImageFont.truetype(str(path), size)
|
||||
|
||||
|
||||
def phone(shot, width, fg=FG, neon=NEON):
|
||||
"""Una captura dentro de un marco grueso con una sombra de color debajo."""
|
||||
im = Image.open(HERE / shot).convert("RGB")
|
||||
h = round(im.height * width / im.width)
|
||||
im = im.resize((width, h), Image.LANCZOS)
|
||||
pad, radius, shadow = 10, 34, 10
|
||||
frame = Image.new("RGBA", (width + 2 * pad, h + 2 * pad + shadow), (0, 0, 0, 0))
|
||||
d = ImageDraw.Draw(frame)
|
||||
d.rounded_rectangle((0, shadow, width + 2 * pad - 1, h + 2 * pad + shadow - 1), radius, fill=neon)
|
||||
d.rounded_rectangle((0, 0, width + 2 * pad - 1, h + 2 * pad - 1), radius, fill=fg)
|
||||
mask = Image.new("L", im.size, 0)
|
||||
ImageDraw.Draw(mask).rounded_rectangle((0, 0, width - 1, h - 1), radius - pad, fill=255)
|
||||
frame.paste(im, (pad, pad), mask)
|
||||
return frame
|
||||
|
||||
|
||||
def portada():
|
||||
W, H = 1600, 1100
|
||||
out = Image.new("RGB", (W, H), DEV_BG)
|
||||
d = ImageDraw.Draw(out)
|
||||
d.text((80, 40), "OASIS MOBILE", font=font(SANS_BOLD, 84), fill=DEV_FG)
|
||||
bottom = d.textbbox((80, 40), "OASIS MOBILE", font=font(SANS_BOLD, 84))[3]
|
||||
d.rectangle((80, bottom + 12, 420, bottom + 18), fill=DEV_ACCENT)
|
||||
d.text((80, 186), "Rama PRUEBAS del hacklab · base Oasis 1.3.5 · lo que sale al instalarla",
|
||||
font=font(SANS, 27), fill=DEV_MUTED)
|
||||
shots = [("01-actividad.png", "Actividad al abrir"), ("02-menu.png", "Menú, perfil Mínimo"),
|
||||
("03-menu-activista.png", "Menú, perfil Activista"), ("04-tribu.png", "Una tribu")]
|
||||
pw, gap, top = 320, 50, 260
|
||||
x = (W - (4 * (pw + 20) + 3 * gap)) // 2
|
||||
cap = font(SANS_BOLD, 26)
|
||||
for shot, label in shots:
|
||||
fr = phone(shot, pw, fg="#000000", neon=DEV_ACCENT)
|
||||
out.paste(fr, (x, top), fr)
|
||||
tw = d.textlength(label, font=cap)
|
||||
d.text((x + (fr.width - tw) / 2, top + fr.height + 18), label, font=cap, fill=DEV_FG)
|
||||
x += fr.width + gap
|
||||
out.save(HERE / "00-portada.png", optimize=True)
|
||||
|
||||
|
||||
def caja(d, box, titulo, lineas, relleno=BG):
|
||||
x0, y0, x1, y1 = box
|
||||
d.rounded_rectangle((x0, y0 + 6, x1, y1 + 6), 18, fill=FG)
|
||||
d.rounded_rectangle(box, 18, fill=relleno, outline=FG, width=4)
|
||||
t = font(ANTON, 30)
|
||||
d.text(((x0 + x1 - d.textlength(titulo, font=t)) / 2, y0 + 18), titulo, font=t, fill=FG)
|
||||
s = font(SANS, 18)
|
||||
for i, l in enumerate(lineas):
|
||||
d.text(((x0 + x1 - d.textlength(l, font=s)) / 2, y0 + 70 + i * 26), l, font=s, fill=FG)
|
||||
|
||||
|
||||
def esquema():
|
||||
W, H = 1400, 840
|
||||
out = Image.new("RGB", (W, H), BG)
|
||||
d = ImageDraw.Draw(out)
|
||||
d.text((46, 26), "LA INTERFAZ DE MÓVIL, POR DENTRO", font=font(ANTON, 46), fill=FG)
|
||||
bottom = d.textbbox((46, 26), "LA INTERFAZ DE MÓVIL, POR DENTRO", font=font(ANTON, 46))[3]
|
||||
d.rectangle((46, bottom + 10, 260, bottom + 16), fill=FG)
|
||||
d.text((46, bottom + 30), "Casi sesenta módulos no caben en una pantalla de teléfono. Lo primero es lo que pasa; el resto, en el menú.",
|
||||
font=font(SANS, 18), fill=MUTED)
|
||||
|
||||
# el movil esquematico
|
||||
px0, py0, px1, py1 = 110, 170, 470, 790
|
||||
d.rounded_rectangle((px0, py0, px1, py1), 30, outline=FG, width=5)
|
||||
d.rounded_rectangle((px0 + 16, py0 + 20, px1 - 16, py0 + 84), 14, fill=BG, outline=FG, width=3)
|
||||
s = font(SANS, 15)
|
||||
d.text((px0 + 46, py0 + 42), "logo · no molestar · avatar", font=s, fill=FG)
|
||||
# en medio, la actividad: lo que ha pasado en la red
|
||||
y = py0 + 110
|
||||
d.text((px0 + 40, y), "ACTIVIDAD", font=font(ANTON, 22), fill=FG)
|
||||
d.line((px0 + 40, y + 32, px1 - 40, y + 32), fill=FG, width=3)
|
||||
y += 52
|
||||
for i in range(4):
|
||||
d.rounded_rectangle((px0 + 40, y, px1 - 40, y + 86), 12, fill=BG, outline=FG, width=3)
|
||||
d.rectangle((px0 + 56, y + 18, px0 + 150, y + 30), fill=FG)
|
||||
d.rectangle((px0 + 56, y + 44, px1 - 70, y + 52), fill=MUTED)
|
||||
d.rectangle((px0 + 56, y + 62, px1 - 120, y + 70), fill=MUTED)
|
||||
y += 104
|
||||
d.rounded_rectangle((px0 + 16, py1 - 84, px1 - 16, py1 - 20), 14, fill=NEON, outline=FG, width=3)
|
||||
d.text((px0 + 62, py1 - 62), "4 atajos que eliges tú · MENÚ", font=s, fill=FG)
|
||||
|
||||
bx0, bx1 = 560, 1320
|
||||
cajas = [
|
||||
((bx0, 190, bx1, 340), "ARRIBA — LA BARRA SUPERIOR",
|
||||
["El logo vuelve al inicio y el avatar abre tu perfil.",
|
||||
"En medio, el botón de No molestar del Teléfono.",
|
||||
"Con muchos módulos activos salen también los filtros Personal y Social."], BG),
|
||||
((bx0, 375, bx1, 565), "EN MEDIO — LA ACTIVIDAD",
|
||||
["Al abrir la app se ve lo que ha pasado en la red, no un menú.",
|
||||
"Dentro de cada módulo, los filtros van en fichas pequeñas",
|
||||
"y el botón principal (crear tribu, crear sala…) siempre igual."], BG),
|
||||
((bx0, 600, bx1, 750), "ABAJO — LOS ATAJOS Y EL MENÚ",
|
||||
["Cuatro atajos a tu elección y una quinta pestaña fija, Menú,",
|
||||
"que abre desde abajo una hoja con todos los módulos por secciones",
|
||||
"(Comunidad, Biblioteca, Gobernanza…). Está en todas las pantallas."], NEON),
|
||||
]
|
||||
flechas = [((px1 + 10, py0 + 52), (bx0 - 12, 262)), ((px1 + 10, 440), (bx0 - 12, 470)),
|
||||
((px1 + 10, py1 - 52), (bx0 - 12, 675))]
|
||||
for (a, b) in flechas:
|
||||
ang = math.atan2(b[1] - a[1], b[0] - a[0])
|
||||
tip = lambda da, r: (b[0] - r * math.cos(ang + da), b[1] - r * math.sin(ang + da))
|
||||
d.line((a, tip(0, 12)), fill=FG, width=4)
|
||||
d.polygon([b, tip(0.45, 20), tip(-0.45, 20)], fill=FG)
|
||||
for box, t, l, r in cajas:
|
||||
caja(d, box, t, l, r)
|
||||
out.save(HERE / "esquema-interfaz.png", optimize=True)
|
||||
|
||||
|
||||
def flecha(d, a, b, ancho=4):
|
||||
ang = math.atan2(b[1] - a[1], b[0] - a[0])
|
||||
tip = lambda da, r: (b[0] - r * math.cos(ang + da), b[1] - r * math.sin(ang + da))
|
||||
d.line((a, tip(0, 12)), fill=FG, width=ancho)
|
||||
d.polygon([b, tip(0.45, 20), tip(-0.45, 20)], fill=FG)
|
||||
|
||||
|
||||
def titulo(d, texto, sub):
|
||||
d.text((46, 26), texto, font=font(ANTON, 46), fill=FG)
|
||||
bottom = d.textbbox((46, 26), texto, font=font(ANTON, 46))[3]
|
||||
d.rectangle((46, bottom + 10, 260, bottom + 16), fill=FG)
|
||||
d.text((46, bottom + 30), sub, font=font(SANS, 18), fill=MUTED)
|
||||
|
||||
|
||||
def esquema_rama():
|
||||
"""Como va la rama encima de Oasis: lo del dev abajo, lo nuestro encima."""
|
||||
W, H = 1400, 760
|
||||
out = Image.new("RGB", (W, H), BG)
|
||||
d = ImageDraw.Draw(out)
|
||||
titulo(d, "CÓMO VA LA RAMA ENCIMA DE OASIS",
|
||||
"Oasis lo cambia el dev, casi una versión al día. La rama solo cambia cómo se ve y se usa en el móvil.")
|
||||
capa = [
|
||||
((60, 210, 380, 400), "ASPECTO",
|
||||
["mobile_base.css: la maqueta", "mobile_ux.css: márgenes, letra,", "botones y piezas nuevas",
|
||||
"Acampada.css: el skin"], NEON),
|
||||
((400, 210, 720, 400), "PANTALLAS",
|
||||
["mobile_ui.js y las vistas", "mobile_*.js. En una vista", "del dev, como mucho una", "línea que las llama"], NEON),
|
||||
((740, 210, 1060, 400), "RUTAS",
|
||||
["fork_routes.js, delante", "del router del dev: lo", "que no atiende pasa al", "suyo"], NEON),
|
||||
((1080, 210, 1340, 400), "ANDROID",
|
||||
["la app del dev tal cual,", "con nuestro backend", "dentro y paquete", "propio"], NEON),
|
||||
]
|
||||
for box, t, l, r in capa:
|
||||
caja(d, box, t, l, r)
|
||||
d.text((60, 166), "LO DE LA RAMA", font=font(ANTON, 26), fill=FG)
|
||||
for x in (220, 560, 900, 1210):
|
||||
flecha(d, (x, 418), (x, 478))
|
||||
caja(d, (60, 500, 1340, 690), "OASIS DEL DEV: NO SE TOCA",
|
||||
["backend.js y su middleware · los modelos (lo que se publica y cómo se cuenta) · SSB y su arranque",
|
||||
"las traducciones · style.css y mobile.css · los temas, también OasisMobile.css",
|
||||
"Comparado con su APK oficial, la rama cambia 17 ficheros suyos y 561 líneas. Ver GUIA_DE_DESARROLLO.md"], BG)
|
||||
out.save(HERE / "esquema-rama.png", optimize=True)
|
||||
|
||||
|
||||
def esquema_llamadas():
|
||||
"""Las llamadas son las del dev; en Android pasan por un puente nativo de la app."""
|
||||
W, H = 1400, 700
|
||||
out = Image.new("RGB", (W, H), BG)
|
||||
d = ImageDraw.Draw(out)
|
||||
titulo(d, "LLAMADAS: LAS DEL DEV",
|
||||
"Teléfono y Salas son de Oasis. En Android el sonido y la cámara pasan por un puente nativo de la app.")
|
||||
cajas = [
|
||||
((50, 200, 360, 430), "TELÉFONO Y SALAS",
|
||||
["De Oasis, tal cual.", "Llamadas de uno a uno", "con buzón de voz; salas", "de hasta 50, con vídeo,", "grabación y emisión."], BG),
|
||||
((400, 200, 700, 430), "LOS ENCHUFES",
|
||||
["phone_*_android.js", "(del dev): se conectan", "a un puerto local que", "deja la app en", ".audio_bridge"], BG),
|
||||
((740, 200, 1040, 430), "EL PUENTE NATIVO",
|
||||
["Dentro de la app:", "R graba el micro", "P reproduce", "V saca la cámara", "S emite un fichero"], NEON),
|
||||
((1080, 200, 1350, 430), "EL MÓVIL",
|
||||
["Micrófono, cámara", "y altavoz, con los", "permisos que se piden", "la primera vez."], BG),
|
||||
]
|
||||
for box, t, l, r in cajas:
|
||||
caja(d, box, t, l, r)
|
||||
for a, b in (((362, 315), (398, 315)), ((702, 315), (738, 315)), ((1042, 315), (1078, 315))):
|
||||
flecha(d, a, b)
|
||||
caja(d, (50, 480, 1350, 630), "DÓNDE ESTÁ CADA COSA",
|
||||
["El puente está en la app Android del dev, que no tiene el código publicado. Por eso la APK de la",
|
||||
"rama se monta sobre la oficial: su app tal cual, nuestro backend dentro y paquete propio."], BG)
|
||||
out.save(HERE / "esquema-llamadas.png", optimize=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
# sin argumentos, todo; con nombres, solo esos (p. ej. "portada")
|
||||
for name in sys.argv[1:] or ["portada", "esquema", "esquema_rama", "esquema_llamadas"]:
|
||||
globals()[name]()
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
# PDF de la guia para el dev
|
||||
|
||||
Fuente de Oasis_Mobile_Guia_de_desarrollo.pdf (5 paginas A4). Para sacarlo:
|
||||
|
||||
chromium --headless=new --no-pdf-header-footer --print-to-pdf=guia.pdf guia.html
|
||||
|
||||
Comprobar con `pdfinfo guia.pdf` que siguen siendo 5 paginas.
|
||||
|
|
@ -1,339 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Oasis Mobile · Guía de desarrollo</title>
|
||||
<style>
|
||||
@font-face { font-family: "Anton"; src: url("file:///home/sito/COFRE/CODERS/OASIS_MOBILE/src/client/assets/fonts/Anton-Regular.ttf"); }
|
||||
@page { size: A4; margin: 0; }
|
||||
:root { --fg: #0b0b0b; --muted: #5a5a5a; --line: #0b0b0b; --cyan: #00d7f0; --soft: #f1f4f5; --red: #c4003b; --amber: #c98a00; --green: #0a8f3c; }
|
||||
* { box-sizing: border-box; }
|
||||
html, body { margin: 0; padding: 0; background: #fff; color: var(--fg); font-family: "Inter", "DejaVu Sans", sans-serif; font-size: 10.5pt; line-height: 1.45; }
|
||||
.page { width: 210mm; height: 297mm; padding: 16mm 17mm 14mm; position: relative; page-break-after: always; overflow: hidden; }
|
||||
.page:last-child { page-break-after: auto; }
|
||||
h1, h2, h3 { font-family: "Anton", Impact, sans-serif; font-weight: 400; text-transform: uppercase; margin: 0; letter-spacing: .01em; line-height: 1; }
|
||||
h1 { font-size: 54pt; }
|
||||
h2 { font-size: 30pt; margin-bottom: 4mm; }
|
||||
h2 + .rule { width: 34mm; height: 2.2mm; background: var(--fg); margin: 0 0 6mm; }
|
||||
h3 { font-size: 14pt; margin: 0 0 2.5mm; }
|
||||
p { margin: 0 0 3mm; }
|
||||
.lead { font-size: 12pt; color: var(--muted); margin-bottom: 6mm; }
|
||||
ul { margin: 0 0 3mm; padding-left: 5mm; }
|
||||
li { margin: 0 0 1.6mm; }
|
||||
li::marker { color: var(--fg); }
|
||||
code { font-family: "DejaVu Sans Mono", monospace; font-size: 8.8pt; background: var(--soft); padding: .2mm 1.2mm; border-radius: 1mm; }
|
||||
.foot { position: absolute; left: 17mm; right: 17mm; bottom: 8mm; display: flex; justify-content: space-between; font-size: 8pt; color: var(--muted); border-top: .4mm solid #ddd; padding-top: 2mm; }
|
||||
.cols { display: grid; grid-template-columns: 1fr 1fr; gap: 7mm; }
|
||||
.cols3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 5mm; }
|
||||
.card { border: .6mm solid var(--fg); border-radius: 3mm; padding: 4.5mm 5mm; }
|
||||
.card.cyan { background: #e2fbff; }
|
||||
.tag { display: inline-block; font-family: "Anton"; text-transform: uppercase; font-size: 11pt; padding: .6mm 3mm; border-radius: 1.5mm; color: #fff; margin-bottom: 3mm; }
|
||||
.tag.red { background: var(--red); } .tag.amber { background: var(--amber); } .tag.green { background: var(--green); }
|
||||
.num { font-family: "Anton"; font-size: 34pt; line-height: 1; }
|
||||
.kpi { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4mm; margin: 6mm 0; }
|
||||
.kpi div { border-top: 1.2mm solid var(--fg); padding-top: 2mm; }
|
||||
.kpi span { display: block; font-size: 8.5pt; color: var(--muted); }
|
||||
figure { margin: 0 0 5mm; }
|
||||
figcaption { font-size: 8.5pt; color: var(--muted); margin-top: 1.5mm; }
|
||||
svg text { font-family: "Inter", sans-serif; }
|
||||
.cover { background: #fff; }
|
||||
.cover .band { position: absolute; left: 0; right: 0; top: 0; height: 9mm; background: var(--cyan); }
|
||||
.cover h1 { margin-top: 30mm; font-size: 64pt; }
|
||||
.cover .sub { font-family: "Anton"; text-transform: uppercase; font-size: 24pt; margin-top: 4mm; }
|
||||
.cover .meta { margin-top: 8mm; font-size: 11pt; color: var(--muted); }
|
||||
.ask { border-left: 2.2mm solid var(--cyan); background: var(--soft); padding: 4mm 5mm; border-radius: 0 3mm 3mm 0; }
|
||||
table { width: 100%; border-collapse: collapse; font-size: 9.5pt; }
|
||||
th { text-align: left; font-family: "Anton"; font-weight: 400; text-transform: uppercase; font-size: 10pt; border-bottom: .6mm solid var(--fg); padding: 1.5mm 2mm; }
|
||||
td { border-bottom: .3mm solid #ddd; padding: 1.6mm 2mm; vertical-align: top; }
|
||||
table.tight td { padding: 1.1mm 2mm; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- 1. PORTADA -->
|
||||
<section class="page cover">
|
||||
<div class="band"></div>
|
||||
<h1>Oasis Mobile</h1>
|
||||
<div class="sub">Guía de desarrollo de la rama del hacklab</div>
|
||||
<div class="meta">Propuesta para epsylon · base Oasis 1.3.3 · rama PRUEBAS · 19 de octubre de 2026</div>
|
||||
|
||||
<div class="kpi">
|
||||
<div><div class="num">39</div><span>versiones de Oasis entre la 1.0.1 y la 1.3.3</span></div>
|
||||
<div><div class="num">17</div><span>ficheros tuyos que la rama cambia, frente a tu APK oficial</span></div>
|
||||
<div><div class="num">2</div><span>líneas nuestras en <code>backend.js</code></span></div>
|
||||
<div><div class="num">0</div><span>cambios en modelos, middleware o traducciones</span></div>
|
||||
</div>
|
||||
|
||||
<h3>Qué es esta rama</h3>
|
||||
<ul>
|
||||
<li>Una forma de usar Oasis en el móvil pensada para una acampada: tribus como comisiones, votaciones de asamblea, salas de voz.</li>
|
||||
<li>No es otro Oasis. Es tu APK oficial con una capa encima: skins, unas pocas vistas, un router propio y textos.</li>
|
||||
<li>Se instala junto a la oficial con otro paquete (<code>net.laenre.oasis</code>) y habla con la misma red.</li>
|
||||
</ul>
|
||||
<h3>Qué te pedimos</h3>
|
||||
<ul>
|
||||
<li>Que revises si la frontera que proponemos (página 3) te parece bien: qué es tuyo y no tocamos, y qué es nuestro.</li>
|
||||
<li>Que nos digas si alguno de los puntos de la página 5 te interesa para Oasis, para dejar de llevarlo nosotros.</li>
|
||||
</ul>
|
||||
|
||||
<figure style="margin-top:6mm">
|
||||
<svg viewBox="0 0 700 150" width="100%">
|
||||
<defs><marker id="ar0" markerWidth="10" markerHeight="10" refX="9" refY="5" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#0b0b0b"/></marker></defs>
|
||||
<rect x="2" y="20" width="200" height="110" rx="10" fill="#fff" stroke="#0b0b0b" stroke-width="2.5"/>
|
||||
<text x="102" y="58" text-anchor="middle" font-size="17" font-weight="700">Tu APK oficial</text>
|
||||
<text x="102" y="82" text-anchor="middle" font-size="12" fill="#5a5a5a">app Android, puente de</text>
|
||||
<text x="102" y="98" text-anchor="middle" font-size="12" fill="#5a5a5a">audio, node_modules</text>
|
||||
<rect x="250" y="20" width="200" height="110" rx="10" fill="#e2fbff" stroke="#0b0b0b" stroke-width="2.5"/>
|
||||
<text x="350" y="58" text-anchor="middle" font-size="17" font-weight="700">+ capa de la rama</text>
|
||||
<text x="350" y="82" text-anchor="middle" font-size="12" fill="#5a5a5a">skins, vistas mobile_*,</text>
|
||||
<text x="350" y="98" text-anchor="middle" font-size="12" fill="#5a5a5a">router propio, textos</text>
|
||||
<rect x="498" y="20" width="200" height="110" rx="10" fill="#0b0b0b" stroke="#0b0b0b" stroke-width="2.5"/>
|
||||
<text x="598" y="58" text-anchor="middle" font-size="17" font-weight="700" fill="#fff">Oasis hacklab</text>
|
||||
<text x="598" y="82" text-anchor="middle" font-size="12" fill="#ddd">otro paquete, misma red,</text>
|
||||
<text x="598" y="98" text-anchor="middle" font-size="12" fill="#ddd">convive con la oficial</text>
|
||||
<line x1="204" y1="75" x2="244" y2="75" stroke="#0b0b0b" stroke-width="2.5" marker-end="url(#ar0)"/>
|
||||
<line x1="452" y1="75" x2="492" y2="75" stroke="#0b0b0b" stroke-width="2.5" marker-end="url(#ar0)"/>
|
||||
</svg>
|
||||
</figure>
|
||||
<div class="foot"><span>Oasis Mobile · Guía de desarrollo</span><span>1 / 5</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. LA REGLA -->
|
||||
<section class="page">
|
||||
<h2>La regla</h2><div class="rule"></div>
|
||||
<p class="lead">Oasis lo cambias tú. Nosotros cambiamos cómo se ve y se usa en el móvil, y lo hacemos en ficheros nuestros.</p>
|
||||
|
||||
<figure>
|
||||
<svg viewBox="0 0 700 330" width="100%">
|
||||
<defs><marker id="ar1" markerWidth="10" markerHeight="10" refX="9" refY="5" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#0b0b0b"/></marker></defs>
|
||||
<text x="0" y="16" font-size="13" font-weight="700" letter-spacing="1">LA CAPA DE LA RAMA</text>
|
||||
<g font-size="12">
|
||||
<rect x="0" y="28" width="166" height="96" rx="9" fill="#e2fbff" stroke="#0b0b0b" stroke-width="2"/>
|
||||
<text x="83" y="54" text-anchor="middle" font-size="15" font-weight="700">Aspecto</text>
|
||||
<text x="83" y="76" text-anchor="middle">mobile_base.css</text><text x="83" y="92" text-anchor="middle">mobile_ux.css</text><text x="83" y="108" text-anchor="middle">Acampada.css</text>
|
||||
<rect x="178" y="28" width="166" height="96" rx="9" fill="#e2fbff" stroke="#0b0b0b" stroke-width="2"/>
|
||||
<text x="261" y="54" text-anchor="middle" font-size="15" font-weight="700">Pantallas</text>
|
||||
<text x="261" y="76" text-anchor="middle">mobile_ui.js</text><text x="261" y="92" text-anchor="middle">mobile_*_view.js</text><text x="261" y="108" text-anchor="middle">hive_views.js</text>
|
||||
<rect x="356" y="28" width="166" height="96" rx="9" fill="#e2fbff" stroke="#0b0b0b" stroke-width="2"/>
|
||||
<text x="439" y="54" text-anchor="middle" font-size="15" font-weight="700">Rutas</text>
|
||||
<text x="439" y="76" text-anchor="middle">fork_routes.js</text><text x="439" y="92" text-anchor="middle">mobile_layer.js</text><text x="439" y="108" text-anchor="middle">fork_workflows.js</text>
|
||||
<rect x="534" y="28" width="166" height="96" rx="9" fill="#e2fbff" stroke="#0b0b0b" stroke-width="2"/>
|
||||
<text x="617" y="54" text-anchor="middle" font-size="15" font-weight="700">Textos y APK</text>
|
||||
<text x="617" y="76" text-anchor="middle">i18n_fork.js</text><text x="617" y="92" text-anchor="middle">(11 idiomas)</text><text x="617" y="108" text-anchor="middle">sobre_oficial.sh</text>
|
||||
</g>
|
||||
<g stroke="#0b0b0b" stroke-width="2" marker-end="url(#ar1)">
|
||||
<line x1="83" y1="130" x2="83" y2="176"/><line x1="261" y1="130" x2="261" y2="176"/><line x1="439" y1="130" x2="439" y2="176"/><line x1="617" y1="130" x2="617" y2="176"/>
|
||||
</g>
|
||||
<text x="270" y="158" font-size="11" fill="#5a5a5a">una línea de enganche, solo con OASIS_MOBILE=1</text>
|
||||
<rect x="0" y="184" width="700" height="140" rx="10" fill="#fff" stroke="#0b0b0b" stroke-width="3"/>
|
||||
<text x="350" y="216" text-anchor="middle" font-size="18" font-weight="700">OASIS: TU CÓDIGO, TAL CUAL</text>
|
||||
<g font-size="12" text-anchor="middle">
|
||||
<rect x="18" y="234" width="152" height="70" rx="7" fill="#f1f4f5"/><text x="94" y="262" font-weight="700">backend.js</text><text x="94" y="280" fill="#5a5a5a">y su middleware</text>
|
||||
<rect x="188" y="234" width="152" height="70" rx="7" fill="#f1f4f5"/><text x="264" y="262" font-weight="700">modelos</text><text x="264" y="280" fill="#5a5a5a">qué se publica y se cuenta</text>
|
||||
<rect x="358" y="234" width="152" height="70" rx="7" fill="#f1f4f5"/><text x="434" y="262" font-weight="700">SSB y servidor</text><text x="434" y="280" fill="#5a5a5a">phone_module, puente</text>
|
||||
<rect x="528" y="234" width="154" height="70" rx="7" fill="#f1f4f5"/><text x="605" y="262" font-weight="700">traducciones y temas</text><text x="605" y="280" fill="#5a5a5a">oasis_*.js, style.css…</text>
|
||||
</g>
|
||||
</svg>
|
||||
<figcaption>La rama son cuatro piezas propias encima de tu código. Lo único que entra en tus ficheros son líneas de enganche.</figcaption>
|
||||
</figure>
|
||||
|
||||
<div class="cols">
|
||||
<div>
|
||||
<h3>Por qué así</h3>
|
||||
<ul>
|
||||
<li>Sacas versión casi cada día y cada una llega en un solo commit: no se pueden coger cambios sueltos.</li>
|
||||
<li><code>backend.js</code> cambió en 34 de 39 versiones, <code>main_views.js</code> en 31, las traducciones en 31.</li>
|
||||
<li>Cada línea nuestra en esos ficheros sería un conflicto en la siguiente integración.</li>
|
||||
<li>Si tocáramos un modelo, nuestro móvil contaría distinto que tu escritorio (votos, tribus, gobierno).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Cómo se mide</h3>
|
||||
<ul>
|
||||
<li>La referencia para el móvil es el <code>nodejs-project</code> de tu APK oficial, no tu git: ahí van tus cambios de móvil.</li>
|
||||
<li>Hoy la rama cambia 17 ficheros tuyos y 561 líneas; en <code>backend.js</code>, 2.</li>
|
||||
<li>En cada versión tuya se repite la comparación y se revisa si ha desaparecido alguna clase CSS de la que tiramos.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="foot"><span>Oasis Mobile · Guía de desarrollo</span><span>2 / 5</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 3. LA FRONTERA -->
|
||||
<section class="page">
|
||||
<h2>Qué se toca y qué no</h2><div class="rule"></div>
|
||||
<p class="lead">Tres zonas. La de en medio es la única que entra en tus ficheros, y solo con una línea.</p>
|
||||
<div class="cols3">
|
||||
<div class="card">
|
||||
<span class="tag red">No se toca</span>
|
||||
<ul>
|
||||
<li><code>backend.js</code>, rutas y cadena de middleware</li>
|
||||
<li>Modelos de <code>src/models</code>: lo que se publica en el log y cómo se cuenta</li>
|
||||
<li><code>src/server</code>: arranque de SSB, dependencias, <code>phone_module</code></li>
|
||||
<li><code>request_guards.js</code> y la CSP: nada en línea</li>
|
||||
<li>Traducciones <code>oasis_*.js</code></li>
|
||||
<li><code>style.css</code>, <code>mobile.css</code> y los temas, también <code>OasisMobile.css</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="tag amber">Una línea</span>
|
||||
<ul>
|
||||
<li>Tus vistas: <code>main_views.js</code>, <code>tribes_view.js</code>, <code>vote_view.js</code>, <code>settings_view.js</code>, <code>welcome_view.js</code></li>
|
||||
<li>La lógica va en <code>mobile_ui.js</code>; en tu vista, una llamada</li>
|
||||
<li>Siempre detrás de <code>OASIS_MOBILE === '1'</code>: en escritorio todo queda como lo dejas</li>
|
||||
<li>Si reescribes la vista, se vuelve a poner la línea</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card cyan">
|
||||
<span class="tag green">Nuestro</span>
|
||||
<ul>
|
||||
<li>Hojas: <code>mobile_base.css</code>, <code>mobile_ux.css</code>, <code>Acampada.css</code></li>
|
||||
<li>Vistas: <code>mobile_ui.js</code>, <code>mobile_modules_view.js</code>, <code>hive_views.js</code>, <code>mobile_icons.js</code></li>
|
||||
<li>Router: <code>fork_routes.js</code> y <code>mobile_layer.js</code></li>
|
||||
<li>Workflows: <code>fork_workflows.js</code></li>
|
||||
<li>Textos: <code>i18n_fork.js</code></li>
|
||||
<li>APK: <code>sobre_oficial.sh</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="margin-top:4mm">Ejemplos concretos</h3>
|
||||
<table class="tight">
|
||||
<tr><th>Lo que hacía falta</th><th>Cómo se ha hecho</th><th>Zona</th></tr>
|
||||
<tr><td>Votar en semáforo o termómetro, como en asamblea</td><td>Tu servidor ya acepta <code>options</code>; solo se añade el selector en el formulario</td><td>Una línea</td></tr>
|
||||
<tr><td>Quien crea una votación no puede votar</td><td>Es una regla de tu modelo: no se cambia, se explica en pantalla</td><td>Nuestro</td></tr>
|
||||
<tr><td>Avisar de que una sección está apagada y encenderla</td><td>Nuestro router mira tu redirección a <code>/modules</code>, sin tocar <code>checkMod</code></td><td>Nuestro</td></tr>
|
||||
<tr><td>Workflow para acampadas</td><td>Se registra <code>acampada</code> en tus arrays; <code>activists</code> queda como el tuyo</td><td>Nuestro</td></tr>
|
||||
<tr><td>Llamadas y salas</td><td>Las tuyas, con tu puente de audio: la APK se monta sobre la oficial</td><td>No se toca</td></tr>
|
||||
<tr><td>Borrar con confirmación</td><td>Función en <code>mobile_ui.js</code>, enganchada en <code>renderContentActions</code></td><td>Una línea</td></tr>
|
||||
</table>
|
||||
<div class="foot"><span>Oasis Mobile · Guía de desarrollo</span><span>3 / 5</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 4. CÓMO FUNCIONA -->
|
||||
<section class="page">
|
||||
<h2>Cómo funciona por dentro</h2><div class="rule"></div>
|
||||
|
||||
<h3>Una petición en el móvil</h3>
|
||||
<figure>
|
||||
<svg viewBox="0 0 700 175" width="100%">
|
||||
<defs><marker id="ar2" markerWidth="10" markerHeight="10" refX="9" refY="5" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#0b0b0b"/></marker></defs>
|
||||
<g font-size="12" text-anchor="middle">
|
||||
<rect x="0" y="40" width="110" height="80" rx="9" fill="#fff" stroke="#0b0b0b" stroke-width="2"/><text x="55" y="76" font-weight="700">WebView</text><text x="55" y="94" fill="#5a5a5a">de tu app</text>
|
||||
<rect x="140" y="40" width="130" height="80" rx="9" fill="#f1f4f5" stroke="#0b0b0b" stroke-width="2"/><text x="205" y="70" font-weight="700">Tu middleware</text><text x="205" y="88" fill="#5a5a5a">contexto, idioma,</text><text x="205" y="102" fill="#5a5a5a">CSP</text>
|
||||
<rect x="300" y="40" width="130" height="80" rx="9" fill="#e2fbff" stroke="#0b0b0b" stroke-width="2"/><text x="365" y="70" font-weight="700">fork_routes</text><text x="365" y="88" fill="#5a5a5a">rutas propias o</text><text x="365" y="102" fill="#5a5a5a">next() al tuyo</text>
|
||||
<rect x="460" y="40" width="110" height="80" rx="9" fill="#f1f4f5" stroke="#0b0b0b" stroke-width="2"/><text x="515" y="76" font-weight="700">Tus rutas</text><text x="515" y="94" fill="#5a5a5a">y vistas</text>
|
||||
<rect x="600" y="40" width="100" height="80" rx="9" fill="#e2fbff" stroke="#0b0b0b" stroke-width="2"/><text x="650" y="70" font-weight="700">mobile_ui</text><text x="650" y="88" fill="#5a5a5a">si la vista</text><text x="650" y="102" fill="#5a5a5a">lo llama</text>
|
||||
</g>
|
||||
<g stroke="#0b0b0b" stroke-width="2" marker-end="url(#ar2)">
|
||||
<line x1="112" y1="80" x2="134" y2="80"/><line x1="272" y1="80" x2="294" y2="80"/><line x1="432" y1="80" x2="454" y2="80"/><line x1="572" y1="80" x2="594" y2="80"/>
|
||||
</g>
|
||||
<text x="440" y="168" text-anchor="middle" font-size="11" fill="#5a5a5a">Lo que contestan tus rutas no se mira ni se cambia</text>
|
||||
<text x="0" y="22" font-size="11" fill="#5a5a5a">Nuestro router va justo delante del tuyo: una sola línea en backend.js lo monta.</text>
|
||||
</svg>
|
||||
</figure>
|
||||
|
||||
<div class="cols">
|
||||
<div>
|
||||
<h3>Hojas de estilo, en este orden</h3>
|
||||
<figure>
|
||||
<svg viewBox="0 0 330 200" width="100%">
|
||||
<g font-size="12">
|
||||
<rect x="0" y="0" width="330" height="34" rx="6" fill="#f1f4f5" stroke="#0b0b0b"/><text x="12" y="22">1 · style.css y mobile.css (tuyas)</text>
|
||||
<rect x="0" y="40" width="330" height="34" rx="6" fill="#e2fbff" stroke="#0b0b0b"/><text x="12" y="62">2 · mobile_base.css: maqueta de la rama</text>
|
||||
<rect x="0" y="80" width="330" height="34" rx="6" fill="#fff" stroke="#0b0b0b"/><text x="12" y="102">3 · skin: Acampada.css o tu OasisMobile.css</text>
|
||||
<rect x="0" y="120" width="330" height="34" rx="6" fill="#e2fbff" stroke="#0b0b0b"/><text x="12" y="142">4 · activista.css (solo con Acampada)</text>
|
||||
<rect x="0" y="160" width="330" height="34" rx="6" fill="#0b0b0b"/><text x="12" y="182" fill="#fff">5 · mobile_ux.css: piezas comunes, la última</text>
|
||||
</g>
|
||||
</svg>
|
||||
</figure>
|
||||
<ul>
|
||||
<li>Con tu skin OasisMobile se ve tu tema tal cual, encima de nuestra maqueta.</li>
|
||||
<li>Colores por variables <code>--ux-*</code>: valen para los dos skins.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3>La APK, montada sobre la tuya</h3>
|
||||
<figure>
|
||||
<svg viewBox="0 0 330 200" width="100%">
|
||||
<defs><marker id="ar3" markerWidth="10" markerHeight="10" refX="9" refY="5" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#0b0b0b"/></marker></defs>
|
||||
<g font-size="12">
|
||||
<rect x="0" y="0" width="330" height="30" rx="6" fill="#fff" stroke="#0b0b0b"/><text x="12" y="20">tu APK oficial de la misma versión</text>
|
||||
<rect x="0" y="42" width="330" height="30" rx="6" fill="#f1f4f5" stroke="#0b0b0b"/><text x="12" y="62">se desmonta (apktool, versión fija)</text>
|
||||
<rect x="0" y="84" width="330" height="30" rx="6" fill="#e2fbff" stroke="#0b0b0b"/><text x="12" y="104">backend de la rama + tu node_modules</text>
|
||||
<rect x="0" y="126" width="330" height="30" rx="6" fill="#e2fbff" stroke="#0b0b0b"/><text x="12" y="146">paquete net.laenre.oasis</text>
|
||||
<rect x="0" y="168" width="330" height="30" rx="6" fill="#0b0b0b"/><text x="12" y="188" fill="#fff">se monta, se alinea y se firma</text>
|
||||
</g>
|
||||
<g stroke="#0b0b0b" stroke-width="1.6" marker-end="url(#ar3)"><line x1="300" y1="31" x2="300" y2="40"/><line x1="300" y1="73" x2="300" y2="82"/><line x1="300" y1="115" x2="300" y2="124"/><line x1="300" y1="157" x2="300" y2="166"/></g>
|
||||
</svg>
|
||||
</figure>
|
||||
<ul>
|
||||
<li>Tu app tal cual: puente de audio, notificaciones, permisos.</li>
|
||||
<li>Se cambian también los authorities, el permiso propio y las acciones de llamada, para no cruzarse con la tuya.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="foot"><span>Oasis Mobile · Guía de desarrollo</span><span>4 / 5</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 5. TRABAJAR JUNTOS -->
|
||||
<section class="page">
|
||||
<h2>Cómo seguimos</h2><div class="rule"></div>
|
||||
|
||||
<div class="cols">
|
||||
<div>
|
||||
<h3>Antes de cada commit</h3>
|
||||
<ul>
|
||||
<li>Nada de la zona roja en el diff; en tus vistas, solo líneas de enganche.</li>
|
||||
<li><code>node --check</code> y el servidor local responde en las pantallas principales.</li>
|
||||
<li>Visto a 360 y 412 px, en tableta, con la letra al 130 % y en un WebView viejo.</li>
|
||||
<li>Textos nuevos en los 11 idiomas, en <code>i18n_fork.js</code>.</li>
|
||||
<li>Nada en línea: la CSP lo bloquea.</li>
|
||||
</ul>
|
||||
<h3>Cuando sacas versión</h3>
|
||||
<ul>
|
||||
<li>Se coge la tuya tal cual; para el móvil, la de tu APK.</li>
|
||||
<li>Se vuelven a poner los enganches en tus vistas.</li>
|
||||
<li>Se repite la medición y se revisan las clases CSS.</li>
|
||||
<li>Se monta la APK sobre tu oficial de esa versión.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Navegación en el móvil</h3>
|
||||
<ul>
|
||||
<li>Al abrir se ve la actividad, no un menú.</li>
|
||||
<li>Abajo, cuatro atajos que elige cada cual y una pestaña Menú que abre todos los módulos desde abajo.</li>
|
||||
<li>Probado en el emulador: dos toques a cualquier módulo desde cualquier pantalla.</li>
|
||||
</ul>
|
||||
<h3>Probado</h3>
|
||||
<ul>
|
||||
<li>Android 16 (APK real): 412 y 360 dp, tableta de 800 dp, letra al 130 %, gestos y tres botones.</li>
|
||||
<li>Motores viejos: WebView 69 (Android 9) y 83 (Android 11), con alternativas donde falta <code>:has</code>, <code>gap</code> o <code>inset</code>.</li>
|
||||
<li>Llamadas: en una sala el micrófono graba y se corta al salir.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="margin-top:2mm">Lo que podría pasar a Oasis</h3>
|
||||
<p>Cosas que hoy llevamos en tus ficheros y que nos gustaría que fueran tuyas, para dejar de mantenerlas aparte:</p>
|
||||
<table>
|
||||
<tr><th>Qué</th><th>Dónde está ahora</th><th>Por qué te puede interesar</th></tr>
|
||||
<tr><td>Limpiar metadatos de las fotos también en Android</td><td><code>blobHandler.js</code> (190 líneas)</td><td>Sin <code>sharp</code> en el móvil, hoy las fotos suben con el GPS dentro</td></tr>
|
||||
<tr><td>Varias identidades en el mismo móvil</td><td><code>ssb_config.js</code> (30 líneas)</td><td>Una persona, varias cuentas, con aviso si dos comparten clave</td></tr>
|
||||
<tr><td>DNS del sistema primero</td><td><code>main.js</code> (45 líneas)</td><td>Respeta la VPN y el DNS privado de Android</td></tr>
|
||||
<tr><td>Selector de idioma con el idioma actual</td><td>nuestro, en <code>mobile_ui.js</code></td><td><code>settings_view</code> lee <code>selectedLanguage</code> al cargar y siempre marca English</td></tr>
|
||||
</table>
|
||||
|
||||
<div class="ask" style="margin-top:3mm">
|
||||
<h3>Para aprobar</h3>
|
||||
<ul style="margin:0">
|
||||
<li>¿Te parece bien la frontera de la página 3?</li>
|
||||
<li>¿Te parece bien que la APK de la rama se monte sobre tu oficial, con otro paquete?</li>
|
||||
<li>¿Quieres alguno de los cuatro puntos de arriba en Oasis?</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="foot"><span>Oasis Mobile · Guía de desarrollo · hacklab · gitea.laenre.net/hacklab/OASIS_MOBILE</span><span>5 / 5</span></div>
|
||||
</section>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue