improve sync ui

This commit is contained in:
Robin Appelman 2024-11-24 20:23:51 +01:00
commit ed63ffa394
8 changed files with 129 additions and 51 deletions

View file

@ -3,6 +3,8 @@ export interface AnalyseMenuProps {
onShare: Function;
canShare: boolean;
isShared: boolean;
clients: number,
inShared: boolean,
}
export function AnalyseMenu(props: AnalyseMenuProps) {
@ -13,17 +15,34 @@ export function AnalyseMenu(props: AnalyseMenuProps) {
style={{width: `${(loc().length * 8)}px`}}
onFocus={(event) => {
(event.target as HTMLInputElement).select()
}}/> : '';
}}/> : <span class="share-text">Start a shared session</span>;
const shareButton = () => (props.canShare) ? <div class="analyse-menu">
<button class="share-session" title="Start a shared session"
onClick={() => {
props.onShare()
}}/>
{shareText}
</div> : '';
const clientCount = () => (props.isShared) ?
<div class="clients">{props.clients} {(props.clients === 1) ? "spectator" : "spectators"}</div> : [];
return (<div>
const shareButton = () => {
if (props.canShare) {
return [
<div class="share">
<button class="share-session" title="Start a shared session"
onClick={() => {
props.onShare()
}}/>
{shareText}
</div>,
clientCount,
]
} else if (props.inShared) {
return <div class="share shared">
You're spectating a session controlled by someone else
</div>
} else {
return [];
}
}
return (<div class="analyse-menu">
{shareButton}
</div>)
}

View file

@ -25,13 +25,14 @@ export const Analyser = (props: AnalyseProps) => {
const [scale, setScale] = createSignal<number>(1);
const [playing, setPlaying] = createSignal<boolean>(false);
const [sessionName, setSessionName] = createSignal<string>("");
const [clients, setClients] = createSignal<number>(0);
let lastFrameTime = 0;
let playStartTick = 0;
let playStartTime = 0;
const onUpdate = (update: StateUpdate) => {
if (update["tick"]) {
if (update.hasOwnProperty("tick")) {
setTick(update["tick"]);
}
if (update.hasOwnProperty("playing")) {
@ -41,6 +42,10 @@ export const Analyser = (props: AnalyseProps) => {
pause();
}
}
if (update.hasOwnProperty("clients")) {
console.log(update["clients"]);
setClients(update["clients"]);
}
}
let session: Session | null = null;
@ -137,7 +142,7 @@ export const Analyser = (props: AnalyseProps) => {
const buildings = () => parser.getBuildingsAtTick(tick());
const kills = parser.getKills();
const playButtonText = () => (playing()) ? '⏸' : '▶️';
const disabled = session && !session.isOwner();
const inShared = session && !session.isOwner();
const isShared = () => sessionName() !== '';
console.log(intervalPerTick);
@ -160,12 +165,15 @@ export const Analyser = (props: AnalyseProps) => {
onShare={() => {
session = Session.create({
tick: tick(),
playing: playing()
});
playing: playing(),
clients: 0,
}, onUpdate);
setSessionName(session.sessionName);
}}
canShare={props.isStored && !disabled}
canShare={props.isStored && !inShared}
isShared={isShared()}
clients={clients()}
inShared={inShared}
/>
<SpecHUD parser={parser} tick={tick()}
players={players()} kills={kills}/>
@ -174,14 +182,14 @@ export const Analyser = (props: AnalyseProps) => {
title={timeTitle()}>
<input class="play-pause-button" type="button"
value={playButtonText()}
disabled={disabled}
disabled={inShared}
onClick={togglePlay}
/>
<Timeline parser={parser} tick={tick()}
onSetTick={throttle(50, (tick) => {
setTickNow(tick);
})}
disabled={disabled}/>
disabled={inShared}/>
</div>
</div>
);

View file

@ -1,24 +1,22 @@
import {ownKeys} from "solid-js/store/types/store";
const syncUri = 'wss://sync.demos.tf';
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 | null = null) {
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): Session {
return new Session(generateToken(), generateToken(), state)
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 {
@ -29,26 +27,36 @@ export class Session {
if (this.socket) {
return;
}
this.socket = new WebSocket(syncUri);
this.socket = new WebSocket(this.syncUri);
this.socket.onopen = () => {
if (this.socket) {
if (this.owner_token) {
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.initialState = null;
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.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',
@ -62,7 +70,7 @@ export class Session {
});
}
if (packet.type === 'play') {
if (packet.play || packet.tick) {
if (packet.play) {
this.onState({
playing: true
});
@ -123,6 +131,7 @@ function generateToken(): string {
export interface PlaybackState {
tick: number,
playing: boolean,
clients: number,
}
export type StateUpdate = Partial<PlaybackState>;
@ -147,7 +156,12 @@ export interface PlayPacket {
type: 'play';
session: string;
play?: boolean;
tick?: boolean; //old sync server
}
export type Packet = JoinPacket | CreatePacket | TickPacket | PlayPacket;
export interface ClientsPacket {
type: 'clients';
session: string;
count: number;
}
export type Packet = JoinPacket | CreatePacket | TickPacket | PlayPacket | ClientsPacket;