Repository navigation
Default alt arts: one setting for the defaults, each deck keeps its own prints (Re:Builder) - #153
Merged
Merged
Conversation
… in Re:Builder The ownership service's « Global » mode rewrote every deck with the global preferences, on the site and on Board Game Arena (apply-to-deck), so a deck could not keep prints of its own. The settings page now sets default alt arts only, and a deck stores the prints it uses: - Settings (plugin ownership): one mode, « Arts alternatifs par défaut », for cards and tokens. - A player still in « Global » is switched to « par deck » on their next visit (includes/func.alt-arts.php); their decks wait for their default alt arts until Re:Builder opens them (table alt_art_pending_decks). - Re:Builder: a card added from the search takes the default alt art of its copy; « Arts alternatifs » in the search lists the alt arts the player owns after their card, added as shown; the brush of a card changes its prints for the deck; « Arts par défaut » applies the defaults to the deck; the token window shows each token large with its illustrations. Import, a copy of someone else's deck and a hero picked without « Alt arts » take the defaults. - Local stack: docker-compose.ownership.yml runs the real AlteredOwnership service, with owned alt arts, default alt arts and a deck to switch from « Global ». Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Yutsa
marked this pull request as draft
October 8, 2026 13:10
The search no longer lists the owned alt arts after their card: a card's plain print stands for all its prints, and a copy added from the search takes its default alt art. The brush changes the prints in the deck. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h or drag; a card at 0 leaves the deck board A copy left free shows its default alt art, faded, and takes it; a touched illustration goes on the first free copy, a dragged one on the copy it is dropped on; a touched copy goes back to its default (slotDefaults, slotChoices). The deck board no longer keeps a card brought to 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne pile of the deck board, copy 1 in front On by default, remembered in the browser. The brush's copy 1 is the deck's own choice: the prints the defaults do not explain come first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… is freed for the next illustration Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o that saving moves nothing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e ribbons, and what the deck uses The brush lists the card's illustrations; touching one opens a menu to make it the 1st, 2nd or 3rd choice. The choices are the player's default alt arts (ownership service) and the deck's copies take them at once. A choice the deck does not use (beyond its copies) has a dashed ribbon; the « Ce que le deck utilise » panel fans out the copies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… sentence, without the list of copies Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…te), one look for every ribbon Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rrow to « Ce que le deck utilise » on the same level Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…chevron that fits into « Ce que le deck utilise » Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…; the plain print is not an explicit choice Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… in {rebuilder_deck_alt_arts}
The brush no longer saves the player's default alt arts (ownership service): its 1st, 2nd and 3rd card are kept for
the deck by papi/rebuilder/deck-alt-arts (core migration 010, the plugin has no install SQL), as the decks API stores
only the deck's references. The deck's copies take them; an added copy takes the next card's. « Arts par défaut » in
the brush and « Appliquer les arts par défaut » drop the deck's choices.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ee cards take the plain print Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e does not move them Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t, 2nd in the middle, 3rd on the right Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…k, the menu on ac-menu - core-altered-cards: cacDeckApiDelete sends the DELETE and forgets the deck (three pages had their own copy) - altArtForgetDeck takes the player: the DELETEs use the tables' primary keys; pending decks in one INSERT - deck-alt-arts: plugin API URL and the CSRF interceptor; exactly three cards - EditorAltArts: ownDeckId, keepCards, familyCopies; the picker gets the copies from it - the brush's menu uses ac-menu; dead CSS and the unused altArtVersion removed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…too; shared illustration labels Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…very deck The site no longer switches players out of « Global » on their next visit. A player picks the mode on the default alt arts page: - « Global »: the service rewrites every deck with the defaults on BGA, as before; Re:Builder writes them in the deck when it opens and after each change, without the brush. - « Par deck »: defaults on add, the brush per deck (unchanged). Leaving « Global » writes in each deck what BGA showed of it (apply-to-deck, while still in « Global »), then sets the mode; a failure keeps « Global ». Switching to « Global » drops the brush choices. The pending-decks table and endpoint are gone; migration_010 becomes 009. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Every deck of the player is written when leaving « Global » (the decks are read 1000 a page), and the four parallel writes no longer wait on the session lock. - One apply-to-deck helper (altArtApplyToDeck) for leaving « Global » and the site's deck builder (cacApplyAltArtPreferencesToCards wraps it). - A deck written on leaving « Global » drops its brush choices there, instead of every deck's on entering « Global ». - The mode endpoint relies on the router (methods, sign-in, CSRF); the page sends the token once and maps each failed step to its message. - Re:Builder asks the mode only when signed in, and the families of the deck stay equal while search results add others. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ns and a menu Each illustration has a 1st, 2nd and 3rd card key: pressed down and filled when that card takes the illustration, raised and faded otherwise. Pressing a raised key gives the illustration that card; a key the copies owned rule out is disabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bove each illustration The keys of the Re:Builder brush become a design system component (ac-keys / ac-key), used by the brush and by the « Arts alternatifs par défaut » page. Each card of that page is a row: its name, type, faction and rarity, what decks take (its cards fanned out, as in the brush), then its illustrations under their keys. The marker flags are gone; the card modals that embed the same widget get the keys too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Re:Builder brush: a pressed key is never disabled (it stayed faded when the copies owned no longer covered the deck's choice). - Token key named by its text (« Choisir » / « Choisie »). - The fan of the default alt arts page is an image named after what each card takes. - One CDN URL helper (the widget's), fan images made once. - e2e: a refused choice puts the keys and the fan back and shows why. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… on a phone Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without a type filter the mock only searched tokens, so the default alt arts page of the local stack showed no character, spell or permanent. It now reads the Common and Rare card groups (Uniques have no alt art) 200 at a time and counts skip / take in families, as AlteredOwnership's /api/alt-arts/search does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fan of what decks take is larger, a token's or a hero's single card much larger, and the illustrations under the keys are 200 px wide. A card of the fan or an illustration opens in core-altered-cards' card lightbox, as on the cards pages (tilt, « Accéder au détail »), without its alt-art widget since the keys of the page already choose. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… and faded A key that was off and a disabled key looked alike (60 % and 30 % opacity). A key that can be pressed now has its text in --ac-color-text-2 and a darker bottom edge at full opacity; a disabled key loses its edge and fill, in --ac-color-text-disabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e right As in Re:Builder's brush (step 1 the illustrations, step 2 « Ce que le deck utilise »): the card's name on top, its illustrations and keys on the left, the fan of what decks take on a panel on the right (below the illustrations on a phone). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…decks take, centred As in Re:Builder's brush: the illustrations on a band ending in a chevron, which fits into the notch of the « what decks take » panel, its fan centred vertically; on a phone the panel goes under the band, the chevron pointing down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s sideways A family with many prints (heroes have up to 5) made rows over 1000 px tall, the fan of what decks take far from the first keys. The illustrations now stay on one line that scrolls sideways, snapping to each print, with an arrow on each side while there is more that way; on a phone two prints and the edge of the next are in view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While a card's line of illustrations has more on one side, a mask fades the cut illustration out on that side (10 % of the line, 96 px at most). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GET /api/decks sends every deck whatever the page: an account of 1000 decks or more got the same list again and again, until the decks API ran out of memory and the switch to « par deck » failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The service fills each line from the family's 1st card: a deck with the alt art on one line and the plain print on another (1st card alt art, 2nd and 3rd plain) got the alt art twice when leaving « Global », though only one copy is owned. The lines of a family are now sent as one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he chevron The e2e reads the player's mode instead of expecting « par deck ». Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Re:Builder conflicts: the PR's alt-art editor and deck board kept, with preprod's loading states (DeckStore.steppersShown, skeletons while the deck's owner and the alt-art mode are not known, now for « Appliquer les arts par défaut » too). The e2e createServerDeck helper takes the copies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
…ger keeps the player in « Global » Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, no layout shift at 1024 px The switch and « Arts par défaut » come with the deck's owner: at 1024 px the row wrapped then, and the board moved 44 px down (CLS 0.043). Their skeletons, at their widths, make the row wrap before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Yutsa
marked this pull request as ready for review
October 22, 2026 11:56
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.

Why
Players choose their alt arts in the ownership service (AlteredOwnership), in one of two modes:
AltArtService.ApplyToDeckAsync). A deck cannot keep prints of its own.Players want to set their alt arts once, as defaults, and still change them deck by deck. Players in « Global » must keep what they see on BGA until they choose otherwise.
How
The two modes
The two modes stay. The preferences keep their storage in the service (
slotReferences), and the mode only changes from the settings page, after a confirmation.In « Global », Re:Builder writes the defaults in the deck when it opens and after each change, so the site's list matches what BGA plays. Preprod already did this; the PR now also falls back to the base art past the owned copies, as the service does.
Switching modes
api/alt-art-leave-global.php,includes/func.alt-arts.php): the page lists the player's decks and writes in each one what BGA showed of it (altArtApplyToDeck, while still in « Global »), four at a time with a progress bar. Then it sets the mode.Re:Builder
The logic is in
core/alt-art-defaults.ts(pure, unit tested) andfeatures/editor/editor-alt-arts.ts.features/editor/alt-art-picker/) chooses the illustration of the 1st, 2nd and 3rd card of a card, for this deck only.rebuilder_deck_alt_arts(sql/migration_009, endpointpapi/rebuilder/deck-alt-arts).api/v1/services/proxy.php) or the site's deck pages (cacDeckApiDelete).localStorage): a card's prints share one pile, copy 1 in front.applyAltArtSlots) andalt-art-slots.Settings page « Arts alternatifs par défaut »
Files:
plugins/ownership/pages/alt-arts.php,js/alt-arts.js,js/alt-art-widget.js.Keys, a design system component
ac-keys/ac-key(design-system/css/components/key.css,docs/components/key.md,/pages/design-system): raised when off, pressed and filled when on. Used by the brush and by the settings page.Not changed
The legacy deck builder (no defaults when a card is added in « par deck »),
altered.json, the decks API.Release
One new table (
migration_009,CREATE TABLE IF NOT EXISTS), applied by the deploy's « Bootstrap & migrate DB » step. No data to migrate, and no change for players in « Global ».Local stack
docker-compose.ownership.ymlruns the real AlteredOwnership (pinned commit) with Postgres and Redis.docker/stack/ownership-real/seeds owned alt arts, defaults, alice in « Global » and two demo decks. CI keeps the mock, which now numbers slots from 1 and lists every card type in the alt-art search, as the service does.Files to review first
includes/func.alt-arts.php,plugins/ownership/api/alt-art-leave-global.php,plugins/ownership/pages/alt-arts.phpplugins/rebuilder/papi/deck-alt-arts.phpplugins/rebuilder/app/src/app/core/alt-art-defaults.ts,features/editor/editor-alt-arts.ts,features/editor/alt-art-picker/design-system/css/components/key.css,plugins/ownership/js/alt-art-widget.jsOutcomes
The settings page screenshots come from the local stack with the real ownership service: bob is in « par deck », alice in « Global ». The Re:Builder screenshots come from the e2e scenarios (ownership mock).
Settings page, « par deck »: the mode and what it does, above the search.
The defaults: one row per card. Keys above each illustration on the left, what a card added to a deck takes on the right.
Keys and owned copies: Fée Clochette's MUSUBI print is owned once, so its 2nd and 3rd card keys are disabled. Scarabot, a token, has one key per illustration.
A card large: a card of the fan or an illustration opens in the cards pages' lightbox.
To « Global »: the illustrations chosen deck by deck will be replaced.
« Global »: the defaults apply to every deck, on the site and on BGA.
Back to « par deck »: the defaults are written in every deck first (best effort).
Adding a card in Re:Builder: Élémentaire de Kélon, once in the search, takes the default alt art of each copy.
The brush: Élémentaire de Kélon, 2 copies. The 1st card's key is pressed on the alt art, the 2nd and 3rd on the plain print, and the deck uses the 1st and 2nd cards.
Keys of the brush: the alt art is on the 1st and 3rd cards. Its 2 owned copies are used, so its 2nd card key is disabled.
« Arts par défaut »: applied to the whole deck after a confirmation.
« Illustrations des jetons »: one illustration per token, for every deck.
Tests
npm run lint(ESLint, i18n all translated),npm test(57 files, 367 tests, includingalt-art-defaults.spec.tsandeditor-alt-arts.spec.ts),npm run buildphp tests/run.php: 116 passedapply-to-deckshowed, then the mode is « par deck »;plugins/ownership/e2e/alt-arts.spec.ts): a key gives an illustration to a card and saves it, the fan follows, the owned copies disable keys, a token's key; a refused choice (409) puts the keys and the fan back and shows why;docker-compose.ownership.yml, README § Full stack)🤖 Generated with Claude Code