(event) Cuando el usuario seleccione un archivo desde su maquina:
Leemos el archivo
Parseamos el archivo
Actualizamos el state
Dibujamos en pantalla
Folder structure
index.html
index.js para iniciar nuestra implementación
modules/file-loader.js para buscar archivos
modules/file-parser.js para interpretar archivos
modules/state.js para guardar el estado
modules/renderer.js para dibujar nuestro state en pixeles
Empezemos
1. Crear la forma de escribir nuestras UIs
🤔🤔🤔
Habia pensando en YAML, pero no resultó ser lo más conveniente(según yo).
Que tan intuitivo queremos que sea la declaracion de nuestra interfaz ?
Cual es el mental model que queremos reflejar ?
Que tan fácil es leer/interpretar/parsear este archivo?
mental model: como se comprende el funcionamiento de algo.
Cuando crees que un audio de wssp es una llamada
Cuando le escribes al Viejo Pascuero, esperas y llegan las cosas.
Si rezaste y algo bueno te pasó, debido a la eficiencia de tu rezo.
no hay falla en su logica, if u know wht i mean
como queremos que se entienda? 🤔
Queremos que se entienda el funcionamiento interno o no?
Le ponemos Viejito Pascuero o no ? 🤔
Un ejemplo de Viejito Pascuero en codigo es: class en Javascript.
Javascript no soporta Clases, pero te muestra un mental model familiar.
Esto tambien se llama: Sintactic Sugar.
" En informática, el azúcar sintáctico es un término acuñado por Peter J. Landin en 1964 para referirse a los añadidos a la sintaxis de un lenguaje de programación diseñados para hacer algunas construcciones más fáciles de leer o expresar. Esto hace el lenguaje "más dulce" para el uso por programadores: las cosas pueden ser expresadas de una manera más clara, más concisas, o de un modo alternativo que se prefiera, sin afectar a la funcionalidad del programa."wikipedia
Ejemplos:
Svelte
Te permite trabajar los aspectos relevantes de tu funcionalidad en 1 solo archivo.
Describiendo cada aspecto en Tags ( como en Plain HTML).
Astro
Cuando escribes en Astro tienes una sección para JS y otra para el template separados por: ---
Angular
Puedes hacer las 2 cosas.
por defecto: puedes tener archivos por separado
o escribirlo todo en un archivo
No importa la forma que escogas, el build será el mismo.
Remix
Es un framework fullStack, te permiten definir el frontend y backend en el mismo archivo.
Qwik
Tambien FullStack y tiene un approach similar.
And so on…
Volvamos
Para nuestra versión,
Vamos a buscar algo sencillo de entender y transformar: JSON.
Vamos a priorizar la facilidad del flujo sobre la experiencia del Dev.
Vamos a permitir configurar 3 aspectos de la interfaz:
screen: para configurar los elementos y aspectos visuales de la UI
env: para configurar nuestro brauser
metadata: agregar informacion adicional
default-ui.json
Crear la forma de escribir nuestras UIs ✅
Sigamos
Fujo
Cuando el usuario seleccione un archivo desde su maquina:
Leemos el archivo
Parseamos el archivo
Actualizamos el state
Dibujamos en pantalla
0.Cuando el usuario seleccione un archivo desde su maquina:
Vamos a escuchar el evento change del input file
Cuando ocurra, vamos a a ejecutar los pasos 1,2,3,4.
Nota: el evento no trae el archivo, trae la referencia del archivo.
1.Leemos el archivo
Evento, dame la referencia al archivo.
file-loader.js, traeme el contenido de esta referencia.
si pudiste leer el archivo => devuelve el contenido.
si no pudiste => throw new Error.
2. Parseamos el archivo
Vamos a crear un modelo en memoria basado en el contenido del archivo.
file-parser: quiero que conviertas este txt en un objeto valido de UI.
file-parser.js
toUIHandler: contiene las diferentes formas de transformar nuestra UI
En esta version vamos a implementar txt => UI
Como hacer el Parseo?
Con un pipeline de ejecucion.
Cuando procesamos archivos estos por lo general se dividen en 3 tipos de transformaciones:
pre-processing: validar la data y preparla para el procesamiento
processing: se procesa la data
post-processing: se limpia la data.
🤔 y porque no todo en un map?
Ordenarlo de esta forma, nos sirve para reforzar el mental-model.
Esta idea viene del Batch processing o procesamiento en lote de archivos.
Puro server masticando datos.
Este approach te da mas control:
Al tener cada Step modularizado puedes medir la eficiencia, consumo, costos de cada uno.
easy to isolate errors
easy to compose
Para el frontend no es tan relevante, puedes tenerlo todo en un map.
Esto es demostrativo.
Tambien nos va a servir tener un pipeline de ejecucion para la parte del Renderer
Como creamos ese pipeline de ejecución?
Necesitamos:
una entidad Processor para guardar y ejecutar los Steps
una entidad ProcessorStep con la transformacion especifica
Parser Steps
Pre-processing:
Validamos que exista contenido
Convertimos a JSON Object
Validamos Schema del JSON
devolvemos Objeto JSON
Processing:
El navegador en esta parte lee y detecta si tiene que cargar recursos externos ( no es nuestro caso)
devuelve objeto
Post-processing:
transformamos la posicion de los objetos de string a Array de números.
position: "0,100" => position[0,100]
Ahora solo nos falta:
instanciar el pipeline con los Steps
ejecutar el pipeline
# Recap
✅ Cuando el usuario seleccione un archivo desde su maquina
✅ Leemos el archivo
✅ Parseamos el archivo
Actualizamos el state
Dibujamos en pantalla
3. Actualizar el state
El state es la información de la aplicación.
Esto es lo que vamos a guardar:
Si volvemos al index.js
Creamos un objeto con la interfaz interpretada
la dejamos como currentUI
y la agregamos al historial del usuario
Actualizamos el state ✅
4. Dibujar en pantalla, El último paso! yei!!!! 😬
El navegador realiza los siguientes pasos para dibujar en pantalla:
Obtiene los elementos visibles de la UI
Calcula la posicion de los elementos
Pinta los elementos
Mezcla todas las capas
este proceso se hace 60 veces por segundo.
60 veces en 1 segundo
Si ves por 3 segundos una pantalla “estática”.
La pantalla te mostró la misma imagen 180veces.
y Nosotros: 🥱 solo 1 imagen/sitio/pagina/app que no se mueve.
Para simular el movimiento, se crean imágenes secuenciales con pequeñas diferencias.
Que luego se muestran de forma “rapida”.
🤔🤔🤔 y en código?
Le decimos al Navegador que ejecute una funcion por frame.
Esta función la puedes ver bajo nombres como:
update()
animate()
En Unity (motor de videjuegos)
Para agregar tu script al Loop, debes sobre-escribir la funcion Update() de una clase heredada.
(nombre clase:MonoBehaviour)
En P5.js (creative-coding y proyectos multimedia)
se llama draw()
En Phaser (JS para hacer videojuegos )
Tambien le llaman update()
Implementemos:
Crearemos una clase Renderer que contendrá todo lo relacionado con dibujar en la pantalla.
engine: nuestro motor grafico, quien hablara con la tarjeta grafica y le dirá que dibujar.
en nuestro caso, el <canvas>
Pipeline de dibujo
Layout
Paint
Composite
Layout
Painting
Composite
UIControl
Es nuestro Elemento visible.
Es el Texto, Cuadrado, Poligono,etc.
Canvas Helper
Helper para dibujar formas en el canvas.
si te fijas la mayoria dibuja un Rect, pero ya tenemos la carcasa
Con esto,
volvemos al index.js y terminamos la implementacion:
creamos un Renderer y le pasamos la referencia del canvas