fix territory modal performance (#1600)

## Description:

The territory patterns modal was listening for keypresses, and would
regenerate all patterns on each render().

So do:
1. Cache territory patterns to prevent regeneration
2. disable handler on close

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I have read and accepted the CLA agreement (only required once).

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
This commit is contained in:
evanpelle
2025-07-28 13:08:07 -07:00
committed by GitHub
parent 1db9b93950
commit bf13c65657
+20 -8
View File
@@ -37,6 +37,8 @@ export class TerritoryPatternsModal extends LitElement {
private userSettings: UserSettings = new UserSettings(); private userSettings: UserSettings = new UserSettings();
private isActive = false;
constructor() { constructor() {
super(); super();
} }
@@ -44,7 +46,6 @@ export class TerritoryPatternsModal extends LitElement {
connectedCallback() { connectedCallback() {
super.connectedCallback(); super.connectedCallback();
this.selectedPattern = this.userSettings.getSelectedPattern(); this.selectedPattern = this.userSettings.getSelectedPattern();
window.addEventListener("keydown", this.handleKeyDown);
this.updateComplete.then(() => { this.updateComplete.then(() => {
const containers = this.renderRoot.querySelectorAll(".preview-container"); const containers = this.renderRoot.querySelectorAll(".preview-container");
if (this.resizeObserver) { if (this.resizeObserver) {
@@ -54,12 +55,11 @@ export class TerritoryPatternsModal extends LitElement {
} }
this.updatePreview(); this.updatePreview();
}); });
this.open();
} }
disconnectedCallback() { disconnectedCallback() {
super.disconnectedCallback(); super.disconnectedCallback();
window.removeEventListener("keydown", this.handleKeyDown);
this.resizeObserver.disconnect();
} }
async onUserMe(userMeResponse: UserMeResponse | null) { async onUserMe(userMeResponse: UserMeResponse | null) {
@@ -220,6 +220,7 @@ export class TerritoryPatternsModal extends LitElement {
} }
render() { render() {
if (!this.isActive) return html``;
return html` return html`
${this.renderTooltip()} ${this.renderTooltip()}
<o-modal <o-modal
@@ -233,10 +234,15 @@ export class TerritoryPatternsModal extends LitElement {
public open() { public open() {
this.modalEl?.open(); this.modalEl?.open();
window.addEventListener("keydown", this.handleKeyDown);
this.isActive = true;
} }
public close() { public close() {
this.modalEl?.close(); this.modalEl?.close();
window.removeEventListener("keydown", this.handleKeyDown);
this.resizeObserver?.disconnect();
this.isActive = false;
} }
private selectPattern(pattern: string | undefined) { private selectPattern(pattern: string | undefined) {
@@ -336,6 +342,7 @@ export class TerritoryPatternsModal extends LitElement {
} }
} }
const patternCache = new Map<string, string>();
const DEFAULT_PATTERN_B64 = "AAAAAA"; // Empty 2x2 pattern const DEFAULT_PATTERN_B64 = "AAAAAA"; // Empty 2x2 pattern
const COLOR_SET = [0, 0, 0, 255]; // Black const COLOR_SET = [0, 0, 0, 255]; // Black
const COLOR_UNSET = [255, 255, 255, 255]; // White const COLOR_UNSET = [255, 255, 255, 255]; // White
@@ -344,11 +351,14 @@ export function generatePreviewDataUrl(
width?: number, width?: number,
height?: number, height?: number,
): string { ): string {
pattern ??= DEFAULT_PATTERN_B64;
if (patternCache.has(pattern)) {
return patternCache.get(pattern)!;
}
// Calculate canvas size // Calculate canvas size
const decoder = new PatternDecoder( const decoder = new PatternDecoder(pattern, base64url.decode);
pattern ?? DEFAULT_PATTERN_B64,
base64url.decode,
);
const scaledWidth = decoder.scaledWidth(); const scaledWidth = decoder.scaledWidth();
const scaledHeight = decoder.scaledHeight(); const scaledHeight = decoder.scaledHeight();
@@ -384,5 +394,7 @@ export function generatePreviewDataUrl(
// Create a data URL // Create a data URL
ctx.putImageData(imageData, 0, 0); ctx.putImageData(imageData, 0, 0);
return canvas.toDataURL("image/png"); const dataUrl = canvas.toDataURL("image/png");
patternCache.set(pattern, dataUrl);
return dataUrl;
} }