From 76f8441b4583fc069025d77145d7e28823d8f0b9 Mon Sep 17 00:00:00 2001 From: Ivan Batsulin Date: Fri, 17 Apr 2026 02:53:38 +0300 Subject: [PATCH] feat: add warning news type and Firefox performance notice (#3680) ## Description: Adds a new `warning` news type to the news banner system and uses it to display a Firefox performance notice. Changes: - Added `warning` type with red styling to `NewsBox.ts` - Added `news_box.warning` key (`"WARNING"`) to `en.json` - Added Firefox performance notice to `resources/news.json` using the new `warning` type - Added `news_box.*` dynamic key pattern to `TranslationSystem.test.ts` to fix unused key detection ## 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 ## UI change: CleanShot 2026-04-16 at 15 04
35@2x ## Please put your Discord username so you can be contacted if a bug or regression is found: fghjk_60845 --- resources/lang/en.json | 4 +++- resources/news.json | 7 +++++++ src/client/components/NewsBox.ts | 22 ++++++++++++++++------ src/core/ApiSchemas.ts | 3 ++- tests/TranslationSystem.test.ts | 1 + tests/client/components/NewsBox.test.ts | 10 +++++++--- 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index a169de7bf..3e70f89e8 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -1068,7 +1068,9 @@ "tournament": "TOURNAMENT", "tutorial": "TUTORIAL", "news": "NEWS", + "warning": "WARNING", "dismiss": "Dismiss", - "go_to_item": "Go to item {num}" + "go_to_item": "Go to item {num}", + "firefox_warning": "OpenFront.io doesn't perform well with [Firefox-based browsers](https://simple.wikipedia.org/wiki/Web_browsers_based_on_Firefox). We recommend you to use a [Chromium-based browser](https://en.wikipedia.org/wiki/Chromium_(web_browser)#Browsers_based_on_Chromium) for best performance." } } diff --git a/resources/news.json b/resources/news.json index 15a568685..71ec384b6 100644 --- a/resources/news.json +++ b/resources/news.json @@ -1,4 +1,11 @@ [ + { + "id": "firefox-performance-issues-2026", + "title": "Firefox Performance Issues", + "descriptionTranslationKey": "news_box.firefox_warning", + "url": null, + "type": "warning" + }, { "id": "clan-tournament-spring-2026", "title": "Upcoming: Spring Clan Tournament", diff --git a/src/client/components/NewsBox.ts b/src/client/components/NewsBox.ts index d43b8e59b..f9ad6e05e 100644 --- a/src/client/components/NewsBox.ts +++ b/src/client/components/NewsBox.ts @@ -1,4 +1,5 @@ import { LitElement, html, nothing } from "lit"; +import { resolveMarkdown } from "lit-markdown"; import { customElement, state } from "lit/decorators.js"; import type { NewsItem } from "../../core/ApiSchemas"; import { getNews } from "../Api"; @@ -24,16 +25,18 @@ export function getVisibleNewsItems(items: NewsItem[]): NewsItem[] { return items.filter((item) => !dismissed.has(item.id)); } -const typeLabelKeys: Record = { +const typeLabelKeys: Record = { tournament: "news_box.tournament", tutorial: "news_box.tutorial", announcement: "news_box.news", + warning: "news_box.warning", }; -const typeLabelColors: Record = { +const typeLabelColors: Record = { tournament: "bg-amber-500/20 text-amber-300", tutorial: "bg-sky-500/20 text-sky-300", announcement: "bg-emerald-500/20 text-emerald-300", + warning: "bg-red-500/20 text-red-300", }; @customElement("news-box") @@ -118,8 +121,10 @@ export class NewsBox extends LitElement { ${translateText(typeLabelKeys[item.type])}${translateText( + typeLabelKeys[item.type] ?? typeLabelKeys["announcement"], + )}
${item.url @@ -133,8 +138,13 @@ export class NewsBox extends LitElement { : html`${item.title}`} - ${item.description}${resolveMarkdown( + item.descriptionTranslationKey + ? translateText(item.descriptionTranslationKey) + : (item.description ?? ""), + )}
${this.items.length > 1 diff --git a/src/core/ApiSchemas.ts b/src/core/ApiSchemas.ts index cb968b576..568c87304 100644 --- a/src/core/ApiSchemas.ts +++ b/src/core/ApiSchemas.ts @@ -201,7 +201,8 @@ export type RankedLeaderboardResponse = z.infer< export const NewsItemSchema = z.object({ id: z.string(), title: z.string(), - description: z.string(), + description: z.string().optional(), + descriptionTranslationKey: z.string().optional(), url: z.string().nullable().optional(), type: z.enum(["tournament", "tutorial", "announcement"]).or(z.string()), }); diff --git a/tests/TranslationSystem.test.ts b/tests/TranslationSystem.test.ts index a70e13404..b0de88f7d 100644 --- a/tests/TranslationSystem.test.ts +++ b/tests/TranslationSystem.test.ts @@ -26,6 +26,7 @@ const DYNAMIC_KEY_PATTERNS: RegExp[] = [ /^territory_patterns\.color_palette\.[^.]+$/, /^build_menu\.desc\.[^.]+$/, /^unit_type\.[^.]+$/, + /^news_box\.(tournament|tutorial|news|warning|firefox_warning)$/, ]; /** diff --git a/tests/client/components/NewsBox.test.ts b/tests/client/components/NewsBox.test.ts index 6767beb7d..6c86b4649 100644 --- a/tests/client/components/NewsBox.test.ts +++ b/tests/client/components/NewsBox.test.ts @@ -67,10 +67,14 @@ describe("NewsBox", () => { expect(typeof item.id).toBe("string"); expect(item.title).toBeDefined(); expect(typeof item.title).toBe("string"); - expect(item.description).toBeDefined(); - expect(typeof item.description).toBe("string"); + const hasDescription = + item.description !== undefined || + item.descriptionTranslationKey !== undefined; + expect(hasDescription).toBe(true); expect(item.type).toBeDefined(); - expect(["tournament", "tutorial", "announcement"]).toContain(item.type); + expect(["tournament", "tutorial", "announcement", "warning"]).toContain( + item.type, + ); } });