Implement Rooms room

This commit is contained in:
Guangcong Luo 2019-03-21 20:10:55 +09:00
parent 3bef3920a8
commit fbaceafac1
10 changed files with 3564 additions and 20 deletions

View File

@ -1,10 +1,10 @@
<!DOCTYPE html>
<html><head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Showdown!</title>
<link rel="shortcut icon" href="favicon.ico" id="dynamic-favicon" />
<link rel="stylesheet" href="/style/client.css" />
<meta id="viewport" name="viewport" content="width=640" />
<link rel="stylesheet" href="/style/client2.css" />
<meta name="robots" content="noindex" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<!--[if lte IE 8]><script>

View File

@ -600,7 +600,7 @@ const PS = new class extends PSModel {
id: roomid2,
type,
connected: true,
});
}, roomid === 'staff' || roomid === 'upperstaff');
room = PS.rooms[roomid2];
} else {
room.type = type;

View File

@ -14,7 +14,7 @@ class ChatRoom extends PSRoom {
super(options);
if (options.pmTarget) this.pmTarget = options.pmTarget as string;
this.updateTarget(true);
if (!this.connected && PS.connected) {
if (!this.connected) {
if (!this.pmTarget) PS.send(`|/join ${this.id}`);
this.connected = true;
}

View File

@ -5,6 +5,8 @@
* @license AGPLv3
*/
type RoomInfo = {title: string, desc: string, userCount: number, subRooms?: string[]};
class MainMenuRoom extends PSRoom {
readonly classType: string = 'mainmenu';
userdetailsCache: {[userid: string]: {
@ -13,6 +15,13 @@ class MainMenuRoom extends PSRoom {
group?: string,
rooms?: {[roomid: string]: {isPrivate?: true, p1?: string, p2?: string}},
}} = {};
roomsCache: {
battleCount?: number,
userCount?: number,
chat?: RoomInfo[],
official?: RoomInfo[],
pspl?: RoomInfo[],
} = {};
receive(line: string) {
const tokens = PS.lineParse(line);
switch (tokens[0]) {
@ -65,8 +74,13 @@ class MainMenuRoom extends PSRoom {
} else {
Object.assign(userdetails, response);
}
const room = PS.rooms[`user-${userid}`] as UserRoom;
if (room) room.update('');
const userRoom = PS.rooms[`user-${userid}`] as UserRoom;
if (userRoom) userRoom.update('');
break;
case 'rooms':
this.roomsCache = response;
const roomsRoom = PS.rooms[`rooms`] as RoomsRoom;
if (roomsRoom) roomsRoom.update('');
break;
}
}

View File

@ -6,18 +6,81 @@
*/
class RoomsRoom extends PSRoom {
readonly classType: string = 'mainmenu';
readonly classType: string = 'rooms';
constructor(options: RoomOptions) {
super(options);
PS.send(`|/cmd rooms`);
}
}
class RoomsPanel extends PSRoomPanel {
hidden = false;
componentDidMount() {
super.componentDidMount();
this.subscriptions.push(PS.user.subscribe(() => {
if (PS.user.named) PS.send(`|/cmd rooms`);
}));
}
hide = () => {
this.hidden = true;
PS.rightRoom = null;
PS.room = PS.leftRoom;
this.forceUpdate();
PS.update();
};
render() {
return <PSPanelWrapper room={this.props.room}>
<div class="mainmessage">
<p>[insert room list here]</p>
<p><a href="/lobby">Lobby</a></p>
<p><a href="/tours">Tours</a></p>
if (this.hidden && PS.isVisible(this.props.room)) this.hidden = false;
if (this.hidden) {
return <PSPanelWrapper room={this.props.room} scrollable>{null}</PSPanelWrapper>;
}
const rooms = PS.mainmenu.roomsCache;
return <PSPanelWrapper room={this.props.room} scrollable><div class="pad">
<button class="button" style="float:right;font-size:10pt;margin-top:3px" onClick={this.hide}>
<i class="fa fa-caret-right"></i> Hide
</button>
<div class="roomcounters">
<span
style="background:transparent url(https://play.pokemonshowdown.com/sprites/smicons-sheet.png?a5) no-repeat scroll -0px -2790px;"
class="picon icon-left"
title="Meloetta is PS's mascot! The Aria forme is about using its voice, and represents our chatrooms."
></span> {}
<button class="button" data-href="/users" title="Find an online user">
<strong>{rooms.userCount || '-'}</strong> users online
</button> {}
<button class="button" data-href="/battles" title="Watch an active battle">
<strong>{rooms.battleCount || '-'}</strong> active battles
</button> {}
<span
style="background:transparent url(https://play.pokemonshowdown.com/sprites/smicons-sheet.png?a5) no-repeat scroll -0px -2220px"
class="picon icon-right"
title="Meloetta is PS's mascot! The Pirouette forme is Fighting-type, and represents our battles."
></span>
</div>
</PSPanelWrapper>;
{rooms.userCount === undefined && <h2>Connecting...</h2>}
{this.renderRoomList("Official chat rooms", rooms.official)}
{this.renderRoomList("PSPL winner", rooms.pspl)}
{this.renderRoomList("Chat rooms", rooms.chat)}
</div></PSPanelWrapper>;
}
renderRoomList(title: string, rooms?: RoomInfo[]) {
if (!rooms || !rooms.length) return null;
return <div class="roomlist">
<h2>{title}</h2>
{rooms.map(roomInfo => <div>
<a href={`/${toId(roomInfo.title)}`} class="ilink">
<small style="float:right">({roomInfo.userCount} users)</small>
<strong><i class="fa fa-comment-o"></i> {roomInfo.title}<br /></strong>
<small>{roomInfo.desc}</small>
{roomInfo.subRooms && <small><br />
<i class="fa fa-level-up fa-rotate-90"></i> Subrooms: <strong>
{roomInfo.subRooms.map((roomName, i) => [
<i class="fa fa-comment-o"></i>, " " + roomName + (i === roomInfo.subRooms!.length - 1 ? "" : ", "),
])}
</strong>
</small>}
</a>
</div>)}
</div>;
}
}

View File

@ -170,7 +170,7 @@ class PSMain extends preact.Component {
e.stopImmediatePropagation();
return;
}
if (elem.tagName === 'A' || elem.className === 'team') {
if (elem.tagName === 'A' || elem.getAttribute('data-href')) {
const roomid = this.roomidFromLink(elem as HTMLAnchorElement);
if (roomid !== null) {
PS.addRoom({

3467
style/client2.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
<!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Showdown!</title>
<link rel="shortcut icon" href="favicon.ico" id="dynamic-favicon" />
<link rel="stylesheet" href="style/client.css" />
<meta id="viewport" name="viewport" content="width=640" />
<link rel="stylesheet" href="style/client2.css" />
<meta name="robots" content="noindex" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<!--[if lte IE 8]><script>

View File

@ -1,7 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta charset="utf-8" />
<meta id="viewport" name="viewport" content="width=device-width" />
<title>Showdown!</title>
<link rel="shortcut icon" href="favicon.ico" id="dynamic-favicon" />
<link rel="stylesheet" href="style/client.css" />
@ -9,7 +10,6 @@
<link rel="stylesheet" href="style/battle.css" />
<link rel="stylesheet" href="style/utilichart.css" />
<link rel="stylesheet" href="style/font-awesome.css" />
<meta id="viewport" name="viewport" content="width=640" />
<meta name="robots" content="noindex" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<script>

View File

@ -19,7 +19,7 @@
"severity": "warning",
"options": {
"limit": 120,
"ignore-pattern": "template\\.replace\\(('\\[|/)|^\\s*(// \\s*)?((let |const )?[a-zA-Z0-9$.]+ \\+?= (\\$\\()?|(return |throw )?(new )?([a-zA-Z0-9$.]+\\()?)?['\"`/]"
"ignore-pattern": "template\\.replace\\(('\\[|/)|[a-z0-9]=|^\\s*(// \\s*)?((let |const )?[a-zA-Z0-9$.]+ \\+?= (\\$\\()?|(return |throw )?(new )?([a-zA-Z0-9$.]+\\()?)?['\"`/]"
}
},
"interface-name": false,