mirror of
https://codeberg.org/demostf/frontend.git
synced 2026-06-03 18:24:12 +02:00
191 lines
No EOL
6 KiB
TypeScript
191 lines
No EOL
6 KiB
TypeScript
export class Session {
|
|
public readonly owner_token: string | null;
|
|
private socket: WebSocket | null;
|
|
public readonly sessionName: string;
|
|
private initialState: PlaybackState | null;
|
|
private readonly onState: (StateUpdate) => void | null;
|
|
private readonly syncUri;
|
|
|
|
constructor(name: string, owner_token: string | null = null, initialState: PlaybackState | null, onState: (StateUpdate) => void) {
|
|
this.owner_token = owner_token;
|
|
this.sessionName = name;
|
|
this.initialState = initialState;
|
|
this.onState = onState;
|
|
this.syncUri = document.querySelector('[data-sync]').getAttribute('data-sync');
|
|
this.open();
|
|
}
|
|
|
|
public static create(state: PlaybackState, onState: (StateUpdate) => void): Session {
|
|
return new Session(generateToken(), generateToken(), state, onState)
|
|
}
|
|
|
|
public static join(name: string, onState: (StateUpdate) => void): Session {
|
|
return new Session(name, null, null, onState);
|
|
}
|
|
|
|
private open() {
|
|
if (this.socket) {
|
|
return;
|
|
}
|
|
this.socket = new WebSocket(this.syncUri);
|
|
this.socket.onopen = () => {
|
|
if (this.socket) {
|
|
if (this.owner_token) {
|
|
if (this.initialState) {
|
|
this.socket.send(JSON.stringify({
|
|
type: 'create',
|
|
session: this.sessionName,
|
|
token: this.owner_token
|
|
}));
|
|
this.socket.send(JSON.stringify({
|
|
type: 'tick',
|
|
session: this.sessionName,
|
|
tick: this.initialState.tick
|
|
}));
|
|
this.socket.send(JSON.stringify({
|
|
type: 'play',
|
|
session: this.sessionName,
|
|
play: this.initialState.playing
|
|
}));
|
|
this.socket.send(JSON.stringify({
|
|
type: 'speed',
|
|
session: this.sessionName,
|
|
speed: this.initialState.speed
|
|
}));
|
|
this.initialState = null;
|
|
}
|
|
this.socket.onmessage = (event) => {
|
|
const packet = JSON.parse(event.data) as Packet;
|
|
if (packet.type === 'clients') {
|
|
this.onState({
|
|
clients: packet.count
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
this.socket.send(JSON.stringify({
|
|
type: 'join',
|
|
session: this.sessionName
|
|
}));
|
|
this.socket.onmessage = (event) => {
|
|
const packet = JSON.parse(event.data) as Packet;
|
|
if (packet.type === 'tick') {
|
|
this.onState({
|
|
tick: packet.tick
|
|
});
|
|
}
|
|
if (packet.type === 'speed') {
|
|
this.onState({
|
|
speed: packet.speed
|
|
});
|
|
}
|
|
if (packet.type === 'play') {
|
|
if (packet.play) {
|
|
this.onState({
|
|
playing: true
|
|
});
|
|
} else {
|
|
this.onState({
|
|
playing: false
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
this.socket.onclose = () => {
|
|
this.socket = null;
|
|
setTimeout(this.open.bind(this), 250);
|
|
};
|
|
this.socket.onerror = () => {
|
|
this.socket = null;
|
|
setTimeout(this.open.bind(this), 250);
|
|
};
|
|
}
|
|
|
|
public isOwner(): boolean {
|
|
return this.owner_token !== null;
|
|
}
|
|
|
|
public update(update: StateUpdate): void {
|
|
if (this.socket && this.isOwner()) {
|
|
if (update["tick"]) {
|
|
this.socket.send(JSON.stringify({
|
|
type: 'tick',
|
|
session: this.sessionName,
|
|
tick: update["tick"]
|
|
}));
|
|
}
|
|
if (update.hasOwnProperty("playing")) {
|
|
this.socket.send(JSON.stringify({
|
|
type: 'play',
|
|
session: this.sessionName,
|
|
play: update["playing"]
|
|
}));
|
|
}
|
|
if (update.hasOwnProperty("speed")) {
|
|
this.socket.send(JSON.stringify({
|
|
type: 'speed',
|
|
session: this.sessionName,
|
|
speed: update["speed"]
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function generateToken(): string {
|
|
let string = "";
|
|
const alphabet = "abcdefghijklmnopqrstuvwxyz";
|
|
|
|
while (string.length < 6) {
|
|
string += alphabet[Math.floor(Math.random() * alphabet.length)];
|
|
}
|
|
return string;
|
|
}
|
|
|
|
export interface PlaybackState {
|
|
tick: number,
|
|
playing: boolean,
|
|
clients: number,
|
|
speed: number,
|
|
}
|
|
|
|
export type StateUpdate = Partial<PlaybackState>;
|
|
|
|
interface JoinPacket {
|
|
type: 'join';
|
|
session: string;
|
|
}
|
|
|
|
interface CreatePacket {
|
|
type: 'create';
|
|
session: string;
|
|
}
|
|
|
|
export interface TickPacket {
|
|
type: 'tick';
|
|
session: string;
|
|
tick: number;
|
|
}
|
|
|
|
export interface SpeedPacket {
|
|
type: 'speed';
|
|
session: string;
|
|
speed: number;
|
|
}
|
|
|
|
export interface PlayPacket {
|
|
type: 'play';
|
|
session: string;
|
|
play?: boolean;
|
|
}
|
|
|
|
export interface ClientsPacket {
|
|
type: 'clients';
|
|
session: string;
|
|
count: number;
|
|
}
|
|
|
|
export type Packet = JoinPacket | CreatePacket | TickPacket | PlayPacket | ClientsPacket | SpeedPacket; |