git.schokokeks.org
Repositories
Help
Report an Issue
wirc-frontend.git
Code
Commits
Branches
Tags
Suche
Strukturansicht:
97e3029
Branches
Tags
master
wirc-frontend.git
source
logic
model.ts
[mov] source/*.ts -> source/logic/*.ts
Christian Fraß
commited
97e3029
at 2021-11-20 15:04:11
model.ts
Blame
History
Raw
namespace ns_model { /** * adds a listener for a certain incident */ export function listen ( model: type_model, incident: string, handler: (details?: any)=>void ): void { if (! model.listeners.hasOwnProperty(incident)) { model.listeners[incident] = []; } else { // do nothing } model.listeners[incident].push(handler); } /** * sends a notification to all listeners for a certain incident */ function notify ( model: type_model, incident: string, details: any = null ): void { if (model.listeners.hasOwnProperty(incident)) { for (const handler of model.listeners[incident]) { handler(details); } } } /** * sets the state */ export function set_state ( model: type_model, state: enum_state ): void { model.state = state; notify(model, "state_changed"); } /** * sets the active spot (channel or query) */ export function set_active ( model: type_model, spot: type_spot ): void { model.active = spot; notify(model, "spots_changed"); notify(model, "entries_changed"); notify(model, "users_changed"); } /** * updates the model according to a list of events */ function process_events ( model: type_model, events: Array<type_event> ): void { let shall_update_spots: boolean = false; let shall_update_entries: boolean = false; let shall_update_users: boolean = false; for (const event of events) { switch (event.kind) { default: { console.warn("unhandled event kind: " + event.kind); break; } case "userlist": { model.channels[event.data["channel"]].users = event.data["users"]; shall_update_users = true; break; } case "message_channel": { model.channels[event.data["channel"]].entries.push ({ "timestamp": event.timestamp, "sender": event.data["sender"], "content": event.data["content"], }); shall_update_entries = true; break; } case "message_query": { if (! model.queries.hasOwnProperty(event.data["user_name"])) { model.queries[event.data["user_name"]] = {"entries": []}; shall_update_spots = true; } else { // do nothing } model.queries[event.data["user_name"]].entries.push ({ "timestamp": event.timestamp, "sender": event.data["sender"], "content": event.data["content"], }); shall_update_entries = true; break; } } } if (shall_update_spots) notify(model, "spots_changed"); if (shall_update_entries) notify(model, "entries_changed"); if (shall_update_users) notify(model, "users_changed"); } /** * establishes the connection */ export async function connect ( conf: type_conf, model: type_model, nickname: string, channel_names: Array<string> ): Promise<void> { set_state(model, enum_state.connecting); const connection_id: string = await backend_call ( conf, model.connection_id, "connect", { "server": conf.irc.server, "channels": channel_names, "nickname": nickname, } ); model.connection_id = connection_id; model.nickname = nickname; for (const channel_name of channel_names) { model.channels[channel_name] = { "users": [], "entries": [], }; } if (channel_names.length > 0) { set_active(model, {"kind": "channel", "name": channel_names[0]}); } return Promise.resolve<void>(undefined); } /** * closes the connection */ export async function disconnect ( conf: type_conf, model: type_model ): Promise<void> { await backend_call ( conf, model.connection_id, "disconnect", null ); set_state(model, enum_state.offline); model.connection_id = null; return Promise.resolve<void>(undefined); } /** * adds a client side message */ export function send ( conf: type_conf, model: type_model, content: string ): void { switch (model.active.kind) { case "channel": { backend_call ( conf, model.connection_id, "send_channel", { "channel": model.active.name, "content": content, } ); const event: type_event = { "timestamp": get_timestamp(), "kind": "message_channel", "data": { "channel": model.active.name, "sender": model.nickname, "content": content, } }; process_events(model, [event]); notify(model, "entries_changed"); notify(model, "message_sent"); break; } case "query": { backend_call ( conf, model.connection_id, "send_query", { "receiver": model.active.name, "content": content, } ); const event: type_event = { "timestamp": get_timestamp(), "kind": "message_query", "data": { "user_name": model.active.name, "sender": model.nickname, "content": content, } }; process_events(model, [event]); notify(model, "entries_changed"); notify(model, "message_sent"); break; } } } /** * sets up the model */ export function setup ( conf: type_conf, model: type_model ): void { setInterval ( async () => { switch (model.state) { default: { throw (new Error(`invalid state '${model.state}'`)); break; } case enum_state.offline: { // do nothing break; } case enum_state.connecting: { const ready: boolean = await backend_call(conf, model.connection_id, "check", null); if (ready) { set_state(model, enum_state.online); } else { // do nothing } break; } case enum_state.online: { const events: Array<type_event> = await backend_call(conf, model.connection_id, "fetch", null); process_events(model, events); break; } } }, conf.settings.poll_interval_in_milliseconds ); set_state(model, enum_state.offline); } }