From e2c8eb3db54652b41f1b4836f7990b5daed9bdd5 Mon Sep 17 00:00:00 2001 From: Guangcong Luo Date: Sat, 24 May 2025 10:10:34 +0000 Subject: [PATCH] Preact minor updates batch 23 - Add panel-example.js - Fix windowing (perf) when sorting teambuilder results - Fix some comments --- .../src/battle-searchresults.tsx | 9 ++-- .../src/battle-team-editor.tsx | 14 ++++-- play.pokemonshowdown.com/src/client-main.ts | 7 +-- play.pokemonshowdown.com/src/panel-example.js | 45 +++++++++++++++++++ .../src/panel-example.tsx | 16 ++++--- 5 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 play.pokemonshowdown.com/src/panel-example.js diff --git a/play.pokemonshowdown.com/src/battle-searchresults.tsx b/play.pokemonshowdown.com/src/battle-searchresults.tsx index 9b58cefb0..78f4ebc3d 100644 --- a/play.pokemonshowdown.com/src/battle-searchresults.tsx +++ b/play.pokemonshowdown.com/src/battle-searchresults.tsx @@ -15,8 +15,9 @@ import { Config } from "./client-main"; export class PSSearchResults extends preact.Component<{ search: DexSearch, windowing?: number | null, hideFilters?: boolean, firstRow?: SearchRow, resultIndex?: number, - /** type = '' means a filter was selected */ - onSelect?: (type: SearchType | '', name: string, moveSlot?: string) => void, + /** type = '' means a filter was selected, + * null means a sort was selected (clear not needed) */ + onSelect?: (type: SearchType | '' | null, name: string, moveSlot?: string) => void, }> { readonly URL_ROOT = `//${Config.routes.dex}/`; speciesId: ID = '' as ID; @@ -453,9 +454,9 @@ export class PSSearchResults extends preact.Component<{ if (filter) { search.removeFilter(filter.split(':') as any); search.find(''); - this.forceUpdate(); ev.preventDefault(); ev.stopPropagation(); + this.props.onSelect?.(null, ''); break; } @@ -464,9 +465,9 @@ export class PSSearchResults extends preact.Component<{ if (sort) { search.toggleSort(sort); search.find(''); - this.forceUpdate(); ev.preventDefault(); ev.stopPropagation(); + this.props.onSelect?.(null, ''); break; } } diff --git a/play.pokemonshowdown.com/src/battle-team-editor.tsx b/play.pokemonshowdown.com/src/battle-team-editor.tsx index 3840ba575..8d229dd35 100644 --- a/play.pokemonshowdown.com/src/battle-team-editor.tsx +++ b/play.pokemonshowdown.com/src/battle-team-editor.tsx @@ -1126,8 +1126,11 @@ class TeamTextbox extends preact.Component<{ this.resetScroll(); this.forceUpdate(); } - selectResult = (type: string, name: string, moveSlot?: string) => { - if (!type) { + selectResult = (type: string | null, name: string, moveSlot?: string) => { + if (type === null) { + this.resetScroll(); + this.forceUpdate(); + } else if (!type) { this.changeSet(this.innerFocus!.type, ''); } else { this.changeSet(type as SelectionType, name, moveSlot); @@ -1745,10 +1748,13 @@ class TeamWizard extends preact.Component<{ if (!TeamEditor.probablyMobile()) searchBox.focus(); } } - selectResult = (type: string, name: string, slot?: string, reverse?: boolean) => { + selectResult = (type: string | null, name: string, slot?: string, reverse?: boolean) => { const { editor } = this.props; this.clearSearchBox(); - if (!type) { + if (type === null) { + this.resetScroll(); + this.forceUpdate(); + } if (!type) { editor.setSearchValue(''); this.resetScroll(); this.forceUpdate(); diff --git a/play.pokemonshowdown.com/src/client-main.ts b/play.pokemonshowdown.com/src/client-main.ts index 0739e91a3..4f80cc381 100644 --- a/play.pokemonshowdown.com/src/client-main.ts +++ b/play.pokemonshowdown.com/src/client-main.ts @@ -2350,9 +2350,10 @@ export const PS = new class extends PSModel { if (!noFocus) { let parentPopup = parentRoom; if ((options.parentElem as HTMLButtonElement)?.name === 'closeRoom') { - // we want to close all popups above the parent element. - // This is usually the parent room, the close button in a roomtablist's - // parent room is the linked room rather than the roomtablist popup, + // We want to close all popups above the parent element. + // This is usually the parent room, but if we're clicking Close + // in the overflow tablist, the close button's parent room is + // the tab rather than the overflow tablist popup, // which needs to be corrected here. parentPopup = PS.rooms['roomtablist'] || parentPopup; } diff --git a/play.pokemonshowdown.com/src/panel-example.js b/play.pokemonshowdown.com/src/panel-example.js new file mode 100644 index 000000000..64d0f3324 --- /dev/null +++ b/play.pokemonshowdown.com/src/panel-example.js @@ -0,0 +1,45 @@ +/** + * Example Panel + * + * An example of how to make a panel for the Preact client in vanilla JS. + * + * For how to create one in TSX, see `panel-example.tsx`. For JSX, just + * use the TSX and remove the type annotations. + * + * @author Guangcong Luo + * @license AGPLv3 + */ + +// Example panel in vanilla JS + +class ExampleVanillaJS extends preact.Component { + shouldComponentUpdate() { + return false; + } + componentDidMount() { + const yourDiv = this.base; + // edit the contents of your panel however you like here + yourDiv.innerHTML = '

Hello World!

'; + } + render() { + return preact.h("div", null); + } +} +class ExampleVanillaJSPanel extends PSRoomPanel { + // This is the ID of the panel type. It can be whatever you want, but + // it must not be the same as any other panel ID. + static id = 'exampleview'; + // This is a list of panel IDs. This would make <> and + // <> open this panel. + static routes = ['exampleview', 'examples-*']; + // The default title (shown on the tab list). You can edit + // `this.props.room.title` to change it. + static title = 'Example View'; + render() { + return preact.h(PSPanelWrapper, { room: this.props.room }, + preact.h(ExampleVanillaJS, null) + ); + } +} + +PS.addRoomType(ExampleVanillaJSPanel); diff --git a/play.pokemonshowdown.com/src/panel-example.tsx b/play.pokemonshowdown.com/src/panel-example.tsx index 27c8d2582..0acf0bae4 100644 --- a/play.pokemonshowdown.com/src/panel-example.tsx +++ b/play.pokemonshowdown.com/src/panel-example.tsx @@ -21,14 +21,20 @@ class ExampleRoom extends PSRoom { } class ExamplePanel extends PSRoomPanel { + // This is the ID of the panel type. It can be whatever you want, but + // it must not be the same as any other panel ID. static readonly id = 'exampleview'; - static readonly routes = ['exampleview']; + // This is a list of panel IDs. This would make <> and + // <> open this panel. + static readonly routes = ['exampleview', 'examples-*']; static readonly Model = ExampleRoom; + // The default title (shown on the tab list). You can edit + // `ExampleRoom`'s `title` property to change it. static readonly title = 'Example View'; override render() { const room = this.props.room; return -

Loading...

+

Hello World!

; } } @@ -38,13 +44,13 @@ PS.addRoomType(ExamplePanel); // Example panel with no room class ExampleViewPanel extends PSRoomPanel { - static readonly id = 'exampleview'; - static readonly routes = ['exampleview']; + static readonly id = 'examplevie2'; + static readonly routes = ['exampleview2']; static readonly title = 'Example View'; override render() { const room = this.props.room; return -

Loading...

+

Hello World!

; } }