Category: Desarrollo

Actualización Mayor para Element Web y Escritorio: Listas de Salas Rediseñadas

2025-09-25
Actualización Mayor para Element Web y Escritorio: Listas de Salas Rediseñadas

Las aplicaciones Element Web y Escritorio han recibido una actualización significativa, reformulando completamente sus listas de salas. Inspirada en el diseño móvil de Element X, esta actualización ofrece una experiencia más elegante e intuitiva. Este es el primer paso de una evolución mayor, con el objetivo de lograr consistencia entre plataformas, mejorar la accesibilidad y crear una base técnica más robusta. El resultado? Una experiencia más simple, rápida y mejor para todos los usuarios. Nuevos filtros ayudan a gestionar listas de salas ocupadas, mostrando claramente mensajes no leídos, menciones y actividades recientes. Mejoras de accesibilidad y actualizaciones de arquitectura subyacentes (como MVVM y Sliding Sync) prometen mayor fiabilidad, tiempos de carga más rápidos y actualizaciones futuras más rápidas.

Desarrollo Rediseño de la IU

Una Teoría Matemática para Layouts de GPU: Aplicando la Teoría de Categorías y los Operads

2025-09-25
Una Teoría Matemática para Layouts de GPU: Aplicando la Teoría de Categorías y los Operads

Este artículo presenta CuTe, un enfoque novedoso para los layouts de memoria de GPU, y profundiza en la teoría matemática subyacente. Los layouts CuTe aprovechan la teoría de categorías y los operads, empleando el cálculo diagramático y las representaciones estándar para resolver el problema de mapear datos multidimensionales a la memoria unidimensional de la GPU. Esto proporciona una base teórica para optimizar los patrones de acceso a la memoria y utilizar instrucciones de hardware especializadas, como los núcleos de tensor. El artículo se centra en el concepto de layouts tratables, funciones de layout y operaciones de layout, como la fusión, el complemento y la composición, demostrando cómo un marco categórico calcula eficientemente la composición de layouts.

Desarrollo layout de memoria

Optimizando objetos de configuración JS con BigInts: Un experimento

2025-09-25
Optimizando objetos de configuración JS con BigInts: Un experimento

Para optimizar las operaciones de serialización, comparación y actualización en una gran cantidad de objetos de configuración, el autor experimentó con el uso del tipo BigInt de JavaScript para almacenar datos de configuración. Al empaquetar varios campos de configuración en un solo BigInt y usar operaciones bit a bit para operaciones de lectura y escritura eficientes, el autor logró una representación de memoria compacta y una serialización/deserialización rápida. Sin embargo, este enfoque también tiene algunas desventajas, como la necesidad de gestionar manualmente los anchos de bits y los desplazamientos de los campos, y los problemas de rendimiento de las operaciones bit a bit de BigInt. El autor aún está evaluando el efecto práctico de este método y planea actualizar el artículo en el futuro.

Desarrollo

Flix: Manejando la Depuración de Impresión con Elegancia

2025-09-25

Los diseñadores del lenguaje Flix se enfrentaron a un dilema: cómo permitir optimizaciones eficientes del compilador al mismo tiempo que permiten a los desarrolladores usar fácilmente la depuración de impresión. Usar `println` directamente rompe el sistema de tipos y efectos, causando errores de compilación. El artículo explora dos soluciones: la primera usa `unchecked_cast` para omitir las comprobaciones del sistema de efectos, pero resulta en que el código se optimiza; la segunda introduce un efecto `Debug`, permitiendo impresiones de depuración sin modificar las firmas de las funciones, y deshabilitando el efecto `Debug` en producción. La solución final equilibra la optimización del compilador y la experiencia del desarrollador.

Desarrollo sistema de efectos

Disputa por la Marca Registrada de Bundler: Una Lucha por la Propiedad de la Comunidad

2025-09-25

Durante 15 años, el autor ha mantenido Bundler, el gestor de dependencias de Ruby. Desde su participación inicial hasta la fundación de Ruby Together para financiar el mantenimiento, y finalmente una disputa de fusión con Ruby Central, el autor registró la marca registrada de Bundler para proteger los intereses de la comunidad. Se compromete a transferir la marca registrada a una organización responsable ante los mantenedores y la comunidad, asegurando que Bundler realmente pertenezca a la comunidad Ruby.

Desarrollo

El Misterio del 'Tiempo de Cabra': Un Enigma de Traducción Automática

2025-09-25

Un usuario japonés, utilizando traducción automática, solicitó ayuda para un error de tiempo de ejecución llamado 'Tiempo de Cabra'. El mensaje de error es extraño, con términos como 'vómito', 'viento, poste y dragón', dejando a todos perplejos. El análisis sugiere que 'vómito' puede referirse a excepciones, 'madera' a registros y 'Tiempo de Cabra' al entorno de tiempo de ejecución. Se especula que 'nalgadas' es una mala traducción de 'ejecutar', y 'habilidad' de 'experiencia'. 'Insulto a las piedras del padre' podría aludir a dependencias de software. El 'viento, poste y dragón' siguen siendo un misterio. Este es un enigma inducido por traducción automática que espera más información para ser resuelto.

El Teatro de los Pull Requests y la Revisión de Código

2025-09-25

La charla de Saša Jurić en Goatmire Elixir Conf transformó la revisión de código en una narrativa convincente. Destacó el problema común de los pull requests (PRs) demasiado grandes y complejos, lo que lleva a revisiones superficiales, riesgos de seguridad y bases de código difíciles de mantener. La conclusión principal: los PRs revisables deberían idealmente tomar de 5 a 10 minutos para revisarlos, idealmente con menos de 300 líneas de código. Esto se logra creando mensajes de commit concisos y narrativos que explican claramente el razonamiento y los pasos de cada cambio. Dividir las grandes funciones en PRs más pequeños y usar herramientas como `git fixup` para mantener un historial de commit limpio son cruciales para una revisión de código eficiente y un código de mayor calidad. La charla enfatizó que decir "No entiendo" es mejor que un "LGTM" sin sentido.

Desarrollo

kwargs al estilo Python en TypeScript: Un truco ingenioso para mejorar la legibilidad

2025-09-25
kwargs al estilo Python en TypeScript: Un truco ingenioso para mejorar la legibilidad

Este artículo presenta una ingeniosa técnica para imitar los argumentos de palabra clave de Python (kwargs) en TypeScript, abordando los desafíos de legibilidad y mantenibilidad que plantean las funciones con numerosos parámetros opcionales. Al usar un objeto que contiene parámetros opcionales como argumento de función, los desarrolladores pueden especificar claramente qué parámetros modificar sin una cadena de valores `undefined`. Esto mejora la legibilidad y la depuración del código, preservando la seguridad de tipos de TypeScript. Si bien los cambios en los nombres de los parámetros pueden romper la compatibilidad, usar esto dentro de las funciones internas simplifica significativamente el código.

Desarrollo

Mejorando el Método de Newton para la Ecuación de Proyección de Mollweide

2025-09-25

Este artículo explora el uso del método de Newton para resolver una ecuación crucial en la proyección cartográfica de Mollweide. Cerca de altas latitudes (aproximándose a π/2), la ecuación presenta una raíz doble, haciendo que el método de Newton disminuya la velocidad o diverja. El artículo propone un método de Newton modificado, ajustando el parámetro 'm' para mejorar la velocidad de convergencia y la precisión cerca de la raíz doble. Sin embargo, los desafíos permanecen muy cerca de la raíz doble, llevando al autor a sugerir la combinación con otros métodos, como la inversión de series de potencias, para una solución completa.

Agente de IA Slate: Automatizando la Portabilidad de un Proyecto Python a TypeScript

2025-09-25

Slate es un agente de IA altamente autónomo diseñado para manejar tareas largas y complejas. Esta publicación detalla cómo Slate portó con éxito el proyecto de código abierto Python Browser Use (70.3k estrellas), una biblioteca de automatización de navegador para LLMs, a TypeScript en menos de dos horas por menos de $60. Slate automatizó la mayor parte del proceso, requiriendo solo una mínima intervención del usuario. El proceso mostró las poderosas capacidades de planificación y ejecución de Slate, así como su capacidad para solucionar problemas de forma autónoma, resultando en una versión TypeScript completamente funcional.

La sorprendente destreza de Go: simulando millones de partículas en una Smart TV

2025-09-25
La sorprendente destreza de Go: simulando millones de partículas en una Smart TV

El autor aborda el desafío de simular millones de partículas en Go, un lenguaje no conocido por su potencia computacional, para un juego multijugador que se ejecuta en una Smart TV. Al descargar todo el trabajo de renderizado al servidor y enviar solo búferes de fotogramas a los clientes, se evitan los cuellos de botella de rendimiento. El artículo detalla las soluciones técnicas, incluida una estrategia de G-buffer, técnicas de compresión de fotogramas y sincronización eficiente de clientes. A pesar de la falta de SIMD en Go, el autor logra resultados impresionantes, ejecutando una simulación de un millón de partículas en un servidor en la nube de bajo costo con cientos de clientes simultáneos.

Desarrollo

Vectores de enteros empaquetados en bits eficientes en Rust: acceso aleatorio O(1) con compresión de bits

2025-09-25
Vectores de enteros empaquetados en bits eficientes en Rust: acceso aleatorio O(1) con compresión de bits

Este artículo explora los desafíos de ingeniería de implementar una estructura de datos eficiente similar a un vector en Rust que almacena enteros en un formato comprimido, empaquetado en bits, logrando simultáneamente un rendimiento de acceso aleatorio O(1) y minimizando el uso de memoria. El artículo detalla la implementación del empaquetado y acceso de bits, el cruce de límites de palabras, el acceso desalineados, los iteradores y la mutabilidad, y demuestra sus ventajas de rendimiento a través de resultados de pruebas de rendimiento. Además, el artículo analiza el diseño arquitectónico de esta estructura de datos, incluyendo abstracciones sobre la capa de almacenamiento físico y la capa de tipo lógico, y el uso de un patrón de constructor, ofreciendo nuevas ideas para construir estructuras de datos eficientes y flexibles.

Desarrollo Empaquetado de bits

Caída de la autenticación de Docker Hub resuelta

2025-09-25

El 24 de septiembre, Docker Hub experimentó una caída de la autenticación que afectó al inicio de sesión de los usuarios en Docker Hub Registry y sus API. El equipo de Docker respondió rápidamente, identificando la causa raíz e implementando una solución en pocas horas. El monitoreo confirma que el servicio está totalmente restaurado; los usuarios simplemente deben cerrar sesión y volver a iniciar sesión para actualizar sus sesiones.

Desarrollo

Wasmer Edge: Python 6 veces más rápido en WebAssembly en el Edge

2025-09-25
Wasmer Edge: Python 6 veces más rápido en WebAssembly en el Edge

Wasmer Edge Beta ahora cuenta con soporte completo para Python, impulsado por WebAssembly y WASIX. Esta versión es significativamente más rápida que las iteraciones anteriores, incluso superando al proyecto py2wasm. Ahora puedes ejecutar frameworks como FastAPI, Streamlit, Django y LangChain directamente en Wasmer y Wasmer Edge. Esto se logró agregando vinculación dinámica, soporte libffi, mejorando los sockets y el soporte de subprocesos, y lanzando un índice de paquetes Python personalizado con muchas bibliotecas nativas populares. En comparación con Cloudflare Workers y AWS Lambda, Wasmer Edge ofrece velocidad, compatibilidad y asequibilidad superiores, lo que lo hace ideal para cargas de trabajo de IA y API en el borde.

Desarrollo

Genéricos en PHP: De la serie de blogs al libro

2025-09-25
Genéricos en PHP: De la serie de blogs al libro

Durante más de una década, los desarrolladores de PHP han debatido la inclusión de genéricos. Un RFC de genéricos en tiempo de compilación de 2025 cambió la conversación. Inspirado en esto, el autor creó una serie de blogs que profundiza en la historia, los detalles y el impacto en el ecosistema de los genéricos en PHP. Esta serie evolucionó en un libro, "Genéricos en PHP: Un viaje guiado a través del RFC de tiempo de compilación". Expandiendo las publicaciones del blog, el libro proporciona capítulos adicionales, ejemplos refinados y perspectivas sobre el futuro de los genéricos en PHP, lo que permite a los desarrolladores escribir código más limpio y seguro.

Desarrollo

SonShell: Descarga Automática de Fotos de tu Cámara Sony

2025-09-25
SonShell: Descarga Automática de Fotos de tu Cámara Sony

SonShell es una herramienta solo para Linux, construida sobre el SDK oficial de Camera Remote de Sony. Se conecta a una cámara Sony A6700 (Wi-Fi/Ethernet), descarga automáticamente las fotos nuevas y, opcionalmente, ejecuta un script en cada archivo descargado. Incluye conexión automática mediante enumeración o IP/MAC directo, reconexión automática, nombres de archivo seguros y mucho más. El desarrollador usó ampliamente ChatGPT durante la creación, lo que resultó en un código limpio y fácil de entender. Perfecto para usuarios de Linux que desean optimizar su flujo de trabajo fotográfico.

Dayflow: Aplicación de línea de tiempo con IA para seguimiento del tiempo y privacidad

2025-09-25
Dayflow: Aplicación de línea de tiempo con IA para seguimiento del tiempo y privacidad

Dayflow es una aplicación nativa para macOS que graba tu actividad en pantalla a 1 FPS, la analiza cada 15 minutos con IA y genera una línea de tiempo limpia con resúmenes. Es ligera y se centra en la privacidad, permitiéndote elegir entre Gemini (clave de API BYO) o modelos locales (Ollama/LM Studio) como proveedor de IA. Creada con el deseo de una línea de tiempo simple y confiable, Dayflow pretende ser un asistente silencioso y respetuoso, no otro panel para gestionar.

Desarrollo

Helium: Un navegador Chromium ligero, centrado en la privacidad y de código abierto

2025-09-25
Helium: Un navegador Chromium ligero, centrado en la privacidad y de código abierto

Helium es un navegador Chromium ligero, centrado en la privacidad y de código abierto. Ofrece funciones como vista dividida, copia rápida de enlaces e instalación de aplicaciones web, todo ello en una interfaz limpia y minimalista. Helium anonimiza las solicitudes a la Chrome Web Store, evitando que Google rastree las descargas de extensiones y los anuncios dirigidos. Su naturaleza de código abierto permite la auto-hospedación de servicios, y prioriza HTTPS, deshabilitando el gestor de contraseñas integrado y la sincronización en la nube de forma predeterminada para una mayor seguridad y privacidad del usuario.

Desarrollo

El editor de código Zed cambia el precio de la IA a un modelo basado en tokens

2025-09-24
El editor de código Zed cambia el precio de la IA a un modelo basado en tokens

El editor de código Zed está cambiando sus precios de IA de basados en prompts a basados en tokens, reflejando mejor el coste real de los servicios de IA. Esto permite a Zed invertir de forma sostenible en funciones del editor y ofertas para empresas. La nueva fijación de precios incluye más modelos de IA, como GPT-5 y Gemini 2.5, y ofrece a los usuarios flexibilidad con opciones como traer sus propias claves API o usar modelos locales. Los usuarios existentes tienen un período de transición de tres meses con soporte. El cambio también simplifica los precios y reduce los costes.

Desarrollo

Liderazgo Técnico: Conectando, no Comandiando

2025-09-24
Liderazgo Técnico: Conectando, no Comandiando

Un desarrollador senior reflexiona sobre su papel: no como un experto técnico, sino como un puente entre los equipos. Traduce problemas complejos de back-end a un lenguaje amigable para el producto, coordina la comunicación entre los equipos y asegura la alineación de los objetivos del equipo. El liderazgo no se trata de poseer el mayor conocimiento, sino de una comunicación y coordinación efectivas, definiendo claramente los problemas, guiando a los equipos hacia las soluciones y empoderando a los miembros del equipo para que sobresalgan. En última instancia, un gran liderazgo crea un entorno donde los expertos pueden prosperar en colaboración, en lugar de intentar ser la persona más inteligente de la sala.

Desarrollo liderazgo técnico

GC DATAS de .NET 10: ¡Prepárate para el despegue!

2025-09-24
GC DATAS de .NET 10: ¡Prepárate para el despegue!

.NET 10 utiliza por defecto DATAS (Dynamic Adaptation of Heap Size), un cambio significativo en el GC que afecta al uso de memoria y requiere atención del usuario, a diferencia de las actualizaciones anteriores. Esta publicación explica el comportamiento adaptativo de DATAS: ajuste del tamaño del montón en función del tamaño de datos activos (LDS), minimizando la memoria mientras se mantiene el rendimiento. Se detallan escenarios donde DATAS no es ideal (por ejemplo, altas demandas de rendimiento, rendimiento crítico de inicio, principalmente GCs de Gen2). Dos estudios de caso ilustran el ajuste de DATAS mediante parámetros de configuración para obtener resultados óptimos.

Desarrollo

Mi caja de herramientas ed(1): Una inmersión profunda en el mundo de las implementaciones ed(1)

2025-09-24

Artyom Bologov, un autoproclamado entusiasta de ed(1), comparte su colección de implementaciones y scripts de ed(1). Utiliza ed(1) extensamente como editor Git, editor sudo e incluso como generador de sitios estáticos. Su caja de herramientas incluye GNU ed, OpenBSD ed (oed), una versión modernizada llamada wed(1), un aed(1) más amigable para el usuario y xed(1) para scripts. Estas herramientas abordan las limitaciones de ed(1), como la falta de soporte para scripts y la falta de facilidad de uso, manteniendo la portabilidad en varios sistemas. Incluso creó implementaciones de ed(1) en Brainfuck, BASIC y Modal, una prueba de su dedicación. Bologov concluye instando a los lectores a abrazar y amar ed(1).

Desarrollo

¿Esquema de verificación de edad: una pesadilla de usabilidad?

2025-09-24
¿Esquema de verificación de edad: una pesadilla de usabilidad?

Una nueva solución de verificación de edad online está causando controversia. Su fuerte dependencia de los smartphones excluye a muchos usuarios sin smartphones o que no quieren usarlos, como los ancianos. Esto afecta significativamente la navegación web, especialmente en los modos privados, requiriendo verificación de edad en cada visita al sitio web. El alto coste de implementación supone un gran obstáculo para las startups, y las elecciones tecnológicas parecen limitantes. Los beneficios de privacidad que reclama la solución también son cuestionables.

Desarrollo

yt-dlp requer Deno para descargas de YouTube

2025-09-24
yt-dlp requer Deno para descargas de YouTube

El popular descargador de YouTube, yt-dlp, pronto requerirá el tiempo de ejecución de JavaScript Deno para funcionar correctamente debido a los cambios en YouTube. Anteriormente, yt-dlp usaba un intérprete de JavaScript integrado, pero ahora es insuficiente para superar las medidas anti-raspado actualizadas de YouTube. Los usuarios deberán instalar Deno y tomar medidas adicionales según su método de instalación (por ejemplo, usando pip o ejecutables oficiales) para actualizar yt-dlp y garantizar la capacidad continua de descarga de videos de YouTube.

Hardened Malloc de GrapheneOS: Una inmersión profunda en sus mejoras de seguridad

2025-09-24
Hardened Malloc de GrapheneOS: Una inmersión profunda en sus mejoras de seguridad

El asignador de memoria reforzado de GrapheneOS, Hardened Malloc, emplea múltiples técnicas para combatir vulnerabilidades de corrupción de memoria. Aprovecha la Extensión de Etiquetado de Memoria (MTE) de ARM para detectar lecturas y escrituras fuera de los límites y vulnerabilidades de uso después de la liberación (use-after-free). Para dispositivos sin soporte MTE, Hardened Malloc utiliza canarios y páginas de protección de tamaño aleatorio para una seguridad mejorada. Su mecanismo único de doble cuarentena, utilizando reemplazo aleatorio y colas FIFO, aumenta significativamente la dificultad de los exploits de uso después de la liberación. El diseño limpio de Hardened Malloc facilita la auditoría y el mantenimiento, proporcionando a GrapheneOS un nivel superior de seguridad.

Desarrollo

El Desafío Berghain de 2025: Una Competición de Codificación Viral Que Rompió Internet

2025-09-24

Listen Labs lanzó un desafío de codificación viral, el Desafío Berghain, que comenzó con una valla publicitaria críptica en San Francisco. El desafío encomendó a los participantes un problema complejo de optimización: seleccionar exactamente 1000 personas de un flujo de llegadas aleatorias, cada una con varios atributos, mientras cumplían con cuotas específicas y minimizaban los rechazos. Este juego, engañosamente simple, atrajo a más de 30.000 ingenieros. El autor, comenzando como un novato en algoritmos, subió al puesto número 16 en la clasificación, detallando su viaje iterativo a través de varios algoritmos, desde enfoques ingenuos codiciosos hasta modelos sofisticados de copula gaussiana y, finalmente, métodos prácticos basados ​​en umbrales. Encontraron sobrecarga del servidor y limitación de velocidad, mostrando la escalabilidad inesperada del desafío. Al analizar las soluciones de mejor rendimiento, el autor destaca las lecciones clave aprendidas: lo simple a menudo supera a lo complejo, el ajuste de parámetros es crucial, la velocidad de iteración supera a la perfección, el conocimiento del dominio proviene de fuentes inesperadas y las restricciones pueden ser características. En última instancia, el Desafío Berghain reavivó la pasión del autor por la programación y ofrece información sobre futuras competiciones técnicas colaborativas.

Ruby Central y DHH: Una comunidad dividida por valores

2025-09-24
Ruby Central y DHH: Una comunidad dividida por valores

La comunidad Ruby está fracturada por los comentarios de DHH (David Heinemeier Hansson) y la respuesta de Ruby Central, el organizador de RailsConf. El autor, Jared White, después de una reunión de Zoom en la que expresó sus preocupaciones sobre la retórica de DHH y su uso de RailsConf para atacar a sus oponentes políticos, consideró insuficiente la respuesta de Ruby Central. Su colaboración con DHH en Rails World exacerbó aún más el conflicto. White finalmente retiró su apoyo a Ruby Central, cuestionando su compromiso con la inclusión y los valores compartidos.

Revolucionando las transacciones entre cadenas con Intents

2025-09-24
Revolucionando las transacciones entre cadenas con Intents

Las transacciones tradicionales entre cadenas son complejas, lentas y costosas. Este artículo presenta un nuevo enfoque llamado "Intents", donde los usuarios simplemente declaran el resultado deseado (por ejemplo, intercambiar 1000 USDC por 100 SOL) sin especificar los pasos. Una red de "solvers" cumple automáticamente la solicitud. Esto es análogo a decir "tráeme leche" en lugar de dar instrucciones de conducción detalladas. El protocolo NEAR fue pionero en un sistema de intenciones entre cadenas, utilizando firmas de cadena para lograr una finalidad de 2 a 3 segundos y soporte nativo para Bitcoin, superando los US$ 1000 millones en volumen total. Su API 1Click simplifica el desarrollo, permitiendo la creación fácil de interfaces DEX entre cadenas.

Arquitectura de Data Warehouse: Una inmersión profunda de lo clásico a lo nativo en la nube

2025-09-24
Arquitectura de Data Warehouse: Una inmersión profunda de lo clásico a lo nativo en la nube

Esta guía completa explora la arquitectura de data warehouse, desde los modelos clásicos de tres niveles hasta los diseños modernos nativos en la nube. Cubre capas clave como la integración de datos, el almacenamiento y el acceso, detallando las ventajas y desventajas de varias arquitecturas (híbrida, de un solo nivel, de dos niveles, de tres niveles, esquema estrella, esquema copo de nieve, etc.) y sus casos de uso. También se analizan tendencias emergentes como lakehouse, data mesh y pipelines en tiempo real, junto con cómo elegir la arquitectura, el esquema y las herramientas adecuadas para optimizar el rendimiento y el costo. Ejemplos del mundo real de Helsana y WashTec muestran cómo las empresas modernizaron sus infraestructuras de datos para mejorar la eficiencia y los conocimientos.

La codificación asistida por IA en móviles: ¿un tropiezo para una tendencia multimillonaria?

2025-09-24
La codificación asistida por IA en móviles: ¿un tropiezo para una tendencia multimillonaria?

Mientras la codificación asistida por IA presume de valoraciones multimillonarias en ordenadores de sobremesa, su equivalente móvil se queda significativamente atrás. Los datos de Appfigures revelan cifras desalentadoras de descargas e ingresos para las aplicaciones de codificación por IA móvil. Incluso la aplicación con mejor rendimiento, Instance: AI App Builder, solo alcanzó 16.000 descargas y 1.000 dólares de ingresos. Vibecode, a pesar de obtener una financiación inicial sustancial, pone de manifiesto la inmadurez del mercado móvil. El problema principal radica en la calidad del código generado por IA, que requiere un esfuerzo considerable por parte de los desarrolladores para corregir errores. Sin embargo, la creciente demanda de los desarrolladores sugiere un futuro prometedor, aunque necesita más mejoras.

Desarrollo
← Previous 1 3 4 5 6 7 8 9 214 215