From 1c0115ec2ebe262fc72bd56668be21b2eaa21808 Mon Sep 17 00:00:00 2001 From: Guangcong Luo Date: Tue, 26 May 2026 15:22:19 +0000 Subject: [PATCH] Preact minor updates batch 31 - Improve team loaded check - Fix reconnect cutoff being wrong sometimes - Fix .htaccess permissions - Fix deleted teams still being editable --- play.pokemonshowdown.com/.htaccess | 4 +++- play.pokemonshowdown.com/src/battle-dex-search.ts | 5 ++++- play.pokemonshowdown.com/src/client-connection.ts | 3 +++ play.pokemonshowdown.com/src/client-main.ts | 9 +++++---- play.pokemonshowdown.com/src/panel-chat.tsx | 11 ++++++----- .../src/panel-teambuilder-team.tsx | 14 +++++++++++--- 6 files changed, 32 insertions(+), 14 deletions(-) diff --git a/play.pokemonshowdown.com/.htaccess b/play.pokemonshowdown.com/.htaccess index e029d56f7..088a1eb1a 100644 --- a/play.pokemonshowdown.com/.htaccess +++ b/play.pokemonshowdown.com/.htaccess @@ -3,7 +3,7 @@ AddType application/x-tgz .tgz AddType application/x-chrome-extension .crx AddType application/x-web-app-manifest+json .webapp - + FileETag None Header unset ETag @@ -164,6 +164,8 @@ RewriteRule ^backup/ - [F] RewriteRule ^\.git/ - [F] RewriteRule ^lib/ - [F] +# TODO: figure this guy out +RewriteCond %{THE_REQUEST} \s/caches/ RewriteRule ^caches/ - [F] RewriteRule ^testclient-old\.html$ - [F] RewriteRule ^testclient-beta\.html$ - [F] diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index 18202f9a9..0e9b71e40 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -1100,7 +1100,10 @@ class BattlePokemonSearch extends BattleTypedSearch<'pokemon'> { } let tierSet: SearchRow[] = table.tierSet; let slices: { [k: string]: number } = table.formatSlices; - if (format === 'ubers' || format === 'uber' || format === 'ubersuu' || format === '4v4doublesuu' || format === 'nationaldexdoubles') { + if ( + format === 'ubers' || format === 'uber' || format === 'ubersuu' || + format === '4v4doublesuu' || format === 'nationaldexdoubles' + ) { tierSet = tierSet.slice(slices.Uber); } else if (isVGCOrBS || (isHackmons && dex.gen === 9 && !this.formatType)) { if (format.endsWith('series13') || format.endsWith('regj') || isHackmons) { diff --git a/play.pokemonshowdown.com/src/client-connection.ts b/play.pokemonshowdown.com/src/client-connection.ts index 3721acbca..da9b81d79 100644 --- a/play.pokemonshowdown.com/src/client-connection.ts +++ b/play.pokemonshowdown.com/src/client-connection.ts @@ -13,6 +13,7 @@ declare const POKEMON_SHOWDOWN_TESTCLIENT_KEY: string | undefined; export class PSConnection { socket: WebSocket | null = null; connected = false; + lastMessageTimeBeforeReconnect = 0; queue: string[] = []; reconnectDelay = 1000; private reconnectCap = 15000; @@ -68,6 +69,7 @@ export class PSConnection { switch (type) { case 'connected': console.log('\u2705 (CONNECTED via worker)'); + this.lastMessageTimeBeforeReconnect = parseInt(PS.lastMessageTime) || 0; this.connected = true; if (PS.prefs.avatar) worker.postMessage({ type: 'send', data: `/avatar ${PS.prefs.avatar},1` }); this.queue.forEach(msg => worker.postMessage({ type: 'send', data: msg })); @@ -121,6 +123,7 @@ export class PSConnection { socket.onopen = () => { console.log('\u2705 (CONNECTED)'); + this.lastMessageTimeBeforeReconnect = parseInt(PS.lastMessageTime) || 0; this.connected = true; this.reconnectDelay = 1000; if (PS.prefs.avatar) socket.send(`/avatar ${PS.prefs.avatar},1`); diff --git a/play.pokemonshowdown.com/src/client-main.ts b/play.pokemonshowdown.com/src/client-main.ts index e1a83f6f0..5f47cd6be 100644 --- a/play.pokemonshowdown.com/src/client-main.ts +++ b/play.pokemonshowdown.com/src/client-main.ts @@ -522,6 +522,7 @@ class PSTeams extends PSStreamModel<'team' | 'format'> { teams[team.teamid] = team; } + const NOT_LOADED_REGEX = /^[^|]*\|\|\|\|\|\|\|\|\|\|\|(?:\][^|]*\|\|\|\|\|\|\|\|\|\|\|)*$/; // find exact teamid matches for (const localTeam of this.list) { if (localTeam.teamid) { @@ -531,7 +532,7 @@ class PSTeams extends PSStreamModel<'team' | 'format'> { } localTeam.uploaded = { teamid: team.teamid, - notLoaded: this.unloadedPackedTeam(team.team) === localTeam.packedTeam, + notLoaded: NOT_LOADED_REGEX.test(localTeam.packedTeam), private: team.private, }; delete teams[localTeam.teamid]; @@ -554,7 +555,7 @@ class PSTeams extends PSStreamModel<'team' | 'format'> { localTeam.teamid = team.teamid; localTeam.uploaded = { teamid: team.teamid, - notLoaded: this.unloadedPackedTeam(team.team) === localTeam.packedTeam, + notLoaded: NOT_LOADED_REGEX.test(localTeam.packedTeam), private: team.private, }; break; @@ -1118,11 +1119,11 @@ export class PSRoom extends PSStreamModel implements RoomOptions { } autoDismissNotifications() { let room = PS.rooms[this.id] as ChatRoom; - if (room.lastMessageTime) { + if (room.lastViewedTime) { // Mark chat messages as read to avoid double-notifying on reload let lastMessageDates = PS.prefs.logtimes || {}; if (!lastMessageDates[PS.server.id]) lastMessageDates[PS.server.id] = {}; - lastMessageDates[PS.server.id][room.id] = room.lastMessageTime || 0; + lastMessageDates[PS.server.id][room.id] = room.lastViewedTime || 0; PS.prefs.set('logtimes', lastMessageDates); } for (let i = this.notifications.length - 1; i >= 0; i--) { diff --git a/play.pokemonshowdown.com/src/panel-chat.tsx b/play.pokemonshowdown.com/src/panel-chat.tsx index 1e3b26d57..c17db3bd1 100644 --- a/play.pokemonshowdown.com/src/panel-chat.tsx +++ b/play.pokemonshowdown.com/src/panel-chat.tsx @@ -52,7 +52,7 @@ export class ChatRoom extends PSRoom { log: BattleLog | null = null; tour: ChatTournament | null = null; lastMessage: Args | null = null; - lastMessageTime: number | null = null; + lastViewedTime: number | null = null; joinLeave: { join: string[], leave: string[], messageId: string } | null = null; /** in order from least to most recent */ @@ -175,6 +175,7 @@ export class ChatRoom extends PSRoom { break; case ':': this.timeOffset = Math.trunc(Date.now() / 1000) - (parseInt(args[1], 10) || 0); + PS.lastMessageTime = args[1]; break; } super.receiveLine(args); @@ -191,7 +192,7 @@ export class ChatRoom extends PSRoom { // then cut off roomintro from the end let cutOffStart = 0; let cutOffEnd = lines.length; - const cutOffTime = parseInt(PS.lastMessageTime); + const cutOffTime = PS.connection?.lastMessageTimeBeforeReconnect || parseInt(PS.lastMessageTime); const cutOffExactLine = this.lastMessage ? '|' + this.lastMessage?.join('|') : ''; let reconnectMessage = '|raw|
You reconnected.
'; for (let i = 0; i < lines.length; i++) { @@ -316,13 +317,13 @@ export class ChatRoom extends PSRoom { // because the time offset to the server can vary slightly, subtract it to not have it affect comparisons between dates const time = serverTime - (this.timeOffset || 0); if (PS.isVisiblePanel(this)) { - this.lastMessageTime = null; + this.lastViewedTime = null; lastMessageDates[PS.server.id][this.id] = time; PS.prefs.set('logtimes', lastMessageDates); } else { // To be saved on focus - const lastMessageTime = this.lastMessageTime || 0; - if (lastMessageTime < time) this.lastMessageTime = time; + const lastViewedTime = this.lastViewedTime || 0; + if (lastViewedTime < time) this.lastViewedTime = time; } if (ChatRoom.getHighlight(message, this.id)) { const mayNotify = time > lastMessageDate; diff --git a/play.pokemonshowdown.com/src/panel-teambuilder-team.tsx b/play.pokemonshowdown.com/src/panel-teambuilder-team.tsx index 6fc19a3f8..c64db5183 100644 --- a/play.pokemonshowdown.com/src/panel-teambuilder-team.tsx +++ b/play.pokemonshowdown.com/src/panel-teambuilder-team.tsx @@ -18,6 +18,7 @@ class TeamRoom extends PSRoom { /** Doesn't _literally_ always exist, but does in basically all code * and constantly checking for its existence is legitimately annoying... */ team!: Team; + teamDeleted = false; forceReload = false; override clientCommands = this.parseClientCommands({ 'validate'(target) { @@ -32,10 +33,17 @@ class TeamRoom extends PSRoom { super(options); const team = PS.teams.byKey[this.id.slice(5)] || null; this.team = team!; - this.title = `[Team] ${this.team?.name || 'Error'}`; + this.title = `[Team] ${this.team?.name || 'Not found'}`; if (team) this.setFormat(team.format); this.load(); } + getTeam() { + const team = PS.teams.byKey[this.id.slice(5)] || null; + this.teamDeleted = !team && (!!this.team || this.teamDeleted); + this.team = team!; + this.title = `[Team] ${this.team?.name || (this.teamDeleted ? 'Team deleted' : 'Not found')}`; + return team; + } setFormat(format: string) { const team = this.team; team.format = toID(format); @@ -202,7 +210,7 @@ class TeamPanel extends PSRoomPanel { } override render() { const { room } = this.props; - const team = room.team; + const team = room.getTeam(); if (!team || room.forceReload) { if (room.forceReload) { room.forceReload = false; @@ -213,7 +221,7 @@ class TeamPanel extends PSRoomPanel { List

- Team doesn't exist + {room.teamDeleted ? 'Team was deleted' : 'Team doesn\'t exist'}

; }