Preact: Add roomlist overflow popup (#2374)

This commit is contained in:
HoeenHero 2025-04-18 00:19:07 -04:00 committed by GitHub
parent b0d565a30b
commit 7ee7c6604a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 11 deletions

View File

@ -7,6 +7,7 @@ import { PSRoom, type RoomOptions, PS, type PSLoginState, type RoomID, type Time
import { type BattleRoom } from "./panel-battle"; import { type BattleRoom } from "./panel-battle";
import type { ChatRoom } from "./panel-chat"; import type { ChatRoom } from "./panel-chat";
import { PSRoomPanel, PSPanelWrapper } from "./panels"; import { PSRoomPanel, PSPanelWrapper } from "./panels";
import { PSHeader } from "./panel-topbar";
/** /**
* User popup * User popup
@ -1207,6 +1208,25 @@ class PopupPanel extends PSRoomPanel {
</div></PSPanelWrapper>; </div></PSPanelWrapper>;
} }
} }
class RoomTabListPanel extends PSRoomPanel {
static readonly id = 'roomtablist';
static readonly routes = ['roomtablist'];
static readonly location = 'semimodal-popup';
static readonly noURL = true;
override render() {
return <PSPanelWrapper room={this.props.room}><div class="tablist">
<ul>
{PS.leftRoomList.map(roomid => PSHeader.renderRoomTab(roomid))}
</ul>
<ul>
{PS.rightRoomList.map(roomid => PSHeader.renderRoomTab(roomid))}
</ul>
</div></PSPanelWrapper>;
}
}
PS.addRoomType( PS.addRoomType(
UserPanel, UserPanel,
UserOptionsPanel, UserOptionsPanel,
@ -1218,5 +1238,6 @@ PS.addRoomType(
RegisterPanel, RegisterPanel,
BattleForfeitPanel, BattleForfeitPanel,
ReplacePlayerPanel, ReplacePlayerPanel,
PopupPanel PopupPanel,
RoomTabListPanel
); );

View File

@ -41,7 +41,7 @@ window.addEventListener('dragover', e => {
}); });
export class PSHeader extends preact.Component<{ style: object }> { export class PSHeader extends preact.Component<{ style: object }> {
handleDragEnter = (e: DragEvent) => { static handleDragEnter = (e: DragEvent) => {
console.log('dragenter ' + e.dataTransfer!.dropEffect); console.log('dragenter ' + e.dataTransfer!.dropEffect);
e.preventDefault(); e.preventDefault();
if (!PS.dragging) return; // TODO: handle dragging other things onto roomtabs if (!PS.dragging) return; // TODO: handle dragging other things onto roomtabs
@ -72,7 +72,7 @@ export class PSHeader extends preact.Component<{ style: object }> {
// Chrome/Safari/Opera // Chrome/Safari/Opera
// if (e.dataTransfer) e.dataTransfer.dropEffect = 'move'; // if (e.dataTransfer) e.dataTransfer.dropEffect = 'move';
}; };
handleDragStart = (e: DragEvent) => { static handleDragStart = (e: DragEvent) => {
const roomid = PS.router.extractRoomID((e.currentTarget as HTMLAnchorElement).href); const roomid = PS.router.extractRoomID((e.currentTarget as HTMLAnchorElement).href);
if (!roomid) return; // should never happen if (!roomid) return; // should never happen
@ -120,7 +120,7 @@ export class PSHeader extends preact.Component<{ style: object }> {
} }
return { icon, title }; return { icon, title };
} }
renderRoomTab(id: RoomID) { static renderRoomTab(id: RoomID) {
const room = PS.rooms[id]; const room = PS.rooms[id];
if (!room) return null; if (!room) return null;
const closable = (id === '' || id === 'rooms' ? '' : ' closable'); const closable = (id === '' || id === 'rooms' ? '' : ' closable');
@ -150,10 +150,33 @@ export class PSHeader extends preact.Component<{ style: object }> {
{closeButton} {closeButton}
</li>; </li>;
} }
handleRoomTabOverflow() {
if (!PS.rightPanel) return; // TODO handle vertical overflow
const avaliableSpace = PS.rightPanel.width - 165; // 165 is the width of the userbar
let usedSpace = 0;
const roomTabs = this.base?.querySelectorAll('ul.siderooms > li');
if (!roomTabs) return; // No rooms
for (const tab of Array.from(roomTabs)) {
usedSpace += tab.clientWidth;
}
const overflow = this.base?.querySelector('.overflow');
if (usedSpace > avaliableSpace) {
overflow?.classList.remove('hidden');
} else {
overflow?.classList.add('hidden');
}
}
override componentDidMount() { override componentDidMount() {
PS.user.subscribe(() => { PS.user.subscribe(() => {
this.forceUpdate(); this.forceUpdate();
}); });
this.handleRoomTabOverflow();
}
override componentDidUpdate() {
this.handleRoomTabOverflow();
} }
renderUser() { renderUser() {
if (!PS.connected) { if (!PS.connected) {
@ -182,16 +205,16 @@ export class PSHeader extends preact.Component<{ style: object }> {
/> />
<div class="tablist"> <div class="tablist">
<ul> <ul>
{this.renderRoomTab(PS.leftRoomList[0])} {PSHeader.renderRoomTab(PS.leftRoomList[0])}
</ul> </ul>
<ul> <ul>
{PS.miniRoomList.map(roomid => this.renderRoomTab(roomid))} {PS.miniRoomList.map(roomid => PSHeader.renderRoomTab(roomid))}
</ul> </ul>
<ul> <ul>
{PS.leftRoomList.slice(1).map(roomid => this.renderRoomTab(roomid))} {PS.leftRoomList.slice(1).map(roomid => PSHeader.renderRoomTab(roomid))}
</ul> </ul>
<ul class="siderooms"> <ul class="siderooms">
{PS.rightRoomList.map(roomid => this.renderRoomTab(roomid))} {PS.rightRoomList.map(roomid => PSHeader.renderRoomTab(roomid))}
</ul> </ul>
</div> </div>
</div> </div>
@ -228,14 +251,19 @@ export class PSHeader extends preact.Component<{ style: object }> {
/> />
<div class="tabbar maintabbar"><div class="inner"> <div class="tabbar maintabbar"><div class="inner">
<ul> <ul>
{this.renderRoomTab(PS.leftRoomList[0])} {PSHeader.renderRoomTab(PS.leftRoomList[0])}
</ul> </ul>
<ul> <ul>
{PS.leftRoomList.slice(1).map(roomid => this.renderRoomTab(roomid))} {PS.leftRoomList.slice(1).map(roomid => PSHeader.renderRoomTab(roomid))}
</ul> </ul>
<ul class="siderooms" style={{ float: 'none', marginLeft: Math.max(PS.leftPanelWidth - 52, 0) }}> <ul class="siderooms" style={{ float: 'none', marginLeft: Math.max(PS.leftPanelWidth - 52, 0) }}>
{PS.rightRoomList.map(roomid => this.renderRoomTab(roomid))} {PS.rightRoomList.map(roomid => PSHeader.renderRoomTab(roomid))}
</ul> </ul>
<div class="overflow hidden" aria-hidden="true">
<button name="tablist" class="button" data-href="roomtablist" aria-label="More" type="button">
<i class="fa fa-caret-down"></i>
</button>
</div>
</div></div> </div></div>
<div class="userbar"> <div class="userbar">
{this.renderUser()} {} {this.renderUser()} {}