Repository navigation
feat(skins): catálogo de skins de Mosaicary en el gestor de skins - #55
Merged
staFF6773 merged 5 commits intoOct 29, 2026
Merged
Conversation
Desde octubre de 2026 Mojang rechaza el cambio de skin por URL (JSON con `url`): su cortafuegos responde 403 con una página HTML, que se mostraba entera en la notificación. La subida del PNG como archivo (multipart) sigue funcionando, así que `upload_skin_url_impl` descarga la imagen (http o https, hasta 1 MB, con firma de PNG) y la sube con la misma función que la subida desde archivo. Arregla también el armario de skins, que vuelve a poner una skin guardada por su URL.
…kins Un botón «Catálogo» junto a la subida de skins abre una ventana con las skins de mosaicary.com para cuentas premium: búsqueda por nombre, etiqueta o jugador, filtros de modelo, orden, ojos vivos, categoría y etiquetas, y tarjetas por fila a elegir. La skin elegida queda pendiente en la vista previa y se guarda con el mismo botón. Las tarjetas son imágenes que dibuja el servidor, cargadas por páginas al acercarse al final. La lista va en bloques de cuatro filas: solo los cercanos a la vista llevan sus tarjetas y el navegador no maqueta ni pinta los demás. En la vista previa, botones para girar, caminar y mover los ojos de Fresh Moves; caminar también se pausa sin actividad, y el centro de giro pasa al pecho.
… fila «Activa» queda junto al nombre, y Cerrar sesión y Eliminar al final de la fila del nombre, también con la ventana más estrecha; debajo quedan solo los datos de la cuenta.
La vista previa y la detección de brazos piden el PNG con for=view; solo guardar la skin lo descarga sin él. Así Mosaicary no cuenta como descarga cada skin mirada ni la descuenta de su límite diario de descargas por dirección.
staFF6773
requested changes
Oct 28, 2026
staFF6773
left a comment
Member
There was a problem hiding this comment.
El tamaño se comprueba después de leer toda la respuesta con bytes().await. Si el servidor devuelve un archivo enorme, podría consumir mucha RAM antes de rechazarlo. ¿Se podría leer por bloques y detener la descarga al superar el límite de 1 MiB?
download_skin leía toda la respuesta con bytes() antes de mirar el tamaño, así que un servidor sin Content-Length (o con uno falso) podía hacerle reservar memoria sin límite. Ahora cuenta lo que llega con chunk() y corta en cuanto pasa de 1 MiB, como ya hacen avatar.rs y ely_profile.rs.
Contributor
Author
|
Entendido, recibido, procesado. Corregido en de2a26a:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Descripcion
Agrega un catálogo de skins al gestor de skins de las cuentas premium (Microsoft), como
hablamos en Discord. Un botón Catálogo, junto a "Subir skin", abre una ventana con las
skins de Mosaicary.
modelo (Clásico / Delgado), orden (nuevas, populares, más descargadas), ojos vivos (skins
cuyos ojos se mueven con el paquete de recursos Fresh Moves), categoría y etiquetas
(
TagPicker.svelte: lista con búsqueda y casillas, hasta 10, alguna o todas a la vez).localStorage. Al bajar por la listaaparece un botón «Filtros» que vuelve arriba.
WalkingAnimationdeskin3d) y, si la skin trae los ojos de Fresh Moves, moverlos como en el juego. Muestran su
nombre al pasar el ratón, se recuerdan, y no aparecen si las animaciones 3D están
desactivadas en Ajustes.
se ve la cara y el torso, no la cintura. Sin desplazar con el botón derecho, y con una
distancia mínima para que la cámara no entre en la figura.
mosaicary.com. Las skins con ojos vivos parpadean y miran a los lados como en la web,
salvo con «Reducir animaciones de la interfaz» activado.
guarda con el mismo botón (
uploadSkinUrl, que ahora sube el PNG como archivo: ver«Arreglo» abajo).
con
?for=view, así Mosaicary no lo cuenta como descarga ni contra su límite de descargaspor dirección. Solo guardar la skin lo descarga.
Clásico en una skin delgada.
mosaicary.com y al repositorio en GitHub.
https://mosaicary.com: el PNG que se subea Mojang sale de ahí.
fila del nombre, también con la ventana más estrecha; debajo quedan solo los datos de la
cuenta.
Arreglo: cambiar la skin por URL
Desde octubre de 2026 Mojang rechaza el cambio de skin por URL (
POST /minecraft/profile/skinscon{"variant", "url"}en JSON): su cortafuegos responde 403 conuna página HTML («The request is blocked»), que el launcher mostraba entera en la
notificación. La subida del PNG como archivo (
multipart/form-data) sigue funcionando; es loque usan Prism y Modrinth. Afectaba también al armario de skins (
skin_closet.rs), quevuelve a poner una skin guardada por su URL.
upload_skin_url_implahora descarga la imagen (http o https, hasta 1 MB, con firma de PNG)y la sube con la misma función que la subida desde archivo (
upload_skin_bytes_impl). Elarmario y el catálogo funcionan sin más cambios.
Rendimiento
render, 256×256, unos 12–15 KBcada una, en caché para siempre) con
loading="lazy": nada de 3D por tarjeta. Los ojosvivos son un APNG (
live) en el que cada fotograma trae solo los píxeles de los ojos quecambian: 2–12 KB más que la imagen fija, y el navegador no lo anima fuera de la vista.
(
IntersectionObservercon una pantalla de margen). La búsqueda espera 350 ms mientrasse escribe, cancela la petición anterior (
AbortController) y descarta respuestas viejaspor generación, como el buscador de modpacks de CurseForge.
Clásico no repite la petición.
menos de una pantalla de la vista llevan sus tarjetas; los demás quedan vacíos con la
altura que medían, y el navegador no maqueta ni pinta los que quedan fuera de la vista
(
content-visibility). La lista se guarda con$state.raw: se reemplaza entera, sinproxy por tarjeta ni copia al guardarla.
(
IDLE_MS).Medido en la ventana del launcher (WebView2, 800×600, portátil de 2 núcleos), desplazando
con la rueda, antes (una sola rejilla) y después (en bloques):
sin tareas largas.
3400, estable.
Con una sola rejilla, cada imagen que llegaba y cada página nueva volvían a maquetar todas
las tarjetas: hasta 124 ms por vez con 800. El botón «Filtros» sabe si la barra de filtros
quedó atrás por un
IntersectionObserver, sin medir nada en cada evento de desplazamiento.Archivos
src-tauri/src/commands/profile.rs: el cambio de skin por URL sube el PNG como archivo.src/lib/api/mosaicarySkins.ts: dirección, lectura validada de la respuesta, petición yla dirección para mirar una skin (
catalogViewUrl).src/lib/components/profiles/SkinCatalogModal.svelte: la ventana, sobreModalBase,llevada al
bodyconuse:portalcomoModpackUpdateModal: dentro del perfil quedabarecortada bajo la barra lateral.
src/lib/components/profiles/TagPicker.svelte: la lista de etiquetas con búsqueda.src/lib/components/profiles/SkinCapeManager.svelte: el botón y la skin pendiente desdeuna URL.
src-tauri/tauri.conf.json:https://mosaicary.comenconnect-src(img-srcyapermite
https:).userMenu.skinCape.catalog.*en es-ES y en-US.src/lib/components/profiles/SkinPreview.svelteySkin3dViewer.svelte: losinterruptores «Girar», «Caminar» y «Mover los ojos» (
rotate,walk,eyes), la pausasin actividad también al caminar y el centro de giro en el pecho.
src/lib/utils/freshEyes.ts: lee la copia de los ojos que Fresh Moves usa en las esquinasde la skin y calcula sus movimientos.
src/lib/components/profiles/ProfileView.svelte: la fila del nombre con el estado y lasacciones.
src/lib/icons/registry.ts,static/images/icons/brand/mosaicary.png,static/images/icons/ui/eye.svg: iconos.tests/frontend/ui/mosaicarySkins.test.mjs(13 tests: la dirección con sus filtros yetiquetas, la de mirar una skin, la lectura y lo guardado por filtros) y
freshEyes.test.mjs(5 tests).La API está descrita en https://mosaicary.com/developers. Solo devuelve skins revisadas y
de 64 px, las que Mojang acepta.
Tipo de cambio
Plataforma
Checklist
bun run build && cargo build)bun run test:all) (ver «Información adicional»)Screenshots / logs (si aplica)
Perfil: la fila del nombre y los botones de la vista previa (girar, caminar, ojos).
El catálogo.
Informacion adicional
La traducción al ruso de las nuevas claves la mando aparte al repositorio Translations.
Pasan
bun run lint,bun run check, Prettier,cargo fmt --checky los tests nuevos(
mosaicarySkins,freshEyes,skinModel: 27). En esta máquina con Windowscargo testno llega a ejecutar nada: el ejecutable de tests termina con
STATUS_ENTRYPOINT_NOT_FOUNDal arrancar, antes del primer test; y unos pocos tests de frontend ajenos a este PR
fallan por la ruta local con espacios. El CI cubre ambos.
Con Rust 1.99,
cargo clippy -- -D warningsse detiene encrates/zellkern/src/resolvers/command.rs:142(clippy::unnecessary_map_or), código que estePR no toca; con esa regla permitida, el resto pasa sin avisos.