Skip to content

v0.27.0

2026-05-20

Module API

  • [x] ArtworkSourceProps.layerId — Forwarded the active map layer ID (e.g. 'background', 'objects', 'tokens') from TokenArtworkEditor through to module-provided artwork source components. Lets modules adapt behaviour per layer without re-deriving context. Specifically requested by genai v0.5.0 Map Mode, which defaults its "top-down orthographic battlemap" prompt prefix to on for the Background layer. Backwards-compatible: existing sources that don't read the prop are unaffected.

Misc

  • [x] On a map with an invalid drawing, multiple issues exist:
    • 1: some sort of error boundary should catch the error and simply not render the broken drawing, instead of crashing the whole map — already implemented in WebGLDrawingLayer via DrawingErrorBoundary
    • 2: TokenDebugModal caught the error. But this modal wasn't open, so it shouldn't be rendering. Fixed: added early return in TokenDebugModal when opened=false to skip row computation entirely (Mantine portals render children even for closed modals).
  • [x] Sort the options in the right-click context menu on the map alphabetically
  • [x] In the right-click context menu on the map, add an option to "Add Background". This works the same way as the same option in the + menu in the palette.
  • [x] When you press cmd-A on the map (not focused on any text fields), select all tokens on the current layer.
  • [x] Bug: in targeting mode, the first time you hover over a token that could potentially be a target, the whole map turns black for a moment. If you hover off then on again, it doesn't recur. Fixed: wrapped TargetingOverlay in React.Suspense — DreiText suspends on first font load, and without a Suspense boundary the suspension bubbled up to the canvas boundary causing the black flash.
  • [x] Increase the width of the Source Image Editor by 100%; as it's too cramped currently.
  • [x] Bug: if user drags and drops a large image (say 4000x4000) onto the background layer, the background token looks as expected, with LOD generated and high-resolution when zoomed. If they use 'Add Background' or 'Add Token' (then switch to Background layer), then provide the same image (upload, google, doesn't seem to make a difference), the token is created without LOD and is low resolution. Fixed: ImageDropZone in TokenArtworkEditor was hardcoded to category="token" (512px max), so any image dropped there was downscaled before upload. Changed to derive category from layerId: 'token' for the tokens layer, 'mapObject' (4096px max) for all other layers.
  • [x] Bug: in the Character Edit page (/characters/:id), in the Artwork editor, the tokenized image thumbnail is never tokenized, regardless of whether the user chose 'tokenize' or 'unchanged'. It always shows the unchanged image. When importing that character into a map, the token on the map and the thumbnail in the character edit page are correct. Fixed: CharacterDetail now generates client-side canvas previews via applyTransformToCanvas for artworks with mapAppearance: 'tokenized' and passes them as processedUrl to CharacterSheet/CharacterArtworkPanel. The preview is also stored immediately when auto-tokenization runs (on handleSetTokenArtworkId).
  • [x] In the Admin / Systems page, the Reload button doesn't refresh the feat/power/equipment lists in the Character Sheet. It should fetch the latest JSON from the server and update the Character Sheet's dropdowns accordingly. Fixed: after a successful reload, AdminSystems calls clearSystemCache() (new export from useCharacters) and clearFeatCache() (existing export from @purple-cat/shared), then dispatches a vtt-system-reloaded window event. CharacterDetail listens for this event and increments a systemRefreshKey that causes the load-data and load-feats effects to re-run with fresh data.
  • [x] Left align the text in the Changelog (in Help/About)
  • [x] Bug: Add Background > genAI > prompt to make a map > image is created > close Source Artwork Editor.
    • Expected: source art has been created and assigned as token art, using 'unchanged' instead of 'tokenized'
    • Observed: source art has been created, no token art assigned.
    • Fixed in v0.27.0: handleArtworksChange in TokenModal only auto-set tokenArtworkId for the tokens layer, leaving background-layer art orphaned. Extended the auto-assign branch to background/objects layers (without portrait duplication) and persist tokenArtworkId immediately via patchToken so it survives modal close/reopen. Background-layer artwork is also coerced to artworkType: 'token-art' with mapAppearance: 'original'.
  • [x] Bug: User drags image of a map onto the background layer. As expected, the Edit Token modal appears with that source art. However, the token image is set to 'tokenized'. Background tokens should always default to 'unchanged'.
    • Fixed in v0.27.0: migrateTokenToArtworks now accepts an optional layerId and defaults mapAppearance to 'original' when layerId === 'background'. TokenArtworkEditor.updateArtworkInArray (newArtwork branch) applies the same layer-aware default. Drag-dropped maps now arrive in the modal as Unchanged.
  • [x] Bug: User creates a background token (any means of providing the image, it's all the same), closes the token modal, and observes the background token is now rendered. They immediately click 'edit token' to reopened the Edit Token modal, whereupon they observe the source art thumbnail and token thumbnail are blank white squares. Source art thumbnail has a ? in it, token thumbnail does not.
    • Further actions: click the pencil icon to open the Source Image Editor again. It says "no source image yet".
    • Further actions: click the pencil icon to open the Token Artwork Editor. It says "no artwork selected".
    • Fixed in v0.27.0: same root cause as Bug 1 — when tokenArtworkId was never set, on reopen the modal could not find the primary art (the artwork persisted with artworkType: 'other' rather than 'token-art'), so getPrimaryTokenArt returned undefined and thumbnails went blank. Fixing the auto-assign + artworkType coercion in handleArtworksChange resolves this downstream.
    • Re-fixed in v0.27.0 (second pass — first attempt was insufficient): the artwork's artworkType and tokenArtworkId round-tripped correctly to the server, but the artwork's imageUrl was being persisted as an empty string. Root cause was in TokenModal.handleSubmit: when useOriginalImage === true (always for background tokens), the upload step uploads the original-source URL to S3 and sets finalImageUrl, but finalOriginalImageUrl was never updated from its blob:/data: source. The active-artwork stamping at line ~869 then wrote imageUrl: finalOriginalImageUrl (still blob:), and the strip step at line ~1013 nuked all blob:/data: URLs to ''. Fix: when useOriginalImage is true, mirror the just-uploaded finalImageUrl onto finalOriginalImageUrl.

Map and Character Lists

  • [x] Add more Sort options to the existing Sort dropdown in the Map and Character lists. Specifically:
    • Name A-Z
    • Name Z-A
    • Recently Created
    • Oldest Created
    • Recently Updated
    • Oldest Updated
    • (if we aren't tracking last updated time, add that to the schema and track it)
  • [x] Remove "Campaign" sort option on /campaigns/:id as every map on that page belongs to the same campaign.
  • [x] When you make a new map from the campaign page, it should automatically open that map in the /play route. With lots of maps, it gets hard to find the new map, and there are sort options that make the new map invisible after creation. This should fix that.

Top-Level Nav

  • [x] Partial rollback of recent redesign. To wit:
    • Narrow (label-free) top-level nav is once again always visible. Adjust left position of sidebars in map accordingly.
    • Mousing over any part of the top nav auto-expands the full width nav. Moving the mouse away collapses it back to the narrow version.
    • Fix bug where the purple cat icon wobbles on mouseover. It should never move in any case.