mirror of
https://github.com/smogon/pokemon-showdown-client.git
synced 2026-03-21 17:50:29 -05:00
Preact minor updates batch 18
Some checks are pending
Node.js CI / build (22.x) (push) Waiting to run
Some checks are pending
Node.js CI / build (22.x) (push) Waiting to run
Minor - Change long tap time to 500 (Fixes #2408) - A compromise between the old 350ms and the briefly newer 1000ms - long clicks are also back at 700ms Teambuilder - Redesign defensive coverage chart - Fix in testclient - Fix pop-outs in text editor - Improve move selection
This commit is contained in:
parent
33f78c413f
commit
96fb9a314a
|
|
@ -9,7 +9,7 @@
|
|||
import preact from "../js/lib/preact";
|
||||
import { type Team } from "./client-main";
|
||||
import { PSTeambuilder } from "./panel-teamdropdown";
|
||||
import { Dex, type ModdedDex, toID, type ID } from "./battle-dex";
|
||||
import { Dex, type ModdedDex, toID, type ID, PSUtils } from "./battle-dex";
|
||||
import { DexSearch, type SearchRow, type SearchType } from "./battle-dex-search";
|
||||
import { PSSearchResults } from "./battle-searchresults";
|
||||
import { BattleNatures, BattleStatNames, type StatName } from "./battle-dex-data";
|
||||
|
|
@ -346,9 +346,11 @@ class TeamEditorState extends PSModel {
|
|||
return coverage as Record<Dex.TypeName, number>;
|
||||
}
|
||||
teamDefensiveCoverage() {
|
||||
const counters: Record<Dex.TypeName, Record<'resists' | 'neutrals' | 'weaknesses', number>> = {} as any;
|
||||
type Counter = { type: Dex.TypeName, resists: number, neutrals: number, weaknesses: number };
|
||||
const counters: Record<Dex.TypeName, Counter> = {} as any;
|
||||
for (const type of this.dex.types.names()) {
|
||||
counters[type] = {
|
||||
type,
|
||||
resists: 0,
|
||||
neutrals: 0,
|
||||
weaknesses: 0,
|
||||
|
|
@ -1130,28 +1132,28 @@ class TeamTextbox extends preact.Component<{ editor: TeamEditorState, onChange?:
|
|||
></div>
|
||||
)}
|
||||
</div>
|
||||
{this.innerFocus && (
|
||||
<div
|
||||
class="searchresults"
|
||||
style={`top:${(this.setInfo[this.innerFocus.setIndex]?.bottomY ?? this.bottomY() + 50) - 12}px`}
|
||||
onScroll={this.scrollResults}
|
||||
>
|
||||
<button class="button closesearch" onClick={this.closeMenu}>
|
||||
{!editor.narrow && <kbd>Esc</kbd>} <i class="fa fa-times" aria-hidden></i> Close
|
||||
</button>
|
||||
{this.innerFocus.type === 'stats' ? (
|
||||
<StatForm editor={editor} set={this.editor.sets[this.innerFocus.setIndex]} onChange={this.handleSetChange} />
|
||||
) : this.innerFocus.type === 'details' ? (
|
||||
<DetailsForm editor={editor} set={this.editor.sets[this.innerFocus.setIndex]} onChange={this.handleSetChange} />
|
||||
) : (
|
||||
<PSSearchResults
|
||||
search={editor.search} resultIndex={editor.searchIndex}
|
||||
windowing={this.windowResults()} onSelect={this.selectResult}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{this.innerFocus && (
|
||||
<div
|
||||
class="searchresults"
|
||||
style={`top:${(this.setInfo[this.innerFocus.setIndex]?.bottomY ?? this.bottomY() + 50) - 12}px`}
|
||||
onScroll={this.scrollResults}
|
||||
>
|
||||
<button class="button closesearch" onClick={this.closeMenu}>
|
||||
{!editor.narrow && <kbd>Esc</kbd>} <i class="fa fa-times" aria-hidden></i> Close
|
||||
</button>
|
||||
{this.innerFocus.type === 'stats' ? (
|
||||
<StatForm editor={editor} set={this.editor.sets[this.innerFocus.setIndex]} onChange={this.handleSetChange} />
|
||||
) : this.innerFocus.type === 'details' ? (
|
||||
<DetailsForm editor={editor} set={this.editor.sets[this.innerFocus.setIndex]} onChange={this.handleSetChange} />
|
||||
) : (
|
||||
<PSSearchResults
|
||||
search={editor.search} resultIndex={editor.searchIndex}
|
||||
windowing={this.windowResults()} onSelect={this.selectResult}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
|
@ -1246,6 +1248,7 @@ class TeamWizard extends preact.Component<{
|
|||
</div>;
|
||||
}
|
||||
while (set.moves.length < 4) set.moves.push('');
|
||||
const overfull = set.moves.length > 4 ? ' overfull' : '';
|
||||
|
||||
const editor = this.props.editor;
|
||||
const species = editor.dex.species.get(set.species);
|
||||
|
|
@ -1285,10 +1288,11 @@ class TeamWizard extends preact.Component<{
|
|||
</button>
|
||||
</div></td>
|
||||
<td rowSpan={2} class="set-moves"><div class="border-collapse">
|
||||
<button class={`button button-middle${cur('move')}`} onClick={this.setFocus} value={`move|${i}`}>
|
||||
<button class={`button button-middle${cur('move')}${overfull}`} onClick={this.setFocus} value={`move|${i}`}>
|
||||
<strong class="label">Moves</strong> {}
|
||||
{set.moves.map(move => <div>
|
||||
{!editor.narrow && <small class="gray">•</small>}{move || (editor.narrow && '-')}
|
||||
{set.moves.map((move, mi) => <div>
|
||||
{!editor.narrow && <small class="gray">•</small>}
|
||||
{mi >= 4 ? <span class="message-error">{move || (editor.narrow && '-') || ''}</span> : move || (editor.narrow && '-')}
|
||||
</div>)}
|
||||
{!set.moves.length && <em>(no moves)</em>}
|
||||
</button>
|
||||
|
|
@ -1369,9 +1373,18 @@ class TeamWizard extends preact.Component<{
|
|||
if (slot) {
|
||||
// intentional; we're _removing_ from the slot
|
||||
const i = parseInt(slot) - 1;
|
||||
if (set.moves[i]) set.moves[i] = '';
|
||||
if (i === set.moves.length - 1) {
|
||||
while (!set.moves[set.moves.length - 1]) set.moves.pop();
|
||||
if (set.moves[i]) {
|
||||
set.moves[i] = '';
|
||||
// remove empty slots at the end
|
||||
if (i === set.moves.length - 1) {
|
||||
while (set.moves.length > 4 && !set.moves[set.moves.length - 1]) {
|
||||
set.moves.pop();
|
||||
}
|
||||
}
|
||||
// if we have more than 4 moves, move the last move into the newly-cleared slot
|
||||
if (set.moves.length > 4 && i < set.moves.length - 1) {
|
||||
set.moves[i] = set.moves.pop()!;
|
||||
}
|
||||
}
|
||||
} else if (set.moves.includes(name)) {
|
||||
set.moves.splice(set.moves.indexOf(name), 1);
|
||||
|
|
@ -1576,28 +1589,32 @@ class TeamWizard extends preact.Component<{
|
|||
}
|
||||
renderDefensiveCoverage() {
|
||||
const { editor } = this.props;
|
||||
const counters = editor.teamDefensiveCoverage();
|
||||
const counters = Object.values(editor.teamDefensiveCoverage());
|
||||
PSUtils.sortBy(counters, counter => [counter.resists, -counter.weaknesses]);
|
||||
const good = [], medium = [], bad = [];
|
||||
const renderTypeDefensive = (type: Dex.TypeName) => (
|
||||
<><strong>{type}</strong>: {counters[type].weaknesses} weaknesses, {counters[type].resists} resists</>
|
||||
const renderTypeDefensive = (counter: typeof counters[number]) => (
|
||||
<tr>
|
||||
<th>{counter.type}</th>
|
||||
<td>{counter.resists} <small>resist{counter.resists === 1 ? '' : 's'}</small></td>
|
||||
<td>{counter.weaknesses} <small>weakness{counter.weaknesses === 1 ? '' : 'es'}</small></td>
|
||||
</tr>
|
||||
);
|
||||
for (const [type, counter] of Object.entries(counters)) {
|
||||
for (const counter of counters) {
|
||||
if (counter.resists > 0) {
|
||||
good.push(renderTypeDefensive(type as Dex.TypeName), <br />);
|
||||
good.push(renderTypeDefensive(counter));
|
||||
} else if (counter.weaknesses <= 0) {
|
||||
medium.push(renderTypeDefensive(type as Dex.TypeName), <br />);
|
||||
medium.push(renderTypeDefensive(counter));
|
||||
} else {
|
||||
bad.push(renderTypeDefensive(type as Dex.TypeName), <br />);
|
||||
bad.push(renderTypeDefensive(counter));
|
||||
}
|
||||
}
|
||||
bad.pop();
|
||||
return <details class="readmore">
|
||||
return <details class="details" style="margin-top:1em">
|
||||
<summary>
|
||||
<h3>Defensive coverage</h3>
|
||||
{bad}
|
||||
<strong>Defensive coverage</strong>
|
||||
<table class="details-preview table">{bad}</table><span class="details-preview ilink"><small>See all</small></span>
|
||||
</summary>
|
||||
{medium}
|
||||
{good}
|
||||
<table class="table">{bad}{medium}{good}</table>
|
||||
</details>;
|
||||
}
|
||||
override render() {
|
||||
|
|
|
|||
|
|
@ -156,7 +156,8 @@ export class BattleTooltips {
|
|||
// tooltips
|
||||
// Touch delay, pressing finger more than that time will cause the tooltip to open.
|
||||
// Shorter time will cause the button to click
|
||||
static LONG_TAP_DELAY = 1000; // ms
|
||||
static LONG_TAP_DELAY = 500; // ms
|
||||
static LONG_CLICK_DELAY = 700; // ms
|
||||
static longTapTimeout = 0;
|
||||
static elem: HTMLDivElement | null = null;
|
||||
static parentElem: HTMLElement | null = null;
|
||||
|
|
@ -243,13 +244,12 @@ export class BattleTooltips {
|
|||
if (BattleTooltips.isLocked) BattleTooltips.hideTooltip();
|
||||
const target = e.currentTarget as HTMLElement;
|
||||
this.showTooltip(target);
|
||||
// let factor = (e.type === 'mousedown' && target.tagName === 'BUTTON' ? 2 : 1);
|
||||
const factor = 1;
|
||||
const isClick = (e.type === 'mousedown' && target.tagName === 'BUTTON');
|
||||
|
||||
BattleTooltips.longTapTimeout = setTimeout(() => {
|
||||
BattleTooltips.longTapTimeout = 0;
|
||||
this.lockTooltip();
|
||||
}, BattleTooltips.LONG_TAP_DELAY * factor);
|
||||
}, isClick ? BattleTooltips.LONG_CLICK_DELAY : BattleTooltips.LONG_TAP_DELAY);
|
||||
};
|
||||
|
||||
showTooltipEvent = (e: Event) => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { PS, type Team } from "./client-main";
|
||||
import { PSPanelWrapper, PSRoomPanel } from "./panels";
|
||||
import { PSIcon, PSPanelWrapper, PSRoomPanel } from "./panels";
|
||||
import { Dex, type ModdedDex, toID, type ID } from "./battle-dex";
|
||||
import { BattleNatures, BattleStatIDs, BattleStatNames, type StatNameExceptHP } from "./battle-dex-data";
|
||||
|
||||
|
|
@ -609,9 +609,10 @@ export function TeamBox(props: { team: Team | null, noLink?: boolean, button?: b
|
|||
if (!team.packedTeam) {
|
||||
icons = <em>(empty team)</em>;
|
||||
} else {
|
||||
icons = PSTeambuilder.packedTeamNames(team.packedTeam).map(species =>
|
||||
// can't use PSIcon, weird interaction with iconCache
|
||||
<span class="picon" style={Dex.getPokemonIcon(species)}></span>
|
||||
icons = PSTeambuilder.packedTeamNames(team.packedTeam).map(pokemon =>
|
||||
// can't use <PSIcon>, weird interaction with iconCache
|
||||
// don't try this at home; I'm a trained professional
|
||||
PSIcon({ pokemon })
|
||||
);
|
||||
}
|
||||
team.iconCache = icons;
|
||||
|
|
|
|||
|
|
@ -596,6 +596,12 @@ you can't delete it by pressing Backspace */
|
|||
.set-button .set-ability .button, .set-button .set-item .button {
|
||||
height: 40px;
|
||||
}
|
||||
.set-button .set-moves .button {
|
||||
line-height: 18px;
|
||||
}
|
||||
.set-button .set-moves .button.overfull {
|
||||
line-height: normal;
|
||||
}
|
||||
.set-button .set-details .button {
|
||||
height: 60px;
|
||||
}
|
||||
|
|
@ -626,7 +632,8 @@ you can't delete it by pressing Backspace */
|
|||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.team-focus-editor .tabbar {
|
||||
overflow: auto;
|
||||
/* note to self: make this scrollable later */
|
||||
/* overflow: auto; */
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tabbar .button.picontab {
|
||||
|
|
|
|||
|
|
@ -154,6 +154,8 @@
|
|||
|
||||
<script src="https://play.pokemonshowdown.com/data/pokedex-mini.js"></script>
|
||||
<script src="https://play.pokemonshowdown.com/data/pokedex-mini-bw.js"></script>
|
||||
<script src="data/typechart.js" onerror="loadRemoteData(this.src)"></script>
|
||||
<script src="data/aliases.js" onerror="loadRemoteData(this.src)"></script>
|
||||
<script src="js/lib/d3.v3.min.js"></script>
|
||||
<script src="js/lib/color-thief.min.js"></script>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user