Christian Fraß commited on 2021-11-19 22:13:06
Zeige 3 geänderte Dateien mit 274 Einfügungen und 124 Löschungen.
| ... | ... |
@@ -36,10 +36,11 @@ |
| 36 | 36 |
</div> |
| 37 | 37 |
<div id="middle"> |
| 38 | 38 |
<ul class="pane" id="users"></ul> |
| 39 |
- <ul class="pane" id="events"></ul> |
|
| 39 |
+ <ul class="pane" id="entries"></ul> |
|
| 40 |
+ <ul class="pane" id="spots"></ul> |
|
| 40 | 41 |
</div> |
| 41 | 42 |
<form action="?"> |
| 42 |
- <input type="text" id="message" placeholder="…"/> |
|
| 43 |
+ <input type="text" id="content" placeholder="…"/> |
|
| 43 | 44 |
<input type="submit" id="send" value="send"/> |
| 44 | 45 |
</form> |
| 45 | 46 |
</div> |
| ... | ... |
@@ -24,14 +24,14 @@ function get_usercolor(name: string): string |
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 | 26 |
|
| 27 |
-async function backend_call(action: string, data: any): Promise<any> |
|
| 27 |
+async function backend_call(connection_id: (null | string), action: string, data: any): Promise<any> |
|
| 28 | 28 |
{
|
| 29 | 29 |
const response = await fetch |
| 30 | 30 |
( |
| 31 | 31 |
`${_conf["backend"]["scheme"]}://${_conf["backend"]["host"]}:${_conf["backend"]["port"].toFixed(0)}/${_conf["backend"]["path"]}`,
|
| 32 | 32 |
{
|
| 33 | 33 |
"method": "POST", |
| 34 |
- "body": JSON.stringify({"action": action, "id": _model.connection_id, "data": data}),
|
|
| 34 |
+ "body": JSON.stringify({"id": connection_id, "action": action, "data": data}),
|
|
| 35 | 35 |
} |
| 36 | 36 |
); |
| 37 | 37 |
if (response.ok) |
| ... | ... |
@@ -53,118 +53,209 @@ enum enum_state |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 | 55 |
|
| 56 |
-type type_model = |
|
| 56 |
+type type_event = |
|
| 57 | 57 |
{
|
| 58 |
- state: enum_state; |
|
| 59 |
- channel: (null | string); |
|
| 60 |
- nickname: (null | string); |
|
| 61 |
- connection_id: (null | string); |
|
| 62 |
- usershash: (null | string); |
|
| 58 |
+ timestamp: int; |
|
| 59 |
+ kind: string; |
|
| 60 |
+ data: any; |
|
| 63 | 61 |
}; |
| 64 | 62 |
|
| 65 | 63 |
|
| 66 |
-var _model: type_model = |
|
| 64 |
+type type_entry = |
|
| 67 | 65 |
{
|
| 68 |
- "state": enum_state.offline, |
|
| 69 |
- "channel": null, |
|
| 70 |
- "nickname": null, |
|
| 71 |
- "connection_id": null, |
|
| 72 |
- "usershash": null, |
|
| 66 |
+ timestamp: int; |
|
| 67 |
+ sender: string; |
|
| 68 |
+ content: string; |
|
| 73 | 69 |
}; |
| 74 | 70 |
|
| 75 | 71 |
|
| 76 |
-function update_state(): void |
|
| 72 |
+type type_user = |
|
| 77 | 73 |
{
|
| 78 |
- document.querySelector("body").setAttribute("class", _model.state);
|
|
| 79 |
-} |
|
| 74 |
+ name: string; |
|
| 75 |
+ role: string; |
|
| 76 |
+}; |
|
| 80 | 77 |
|
| 81 | 78 |
|
| 82 |
-function update_events(events): void |
|
| 79 |
+type type_channel = |
|
| 83 | 80 |
{
|
| 84 |
- let dom_events: HTMLUListElement = document.querySelector("#events");
|
|
| 85 |
- for (const event of events) |
|
| 81 |
+ users: Array<type_user>; |
|
| 82 |
+ entries: Array<type_entry>; |
|
| 83 |
+}; |
|
| 84 |
+ |
|
| 85 |
+ |
|
| 86 |
+type type_query = |
|
| 86 | 87 |
{
|
| 87 |
- const timestring: string = (new Date(event["timestamp"]*1000)).toISOString().slice(11, 19); |
|
| 88 |
- let dom_event: HTMLLIElement = document.createElement("li");
|
|
| 89 |
- dom_event.classList.add("event");
|
|
| 90 |
- switch (event["kind"]) |
|
| 88 |
+ entries: Array<type_entry>; |
|
| 89 |
+}; |
|
| 90 |
+ |
|
| 91 |
+ |
|
| 92 |
+type type_model = |
|
| 93 |
+{
|
|
| 94 |
+ state: enum_state; |
|
| 95 |
+ connection_id: (null | string); |
|
| 96 |
+ nickname: (null | string); |
|
| 97 |
+ channels: Record<string, type_channel>; |
|
| 98 |
+ queries: Record<string, type_query>; |
|
| 99 |
+ active: (null | {kind: string, name: string});
|
|
| 100 |
+}; |
|
| 101 |
+ |
|
| 102 |
+ |
|
| 103 |
+ |
|
| 104 |
+function model_set_state(model: type_model, state: enum_state): void |
|
| 105 |
+{
|
|
| 106 |
+ model.state = state; |
|
| 107 |
+ view_update_state(model); |
|
| 108 |
+} |
|
| 109 |
+ |
|
| 110 |
+ |
|
| 111 |
+function model_process_event(model: type_model, event: type_event): void |
|
| 112 |
+{
|
|
| 113 |
+ switch (event.kind) |
|
| 91 | 114 |
{
|
| 92 | 115 |
default: |
| 93 | 116 |
{
|
| 94 |
- dom_event.textContent = ("-- unhandled event: " + JSON.stringify(event));
|
|
| 117 |
+ console.warn("unhandled event kind: " + event.kind);
|
|
| 95 | 118 |
break; |
| 96 | 119 |
} |
| 97 |
- case "private_message": |
|
| 98 |
- {
|
|
| 120 |
+ case "userlist": |
|
| 99 | 121 |
{
|
| 100 |
- let dom_time: HTMLSpanElement = document.createElement("span");
|
|
| 101 |
- dom_time.classList.add("event_time");
|
|
| 102 |
- dom_time.textContent = timestring; |
|
| 103 |
- dom_event.appendChild(dom_time); |
|
| 122 |
+ model.channels[event.data["channel"]].users = event.data["users"]; |
|
| 123 |
+ break; |
|
| 104 | 124 |
} |
| 125 |
+ case "message_channel": |
|
| 105 | 126 |
{
|
| 106 |
- let dom_type: HTMLSpanElement = document.createElement("span");
|
|
| 107 |
- dom_type.classList.add("event_type");
|
|
| 108 |
- dom_type.textContent = 'private'; |
|
| 109 |
- dom_event.appendChild(dom_type); |
|
| 127 |
+ model.channels[event.data["channel"]].entries.push |
|
| 128 |
+ ({
|
|
| 129 |
+ "timestamp": event.timestamp, |
|
| 130 |
+ "sender": event.data["sender"], |
|
| 131 |
+ "content": event.data["content"], |
|
| 132 |
+ }); |
|
| 133 |
+ break; |
|
| 110 | 134 |
} |
| 135 |
+ case "message_query": |
|
| 111 | 136 |
{
|
| 112 |
- let dom_sender: HTMLSpanElement = document.createElement("span");
|
|
| 113 |
- dom_sender.classList.add("event_sender");
|
|
| 114 |
- dom_sender.style.color = get_usercolor(event["data"]["from"] ?? ""); |
|
| 115 |
- dom_sender.textContent = event["data"]["from"]; |
|
| 116 |
- dom_event.appendChild(dom_sender); |
|
| 137 |
+ if (! model.queries.hasOwnProperty(event.data["sender"])) |
|
| 138 |
+ {
|
|
| 139 |
+ model.queries[event.data["sender"]] = {"entries": []};
|
|
| 117 | 140 |
} |
| 141 |
+ else |
|
| 118 | 142 |
{
|
| 119 |
- let dom_message: HTMLSpanElement = document.createElement("span");
|
|
| 120 |
- dom_message.classList.add("event_message");
|
|
| 121 |
- dom_message.textContent = event["data"]["message"]; |
|
| 122 |
- dom_event.appendChild(dom_message); |
|
| 143 |
+ // do nothing |
|
| 123 | 144 |
} |
| 145 |
+ model.queries[event.data["sender"]].entries.push |
|
| 146 |
+ ({
|
|
| 147 |
+ "timestamp": event.timestamp, |
|
| 148 |
+ "sender": event.data["sender"], |
|
| 149 |
+ "content": event.data["content"], |
|
| 150 |
+ }); |
|
| 124 | 151 |
break; |
| 125 | 152 |
} |
| 126 |
- case "channel_message": |
|
| 127 |
- {
|
|
| 153 |
+ } |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 156 |
+ |
|
| 157 |
+function view_update_state(model: type_model): void |
|
| 128 | 158 |
{
|
| 129 |
- let dom_time: HTMLSpanElement = document.createElement("span");
|
|
| 130 |
- dom_time.classList.add("event_time");
|
|
| 131 |
- dom_time.textContent = timestring; |
|
| 132 |
- dom_event.appendChild(dom_time); |
|
| 159 |
+ document.querySelector("body").setAttribute("class", model.state);
|
|
| 133 | 160 |
} |
| 161 |
+ |
|
| 162 |
+ |
|
| 163 |
+function view_update_spots(model: type_model): void |
|
| 134 | 164 |
{
|
| 135 |
- let dom_sender: HTMLSpanElement = document.createElement("span");
|
|
| 136 |
- dom_sender.classList.add("event_sender");
|
|
| 137 |
- dom_sender.style.color = get_usercolor(event["data"]["from"] ?? ""); |
|
| 138 |
- dom_sender.textContent = event["data"]["from"]; |
|
| 139 |
- dom_event.appendChild(dom_sender); |
|
| 165 |
+ let dom_spots: HTMLUListElement = document.querySelector("#spots");
|
|
| 166 |
+ const spots: Array<{kind: string; name: string}> = (
|
|
| 167 |
+ [] |
|
| 168 |
+ .concat(Object.keys(model.channels).map((name) => ({"kind": "channel", "name": name})))
|
|
| 169 |
+ .concat(Object.keys(model.queries).map((name) => ({"kind": "channel", "name": name})))
|
|
| 170 |
+ ); |
|
| 171 |
+ dom_spots.textContent = ""; |
|
| 172 |
+ for (const spot of spots) |
|
| 173 |
+ {
|
|
| 174 |
+ let dom_spot: HTMLLIElement = document.createElement("li");
|
|
| 175 |
+ dom_spot.classList.add("spot");
|
|
| 176 |
+ {
|
|
| 177 |
+ let dom_name: HTMLSpanElement = document.createElement("span");
|
|
| 178 |
+ dom_name.classList.add("spot_sender");
|
|
| 179 |
+ dom_name.textContent = spot.name; |
|
| 180 |
+ dom_spot.appendChild(dom_name); |
|
| 181 |
+ } |
|
| 182 |
+ dom_spots.appendChild(dom_spot); |
|
| 140 | 183 |
} |
| 184 |
+} |
|
| 185 |
+ |
|
| 186 |
+ |
|
| 187 |
+function view_update_entries(model: type_model): void |
|
| 188 |
+{
|
|
| 189 |
+ let dom_entries: HTMLUListElement = document.querySelector("#entries");
|
|
| 190 |
+ let source: Array<type_entry>; |
|
| 191 |
+ switch (model.active.kind) |
|
| 141 | 192 |
{
|
| 142 |
- let dom_message: HTMLSpanElement = document.createElement("span");
|
|
| 143 |
- dom_message.classList.add("event_message");
|
|
| 144 |
- dom_message.textContent = event["data"]["message"]; |
|
| 145 |
- dom_event.appendChild(dom_message); |
|
| 193 |
+ case "channel": |
|
| 194 |
+ {
|
|
| 195 |
+ source = model.channels[model.active.name].entries; |
|
| 196 |
+ break; |
|
| 146 | 197 |
} |
| 198 |
+ case "query": |
|
| 199 |
+ {
|
|
| 200 |
+ source = model.queries[model.active.name].entries; |
|
| 147 | 201 |
break; |
| 148 | 202 |
} |
| 149 | 203 |
} |
| 150 |
- dom_events.appendChild(dom_event); |
|
| 204 |
+ dom_entries.textContent = ""; |
|
| 205 |
+ for (const entry of model.channels[model.active.name].entries) |
|
| 206 |
+ {
|
|
| 207 |
+ let dom_entry: HTMLLIElement = document.createElement("li");
|
|
| 208 |
+ dom_entry.classList.add("entry");
|
|
| 209 |
+ {
|
|
| 210 |
+ let dom_time: HTMLSpanElement = document.createElement("span");
|
|
| 211 |
+ dom_time.classList.add("entry_time");
|
|
| 212 |
+ dom_time.textContent = (new Date(entry.timestamp*1000)).toISOString().slice(11, 19); |
|
| 213 |
+ dom_entry.appendChild(dom_time); |
|
| 151 | 214 |
} |
| 152 |
- if (events.length > 0) |
|
| 153 | 215 |
{
|
| 154 |
- dom_events.scrollTo(0, dom_events["scrollTopMax"]); |
|
| 216 |
+ let dom_sender: HTMLSpanElement = document.createElement("span");
|
|
| 217 |
+ dom_sender.classList.add("entry_sender");
|
|
| 218 |
+ dom_sender.style.color = get_usercolor(entry.sender); |
|
| 219 |
+ dom_sender.textContent = entry.sender; |
|
| 220 |
+ dom_entry.appendChild(dom_sender); |
|
| 155 | 221 |
} |
| 156 |
- else |
|
| 157 | 222 |
{
|
| 158 |
- // do nothing |
|
| 223 |
+ let dom_content: HTMLSpanElement = document.createElement("span");
|
|
| 224 |
+ dom_content.classList.add("entry_content");
|
|
| 225 |
+ dom_content.textContent = entry.content; |
|
| 226 |
+ dom_entry.appendChild(dom_content); |
|
| 159 | 227 |
} |
| 228 |
+ dom_entries.appendChild(dom_entry); |
|
| 229 |
+ } |
|
| 230 |
+ dom_entries.scrollTo(0, dom_entries["scrollTopMax"]); |
|
| 160 | 231 |
} |
| 161 | 232 |
|
| 162 | 233 |
|
| 163 |
-function update_users(users: Array<{name: string; role: string;}>): void
|
|
| 234 |
+function view_update_users(model: type_model): void |
|
| 164 | 235 |
{
|
| 165 | 236 |
let dom_users: HTMLUListElement = document.querySelector("#users");
|
| 166 | 237 |
dom_users.textContent = ""; |
| 167 |
- const users_sorted: Array<{name: string; role: string;}> = users.sort
|
|
| 238 |
+ let source: Array<type_user>; |
|
| 239 |
+ switch (model.active.kind) |
|
| 240 |
+ {
|
|
| 241 |
+ default: |
|
| 242 |
+ {
|
|
| 243 |
+ console.warn("unhandled kind: " + model.active.kind);
|
|
| 244 |
+ source = []; |
|
| 245 |
+ break; |
|
| 246 |
+ } |
|
| 247 |
+ case "channel": |
|
| 248 |
+ {
|
|
| 249 |
+ source = model.channels[model.active.name].users; |
|
| 250 |
+ break; |
|
| 251 |
+ } |
|
| 252 |
+ case "query": |
|
| 253 |
+ {
|
|
| 254 |
+ source = [{"name": model.nickname, "role": ""}, {"name": model.active.name, "role": ""}];
|
|
| 255 |
+ break; |
|
| 256 |
+ } |
|
| 257 |
+ } |
|
| 258 |
+ const users_sorted: Array<type_user> = source.sort |
|
| 168 | 259 |
( |
| 169 | 260 |
(x, y) => |
| 170 | 261 |
( |
| ... | ... |
@@ -197,14 +288,7 @@ function update_users(users: Array<{name: string; role: string;}>): void
|
| 197 | 288 |
} |
| 198 | 289 |
|
| 199 | 290 |
|
| 200 |
-function set_state(state: enum_state): void |
|
| 201 |
-{
|
|
| 202 |
- _model.state = state; |
|
| 203 |
- update_state(); |
|
| 204 |
-} |
|
| 205 |
- |
|
| 206 |
- |
|
| 207 |
-function setup_view(): void |
|
| 291 |
+function view_setup(model: type_model): void |
|
| 208 | 292 |
{
|
| 209 | 293 |
document.querySelector<HTMLInputElement>("#channel").value = _conf["irc"]["predefined_channel"];
|
| 210 | 294 |
document.querySelector<HTMLInputElement>("#nickname").value = (_conf["irc"]["predefined_nickname_prefix"] + (Math.random()*100).toFixed(0));
|
| ... | ... |
@@ -212,11 +296,11 @@ function setup_view(): void |
| 212 | 296 |
( |
| 213 | 297 |
async () => |
| 214 | 298 |
{
|
| 215 |
- switch (_model.state) |
|
| 299 |
+ switch (model.state) |
|
| 216 | 300 |
{
|
| 217 | 301 |
default: |
| 218 | 302 |
{
|
| 219 |
- throw (new Error("invalid state: " + _model.state));
|
|
| 303 |
+ throw (new Error("invalid state: " + model.state));
|
|
| 220 | 304 |
break; |
| 221 | 305 |
} |
| 222 | 306 |
case enum_state.offline: |
| ... | ... |
@@ -226,10 +310,10 @@ function setup_view(): void |
| 226 | 310 |
} |
| 227 | 311 |
case enum_state.connecting: |
| 228 | 312 |
{
|
| 229 |
- const ready: boolean = await backend_call("check", null);
|
|
| 313 |
+ const ready: boolean = await backend_call(model.connection_id, "check", null); |
|
| 230 | 314 |
if (ready) |
| 231 | 315 |
{
|
| 232 |
- set_state(enum_state.online); |
|
| 316 |
+ model_set_state(model, enum_state.online); |
|
| 233 | 317 |
} |
| 234 | 318 |
else |
| 235 | 319 |
{
|
| ... | ... |
@@ -239,29 +323,25 @@ function setup_view(): void |
| 239 | 323 |
} |
| 240 | 324 |
case enum_state.online: |
| 241 | 325 |
{
|
| 242 |
- const stuff: any = await backend_call("fetch", null);
|
|
| 243 |
- update_events(stuff["events"]); |
|
| 244 |
- const usershash: string = btoa(JSON.stringify(stuff["users"])); |
|
| 245 |
- if (_model.usershash !== usershash) |
|
| 246 |
- {
|
|
| 247 |
- _model.usershash = usershash; |
|
| 248 |
- update_users(stuff["users"]); |
|
| 249 |
- } |
|
| 250 |
- else |
|
| 326 |
+ const events: Array<type_event> = await backend_call(model.connection_id, "fetch", null); |
|
| 327 |
+ for (const event of events) |
|
| 251 | 328 |
{
|
| 252 |
- // do nothing |
|
| 329 |
+ model_process_event(model, event); |
|
| 253 | 330 |
} |
| 331 |
+ view_update_users(model); |
|
| 332 |
+ view_update_entries(model); |
|
| 333 |
+ view_update_spots(model); |
|
| 254 | 334 |
break; |
| 255 | 335 |
} |
| 256 | 336 |
} |
| 257 | 337 |
}, |
| 258 | 338 |
_conf["settings"]["poll_interval_in_milliseconds"] |
| 259 | 339 |
); |
| 260 |
- set_state(enum_state.offline); |
|
| 340 |
+ model_set_state(model, enum_state.offline); |
|
| 261 | 341 |
} |
| 262 | 342 |
|
| 263 | 343 |
|
| 264 |
-function setup_control(): void |
|
| 344 |
+function control_setup(model: type_model): void |
|
| 265 | 345 |
{
|
| 266 | 346 |
document.querySelector("#connect > form").addEventListener
|
| 267 | 347 |
( |
| ... | ... |
@@ -269,23 +349,36 @@ function setup_control(): void |
| 269 | 349 |
async (event) => |
| 270 | 350 |
{
|
| 271 | 351 |
event.preventDefault(); |
| 352 |
+ |
|
| 353 |
+ model_set_state(model, enum_state.connecting); |
|
| 354 |
+ |
|
| 272 | 355 |
let dom_nickname: HTMLInputElement = document.querySelector<HTMLInputElement>("#nickname");
|
| 273 | 356 |
let dom_channel: HTMLInputElement = document.querySelector<HTMLInputElement>("#channel");
|
| 274 | 357 |
const nickname: string = dom_nickname.value; |
| 275 |
- const channel: string = dom_channel.value; |
|
| 358 |
+ const channel_names: Array<string> = dom_channel.value.split(",");
|
|
| 359 |
+ |
|
| 276 | 360 |
const connection_id: string = await backend_call |
| 277 | 361 |
( |
| 362 |
+ model.connection_id, |
|
| 278 | 363 |
"connect", |
| 279 | 364 |
{
|
| 280 | 365 |
"server": _conf["irc"]["server"], |
| 281 |
- "channels": [channel], |
|
| 366 |
+ "channels": channel_names, |
|
| 282 | 367 |
"nickname": nickname, |
| 283 | 368 |
} |
| 284 | 369 |
); |
| 285 |
- _model.connection_id = connection_id; |
|
| 286 |
- _model.channel = channel; |
|
| 287 |
- _model.nickname = nickname; |
|
| 288 |
- set_state(enum_state.connecting); |
|
| 370 |
+ model.connection_id = connection_id; |
|
| 371 |
+ model.nickname = nickname; |
|
| 372 |
+ for (const channel_name of channel_names) |
|
| 373 |
+ {
|
|
| 374 |
+ model.channels[channel_name] = |
|
| 375 |
+ {
|
|
| 376 |
+ "users": [], |
|
| 377 |
+ "entries": [], |
|
| 378 |
+ }; |
|
| 379 |
+ } |
|
| 380 |
+ // TODO: can crash |
|
| 381 |
+ model.active = {"kind": "channel", "name": channel_names[0]};
|
|
| 289 | 382 |
} |
| 290 | 383 |
); |
| 291 | 384 |
document.querySelector("#disconnect").addEventListener
|
| ... | ... |
@@ -295,42 +388,80 @@ function setup_control(): void |
| 295 | 388 |
{
|
| 296 | 389 |
await backend_call |
| 297 | 390 |
( |
| 391 |
+ model.connection_id, |
|
| 298 | 392 |
"disconnect", |
| 299 | 393 |
null |
| 300 | 394 |
); |
| 301 |
- set_state(enum_state.offline); |
|
| 302 |
- _model.connection_id = null; |
|
| 395 |
+ model_set_state(model, enum_state.offline); |
|
| 396 |
+ model.connection_id = null; |
|
| 303 | 397 |
} |
| 304 | 398 |
); |
| 305 | 399 |
document.querySelector("#main > form").addEventListener
|
| 306 | 400 |
( |
| 307 | 401 |
"submit", |
| 308 |
- async (event) => |
|
| 402 |
+ async (e) => |
|
| 309 | 403 |
{
|
| 310 | 404 |
event.preventDefault(); |
| 311 |
- let dom_message: HTMLInputElement = document.querySelector<HTMLInputElement>("#message");
|
|
| 312 |
- const message: string = dom_message.value; |
|
| 313 |
- dom_message.value = ""; |
|
| 314 |
- dom_message.focus(); |
|
| 315 |
- const event_: any = |
|
| 405 |
+ |
|
| 406 |
+ let dom_content: HTMLInputElement = document.querySelector<HTMLInputElement>("#content");
|
|
| 407 |
+ const content: string = dom_content.value; |
|
| 408 |
+ dom_content.value = ""; |
|
| 409 |
+ dom_content.focus(); |
|
| 410 |
+ switch (model.active.kind) |
|
| 411 |
+ {
|
|
| 412 |
+ case "channel": |
|
| 413 |
+ {
|
|
| 414 |
+ const event: type_event = |
|
| 316 | 415 |
{
|
| 317 | 416 |
"timestamp": get_timestamp(), |
| 318 |
- "kind": "channel_message", |
|
| 319 |
- "data": {
|
|
| 320 |
- "from": _model.nickname, |
|
| 321 |
- "to": _model.channel, |
|
| 322 |
- "message": message, |
|
| 417 |
+ "kind": "message_channel", |
|
| 418 |
+ "data": |
|
| 419 |
+ {
|
|
| 420 |
+ "channel": model.active.name, |
|
| 421 |
+ "sender": model.nickname, |
|
| 422 |
+ "content": content, |
|
| 323 | 423 |
} |
| 324 | 424 |
}; |
| 325 |
- update_events([event_]); |
|
| 326 |
- await backend_call |
|
| 425 |
+ model_process_event(model, event); |
|
| 426 |
+ view_update_entries(model); |
|
| 427 |
+ backend_call |
|
| 327 | 428 |
( |
| 328 |
- "send", |
|
| 429 |
+ model.connection_id, |
|
| 430 |
+ "send_channel", |
|
| 431 |
+ {
|
|
| 432 |
+ "channel": model.active.name, |
|
| 433 |
+ "content": content, |
|
| 434 |
+ } |
|
| 435 |
+ ); |
|
| 436 |
+ break; |
|
| 437 |
+ } |
|
| 438 |
+ case "query": |
|
| 329 | 439 |
{
|
| 330 |
- "channel": _model.channel, |
|
| 440 |
+ /* |
|
| 441 |
+ const event: type_event = |
|
| 442 |
+ {
|
|
| 443 |
+ "timestamp": get_timestamp(), |
|
| 444 |
+ "kind": "message_query", |
|
| 445 |
+ "data": |
|
| 446 |
+ {
|
|
| 447 |
+ "sender": model.nickname, |
|
| 331 | 448 |
"message": message, |
| 332 | 449 |
} |
| 450 |
+ }; |
|
| 451 |
+ model_process_event(model, event); |
|
| 452 |
+ */ |
|
| 453 |
+ backend_call |
|
| 454 |
+ ( |
|
| 455 |
+ model.connection_id, |
|
| 456 |
+ "send_query", |
|
| 457 |
+ {
|
|
| 458 |
+ "receiver": model.active.name, |
|
| 459 |
+ "content": content, |
|
| 460 |
+ } |
|
| 333 | 461 |
); |
| 462 |
+ break; |
|
| 463 |
+ } |
|
| 464 |
+ } |
|
| 334 | 465 |
} |
| 335 | 466 |
); |
| 336 | 467 |
} |
| ... | ... |
@@ -339,8 +470,17 @@ function setup_control(): void |
| 339 | 470 |
async function main(): Promise<void> |
| 340 | 471 |
{
|
| 341 | 472 |
_conf = await fetch("conf.json").then(x => x.json());
|
| 342 |
- setup_view(); |
|
| 343 |
- setup_control(); |
|
| 473 |
+ const model: type_model = |
|
| 474 |
+ {
|
|
| 475 |
+ "state": enum_state.offline, |
|
| 476 |
+ "connection_id": null, |
|
| 477 |
+ "nickname": null, |
|
| 478 |
+ "channels": {},
|
|
| 479 |
+ "queries": {},
|
|
| 480 |
+ "active": null, |
|
| 481 |
+ }; |
|
| 482 |
+ view_setup(model); |
|
| 483 |
+ control_setup(model); |
|
| 344 | 484 |
} |
| 345 | 485 |
|
| 346 | 486 |
|
| ... | ... |
@@ -41,12 +41,12 @@ label |
| 41 | 41 |
margin: 16px 0; |
| 42 | 42 |
} |
| 43 | 43 |
|
| 44 |
-.event > * |
|
| 44 |
+.entry > * |
|
| 45 | 45 |
{
|
| 46 | 46 |
display: inline-block; |
| 47 | 47 |
} |
| 48 | 48 |
|
| 49 |
-.event_time |
|
| 49 |
+.entry_time |
|
| 50 | 50 |
{
|
| 51 | 51 |
margin: 0 4px; |
| 52 | 52 |
|
| ... | ... |
@@ -63,7 +63,7 @@ label |
| 63 | 63 |
} |
| 64 | 64 |
} |
| 65 | 65 |
|
| 66 |
-.event_type |
|
| 66 |
+.entry_type |
|
| 67 | 67 |
{
|
| 68 | 68 |
margin: 0 4px; |
| 69 | 69 |
|
| ... | ... |
@@ -80,7 +80,7 @@ label |
| 80 | 80 |
} |
| 81 | 81 |
} |
| 82 | 82 |
|
| 83 |
-.event_sender |
|
| 83 |
+.entry_sender |
|
| 84 | 84 |
{
|
| 85 | 85 |
margin: 0 4px; |
| 86 | 86 |
|
| ... | ... |
@@ -167,7 +167,16 @@ body |
| 167 | 167 |
flex-direction: row-reverse; |
| 168 | 168 |
flex-wrap: wrap; |
| 169 | 169 |
|
| 170 |
- & #events |
|
| 170 |
+ & #spots |
|
| 171 |
+ {
|
|
| 172 |
+ flex-grow: 1; |
|
| 173 |
+ flex-shrink: 1; |
|
| 174 |
+ |
|
| 175 |
+ min-width: 240px; |
|
| 176 |
+ height: 75vh; |
|
| 177 |
+ } |
|
| 178 |
+ |
|
| 179 |
+ & #entries |
|
| 171 | 180 |
{
|
| 172 | 181 |
flex-grow: 4; |
| 173 | 182 |
flex-shrink: 4; |
| ... | ... |
@@ -186,7 +195,7 @@ body |
| 186 | 195 |
} |
| 187 | 196 |
} |
| 188 | 197 |
|
| 189 |
-#message |
|
| 198 |
+#content |
|
| 190 | 199 |
{
|
| 191 | 200 |
border: none; |
| 192 | 201 |
|
| ... | ... |
@@ -203,7 +212,7 @@ body |
| 203 | 212 |
flex-direction: row; |
| 204 | 213 |
flex-wrap: wrap; |
| 205 | 214 |
|
| 206 |
- & > #message {flex: 7;}
|
|
| 215 |
+ & > #content {flex: 7;}
|
|
| 207 | 216 |
& > #send {flex: 1;}
|
| 208 | 217 |
} |
| 209 | 218 |
|
| 210 | 219 |