diff options
Diffstat (limited to 'client-web/source')
-rw-r--r-- | client-web/source/chat.ts | 41 | ||||
-rw-r--r-- | client-web/source/helper.ts | 18 | ||||
-rw-r--r-- | client-web/source/index.ts | 16 | ||||
-rw-r--r-- | client-web/source/logger.ts | 13 | ||||
-rw-r--r-- | client-web/source/menu.ts | 24 | ||||
-rw-r--r-- | client-web/source/room.ts | 2 | ||||
-rw-r--r-- | client-web/source/user/local.ts | 4 |
7 files changed, 95 insertions, 23 deletions
diff --git a/client-web/source/chat.ts b/client-web/source/chat.ts new file mode 100644 index 0000000..d1165ee --- /dev/null +++ b/client-web/source/chat.ts @@ -0,0 +1,41 @@ +import { ediv, espan } from "./helper.ts"; +import { CHAT } from "./index.ts"; +import { Room } from "./room.ts"; +import { User } from "./user/mod.ts"; + +export class Chat { + private _shown = false; + + messages = ediv({ class: "messages" }) + controls = ediv({ class: "controls" }) + + get shown() { return this._shown } + set shown(value: boolean) { + if (value && !this._shown) document.body.prepend(CHAT) + if (!value && this._shown) document.body.removeChild(CHAT) + this._shown = value + } + + constructor(public room: Room) { + const send = document.createElement("input") + send.type = "text" + send.onkeydown = (ev) => { + if (ev.code == "Enter") { + room.local_user.chat(send.value) + this.send_message(room.local_user, send.value) + send.value = "" + } + } + this.controls.append(send) + this.messages.append(document.createElement("hr")) + CHAT.append(this.messages, this.controls) + } + + send_message(sender: User, message: string) { + this.messages.append(ediv({ class: "message" }, + espan(sender.display_name, { class: "author" }), + ": ", + espan(message, { class: "content" }) + )) + } +} diff --git a/client-web/source/helper.ts b/client-web/source/helper.ts index 4f97ebb..8dafd29 100644 --- a/client-web/source/helper.ts +++ b/client-web/source/helper.ts @@ -6,14 +6,24 @@ export function hex_id(len = 8): string { } const elem = (s: string) => document.createElement(s) -const elem_with_content = (s: string) => (c: string) => { + +interface Opts { class?: string[] | string, id?: string } + +function apply_opts(e: HTMLElement, o: Opts | undefined) { + if (!o) return + if (o.id) e.id = o.id + if (typeof o?.class == "string") e.classList.add(o.class) + if (typeof o?.class == "object") e.classList.add(...o.class) +} +const elem_with_content = (s: string) => (c: string, opts?: Opts) => { const e = elem(s) + apply_opts(e, opts) e.textContent = c return e } -const elem_with_children = (s: string) => (opts: { class?: string[] }, ...cs: (HTMLElement | string)[]) => { +const elem_with_children = (s: string) => (opts?: Opts, ...cs: (HTMLElement | string)[]) => { const e = elem(s) - if (opts.class) e.classList.add(...opts.class) + apply_opts(e, opts) for (const c of cs) { e.append(c) } @@ -28,4 +38,6 @@ export const eh4 = elem_with_content("h4") export const eh5 = elem_with_content("h5") export const eh6 = elem_with_content("h6") export const ediv = elem_with_children("div") +export const espan = elem_with_content("span") +export const elabel = elem_with_content("label") diff --git a/client-web/source/index.ts b/client-web/source/index.ts index a57cec3..e8bbc0b 100644 --- a/client-web/source/index.ts +++ b/client-web/source/index.ts @@ -2,13 +2,17 @@ import { ediv } from "./helper.ts"; import { log } from "./logger.ts" -import { create_menu } from "./menu.ts"; +import { setup_menus } from "./menu.ts"; import { load_params, PREFS } from "./preferences.ts"; import { SignalingConnection } from "./protocol/mod.ts"; import { Room } from "./room.ts" -export const BOTTOM_CONTAINER = ediv({ class: ["bottom-container"] }) -export const ROOM_CONTAINER = ediv({ class: ["room"] }) +export const VERSION = "0.1.8" +export const BOTTOM_CONTAINER = ediv({ class: "bottom-container" }) +export const ROOM_CONTAINER = ediv({ class: "room" }) +export const MENU_BR = ediv({ class: "menu-br" }) +export const CHAT = ediv({ class: "chat" }) +export const LOGGER_CONTAINER = ediv({ class: "logger-container" }) export const RTC_CONFIG: RTCConfiguration = { // google stun!? @@ -36,7 +40,7 @@ export async function main() { if (PREFS.warn_redirect) log({ scope: "crypto", warn: true }, "You were redirected from the old URL format. The server knows you room name now - e2ee is insecure!") const conn = await (new SignalingConnection().connect(room_name)) - new Room(conn) - create_menu() - document.body.append(ROOM_CONTAINER, BOTTOM_CONTAINER) + const r = new Room(conn) + setup_menus(r) + document.body.append(ROOM_CONTAINER, BOTTOM_CONTAINER, MENU_BR, LOGGER_CONTAINER) } diff --git a/client-web/source/logger.ts b/client-web/source/logger.ts index 935eb20..c44ea6b 100644 --- a/client-web/source/logger.ts +++ b/client-web/source/logger.ts @@ -1,5 +1,7 @@ /// <reference lib="dom" /> +import { LOGGER_CONTAINER } from "./index.ts"; + const log_scope_color = { "*": "#ff4a7c", crypto: "#c14aff", @@ -13,8 +15,6 @@ const log_scope_color = { export type LogScope = keyof typeof log_scope_color export interface LogDesc { scope: LogScope, error?: boolean, warn?: boolean } -let logger_container: HTMLDivElement - export function log(k: LogScope | LogDesc, message: string, ...data: unknown[]) { for (let i = 0; i < data.length; i++) { @@ -27,14 +27,14 @@ export function log(k: LogScope | LogDesc, message: string, ...data: unknown[]) (d.error ? console.error : d.warn ? console.warn : console.log)(`%c[${d.scope}] ${message}`, `color:${log_scope_color[d.scope]}`, ...data); - if (logger_container) { + if (LOGGER_CONTAINER) { const e = document.createElement("p") e.classList.add("logger-line") if (d.error) e.classList.add("logger-error") else if (d.warn) e.classList.add("logger-warn") else e.style.color = log_scope_color[d.scope] e.textContent = `[${d.scope}] ${message}` - logger_container.append(e) + LOGGER_CONTAINER.append(e) setTimeout(() => { e.classList.add("logger-line-disappear") setTimeout(() => { @@ -45,11 +45,6 @@ export function log(k: LogScope | LogDesc, message: string, ...data: unknown[]) } globalThis.addEventListener("load", () => { - const d = document.createElement("div") - d.classList.add("logger-container") - document.body.append(d) - logger_container = d - // clear the console every hour so logs dont accumulate setInterval(() => console.clear(), 1000 * 60 * 60) }) diff --git a/client-web/source/menu.ts b/client-web/source/menu.ts index a3755c3..5abb8f0 100644 --- a/client-web/source/menu.ts +++ b/client-web/source/menu.ts @@ -1,10 +1,10 @@ /// <reference lib="dom" /> -export function create_menu() { - const menu = document.createElement("div") - menu.classList.add("menu-overlay") - document.body.append(menu) +import { ep } from "./helper.ts" +import { BOTTOM_CONTAINER, MENU_BR, VERSION } from "./index.ts" +import { Room } from "./room.ts" +export function setup_menus(room: Room) { const item = (name: string, cb: (() => void) | string) => { const p = document.createElement("p") const a = document.createElement("a") @@ -17,9 +17,23 @@ export function create_menu() { return p } - menu.append( + MENU_BR.append( + ep(`keks-meet ${VERSION}`, { class: "version" }), item("Settings", () => alert("todo, refer to the url parameters in the docs for now")), item("Licence", "/licence"), item("Sources / Documentation", "https://codeberg.org/metamuffin/keks-meet"), ) + + + // TODO this should ideally be a checkbox + const chat_toggle = document.createElement("input") + chat_toggle.type = "button" + chat_toggle.id = "chat_toggle" + chat_toggle.value = "Toggle chat" + chat_toggle.onclick = () => { + room.chat.shown = !room.chat.shown + if (room.chat.shown) chat_toggle.classList.add("active") + else chat_toggle.classList.remove("active") + } + BOTTOM_CONTAINER.append(chat_toggle) } diff --git a/client-web/source/room.ts b/client-web/source/room.ts index 5813faa..53c020f 100644 --- a/client-web/source/room.ts +++ b/client-web/source/room.ts @@ -6,12 +6,14 @@ import { User } from "./user/mod.ts"; import { LocalUser } from "./user/local.ts"; import { ClientboundPacket, RelayMessage } from "../../common/packets.d.ts"; import { SignalingConnection } from "./protocol/mod.ts"; +import { Chat } from "./chat.ts"; export class Room { public users: Map<number, User> = new Map() public remote_users: Map<number, RemoteUser> = new Map() public local_user!: LocalUser public my_id!: number + public chat: Chat = new Chat(this) constructor(public signaling: SignalingConnection) { this.signaling.control_handler = (a) => this.control_handler(a) diff --git a/client-web/source/user/local.ts b/client-web/source/user/local.ts index 2ea1ea6..053bc0a 100644 --- a/client-web/source/user/local.ts +++ b/client-web/source/user/local.ts @@ -46,6 +46,10 @@ export class LocalUser extends User { }) } + chat(content: string) { + this.room.signaling.send_relay({ chat: { content } }) + } + add_initial_to_remote(u: RemoteUser) { this.tracks.forEach(t => u.peer.addTrack(t.track)) } |