From 734ce0d71d4af3c5aeb2b4d21da8db1500afcee5 Mon Sep 17 00:00:00 2001 From: Guangcong Luo Date: Sat, 26 Apr 2025 02:38:13 +0000 Subject: [PATCH] Preact minor updates batch 16 Minor - Light mode scrollbar in line with dark mode - OS default scrollbars all look ugly for some reason, unless you use macOS's hidden scrollbars, which are nice except they're hidden. - Add Aurastic to credits - Fix subtle notifications - Fix "Copy" button and HTML popups - These are both for the replay upload popup. - Fix escaping in teambuilder tables - They're escaped in Preact but raw HTML in old client, so using Unicode make them work correctly in both. - Fix a weird issue where history.replaceState was being called too often - I don't know exactly why this is only recently became a problem, but it's easy enough to fix... Trivial - More ARIA roles (for blind users) - The accessibility tree looks great now. - Fix an unnecessary closure in AvatarsPanel - Fix non-ASCII in battle.ts - Fix class="readmore" to work like class="details" (re: don't do expand/collapse hover effect if hovering over a link) - Fix resizing from one-panel to two-panel mode - This was really just one bug in `focusRoom` left over from an old architecture where mini-rooms could be panels in vertical tab mode. - But I took the opportunity to refactor a bunch of panel code to be clearer. - Slightly redesign open team sheets - The yellow and black "construction" message no longer needs nested divs --- build-tools/build-indexes | 2 +- .../src/battle-dex-search.ts | 6 +- play.pokemonshowdown.com/src/battle-log.ts | 2 +- play.pokemonshowdown.com/src/battle.ts | 2 +- play.pokemonshowdown.com/src/client-main.ts | 57 ++++++++-------- .../src/panel-mainmenu.tsx | 4 +- play.pokemonshowdown.com/src/panel-popups.tsx | 10 ++- play.pokemonshowdown.com/src/panel-topbar.tsx | 12 ++-- play.pokemonshowdown.com/src/panels.tsx | 24 +++++-- play.pokemonshowdown.com/style/battle-log.css | 5 +- play.pokemonshowdown.com/style/battle.css | 2 +- play.pokemonshowdown.com/style/client2.css | 66 +++++++++++++++++-- pokemonshowdown.com/credits.php | 3 +- 13 files changed, 138 insertions(+), 57 deletions(-) diff --git a/build-tools/build-indexes b/build-tools/build-indexes index 9153baff3..112405f8d 100755 --- a/build-tools/build-indexes +++ b/build-tools/build-indexes @@ -658,7 +658,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... "); const greatItems = [['header', "Popular items"]]; const goodItems = [['header', "Items"]]; - const specificItems = [['header', "Pokémon-specific items"]]; + const specificItems = [['header', "Pok\u00e9mon-specific items"]]; const poorItems = [['header', "Usually useless items"]]; const badItems = [['header', "Useless items"]]; const unreleasedItems = []; diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index 520dc7ae3..980ea8e2b 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -56,7 +56,7 @@ export class DexSearch { article: 9, }; static typeName = { - pokemon: 'Pokémon', + pokemon: 'Pok\u00e9mon', type: 'Type', tier: 'Tiers', move: 'Moves', @@ -460,7 +460,7 @@ export class DexSearch { switch (fType) { case 'type': let type = fId.charAt(0).toUpperCase() + fId.slice(1) as Dex.TypeName; - buf.push(['header', `${type}-type Pokémon`]); + buf.push(['header', `${type}-type Pok\u00e9mon`]); for (let id in BattlePokedex) { if (!BattlePokedex[id].types) continue; if (this.dex.species.get(id).types.includes(type)) { @@ -470,7 +470,7 @@ export class DexSearch { break; case 'ability': let ability = Dex.abilities.get(fId).name; - buf.push(['header', `${ability} Pokémon`]); + buf.push(['header', `${ability} Pok\u00e9mon`]); for (let id in BattlePokedex) { if (!BattlePokedex[id].abilities) continue; if (Dex.hasAbility(this.dex.species.get(id), ability)) { diff --git a/play.pokemonshowdown.com/src/battle-log.ts b/play.pokemonshowdown.com/src/battle-log.ts index 6360a7327..90ff2be94 100644 --- a/play.pokemonshowdown.com/src/battle-log.ts +++ b/play.pokemonshowdown.com/src/battle-log.ts @@ -317,7 +317,7 @@ export class BattleLog { } return buf; }).join(''); - divHTML = `
Open Team Sheet for ${side.name}${exportedTeam}
`; + divHTML = `
Open team sheet for ${side.name}${exportedTeam}
`; break; } diff --git a/play.pokemonshowdown.com/src/battle.ts b/play.pokemonshowdown.com/src/battle.ts index 2b8493953..38aaebfd5 100644 --- a/play.pokemonshowdown.com/src/battle.ts +++ b/play.pokemonshowdown.com/src/battle.ts @@ -592,7 +592,7 @@ export class Pokemon implements PokemonDetails, PokemonHealth { if (pokemon.maxhp === 100) return `${pokemon.hp}%`; if (pokemon.maxhp !== 48) return (100 * pokemon.hp / pokemon.maxhp).toFixed(precision) + '%'; let range = Pokemon.getPixelRange(pokemon.hp, pokemon.hpcolor); - return Pokemon.getFormattedRange(range, precision, '–'); + return Pokemon.getFormattedRange(range, precision, '\u2013'); } destroy() { if (this.sprite) this.sprite.destroy(); diff --git a/play.pokemonshowdown.com/src/client-main.ts b/play.pokemonshowdown.com/src/client-main.ts index a53bfdf03..46f46e62e 100644 --- a/play.pokemonshowdown.com/src/client-main.ts +++ b/play.pokemonshowdown.com/src/client-main.ts @@ -819,6 +819,7 @@ export class PSRoom extends PSStreamModel implements RoomOptions { subtleNotify() { if (PS.isVisible(this)) return; this.isSubtleNotifying = true; + PS.update(); } dismissNotification(id: string) { this.notifications = this.notifications.filter(notification => notification.id !== id); @@ -1394,26 +1395,6 @@ export const PS = new class extends PSModel { /** Currently active popups, in stack order (bottom to top) */ popups: RoomID[] = []; - /** - * Currently active left room. - * - * In two-panel mode, this will be the visible left panel. - * - * In one-panel mode, this is the visible room only if it is - * `PS.room`. Still tracked when not visible, so we know which - * panels to display if PS is resized to two-panel mode. - */ - leftPanel: PSRoom = null!; - /** - * Currently active right room. - * - * In two-panel mode, this will be the visible right panel. - * - * In one-panel mode, this is the visible room only if it is - * `PS.room`. Still tracked when not visible, so we know which - * panels to display if PS is resized to two-panel mode. - */ - rightPanel: PSRoom | null = null; /** * The currently focused room. Should always be the topmost popup * if it exists. If no popups are open, it should be @@ -1425,13 +1406,34 @@ export const PS = new class extends PSModel { */ room: PSRoom = null!; /** - * The currently active panel. Should always be either `PS.leftRoom` - * or `PS.rightRoom`. If no popups are open, should be `PS.room`. + * The currently active panel. Should always be either `PS.leftPanel` + * or `PS.leftPanel`. If no popups are open, should be `PS.room`. * * In one-panel mode, determines whether the left or right panel is - * visible. Otherwise, no effect. + * visible. Otherwise, it just tracks which panel will be in focus + * after all popups are closed. */ panel: PSRoom = null!; + /** + * Currently active left room. + * + * In two-panel mode, this will be the visible left panel. + * + * In one-panel mode, this is the visible room only if it is + * `PS.panel`. Still tracked when not visible, so we know which + * panels to display if PS is resized to two-panel mode. + */ + leftPanel: PSRoom = null!; + /** + * Currently active right room. + * + * In two-panel mode, this will be the visible right panel. + * + * In one-panel mode, this is the visible room only if it is + * `PS.panel`. Still tracked when not visible, so we know which + * panels to display if PS is resized to two-panel mode. + */ + rightPanel: PSRoom | null = null; /** * * 0 = only one panel visible * * null = vertical nav layout @@ -1833,13 +1835,12 @@ export const PS = new class extends PSModel { room.focusNextUpdate = true; } if (PS.isNormalRoom(room)) { - if (room.location === 'right' && !this.prefs.onepanel) { - this.rightPanel = this.panel = room; + if (room.location === 'right') { + this.rightPanel = room; } else { - this.leftPanel = this.panel = room; + this.leftPanel = room; } - PS.closeAllPopups(true); - this.room = room; + this.panel = this.room = room; } else { // popup or mini-window if (room.location === 'mini-window') { this.leftPanel = this.panel = PS.mainmenu; diff --git a/play.pokemonshowdown.com/src/panel-mainmenu.tsx b/play.pokemonshowdown.com/src/panel-mainmenu.tsx index 47f6843bc..e71534e6c 100644 --- a/play.pokemonshowdown.com/src/panel-mainmenu.tsx +++ b/play.pokemonshowdown.com/src/panel-mainmenu.tsx @@ -408,7 +408,7 @@ class NewsPanel extends PSRoomPanel { override render() { const cookieSet = document.cookie.includes('preactalpha=1'); return -
+
This is the Preact client alpha test.
-
+
; } diff --git a/play.pokemonshowdown.com/src/panel-popups.tsx b/play.pokemonshowdown.com/src/panel-popups.tsx index 31bb6109b..2b94478af 100644 --- a/play.pokemonshowdown.com/src/panel-popups.tsx +++ b/play.pokemonshowdown.com/src/panel-popups.tsx @@ -923,7 +923,7 @@ class AvatarsPanel extends PSRoomPanel { return
{avatars.map(([i, avatar]) => ( @@ -1590,6 +1590,12 @@ class PopupPanel extends PSRoomPanel { if (!textbox) return; textbox.value = this.props.room.args?.value as string || ''; } + parseMessage(message: string) { + if (message.startsWith('|html|')) { + return BattleLog.sanitizeHTML(message.slice(6)); + } + return BattleLog.parseMessage(message); + } override render() { const room = this.props.room; @@ -1601,7 +1607,7 @@ class PopupPanel extends PSRoomPanel { return
{room.args?.message &&

} {!!type &&

}

diff --git a/play.pokemonshowdown.com/src/panel-topbar.tsx b/play.pokemonshowdown.com/src/panel-topbar.tsx index 2d69ba84a..70a16d0a8 100644 --- a/play.pokemonshowdown.com/src/panel-topbar.tsx +++ b/play.pokemonshowdown.com/src/panel-topbar.tsx @@ -129,11 +129,11 @@ export class PSHeader extends preact.Component<{ style: object }> { if (!room) return null; const closable = (id === '' || id === 'rooms' ? '' : ' closable'); const cur = PS.isVisible(room) ? ' cur' : ''; - let notifying = ''; + let notifying = room.isSubtleNotifying ? ' subtle-notifying' : ''; let hoverTitle = ''; const notifications = room.notifications; if (notifications.length) { - notifying = room.isSubtleNotifying ? ' subtle-notifying' : ' notifying'; + notifying = ' notifying'; for (const notif of notifications) { if (!notif.body) continue; hoverTitle += `${notif.title}\n${notif.body}\n`; @@ -218,7 +218,7 @@ export class PSHeader extends preact.Component<{ style: object }> { alt="Pokémon Showdown! (beta)" width="50" height="50" /> -

+
    {PSHeader.renderRoomTab(PS.leftRoomList[0])}
@@ -255,8 +255,8 @@ export class PSHeader extends preact.Component<{ style: object }> { return