From cbecfac9813ebcd3f5c6df798d4dbc34934acff7 Mon Sep 17 00:00:00 2001 From: Guillaume Quarmeau Date: Mon, 2 Jun 2025 20:39:16 +0200 Subject: [PATCH] Added support for dark mode icons for Alliance Request Icon and Embargo Icon (#993) ## Description: Alliance Request and Embargo icons now switch from white to black according to whether dark mode is enabled. ![Screenshot 2025-06-01 120058](https://github.com/user-attachments/assets/ccc97b7b-088c-4294-953b-63fdfb0c354e) *Dark mode off* ![Screenshot 2025-06-01 120011](https://github.com/user-attachments/assets/1ff3f9bb-c01e-4c49-b03b-97851914af1b) *Dark mode on* ## Potential issue: The only caveat is that upon changing the theme when both icons are displayed, the display order is not conserved, so they may appear in a different order than before. This seems however to be a very small use case, and rather insignificant as icons don't have an order to begin with. Do let me know if this is a problem though! ## 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 understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors ## Please put your Discord username so you can be contacted if a bug or regression is found: @vermylion --- ...tIcon.svg => AllianceRequestBlackIcon.svg} | 26 +++---- resources/images/AllianceRequestWhiteIcon.svg | 14 ++++ .../{EmbargoIcon.svg => EmbargoBlackIcon.svg} | 0 resources/images/EmbargoWhiteIcon.svg | 29 ++++++++ src/client/graphics/layers/NameLayer.ts | 69 ++++++++++++++----- 5 files changed, 108 insertions(+), 30 deletions(-) rename resources/images/{AllianceRequestIcon.svg => AllianceRequestBlackIcon.svg} (98%) mode change 100755 => 100644 create mode 100644 resources/images/AllianceRequestWhiteIcon.svg rename resources/images/{EmbargoIcon.svg => EmbargoBlackIcon.svg} (100%) mode change 100755 => 100644 create mode 100644 resources/images/EmbargoWhiteIcon.svg diff --git a/resources/images/AllianceRequestIcon.svg b/resources/images/AllianceRequestBlackIcon.svg old mode 100755 new mode 100644 similarity index 98% rename from resources/images/AllianceRequestIcon.svg rename to resources/images/AllianceRequestBlackIcon.svg index f5981e241..5fa1e9e31 --- a/resources/images/AllianceRequestIcon.svg +++ b/resources/images/AllianceRequestBlackIcon.svg @@ -1,14 +1,14 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/resources/images/AllianceRequestWhiteIcon.svg b/resources/images/AllianceRequestWhiteIcon.svg new file mode 100644 index 000000000..c34774dd4 --- /dev/null +++ b/resources/images/AllianceRequestWhiteIcon.svg @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/resources/images/EmbargoIcon.svg b/resources/images/EmbargoBlackIcon.svg old mode 100755 new mode 100644 similarity index 100% rename from resources/images/EmbargoIcon.svg rename to resources/images/EmbargoBlackIcon.svg diff --git a/resources/images/EmbargoWhiteIcon.svg b/resources/images/EmbargoWhiteIcon.svg new file mode 100644 index 000000000..c5a966b73 --- /dev/null +++ b/resources/images/EmbargoWhiteIcon.svg @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/src/client/graphics/layers/NameLayer.ts b/src/client/graphics/layers/NameLayer.ts index 741b095d2..53f39dbc8 100644 --- a/src/client/graphics/layers/NameLayer.ts +++ b/src/client/graphics/layers/NameLayer.ts @@ -1,7 +1,9 @@ import allianceIcon from "../../../../resources/images/AllianceIcon.svg"; -import allianceRequestIcon from "../../../../resources/images/AllianceRequestIcon.svg"; +import allianceRequestBlackIcon from "../../../../resources/images/AllianceRequestBlackIcon.svg"; +import allianceRequestWhiteIcon from "../../../../resources/images/AllianceRequestWhiteIcon.svg"; import crownIcon from "../../../../resources/images/CrownIcon.svg"; -import embargoIcon from "../../../../resources/images/EmbargoIcon.svg"; +import embargoBlackIcon from "../../../../resources/images/EmbargoBlackIcon.svg"; +import embargoWhiteIcon from "../../../../resources/images/EmbargoWhiteIcon.svg"; import nukeRedIcon from "../../../../resources/images/NukeIconRed.svg"; import nukeWhiteIcon from "../../../../resources/images/NukeIconWhite.svg"; import shieldIcon from "../../../../resources/images/ShieldIconBlack.svg"; @@ -11,6 +13,7 @@ import { PseudoRandom } from "../../../core/PseudoRandom"; import { Theme } from "../../../core/configuration/Config"; import { AllPlayers, Cell, nukeTypes, UnitType } from "../../../core/game/Game"; import { GameView, PlayerView } from "../../../core/game/GameView"; +import { UserSettings } from "../../../core/game/UserSettings"; import { createCanvas, renderNumber, renderTroops } from "../../Utils"; import { TransformHandler } from "../TransformHandler"; import { Layer } from "./Layer"; @@ -37,17 +40,20 @@ export class NameLayer implements Layer { private renders: RenderInfo[] = []; private seenPlayers: Set = new Set(); private traitorIconImage: HTMLImageElement; - private allianceRequestIconImage: HTMLImageElement; + private allianceRequestBlackIconImage: HTMLImageElement; + private allianceRequestWhiteIconImage: HTMLImageElement; private allianceIconImage: HTMLImageElement; private targetIconImage: HTMLImageElement; private crownIconImage: HTMLImageElement; - private embargoIconImage: HTMLImageElement; + private embargoBlackIconImage: HTMLImageElement; + private embargoWhiteIconImage: HTMLImageElement; private nukeWhiteIconImage: HTMLImageElement; private nukeRedIconImage: HTMLImageElement; private shieldIconImage: HTMLImageElement; private container: HTMLDivElement; private firstPlace: PlayerView | null = null; private theme: Theme = this.game.config().theme(); + private userSettings: UserSettings = new UserSettings(); constructor( private game: GameView, @@ -57,14 +63,18 @@ export class NameLayer implements Layer { this.traitorIconImage.src = traitorIcon; this.allianceIconImage = new Image(); this.allianceIconImage.src = allianceIcon; - this.allianceRequestIconImage = new Image(); - this.allianceRequestIconImage.src = allianceRequestIcon; + this.allianceRequestBlackIconImage = new Image(); + this.allianceRequestBlackIconImage.src = allianceRequestBlackIcon; + this.allianceRequestWhiteIconImage = new Image(); + this.allianceRequestWhiteIconImage.src = allianceRequestWhiteIcon; this.crownIconImage = new Image(); this.crownIconImage.src = crownIcon; this.targetIconImage = new Image(); this.targetIconImage.src = targetIcon; - this.embargoIconImage = new Image(); - this.embargoIconImage.src = embargoIcon; + this.embargoBlackIconImage = new Image(); + this.embargoBlackIconImage.src = embargoBlackIcon; + this.embargoWhiteIconImage = new Image(); + this.embargoWhiteIconImage.src = embargoWhiteIcon; this.nukeWhiteIconImage = new Image(); this.nukeWhiteIconImage.src = nukeWhiteIcon; this.nukeRedIconImage = new Image(); @@ -322,6 +332,7 @@ export class NameLayer implements Layer { ) as HTMLDivElement; const iconSize = Math.min(render.fontSize * 1.5, 48); const myPlayer = this.game.myPlayer(); + const isDarkMode = this.userSettings.darkMode(); // Crown icon const existingCrown = iconsDiv.querySelector('[data-icon="crown"]'); @@ -373,13 +384,27 @@ export class NameLayer implements Layer { } // Alliance request icon - const data = '[data-icon="alliance-request"]'; - const existingRequestAlliance = iconsDiv.querySelector(data); + let existingRequestAlliance = iconsDiv.querySelector( + '[data-icon="alliance-request"]', + ); + const isThemeAllianceRequestIcon = + existingRequestAlliance?.getAttribute("dark-mode") === + isDarkMode.toString(); + const AllianceRequestIconImageSrc = isDarkMode + ? this.allianceRequestWhiteIconImage.src + : this.allianceRequestBlackIconImage.src; + if (myPlayer !== null && render.player.isRequestingAllianceWith(myPlayer)) { + // Create new icon to match theme + if (existingRequestAlliance && !isThemeAllianceRequestIcon) { + existingRequestAlliance.remove(); + existingRequestAlliance = null; + } + if (!existingRequestAlliance) { iconsDiv.appendChild( this.createIconElement( - this.allianceRequestIconImage.src, + AllianceRequestIconImageSrc, iconSize, "alliance-request", ), @@ -434,19 +459,28 @@ export class NameLayer implements Layer { existingEmoji.remove(); } - const existingEmbargo = iconsDiv.querySelector('[data-icon="embargo"]'); + // Embargo icon + let existingEmbargo = iconsDiv.querySelector('[data-icon="embargo"]'); const hasEmbargo = myPlayer && (render.player.hasEmbargoAgainst(myPlayer) || myPlayer.hasEmbargoAgainst(render.player)); + const isThemeEmbargoIcon = + existingEmbargo?.getAttribute("dark-mode") === isDarkMode.toString(); + const embargoIconImageSrc = isDarkMode + ? this.embargoWhiteIconImage.src + : this.embargoBlackIconImage.src; + if (myPlayer && hasEmbargo) { + // Create new icon to match theme + if (existingEmbargo && !isThemeEmbargoIcon) { + existingEmbargo.remove(); + existingEmbargo = null; + } + if (!existingEmbargo) { iconsDiv.appendChild( - this.createIconElement( - this.embargoIconImage.src, - iconSize, - "embargo", - ), + this.createIconElement(embargoIconImageSrc, iconSize, "embargo"), ); } } else if (existingEmbargo) { @@ -520,6 +554,7 @@ export class NameLayer implements Layer { icon.style.width = `${size}px`; icon.style.height = `${size}px`; icon.setAttribute("data-icon", id); + icon.setAttribute("dark-mode", this.userSettings.darkMode().toString()); if (center) { icon.style.position = "absolute"; icon.style.top = "50%";