Preact: Add avatar and status options (#2360)

This commit is contained in:
Aurastic
2025-04-15 13:43:03 +05:30
committed by GitHub
parent 0773f81d54
commit 2e50c0aad7

View File

@@ -153,6 +153,7 @@ class UserPanel extends PSRoomPanel<UserRoom> {
return [<div class="userdetails">
{user.avatar !== '[loading]' &&
<img
{...(room.isSelf ? { 'data-href': 'avatars' } : {})}
class={'trainersprite' + (room.isSelf ? ' yours' : '')}
src={Dex.resolveAvatar(`${user.avatar || 'unknown'}`)}
/>}
@@ -279,6 +280,7 @@ class OptionsPanel extends PSRoomPanel {
static readonly id = 'options';
static readonly routes = ['options'];
static readonly location = 'popup';
declare state: { showStatusInput?: boolean, showStatusUpdated?: boolean };
setTheme = (e: Event) => {
const theme = (e.currentTarget as HTMLSelectElement).value as 'light' | 'dark' | 'system';
@@ -300,6 +302,21 @@ class OptionsPanel extends PSRoomPanel {
}
PS.update();
};
handleShowStatusInput = (ev: Event) => {
ev.preventDefault();
ev.stopImmediatePropagation();
this.setState({ showStatusInput: !this.state.showStatusInput });
};
editStatus = (ev: Event) => {
const statusInput = this.base!.querySelector<HTMLInputElement>('input[name=statustext]');
PS.send(statusInput?.value?.length ? `|/status ${statusInput.value}` : `|/clearstatus`);
this.setState({ showStatusUpdated: true, showStatusInput: false });
ev.preventDefault();
ev.stopImmediatePropagation();
};
override render() {
const room = this.props.room;
return <PSPanelWrapper room={room}><div class="pad">
@@ -308,8 +325,24 @@ class OptionsPanel extends PSRoomPanel {
class="trainersprite yours" width="40" height="40" style={{ verticalAlign: 'middle' }}
src={Dex.resolveAvatar(`${PS.user.avatar}`)}
/> {}
{PS.user.name}
<strong>{PS.user.name}</strong>
</p>
<p>
<button class="button" data-href="avatars"> Avatar..</button>
</p>
{this.state.showStatusInput ? (
<p>
<input name="statustext"></input>
<button class="button" onClick={this.editStatus}><i class="fa fa-pencil"></i></button>
</p>
) : (
<p>
<button class="button" onClick={this.handleShowStatusInput} disabled={this.state.showStatusUpdated}>
{this.state.showStatusUpdated ? 'Status Updated' : 'Status..'}</button>
</p>
)}
<hr />
<h3>Graphics</h3>
<p>
@@ -490,6 +523,68 @@ class LoginPanel extends PSRoomPanel {
}
}
class AvatarsPanel extends PSRoomPanel {
static readonly id = 'avatars';
static readonly routes = ['avatars'];
static readonly location = 'semimodal-popup';
handleAvatar = (ev: Event) => {
let curtarget = ev.currentTarget as HTMLButtonElement;
let avatar = curtarget.value;
if (window.BattleAvatarNumbers) {
if (window.BattleAvatarNumbers[avatar]) avatar = window.BattleAvatarNumbers[avatar];
}
PS.rooms['']?.send('/avatar ' + avatar);
PS.user.avatar = avatar;
ev.preventDefault();
this.close();
};
update = () => {
this.forceUpdate();
};
override render() {
const room = this.props.room;
let avatars: number[] = [];
let cur = Number(PS.user.avatar);
for (let i = 1; i <= 293; i++) {
if (i === 162 || i === 168) continue;
avatars.push(i);
}
return <PSPanelWrapper room={room} width={480}><div class="pad">
<label class="optlabel"><strong>Choose an avatar or </strong>
<button class="button" onClick={() => this.close()}> Cancel</button>
</label>
<div class="avatarlist">
{avatars.map(i => {
const offset = `-${((i - 1) % 16) * 80 + 1}px -${Math.floor((i - 1) / 16) * 80 + 1}px`;
const style = {
backgroundPosition: offset,
};
const className = `option pixelated${i === cur ? ' cur' : ''}`;
return (
<button
key={i}
value={i}
style={style}
className={className}
title={`/avatar ${i}`}
onClick={this.handleAvatar}
/>
);
})}
</div>
<div style="clear:left"></div>
<p><button class="button" data-cmd="/close">Cancel</button></p>
</div></PSPanelWrapper>;
}
}
class PopupPanel extends PSRoomPanel {
static readonly id = 'popup';
static readonly routes = ['popup-*'];
@@ -511,4 +606,4 @@ class PopupPanel extends PSRoomPanel {
}
}
PS.addRoomType(UserPanel, VolumePanel, OptionsPanel, LoginPanel, PopupPanel);
PS.addRoomType(UserPanel, VolumePanel, OptionsPanel, LoginPanel, AvatarsPanel, PopupPanel);