This commit is contained in:
Aurastic 2026-05-08 15:22:02 +05:30 committed by GitHub
commit 5eb900c52c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 159 additions and 8 deletions

View File

@ -19,6 +19,7 @@ import { BattleTextParser, type Args } from './battle-text-parser';
import type { BattleRoom } from './panel-battle';
import { Teams } from './battle-teams';
import type preact from '../js/lib/preact';
import { PSHeader } from './panel-topbar';
declare const BattleTextAFD: any;
declare const BattleTextNotAFD: any;
@ -1044,6 +1045,11 @@ export class PSRoom extends PSStreamModel<Args | null> implements RoomOptions {
}
}
} catch {}
// extra check because the roomIsFocused is not accurate for some reason
if (document.visibilityState !== 'visible') {
PS.isNotifying = true;
PSHeader.updateFavicon();
}
}
if (options.noAutoDismiss && !options.id) {
throw new Error(`Must specify id for manual dismissing`);
@ -1073,6 +1079,7 @@ export class PSRoom extends PSStreamModel<Args | null> implements RoomOptions {
this.notifications[i].notification?.close();
} catch {}
this.notifications.splice(i, 1);
PSHeader.updateFavicon();
}
dismissNotification(id: string) {
const index = this.notifications.findIndex(n => n.id === id);
@ -1504,6 +1511,12 @@ export class PSRoom extends PSStreamModel<Args | null> implements RoomOptions {
PS.prefs.set('nounlink', false);
this.add('||Locked/banned users\' chat messages: HIDDEN');
},
'whatsnew'() {
const success = PSHeader.clickCounter.click();
if (success) {
PS.join('patchnotes' as RoomID);
}
},
'hl,highlight'(target) {
let highlights = PS.prefs.highlights || {};
if (target.includes(' ')) {
@ -1930,6 +1943,8 @@ export const PS = new class extends PSModel {
/** Tracks whether or not to display the "Use arrow keys" hint */
arrowKeysUsed = false;
isNotifying = false;
newsHTML = document.querySelector('#room-news .readable-bg')?.innerHTML || '';
newsId = document.getElementById('room-news')?.getAttribute('data-newsid') || null;
@ -2790,6 +2805,15 @@ export const PS = new class extends PSModel {
this.prefs.set('autojoin', autojoin);
}
}
getNotificationsCount() {
let count = 0;
const notificationRooms = [...PS.leftRoomList, ...PS.rightRoomList, ...PS.miniRoomList];
for (const roomid of notificationRooms) {
const miniNotifications = PS.rooms[roomid]?.notifications;
if (miniNotifications?.length) count++;
}
return count;
}
requestNotifications() {
try {
if (window.webkitNotifications?.requestPermission) {

View File

@ -1928,6 +1928,102 @@ class RulesPanel extends PSRoomPanel<PopupRoom> {
}
}
class PatchNotesPanel extends PSRoomPanel<PopupRoom> {
static readonly id = 'patchnotes';
static readonly routes = ['patchnotes'];
static readonly location = 'semimodal-popup';
static readonly noURL = true;
static readonly Model = PopupRoom;
getRandomPatchNotes() {
const allTitles = [
"Patch Notes (because chaos needs documentation)",
"Patch Notes: Now with 30% fewer bugs (No promises)",
"Patch Notes — We Swear Its Better This Time",
"Patch Notes: Definitely Didnt Break Anything Else",
"Patch Notes: Technically “Improvements”",
"Patch Notes — Version: “It Works on My Machine”",
"Patch Notes (We Fixed Things You Didnt Know Were Broken)",
"Patch Notes: Stability? Never Heard of It.",
"Patch Notes — Slightly More Functional Than Yesterday",
"Patch Notes: The Bugs Strike Back",
"Patch Notes (A Love Letter to Debugging)",
"Patch Notes: Powered by Caffeine and Regret",
"Patch Notes — “Trust Me Bro” Edition",
];
const allNotes = [
"Fixed a bug where clicking really hard didnt make things load faster.",
"Improved stability by removing one line of code we didnt understand.",
"Added a 'quantum uncertainty' mode — the UI may or may not respond.",
"Performance improved by at least 0.0001% (scientifically proven).",
"Added new AI: 'Emotionally Unstable Bot' — it forfeits if youre mean.",
"Pokémon now occasionally question the meaning of their existence mid-battle.",
"Critical hits are now determined by your karma.",
"Fixed a bug where RNG was too fair.",
"Improved matchmaking: youll now face someone just as tilted as you.",
"Added experimental 'Therapist Mode': the game listens, you vent.",
"The app now looks 30% faster, even if it isnt.",
"Chat filters now detect sarcasm with 4% accuracy.",
"Fixed a bug where players were sometimes right on the internet.",
"Improved mod tools: moderators can now sense chaos before it happens.",
"Backend now powered by pure friendship and caffeine.",
"Optimized the code to run slightly worse, but with more confidence.",
"Fixed an issue where the bug fix introduced more bugs.",
"Added 'Are you sure?' dialog. It doesnt do anything, but feels safe.",
"Reduced load times by moving progress bar faster.",
"Replaced all semicolons with good vibes.",
"New setting: 'Developer Tears Mode' — enhances realism.",
"You can now press any key to feel like youre helping.",
"Made UI 15% shinier for improved morale.",
"Bug reports are now automatically forwarded to the void.",
"Buffed RNG. Its now personal.",
"Lucarios aura now glows brighter when you lie.",
"Fixed crash where Trainer couldnt accept defeat gracefully.",
"Buffed memes. Nerfed logic.",
"New mechanic: 'Disconnect Immunity' — doesnt exist, but sounds nice.",
"Fixed an issue where players believed in fair matchups.",
"Nerfed stall strategies. (Youre welcome.)",
"Fixed an exploit where players had hope during battles.",
"Blissey now charges for therapy sessions.",
"Togekisss Air Slash now comes with a free rage quit.",
"Increased Confusion duration — the devs thought it was funny.",
"Garchomps Sand Veil now works indoors, somehow.",
"Rebalanced RNG: it now hates everyone equally.",
"Pikachus Thunderbolt now powered by real electricity bills.",
"Machamp now flexes every 3 turns automatically.",
"Buffed Magikarps Splash — it now causes mild emotional distress.",
"Nerfed Toxic stall teams. Were doing this for humanity.",
"Alakazam now needs a PhD to understand its own Special Attack stat.",
"Zoroarks Illusion now also fools itself sometimes.",
"Fixed a bug where Ditto copied your emotional damage too.",
"Gengar now giggles 20% more menacingly.",
"Nerfed RNG. It was getting too self-aware.",
"Charizard finally acknowledged that its not a Dragon-type. Therapy helped.",
];
const title = allTitles.sort(() => 0.5 - Math.random())[0];
const notes = allNotes.sort(() => 0.5 - Math.random()).slice(0, 12);
return { title, notes };
}
override render() {
const room = this.props.room;
const patchNotesData = this.getRandomPatchNotes();
return <PSPanelWrapper room={room} width={room.args?.width as number || 780}>
<div class="pad">
<h2>{patchNotesData.title}</h2>
{patchNotesData.notes
.map((note, i) => <p><b>{i + 1}.</b> {note}</p>)}
<p class="buttonbar"><button
name="close"
data-cmd="/close" class="button autofocus"
> Close</button></p>
</div>
</PSPanelWrapper>;
}
}
PS.addRoomType(
UserPanel,
UserOptionsPanel,
@ -1947,5 +2043,6 @@ PS.addRoomType(
RoomTabListPanel,
BattleOptionsPanel,
BattleTimerPanel,
RulesPanel
RulesPanel,
PatchNotesPanel
);

View File

@ -21,6 +21,28 @@ window.addEventListener('dragover', e => {
});
export class PSHeader extends preact.Component {
static clickCounter = {
count: 0,
lastClick: 0,
maxGap: 500,
click() {
const now = Date.now();
if (now - this.lastClick > this.maxGap) {
this.count = 1;
} else {
this.count++;
}
this.lastClick = now;
if (this.count === 10) {
this.count = 0;
return true;
}
return false;
},
};
static toggleMute = (e: Event) => {
PS.prefs.set('mute', !PS.prefs.mute);
PS.update();
@ -152,6 +174,13 @@ export class PSHeader extends preact.Component {
{closeButton}
</li>;
}
static updateFavicon() {
const favicon = document.querySelector('#dynamic-favicon');
if (favicon instanceof HTMLLinkElement) {
favicon.href = `${window.Dex.resourcePrefix}/${PS.isNotifying ? 'favicon-notify.ico' : 'favicon.ico'}`;
favicon.dataset.on = PS.isNotifying ? '1' : '';
}
}
handleResize = () => {
if (!this.base) return;
@ -228,6 +257,7 @@ export class PSHeader extends preact.Component {
src={`https://${Config.routes.client}/favicon-256.png`}
alt="Pokémon Showdown! (beta)"
width="50" height="50"
data-cmd="/whatsnew"
/>
<div class="tablist" role="tablist">
<ul>
@ -269,6 +299,7 @@ export class PSHeader extends preact.Component {
src={`https://${Config.routes.client}/favicon-256.png`}
alt="Pokémon Showdown! (beta)"
width="48" height="48"
data-cmd="/whatsnew"
/>
</li>
{PSHeader.renderRoomTab(PS.leftRoomList[0])}
@ -308,13 +339,7 @@ export class PSMiniHeader extends preact.Component {
};
override render() {
if (PS.leftPanelWidth !== null) return null;
let notificationsCount = 0;
const notificationRooms = [...PS.leftRoomList, ...PS.rightRoomList];
for (const roomid of notificationRooms) {
const miniNotifications = PS.rooms[roomid]?.notifications;
if (miniNotifications?.length) notificationsCount++;
}
const notificationsCount = PS.getNotificationsCount();
const { icon, title } = PSHeader.roomInfo(PS.panel);
const userColor = window.BattleLog && `color:${PS.user.away ? '#888' : BattleLog.usernameColor(PS.user.userid)}`;
const showMenuButton = PSView.narrowMode;

View File

@ -646,6 +646,11 @@ export class PSView extends preact.Component {
PS.dragging = null;
});
window.addEventListener('focus', () => {
PS.isNotifying = false;
PSHeader.updateFavicon();
});
const colorSchemeQuery = window.matchMedia?.('(prefers-color-scheme: dark)');
if (colorSchemeQuery?.media !== 'not all') {
colorSchemeQuery.addEventListener('change', cs => {