Preact minor updates batch 28
Some checks failed
Node.js CI / build (22.x) (push) Has been cancelled

Most of these were found by andrebastosdias (thanks!)

Teambuilder
- SpA/SpD columns weren't appearing in gen 2
- buggy behavior with EVs in gen 1-2 or Let's Go
- save teams after doing things (Fixes #2493)
- import old box syntax

UI
- layout breaking when resizing
This commit is contained in:
Guangcong Luo 2025-11-02 15:16:50 +00:00
parent 96c625ae97
commit 64e79f49eb
5 changed files with 41 additions and 21 deletions

View File

@ -128,8 +128,8 @@ export class PSSearchResults extends preact.Component<{
<span class="col statcol"><em>HP</em><br />{stats.hp}</span> <span class="col statcol"><em>HP</em><br />{stats.hp}</span>
<span class="col statcol"><em>Atk</em><br />{stats.atk}</span> <span class="col statcol"><em>Atk</em><br />{stats.atk}</span>
<span class="col statcol"><em>Def</em><br />{stats.def}</span> <span class="col statcol"><em>Def</em><br />{stats.def}</span>
{search.dex.gen > 2 && <span class="col statcol"><em>SpA</em><br />{stats.spa}</span>} {search.dex.gen >= 2 && <span class="col statcol"><em>SpA</em><br />{stats.spa}</span>}
{search.dex.gen > 2 && <span class="col statcol"><em>SpD</em><br />{stats.spd}</span>} {search.dex.gen >= 2 && <span class="col statcol"><em>SpD</em><br />{stats.spd}</span>}
{search.dex.gen < 2 && <span class="col statcol"><em>Spc</em><br />{stats.spa}</span>} {search.dex.gen < 2 && <span class="col statcol"><em>Spc</em><br />{stats.spa}</span>}
<span class="col statcol"><em>Spe</em><br />{stats.spe}</span> <span class="col statcol"><em>Spe</em><br />{stats.spe}</span>
<span class="col bstcol"><em>BST<br />{bst}</em></span> <span class="col bstcol"><em>BST<br />{bst}</em></span>

View File

@ -314,6 +314,7 @@ export class TeamEditorState extends PSModel {
const sets = Teams.unpack(team.packedTeam); const sets = Teams.unpack(team.packedTeam);
sets.splice(source, 1); sets.splice(source, 1);
team.packedTeam = Teams.pack(sets); team.packedTeam = Teams.pack(sets);
team.iconCache = null;
} }
} }
} }
@ -335,6 +336,7 @@ export class TeamEditorState extends PSModel {
index++; index++;
} }
TeamEditorState.clipboard = null; TeamEditorState.clipboard = null;
this.save();
} }
static pasteTeam(index: number, isMove?: boolean, folder = '') { static pasteTeam(index: number, isMove?: boolean, folder = '') {
if (!TeamEditorState.clipboard) return; if (!TeamEditorState.clipboard) return;
@ -656,9 +658,7 @@ export class TeamEditorState extends PSModel {
} }
} }
getStat(stat: StatName, set: Dex.PokemonSet, ivOverride: number, evOverride?: number, natureOverride?: number) { getStat(stat: StatName, set: Dex.PokemonSet, ivOverride: number, evOverride?: number, natureOverride?: number) {
const team = this.team; const supportsEVs = !this.isLetsGo;
const supportsEVs = !team.format.includes('letsgo');
const supportsAVs = !supportsEVs; const supportsAVs = !supportsEVs;
// do this after setting set.evs because it's assumed to exist // do this after setting set.evs because it's assumed to exist
@ -1195,6 +1195,7 @@ class TeamTextbox extends preact.Component<{
this.replace(paste.paste.replace(/\r\n/g, '\n'), valueIndex, valueIndex + value.length); this.replace(paste.paste.replace(/\r\n/g, '\n'), valueIndex, valueIndex + value.length);
} else { } else {
this.editor.import(pasteTxt); this.editor.import(pasteTxt);
this.props.onChange?.();
} }
const notes = paste["notes"] as string; const notes = paste["notes"] as string;
if (notes.startsWith("Format: ")) { if (notes.startsWith("Format: ")) {
@ -2457,14 +2458,13 @@ class StatForm extends preact.Component<{
onChange: () => void, onChange: () => void,
}> { }> {
static renderStatGraph(set: Dex.PokemonSet, editor: TeamEditorState, evs?: boolean) { static renderStatGraph(set: Dex.PokemonSet, editor: TeamEditorState, evs?: boolean) {
// const supportsEVs = !team.format.includes('letsgo');
const defaultEV = (editor.gen > 2 ? 0 : 252); const defaultEV = (editor.gen > 2 ? 0 : 252);
const ivs = editor.getIVs(set); const ivs = editor.getIVs(set);
return Dex.statNames.map(statID => { return Dex.statNames.map(statID => {
if (statID === 'spd' && editor.gen === 1) return null; if (statID === 'spd' && editor.gen === 1) return null;
const stat = editor.getStat(statID, set, ivs[statID]); const stat = editor.getStat(statID, set, ivs[statID]);
let ev: number | string = set.evs?.[statID] ?? defaultEV; let ev: number | string = set.evs ? (set.evs[statID] || 0) : defaultEV;
let width = stat * 75 / 504; let width = stat * 75 / 504;
if (statID === 'hp') width = stat * 75 / 704; if (statID === 'hp') width = stat * 75 / 704;
if (width > 75) width = 75; if (width > 75) width = 75;
@ -2746,7 +2746,11 @@ class StatForm extends preact.Component<{
if (isNaN(value)) { if (isNaN(value)) {
if (set.evs) delete set.evs[statID]; if (set.evs) delete set.evs[statID];
} else { } else {
set.evs ||= {}; if (this.maxEVs() < 6 * 252 || this.props.editor.isLetsGo) {
set.evs ||= {};
} else {
set.evs ||= { hp: 252, atk: 252, def: 252, spa: 252, spd: 252, spe: 252 };
}
set.evs[statID] = value; set.evs[statID] = value;
} }
@ -2844,20 +2848,19 @@ class StatForm extends preact.Component<{
this.props.onChange(); this.props.onChange();
}; };
maxEVs() { maxEVs() {
const team = this.props.editor.team; const editor = this.props.editor;
const useEVs = !team.format.includes('letsgo'); const useEVs = !editor.isLetsGo && editor.gen >= 3;
return useEVs ? 510 : Infinity; return useEVs ? 510 : Infinity;
} }
override render() { override render() {
const { editor, set } = this.props; const { editor, set } = this.props;
const team = editor.team;
const species = editor.dex.species.get(set.species); const species = editor.dex.species.get(set.species);
const baseStats = species.baseStats; const baseStats = species.baseStats;
const nature = BattleNatures[set.nature || 'Serious']; const nature = BattleNatures[set.nature || 'Serious'];
const useEVs = !team.format.includes('letsgo'); const useEVs = !editor.isLetsGo;
// const useAVs = !useEVs && team.format.endsWith('norestrictions'); // const useAVs = !useEVs && team.format.endsWith('norestrictions');
const maxEV = useEVs ? 252 : 200; const maxEV = useEVs ? 252 : 200;
const stepEV = useEVs ? 4 : 1; const stepEV = useEVs ? 4 : 1;
@ -2881,14 +2884,14 @@ class StatForm extends preact.Component<{
] as const); ] as const);
let remaining = null; let remaining = null;
const maxEv = this.maxEVs(); const maxEVs = this.maxEVs();
if (maxEv < 6 * 252) { if (maxEVs < 6 * 252) {
let totalEv = 0; let totalEv = 0;
for (const ev of Object.values(set.evs || {})) totalEv += ev; for (const ev of Object.values(set.evs || {})) totalEv += ev;
if (totalEv <= maxEv) { if (totalEv <= maxEVs) {
remaining = (totalEv > (maxEv - 2) ? 0 : (maxEv - 2) - totalEv); remaining = (totalEv > (maxEVs - 2) ? 0 : (maxEVs - 2) - totalEv);
} else { } else {
remaining = maxEv - totalEv; remaining = maxEVs - totalEv;
} }
remaining ||= null; remaining ||= null;
} }

View File

@ -73,11 +73,15 @@ class TeambuilderRoom extends PSRoom {
} else { } else {
PS.teams.unshift(this.createTeam(null, isBox)); PS.teams.unshift(this.createTeam(null, isBox));
} }
PS.teams.save();
this.update(null); this.update(null);
}, },
'deleteteam'(target) { 'deleteteam'(target) {
const team = PS.teams.byKey[target]; const team = PS.teams.byKey[target];
if (team) PS.teams.delete(team); if (!team) return this.errorReply(`Team not found: ${target}`);
PS.teams.delete(team);
PS.teams.save();
this.update(null); this.update(null);
}, },
'copyteam'(target) { 'copyteam'(target) {
@ -96,12 +100,14 @@ class TeambuilderRoom extends PSRoom {
const index = team ? PS.teams.list.indexOf(team) : PS.teams.list.length; const index = team ? PS.teams.list.indexOf(team) : PS.teams.list.length;
const folder = this.curFolder?.endsWith('/') ? this.curFolder.slice(0, -1) : ''; const folder = this.curFolder?.endsWith('/') ? this.curFolder.slice(0, -1) : '';
TeamEditorState.pasteTeam(index, cmd === 'moveteamabove', folder); TeamEditorState.pasteTeam(index, cmd === 'moveteamabove', folder);
PS.teams.save();
PS.update(); PS.update();
this.update(null); this.update(null);
}, },
'undeleteteam'() { 'undeleteteam'() {
PS.teams.undelete(); PS.teams.undelete();
PS.teams.save();
this.update(null); this.update(null);
}, },
'backup'() { 'backup'() {
@ -421,6 +427,9 @@ class TeambuilderPanel extends PSRoomPanel<TeambuilderRoom> {
this.forceUpdate(); this.forceUpdate();
}; };
static handleDrop(ev: DragEvent) { static handleDrop(ev: DragEvent) {
if (PS.dragging?.type === 'team' && typeof PS.dragging?.team === 'object') {
PS.teams.save();
}
return !!this.addDraggedTeam(ev, (PS.rooms['teambuilder'] as TeambuilderRoom)?.curFolder); return !!this.addDraggedTeam(ev, (PS.rooms['teambuilder'] as TeambuilderRoom)?.curFolder);
} }
updateSearch = (ev: KeyboardEvent) => { updateSearch = (ev: KeyboardEvent) => {
@ -499,7 +508,7 @@ class TeambuilderPanel extends PSRoomPanel<TeambuilderRoom> {
const room = this.props.room; const room = this.props.room;
room.exportMode = false; room.exportMode = false;
PS.teams.update('team'); PS.teams.save();
room.update(null); room.update(null);
}; };
renameFolder = (ev: MouseEvent) => { renameFolder = (ev: MouseEvent) => {

View File

@ -62,9 +62,16 @@ export class PSTeambuilder {
line = line.slice(3, -3).trim(); line = line.slice(3, -3).trim();
[curTeam.format, line] = this.splitPrefix(line, ']', 1) as [ID, string]; [curTeam.format, line] = this.splitPrefix(line, ']', 1) as [ID, string];
if (!curTeam.format) curTeam.format = 'gen8' as ID; if (!curTeam.format) {
else if (!curTeam.format.startsWith('gen')) curTeam.format = `gen6${curTeam.format}` as ID; curTeam.format = 'gen8' as ID;
} else if (curTeam.format.endsWith('-box')) {
curTeam.format = curTeam.format.slice(0, -4) as ID;
curTeam.isBox = true;
}
if (curTeam.format.startsWith('[')) curTeam.format = curTeam.format.slice(1) as ID;
if (!curTeam.format.startsWith('gen')) curTeam.format = `gen6${curTeam.format}` as ID;
line = line.trim();
[curTeam.folder, curTeam.name] = this.splitPrefix(line, '/'); [curTeam.folder, curTeam.name] = this.splitPrefix(line, '/');
} else if (line.includes('|')) { } else if (line.includes('|')) {
if (curTeam) { if (curTeam) {

View File

@ -175,6 +175,7 @@ export class PSHeader extends preact.Component {
} }
if (PSView.narrowMode) { if (PSView.narrowMode) {
document.documentElement.classList?.remove('scroll-snap-enabled'); document.documentElement.classList?.remove('scroll-snap-enabled');
document.documentElement.style.width = 'auto';
PSView.narrowMode = false; PSView.narrowMode = false;
} }