mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-07 19:06:03 +00:00
2fd8757e66
## Description: - **News notification dot (desktop + mobile)**: Added a red pinging dot on the "News" nav entry that appears when a new version is released. The current app version is saved to localStorage (`newsSeenVersion`) on first visit. On subsequent visits, if the version has changed, the dot appears. Clicking "News" dismisses it by updating the stored version. - **Mobile Store**: Replaced the static "NEW" text badge on the Store nav item with a red pinging dot (matching the desktop navbar style). The dot is conditionally shown based on cosmetics hash changes tracked in localStorage, and dismissed when the user clicks Store. - **Help dot on mobile**: Added the yellow help dot (already present on desktop) to the mobile navbar for consistency, shown for users with fewer than 10 games played. ### Screenshots: <img width="1028" height="97" alt="Screenshot 2026-02-21 174029" src="https://github.com/user-attachments/assets/1ed460dd-4e41-4287-bcb9-73f431e8a953" /> <img width="513" height="700" alt="Screenshot 2026-02-21 174333" src="https://github.com/user-attachments/assets/c6b81296-d36b-424e-9637-e738acd8007a" /> ## 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 ## Please put your Discord username so you can be contacted if a bug or regression is found: FloPinguin
92 lines
2.5 KiB
TypeScript
92 lines
2.5 KiB
TypeScript
import { ReactiveController, ReactiveControllerHost } from "lit";
|
|
import version from "resources/version.txt?raw";
|
|
import { getCosmeticsHash } from "../Cosmetics";
|
|
import { getGamesPlayed } from "../Utils";
|
|
|
|
const HELP_SEEN_KEY = "helpSeen";
|
|
const STORE_SEEN_HASH_KEY = "storeSeenHash";
|
|
const NEWS_SEEN_VERSION_KEY = "newsSeenVersion";
|
|
|
|
export class NavNotificationsController implements ReactiveController {
|
|
private host: ReactiveControllerHost;
|
|
|
|
private _helpSeen = localStorage.getItem(HELP_SEEN_KEY) === "true";
|
|
private _hasNewCosmetics = false;
|
|
private _hasNewVersion = false;
|
|
|
|
private get normalizedVersion(): string {
|
|
const trimmed = version.trim();
|
|
return trimmed.startsWith("v") ? trimmed : `v${trimmed}`;
|
|
}
|
|
|
|
constructor(host: ReactiveControllerHost) {
|
|
this.host = host;
|
|
host.addController(this);
|
|
}
|
|
|
|
hostConnected(): void {
|
|
// Check if cosmetics have changed
|
|
getCosmeticsHash()
|
|
.then((hash: string | null) => {
|
|
const seenHash = localStorage.getItem(STORE_SEEN_HASH_KEY);
|
|
this._hasNewCosmetics = hash !== null && hash !== seenHash;
|
|
this.host.requestUpdate();
|
|
})
|
|
.catch(() => {});
|
|
|
|
// Check if version has changed
|
|
const currentVersion = this.normalizedVersion;
|
|
const seenVersion = localStorage.getItem(NEWS_SEEN_VERSION_KEY);
|
|
this._hasNewVersion =
|
|
seenVersion !== null && seenVersion !== currentVersion;
|
|
if (seenVersion === null) {
|
|
localStorage.setItem(NEWS_SEEN_VERSION_KEY, currentVersion);
|
|
}
|
|
}
|
|
|
|
hostDisconnected(): void {}
|
|
|
|
// Only show one dot at a time to prevent
|
|
// overwhelming users. Priority: News > Store > Help.
|
|
showNewsDot(): boolean {
|
|
return this._hasNewVersion;
|
|
}
|
|
|
|
showStoreDot(): boolean {
|
|
return this._hasNewCosmetics && !this.showNewsDot();
|
|
}
|
|
|
|
showHelpDot(): boolean {
|
|
return (
|
|
getGamesPlayed() < 10 &&
|
|
!this._helpSeen &&
|
|
!this.showNewsDot() &&
|
|
!this.showStoreDot()
|
|
);
|
|
}
|
|
|
|
onNewsClick = (): void => {
|
|
this._hasNewVersion = false;
|
|
localStorage.setItem(NEWS_SEEN_VERSION_KEY, this.normalizedVersion);
|
|
this.host.requestUpdate();
|
|
};
|
|
|
|
onStoreClick = (): void => {
|
|
this._hasNewCosmetics = false;
|
|
getCosmeticsHash()
|
|
.then((hash: string | null) => {
|
|
if (hash !== null) {
|
|
localStorage.setItem(STORE_SEEN_HASH_KEY, hash);
|
|
}
|
|
})
|
|
.catch(() => {});
|
|
this.host.requestUpdate();
|
|
};
|
|
|
|
onHelpClick = (): void => {
|
|
localStorage.setItem(HELP_SEEN_KEY, "true");
|
|
this._helpSeen = true;
|
|
this.host.requestUpdate();
|
|
};
|
|
}
|