Phase 2: character portraits → token icons (local + realtime)
- character.portrait + mapToken.image (data URLs, Dexie v10, additive). - src/lib/img/resize.ts: center-crop + downscale helper (160px tokens / 256px portraits) keeping IndexedDB + wire payloads small. - Portrait uploader on the character sheet; token icon uploader in the map token modal (falls back to the linked character's portrait). Palette PC entries show the portrait thumbnail. - Tokens render the image clipped to the circle (HP ring + condition badge on top). - Realtime: generalized the image channel to many images (map bg + token/portrait icons), deduped by content and resent on reconnect. Player tokens/party carry an imageId resolved from the session image cache; party panel shows portraits. - Also: fix the encounter-picker dropdown text being clipped (drop fixed height). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -88,6 +88,26 @@ test('maps: place a token from a planned encounter via the palette', async ({ pa
|
||||
await expect(page.getByTestId('map-token')).toContainText('Bandit');
|
||||
});
|
||||
|
||||
test('maps: a character portrait becomes the token icon', async ({ page }) => {
|
||||
await page.getByRole('button', { name: '+ New campaign' }).first().click();
|
||||
await page.locator('input[data-autofocus]').fill('Art');
|
||||
await page.getByRole('button', { name: 'Create' }).click();
|
||||
|
||||
await page.getByRole('link', { name: 'Characters' }).click();
|
||||
await createCharacter(page, 'Aria');
|
||||
// Upload a portrait on the sheet; it renders in the header avatar.
|
||||
await page.getByLabel('Portrait').setInputFiles('public/pwa-512x512.png');
|
||||
await expect(page.locator('label img').first()).toBeVisible();
|
||||
|
||||
await page.getByRole('link', { name: 'Dashboard' }).click();
|
||||
await page.getByRole('link', { name: 'Maps' }).click();
|
||||
await page.locator('input[type="file"]').setInputFiles('public/pwa-512x512.png');
|
||||
|
||||
// Placing the PC drops a token that shows the portrait image.
|
||||
await page.getByRole('button', { name: /Aria/ }).click();
|
||||
await expect(page.getByTestId('map-token').first().locator('img')).toBeVisible();
|
||||
});
|
||||
|
||||
test('maps: place a party token from the palette', async ({ page }) => {
|
||||
await page.getByRole('button', { name: '+ New campaign' }).first().click();
|
||||
await page.locator('input[data-autofocus]').fill('Party');
|
||||
|
||||
Reference in New Issue
Block a user