Skip to content

Biblioteca de mazos

Pablo Martínez López edited this page Oct 27, 2026 · 7 revisions

Biblioteca de mazos

English · Español

La Biblioteca es la pantalla que lista todos los mazos guardados en esta máquina y permite organizarlos: etiquetas, favoritos, notas, una carta de portada elegida, un idioma del mazo manual, búsqueda, filtros, ordenación, agrupación, una vista en cuadrícula y otra en lista, y acciones en bloque. Los datos baratos (nombres, recuentos, etiquetas) se leen directamente de SQLite; los «detalles» costosos de cada mazo (colores, clase de mazo, precio, idiomas, formatos legales) se calculan sin conexión en Rust a partir de los datos de Scryfall en caché y se guardan en memoria.

Cuadrícula de la biblioteca Lista de la biblioteca

La arquitectura de un vistazo

flowchart LR
    subgraph UI["src/features/library"]
        LS["library-screen.tsx LibraryScreen"]
        ST["store.ts useBiblioteca"]
        PF["preferencias.ts usePrefsBiblioteca / useFiltrosBiblioteca"]
        OZ["organizar.ts filtrar / ordenar / agrupar"]
    end
    subgraph Cmds["commands/library.rs"]
        DL["deck_list"]
        DD["deck_details"]
        TG["tag_* / deck_tags_set / deck_pin / deck_notes_set / deck_lang_set / deck_cover_set"]
    end
    subgraph Core["Rust"]
        DK["store/decks.rs list, save, duplicate"]
        ET["store/etiquetas.rs"]
        BI["biblioteca.rs detalles, CacheDetalles"]
        SC["commands/stats.rs calcular_sin_red"]
    end
    LS --> ST --> DL --> DK
    ST --> DD --> BI --> SC
    BI --> DK
    ST --> TG --> ET
    LS --> OZ
    LS --> PF
Loading

Decisión: filtrar, ordenar y agrupar ocurre en la vista web (funciones puras en organizar.ts), no en Rust. Motivo: solo reordenan datos que la pantalla ya tiene (DeckSummary + DeckDetails), necesitan respuesta instantánea mientras se escribe y no realizan ningún cálculo pesado; la parte pesada (los detalles) está en Rust. Este es el único sitio donde la regla de «todo lo pesado en Rust» se cumple con el cálculo de los detalles, no con la lógica de la lista.

Ficheros

Fichero Responsabilidad
src-tauri/src/biblioteca.rs DeckDetails, detalles_de, detalles, CacheDetalles
src-tauri/src/store/etiquetas.rs Etiquetas, favoritos, notas, portada, idioma manual (Tag, COLORES, IDIOMAS, create, update, delete, etiquetar, de_deck, favorito, notas, idioma, portada)
src-tauri/src/store/decks.rs DeckSummary, list, open, save, duplicate, delete, marcar_abierto, notas_de, idioma_de
src-tauri/src/store/migrations/0003_biblioteca.sql, 0004_idioma_deck.sql Esquema de las funciones de la biblioteca
src-tauri/src/commands/library.rs Los comandos de Tauri (abajo)
src-tauri/src/package.rs Exportación/importación de .pbdeck con etiquetas, notas e idioma
src/features/library/library-screen.tsx LibraryScreen: composición, selección, teclado, diálogos, barra de selección
src/features/library/zona-decks.tsx useOrganizados (filtrar → ordenar → agrupar, grupos plegados) y ZonaDecks (chips de filtros activos, vistas con grupos, estados vacíos, totales del pie), compartidos por la Biblioteca y la pestaña Jugar
src/features/library/etiquetas-ui.tsx useEtiquetasUi: estado y diálogos para crear, editar y borrar etiquetas, compartidos por las dos pantallas
src/features/library/store.ts useBiblioteca (zustand): mazos, detalles, etiquetas y las acciones
src/features/library/preferencias.ts usePrefsBiblioteca / usePrefsJugar (preferencias de vista persistidas) y useFiltrosBiblioteca / useFiltrosJugar (sin persistir); OrganizadorContexto dice qué pareja usan las piezas compartidas
src/features/library/organizar.ts Lógica pura de filtrar/ordenar/agrupar/seleccionar
src/features/library/barra-herramientas.tsx Búsqueda, ordenación, agrupación, popover de filtros (PanelFiltros), alternador de vista (recibe el titulo de la pantalla), chips de filtros activos (FiltrosActivos)
src/features/library/barra-lateral.tsx Barra lateral de etiquetas (BarraLateral)
src/features/library/vista-cuadricula.tsx, vista-lista.tsx Vistas de cuadrícula (VistaCuadricula, TarjetaDeck) y de tabla (VistaLista)
src/features/library/menu-deck.tsx Menú de mazo compartido: MenuDeck (desplegable) y MenuContextualDeck (clic derecho) sobre un único componente Items; el de clic derecho se pinta con ContenidoContextual, que ignora el puntero 250 ms tras abrirse (Vista previa en vivo)
src/features/library/propiedades-dialog.tsx Diálogo de propiedades (nombre, etiquetas, notas, portada, resumen)
src/features/library/etiqueta-dialog.tsx Diálogo de crear / editar etiqueta
src/features/library/piezas.tsx Piezas pequeñas: chips de etiqueta, puntos de color, IDIOMAS (los nombres propios de IDIOMAS_SCRYFALL de src/lib/idiomas.ts, más «Phyrexiano» traducido para ph, que no es un idioma de la app), CLASES, FORMATOS, useFecha, useHace, useDinero (fechas, tiempos relativos y precios con localeDe(lang), el locale del idioma de la interfaz)
src/features/library/__tests__/organizar.test.ts Tests de organizar.ts

Modelo de datos

SQLite (src-tauri/src/store/migrations)

La migración 0003_biblioteca.sql añade a decks: pinned INTEGER NOT NULL DEFAULT 0, notes TEXT NOT NULL DEFAULT '', opened_at INTEGER, cover_card_id TEXT, y dos tablas. La migración 0004_idioma_deck.sql añade decks.lang_override TEXT (NULL = calculado a partir de las cartas). Las migraciones se registran en src-tauri/src/store/db.rs ((3, include_str!(...)), (4, ...)); la conexión activa PRAGMA foreign_keys = ON, lo que hace que funcionen las cascadas de abajo.

erDiagram
    decks ||--o{ deck_tags : has
    tags ||--o{ deck_tags : labels
    decks {
        text id PK
        text name
        int updated_at
        int pinned
        text notes
        int opened_at
        text cover_card_id
        text lang_override
    }
    tags {
        text id PK
        text name "unique, NOCASE"
        text color
        int created_at
    }
    deck_tags {
        text deck_id FK "ON DELETE CASCADE"
        text tag_id FK "ON DELETE CASCADE"
    }
Loading

tags_name es un índice único sobre name COLLATE NOCASE; deck_tags_tag indexa tag_id.

Invariante: organizar nunca toca updated_at

Decisión: favorito, notas, portada, etiquetas e idioma manual son metadatos de la biblioteca, no del mazo. etiquetas::favorito/notas/portada/idioma actualizan solo su propia columna, y decks::save hace upsert únicamente del nombre, el texto de la lista, los ajustes, el reverso por defecto, la versión del esquema y updated_at (su lista de ON CONFLICT DO UPDATE no nombra esas columnas). Motivo: updated_at gobierna la ordenación por «Modificado», la lógica del autoguardado y la clave de la caché de detalles; marcar un mazo como favorito no debe hacer que parezca editado ni invalidar sus detalles calculados. Lo fijan los tests de Rust favorito_notas_y_portada_no_cambian_la_fecha y el_idioma_elegido_no_cambia_la_fecha_y_se_quita en store/etiquetas.rs. (Renombrar sí actualiza updated_at: decks::rename.)

DeckSummary (store/decks.rs)

Lo devuelve deck_list (decks::list, ordenado por updated_at DESC). Campos: id, name, cardCount, createdAt, updatedAt, openedAt?, thumbnail? (hash de blob de la imagen de portada), coverName?, coverCardId?, pinned, notes, langOverride?, tags (ids de etiqueta). La portada es la carta elegida si sigue en el mazo y tiene imagen; si no, la primera carta con imagen (una sola consulta SQL con COALESCE, json_extract(card_json, '$.meta.name') para el nombre).

DeckDetails (biblioteca.rs)

Lo devuelve deck_details. Campos y significado:

Campo Significado
kind (DeckKind) commander, constructed o limited, deducido por proxy_core::stats::deducir: menos de 50 cartas que no son fichas es limited; 90-110 con como mucho dos cartas repetidas que no son básicas es Commander; en otro caso constructed
colorIdentity Subconjunto de W U B R G, ordenado en orden WUBRG; vacío = incoloro
deckSize, lands, tokens Copias contadas por las estadísticas (las fichas se excluyen de deckSize)
unknown Copias sin datos de Scryfall (imágenes propias sin vincular, nada en la caché)
averageCmc Valor de maná medio sin contar las tierras
priceEur, priceUsd Total a partir de los precios en caché; null cuando ninguna carta tiene ese precio
designed, designedReady Cartas con un diseño del editor, y las que tienen estado Ready
custom, customLinked Cartas con imagen propia, y las vinculadas a Scryfall
dfc Copias de doble cara
langs Idiomas por uso, el más usado primero (los empates, por orden alfabético)
legalFormats Formatos en los que todas las cartas son legales
bracket Bracket mínimo de Commander que permiten las cartas (2-4), si lo hay
cardNames Nombres de carta únicos, para la búsqueda «mazos que contienen…»

Cómo se calcula (detalles_de(db, deck)):

  1. commands::stats::calcular_sin_red(db, &deck.cards) ejecuta el motor de estadísticas normal con una API SinRed, de modo que lee solo la caché local de Scryfall y nunca toca la red. Las cartas marcadas como variante/opcional/banquillo se dejan fuera (proxy_core::model::cuentan), exactamente igual que en el diálogo de estadísticas; véase Estadísticas.
  2. Una sola pasada por las cartas: se saltan las casillas en blanco; una carta diseñada cuenta para designed y su idioma es el settings.design_lang del mazo; en otro caso el idioma es idioma_de_la_carta(c).
  3. Decisión: para una carta con imagen propia (CardSource::Custom) el idioma es meta.imageLang, no meta.lang. Motivo: una carta vinculada a la impresión en inglés pero cuya imagen está en español haría que un mazo en español pareciera en inglés. Las cartas propias con idioma de imagen desconocido no cuentan (probado en cuenta_idiomas_propias_y_guarda_en_memoria).

Caché en memoria

CacheDetalles (AppState.detalles, src-tauri/src/state.rs) asocia id de mazo -> (updated_at, DeckDetails) tras un mutex. detalles(db, cache, ids) lista los mazos (decks::list), filtra por ids (todos si está vacío) y, para cada mazo, reutiliza la entrada si su updated_at coincide con el actual del mazo; en caso contrario abre el mazo, calcula los detalles y los guarda.

Trampas conocidas:

  • La clave es solo updated_at. Los cambios en la caché de Scryfall que ocurren sin editar el mazo (por ejemplo, los precios actualizados por el diálogo de estadísticas) no invalidan una entrada; las cifras nuevas aparecen después de guardar el mazo la próxima vez o al reiniciar la app.
  • La caché vive solo en memoria. La primera carga de la biblioteca tras arrancar calcula todos los mazos; las cargas posteriores son baratas.
  • Las entradas de los mazos borrados nunca se eliminan (no hay código de eliminación en biblioteca.rs); es inofensivo porque las búsquedas son por id a partir de la lista viva.

Comandos de Tauri (src-tauri/src/commands/library.rs)

Comando Argumentos Devuelve Notas
deck_list ninguno DeckSummary[]
deck_details ids (vacío = todos) DeckDetails[] asíncrono, sin conexión, memoizado
deck_peek id Deck Abre un mazo para leerlo (selector de portada) sin establecer opened_at
deck_open id Deck También llama a decks::marcar_abierto (opened_at = now)
deck_create name Deck Mazo vacío con el reverso genérico
deck_save, deck_rename, deck_delete
deck_duplicate id, name Deck Ids de carta nuevos; copia etiquetas, notas, portada (reasignada al id de la carta nueva) e idioma manual, y las listas para jugar de la mesa de juego (con los ids de carta reasignados); no el favorito
tag_list ninguno Tag[] Ordenado por nombre, sin distinguir mayúsculas
tag_create name, color Tag Si ya existe una etiqueta con ese nombre (con cualquier capitalización), la devuelve sin cambios
tag_update id, name, color Tag InvalidInput (motivo = "tag_repetido") si otra etiqueta tiene el nombre; NotFound si el id es desconocido
tag_delete id La cascada la quita de los mazos; los mazos no se tocan
deck_tags_set decks, add, remove Una transacción; INSERT OR IGNORE solo si existen tanto el mazo como la etiqueta
deck_pin decks, pinned Favoritos (columna pinned)
deck_notes_set id, notes Recortado por el final, limitado a 4000 caracteres; NotFound para un mazo desconocido
deck_lang_set decks, lang? None lo borra; solo los códigos de etiquetas::IDIOMAS (es en fr de it pt ja ko ru zhs zht ph), si no InvalidInput con motivo = "idioma"
deck_cover_set id, card? None = la primera carta
deck_export_package, deck_import_package .pbdeck, véase abajo
blob_gc GcReport Botón «Liberar espacio»: borra las imágenes que ningún mazo usa y de más de 24 h; falla con Busy mientras corre un trabajo (state.ocupado())

Reglas de las etiquetas (etiquetas::limpiar): al nombre se le colapsan los espacios en blanco y se corta a 40 caracteres; un nombre vacío es InvalidInput (motivo = "tag_vacio"); un color fuera de COLORES (gray red orange amber green teal sky blue violet pink) pasa silenciosamente a gray.

Estado del frontend

useBiblioteca (store.ts)

Contiene decks (null hasta cargar), detalles (registro por id), etiquetas, contando. Acciones:

  • cargar(): guardarAhora() (vuelca el autoguardado pendiente del mazo abierto para que la lista esté al día), luego refrescar() (deck_list + tag_list en paralelo), luego deck_details { ids: [] } para todos los mazos. contando es true mientras se calculan los detalles, así la lista aparece de inmediato y los colores/precios se rellenan después.
  • refrescar(): solo la lista y las etiquetas.
  • etiquetar, crearEtiqueta, editarEtiqueta, borrarEtiqueta, favorito, idioma, notas, portada: llaman a Rust y luego a refrescar() (los detalles no se recalculan, porque ninguna de estas acciones los cambia).

LibraryScreen llama a cargar() al montarse. Crear, duplicar, importar y borrar mazos llaman a recargar() (un cargar completo). Como la llamada de detalles se hace una sola vez para todo, un mazo cuyos detalles aún no han llegado se trata en todas partes: nunca pasa un filtro que necesite detalles, va el último al ordenar por columnas de detalle y se agrupa bajo «Sin datos» / «Calculando…».

Preferencias (preferencias.ts)

usePrefsBiblioteca persiste en localStorage con la clave proxybuilder.biblioteca (lecturas y escrituras envueltas en try/catch): vista (cuadricula | lista), orden, ascendente, agrupar, tamano (s | m | l), lateral (barra lateral visible), favoritosArriba (por defecto true). useFiltrosBiblioteca guarda los filtros y no se persiste: cada visita empieza sin filtros. ascendentePorDefecto(orden) elige la dirección natural (ascendente para nombre, colores, coste; descendente para el resto).

Una barra, dos pantallas. El selector de decks de la pestaña Jugar reutiliza la barra de herramientas de la Biblioteca, la barra lateral de etiquetas, los filtros, la ordenación, la agrupación y las vistas de cuadrícula y lista. Las piezas no nombran un store: leen la pareja de stores de OrganizadorContexto con usePrefs, usePrefsSel y useFiltros (por defecto, los de la Biblioteca). EntradaMesa se envuelve en ORGANIZADOR_JUGAR, cuyos stores (usePrefsJugar, clave proxybuilder.jugar, y useFiltrosJugar) son aparte: cada pantalla recuerda su vista, orden y agrupación, y un filtro puesto en una no esconde decks en la otra. Los datos (useBiblioteca: decks, detalles, etiquetas) son los mismos. Las anclas del tutorial (biblioteca-barra…) salen de useAncla, que no devuelve nada si el contexto no trae ancla, así que la pestaña Jugar no las repite. Borrar una etiqueta la quita de los filtros de las dos pantallas.

Lo que cambia en la pestaña Jugar es el contexto SeleccionDecks que da: casillas: false esconde las casillas (la cuadrícula y la lista quitan la columna), pulsar elige el deck, alDobleClic empieza en solitario (solo si el clic cae sobre el deck ya elegido, no hay un trabajo en marcha y no falta una lista) y abierto es el deck elegido (con el anillo). AccionesDeck solo ofrece ahí Abrir (en la pestaña Deck), Propiedades y los submenús de etiquetas, idioma y favorito: en Acciones, renombrar, duplicar, exportar y borrar son opcionales y menu-deck.tsx esconde las entradas cuya acción falta.

Filtrar, ordenar y agrupar (organizar.ts)

Todas son funciones puras; la pantalla solo las llama dentro de useMemo.

filtrar(decks, detalles, etiquetas, filtros):

  • Texto: las palabras se normalizan (normalizar: NFD, se quitan los diacríticos, minúsculas) y todas deben aparecer en un pajar formado por el nombre, el nombre de la carta de portada, las notas, los nombres de las etiquetas y cardNames.
  • Etiquetas: todasLasEtiquetas elige entre «tiene todas» y «tiene alguna» para las etiquetas seleccionadas; sinEtiqueta; favoritos.
  • Los filtros del panel (colores, clase, formato, idioma, «con diseños», «con imágenes propias») requieren los detalles del mazo; sin ellos el mazo queda excluido.
  • Los colores tienen tres modos (ModoColor): incluye (tiene todos los colores elegidos; con C exige además incoloro), exacto (exactamente esos), dentro (no usa ningún color fuera de ellos: «se puede jugar con estos»).
  • El idioma usa idiomasDe(deck, details): gana el langOverride manual; si no, los langs calculados.

ordenar(decks, detalles, orden, ascendente, favoritosArriba): ordena por modificado, creado, abierto, nombre, cartas, precio (EUR, si no USD), coste (null si el mazo no tiene cartas conocidas que no sean tierras), colores (claveColores: primero los de menos colores, luego la posición en WUBRG). Los mazos que carecen del valor van los últimos sea cual sea la dirección; los empates recurren al nombre normalizado. Con favoritosArriba, los favoritos van primero sea cual sea la ordenación.

agrupar(decks, detalles, etiquetas, por) devuelve Grupo[] (id, clave: ClaveGrupo, decks). Agrupaciones: ninguna, etiqueta (un mazo con varias etiquetas aparece en cada grupo, y luego en «Sin etiqueta»), colores, clase (commander, constructed, limited) e idioma (el idioma manual no necesita detalles). Los grupos sin datos o sin idioma van los últimos. La pantalla convierte ClaveGrupo en un título (TituloGrupo) y deja plegar los grupos.

Selección: seleccionar(actual, visibles, id, ancla, modo) implementa Ctrl-alternar y Shift-rango sobre el orden en pantalla (enPantalla, que excluye los grupos plegados); contar(decks) da los recuentos que se muestran en la barra lateral.

Comportamiento de la interfaz

  • Abrir un mazo: pulsar una tarjeta/fila lo abre (abrirDeck(id) de src/stores/deck-store.ts guarda primero el mazo actual, llama a deck_open, guarda last_deck_id y luego useUi.setVista("deck")). Con cualquier selección activa, un clic alterna la selección en su lugar (se abre desde el menú, o con doble clic en la vista de lista).
  • Selección y teclado (un manejador de keydown en window, ignorado dentro de diálogos, menús y campos de texto): Ctrl+F enfoca la búsqueda, Ctrl+A selecciona todo lo visible, Esc borra el texto de búsqueda o la selección, Supr pide borrar la selección.
  • Menú compartido (menu-deck.tsx): un único componente Items se renderiza contra dos conjuntos de primitivas (DESPLEGABLE para el desplegable ..., CONTEXTUAL para el clic derecho), así que ambos menús son idénticos. Si el mazo pulsado forma parte de una selección múltiple, las acciones (favorito, etiquetas, idioma, borrar) se aplican a todos los mazos seleccionados (ids); las acciones de un solo mazo (abrir, propiedades, renombrar, duplicar, exportar .pbdeck) se ocultan cuando hay varios seleccionados. Las etiquetas son elementos con casilla que muestran un estado indeterminado cuando solo algunos de los mazos seleccionados tienen la etiqueta, y mantienen el menú abierto (preventDefault) para poder alternar varias.
  • Barra lateral de etiquetas (barra-lateral.tsx): «Todos los decks», «Favoritos», «Sin etiqueta» y cada etiqueta con su recuento; un clic filtra, Ctrl+clic elige varias; cada etiqueta tiene un menú para editar el color/nombre o borrarla. Crear un mazo nuevo con exactamente un filtro de etiqueta activo le da esa etiqueta al mazo.
  • Diálogo de etiqueta (etiqueta-dialog.tsx): crear una etiqueta con un nombre que ya existe simplemente aplica la existente a los mazos seleccionados; renombrar sobre el nombre de otra etiqueta está bloqueado (bloqueada).
  • Diálogo de propiedades (propiedades-dialog.tsx): nombre, etiquetas, notas y portada. Carga las cartas mediante deck_peek y ofrece una carta por cada imagen frontal distinta como opción de portada; al guardar solo llama a los comandos cuyo valor cambió (deck_rename, deck_notes_set, deck_cover_set; elegir la primera carta guarda null). También muestra el resumen construido a partir de DeckDetails (clase, colores, tierras, coste medio, precio estimado, idiomas, imágenes propias/vinculadas, diseñadas/listas, doble cara, fechas).
  • Pestaña de partidas (partidas-deck.tsx, dentro del diálogo de propiedades): el historial de ese deck a partir de partidas_de_deck (fase H): partidas, victorias y porcentaje, y una fila por partida con el resultado («Victoria» o el puesto), los nombres de los otros asientos como rivales («En solitario» si no hay), rondas, duración y fecha; «Ver repetición» abre la repetición de esa partida (solo si tiene registro) y un botón borra la partida tras confirmar. Detalles en Mesa de juego.
  • Cuadrícula (vista-cuadricula.tsx): miniaturas de portada mediante urlMiniatura(d.thumbnail, PORTADA, …) (parámetros de edición neutros, 244 o 488 px según el tamaño de la tarjeta) montadas solo cuando son visibles (useVisible, con el RaizScroll del ScrollArea principal).
  • Lista (vista-lista.tsx): COLUMNAS (nombre, colores, clase, cartas, coste medio, precio, idioma, propias, modificado, abierto). La celda «propias» enseña además el número de cartas diseñadas tras un icono Pencil de lucide. queCaben(ancho) mide el ancho disponible con un ResizeObserver y descarta las columnas de menor prioridad (orden de quitar) hasta que el resto caben. Pulsar la cabecera de una columna ordenable cambia la ordenación.
  • Pie (Pie): recuento de mazos visibles («Mostrando a de b»), total de cartas y un precio total estimado (EUR si algún mazo lo tiene, si no USD).
  • Importar/exportar: «Importar .pbdeck» (deck_import_package) y «Exportar .pbdeck» por mazo (deck_export_package; diálogos de ficheros mediante src/lib/dialogos.ts).
  • Borrar: si se borra el mazo abierto, se crea y abre un mazo vacío nuevo.

.pbdeck lleva etiquetas, notas e idioma

src-tauri/src/package.rs guarda en el manifiesto una estructura Biblioteca { etiquetas: [{nombre, color}], notas, idioma? } (con #[serde(default)] en todo, de modo que los ficheros antiguos y las versiones antiguas de la app que ignoran el campo siguen funcionando). Al importar: las etiquetas se emparejan por nombre (sin distinguir mayúsculas, mediante etiquetas::create, así que una etiqueta local existente conserva su propio color) o se crean, y luego se asocian con etiquetar; las notas se restauran si no están vacías; un idioma manual desconocido para esta compilación se ignora. No se transportan: favorito, portada, fecha de apertura. Probado por las_etiquetas_y_las_notas_viajan en package.rs. El formato completo, en Formato del paquete de mazo.

Modos de fallo

Código / situación Dónde
InvalidInput + motivo tag_vacio / tag_repetido / idioma store/etiquetas.rs; la pantalla lo traduce mediante mensaje(e)
NotFound con el parámetro tag o deck tag_update, deck_notes_set, deck_cover_set
Db cualquier fallo de SQLite
Detalles sin preparar Se trata en la interfaz (véase Estado del frontend); sin error
Nombres de mazo duplicados al importar El importador añade « (importado)» al nombre

Tests

  • src/features/library/__tests__/organizar.test.ts: filtrar (texto sin distinguir acentos entre nombre/portada/notas/etiquetas/cartas, etiqueta alguna/todas, colores en los tres modos, clase, formato, idioma incluida la sobrescritura manual, diseños/propias), ordenar (fechas, nombre, precio, valores ausentes al final, favoritos primero, colores), agrupar (etiqueta, color, idioma, clase), contar, normalizar, seleccionar.
  • Rust: biblioteca.rs (cuenta_idiomas_propias_y_guarda_en_memoria), store/etiquetas.rs (crear devuelve la existente, conflictos al renombrar, etiquetado en bloque y borrado en cascada, invariantes de fecha, idioma), store/decks.rs (la_portada_elegida_y_lo_que_se_lleva_la_copia, duplicar_renombrar_y_borrar), package.rs (las_etiquetas_y_las_notas_viajan).

Por dónde empezar para ampliarlo

  • Un detalle nuevo (por ejemplo, una insignia nueva): añade el campo a DeckDetails en biblioteca.rs, rellénalo en detalles_de, ejecuta pnpm bindings, úsalo en organizar.ts / vista-lista.tsx y añade un test.
  • Un metadato nuevo por mazo (como las notas): añade una columna en una migración nueva (el siguiente número en store/db.rs), una función en store/etiquetas.rs que no toque updated_at, un comando en commands/library.rs registrado en src-tauri/src/lib.rs, una acción en store.ts, y decide si duplicate y .pbdeck deben llevarlo.
  • Un filtro nuevo: añádelo a Filtros y FILTROS_VACIOS, a filtrar, a filtrosDelPanel y al popover de barra-herramientas.tsx.

Véase también

Documentation · Documentación

Language: English · Español

Use and build · Uso y desarrollo

Architecture · Arquitectura

Data · Datos

Getting cards · Conseguir cartas

Layout, images, PDF · Maquetación, imagen y PDF

Card designer · Diseñador de cartas

Game table · Mesa de juego

Frontend · Frontend

Reference · Referencia

Clone this wiki locally