[mod] selektives view-update
Christian Fraß

Christian Fraß commited on 2021-11-19 23:49:28
Zeige 3 geänderte Dateien mit 106 Einfügungen und 60 Löschungen.

... ...
@@ -40,8 +40,12 @@
40 40
 				<ul class="pane" id="spots"></ul>
41 41
 			</div>
42 42
 			<form action="?">
43
+				<div id="container_content">
43 44
 					<input type="text" id="content" placeholder="…"/>
45
+				</div>
46
+				<div id="container_send">
44 47
 					<input type="submit" id="send" value="send"/>
48
+				</div>
45 49
 			</form>
46 50
 		</div>
47 51
 	</body>
... ...
@@ -61,6 +61,13 @@ type type_event =
61 61
 };
62 62
 
63 63
 
64
+type type_spot =
65
+{
66
+	kind: string;
67
+	name: string;
68
+};
69
+
70
+
64 71
 type type_entry =
65 72
 {
66 73
 	timestamp: int;
... ...
@@ -96,7 +103,7 @@ type type_model =
96 103
 	nickname: (null | string);
97 104
 	channels: Record<string, type_channel>;
98 105
 	queries: Record<string, type_query>;
99
-	active: (null | {kind: string, name: string});
106
+	active: (null | type_spot);
100 107
 };
101 108
 
102 109
 
... ...
@@ -108,7 +115,21 @@ function model_set_state(model: type_model, state: enum_state): void
108 115
 }
109 116
 
110 117
 
111
-function model_process_event(model: type_model, event: type_event): void
118
+function model_set_active(model: type_model, spot: type_spot): void
119
+{
120
+	model.active = spot;
121
+	view_update_spots(model);
122
+	view_update_entries(model);
123
+	view_update_users(model);
124
+}
125
+
126
+
127
+function model_process_events(model: type_model, events: Array<type_event>): void
128
+{
129
+	let shall_update_spots: boolean = false;
130
+	let shall_update_entries: boolean = false;
131
+	let shall_update_users: boolean = false;
132
+	for (const event of events)
112 133
 	{
113 134
 		switch (event.kind)
114 135
 		{
... ...
@@ -120,6 +141,7 @@ function model_process_event(model: type_model, event: type_event): void
120 141
 			case "userlist":
121 142
 			{
122 143
 				model.channels[event.data["channel"]].users = event.data["users"];
144
+				shall_update_users = true;
123 145
 				break;
124 146
 			}
125 147
 			case "message_channel":
... ...
@@ -130,29 +152,41 @@ function model_process_event(model: type_model, event: type_event): void
130 152
 					"sender": event.data["sender"],
131 153
 					"content": event.data["content"],
132 154
 				});
155
+				shall_update_entries = true;
133 156
 				break;
134 157
 			}
135 158
 			case "message_query":
136 159
 			{
137
-			if (! model.queries.hasOwnProperty(event.data["sender"]))
160
+				if (! model.queries.hasOwnProperty(event.data["user_name"]))
138 161
 				{
139
-				model.queries[event.data["sender"]] = {"entries": []};
162
+					model.queries[event.data["user_name"]] = {"entries": []};
163
+					shall_update_spots = true;
140 164
 				}
141 165
 				else
142 166
 				{
143 167
 					// do nothing
144 168
 				}
145
-			model.queries[event.data["sender"]].entries.push
169
+				model.queries[event.data["user_name"]].entries.push
146 170
 				({
147 171
 					"timestamp": event.timestamp,
148 172
 					"sender": event.data["sender"],
149 173
 					"content": event.data["content"],
150 174
 				});
175
+				shall_update_entries = true;
151 176
 				break;
152 177
 			}
153 178
 		}
154 179
 	}
155 180
 	
181
+	// update view
182
+	{
183
+		if (shall_update_spots) view_update_spots(model);
184
+		if (shall_update_entries) view_update_entries(model);
185
+		if (shall_update_users) view_update_users(model);
186
+	}
187
+}
188
+
189
+
156 190
 
157 191
 function view_update_state(model: type_model): void
158 192
 {
... ...
@@ -163,22 +197,37 @@ function view_update_state(model: type_model): void
163 197
 function view_update_spots(model: type_model): void
164 198
 {
165 199
 	let dom_spots: HTMLUListElement = document.querySelector("#spots");
166
-	const spots: Array<{kind: string; name: string}> =  (
200
+	const spots: Array<type_spot> = (
167 201
 		[]
168 202
 		.concat(Object.keys(model.channels).map((name) => ({"kind": "channel", "name": name})))
169
-		.concat(Object.keys(model.queries).map((name) => ({"kind": "channel", "name": name})))
203
+		.concat(Object.keys(model.queries).map((name) => ({"kind": "query", "name": name})))
170 204
 	);
171 205
 	dom_spots.textContent = "";
172 206
 	for (const spot of spots)
173 207
 	{
174 208
 		let dom_spot: HTMLLIElement = document.createElement("li");
175 209
 		dom_spot.classList.add("spot");
210
+		{
211
+			let dom_kind: HTMLSpanElement = document.createElement("span");
212
+			dom_kind.classList.add("spot_kind");
213
+			dom_kind.textContent = spot.kind;
214
+			dom_spot.appendChild(dom_kind);
215
+		}
176 216
 		{
177 217
 			let dom_name: HTMLSpanElement = document.createElement("span");
178 218
 			dom_name.classList.add("spot_sender");
179 219
 			dom_name.textContent = spot.name;
180 220
 			dom_spot.appendChild(dom_name);
181 221
 		}
222
+		dom_spot.classList.toggle("spot_active", ((spot.kind === model.active.kind) && (spot.name === model.active.name)));
223
+		dom_spot.addEventListener
224
+		(
225
+			"click",
226
+			(e) =>
227
+			{
228
+				model_set_active(model, spot);
229
+			}
230
+		);
182 231
 		dom_spots.appendChild(dom_spot);
183 232
 	}
184 233
 }
... ...
@@ -187,22 +236,22 @@ function view_update_spots(model: type_model): void
187 236
 function view_update_entries(model: type_model): void
188 237
 {
189 238
 	let dom_entries: HTMLUListElement = document.querySelector("#entries");
190
-	let source: Array<type_entry>;
239
+	let entries: Array<type_entry>;
191 240
 	switch (model.active.kind)
192 241
 	{
193 242
 		case "channel":
194 243
 		{
195
-			source = model.channels[model.active.name].entries;
244
+			entries = model.channels[model.active.name].entries;
196 245
 			break;
197 246
 		}
198 247
 		case "query":
199 248
 		{
200
-			source = model.queries[model.active.name].entries;
249
+			entries = model.queries[model.active.name].entries;
201 250
 			break;
202 251
 		}
203 252
 	}
204 253
 	dom_entries.textContent = "";
205
-	for (const entry of model.channels[model.active.name].entries)
254
+	for (const entry of entries)
206 255
 	{
207 256
 		let dom_entry: HTMLLIElement = document.createElement("li");
208 257
 		dom_entry.classList.add("entry");
... ...
@@ -235,27 +284,27 @@ function view_update_users(model: type_model): void
235 284
 {
236 285
 	let dom_users: HTMLUListElement = document.querySelector("#users");
237 286
 	dom_users.textContent = "";
238
-	let source: Array<type_user>;
287
+	let users: Array<type_user>;
239 288
 	switch (model.active.kind)
240 289
 	{
241 290
 		default:
242 291
 		{
243 292
 			console.warn("unhandled kind: " + model.active.kind);
244
-			source = [];
293
+			users = [];
245 294
 			break;
246 295
 		}
247 296
 		case "channel":
248 297
 		{
249
-			source = model.channels[model.active.name].users;
298
+			users = model.channels[model.active.name].users;
250 299
 			break;
251 300
 		}
252 301
 		case "query":
253 302
 		{
254
-			source = [{"name": model.nickname, "role": ""}, {"name": model.active.name, "role": ""}];
303
+			users = [{"name": model.nickname, "role": ""}, {"name": model.active.name, "role": ""}];
255 304
 			break;
256 305
 		}
257 306
 	}
258
-	const users_sorted: Array<type_user> = source.sort
307
+	const users_sorted: Array<type_user> = users.sort
259 308
 	(
260 309
 		(x, y) =>
261 310
 		(
... ...
@@ -324,13 +373,7 @@ function view_setup(model: type_model): void
324 373
 				case enum_state.online:
325 374
 				{
326 375
 					const events: Array<type_event> = await backend_call(model.connection_id, "fetch", null);
327
-					for (const event of events)
328
-					{
329
-						model_process_event(model, event);
330
-					}
331
-					view_update_users(model);
332
-					view_update_entries(model);
333
-					view_update_spots(model);
376
+					model_process_events(model, events);
334 377
 					break;
335 378
 				}
336 379
 			}
... ...
@@ -378,7 +421,7 @@ function control_setup(model: type_model): void
378 421
 				};
379 422
 			}
380 423
 			// TODO: can crash
381
-			model.active = {"kind": "channel", "name": channel_names[0]};
424
+			model_set_active(model, {"kind": "channel", "name": channel_names[0]});
382 425
 		}
383 426
 	);
384 427
 	document.querySelector("#disconnect").addEventListener
... ...
@@ -422,7 +465,7 @@ function control_setup(model: type_model): void
422 465
 							"content": content,
423 466
 						}
424 467
 					};
425
-					model_process_event(model, event);
468
+					model_process_events(model, [event]);
426 469
 					view_update_entries(model);
427 470
 					backend_call
428 471
 					(
... ...
@@ -437,19 +480,18 @@ function control_setup(model: type_model): void
437 480
 				}
438 481
 				case "query":
439 482
 				{
440
-					/*
441 483
 					const event: type_event =
442 484
 					{
443 485
 						"timestamp": get_timestamp(),
444 486
 						"kind": "message_query",
445 487
 						"data":
446 488
 						{
489
+							"user_name": model.active.name,
447 490
 							"sender": model.nickname,
448
-							"message": message,
491
+							"content": content,
449 492
 						}
450 493
 					};
451
-					model_process_event(model, event);
452
-					 */
494
+					model_process_events(model, [event]);
453 495
 					backend_call
454 496
 					(
455 497
 						model.connection_id,
... ...
@@ -467,6 +509,7 @@ function control_setup(model: type_model): void
467 509
 }
468 510
 
469 511
 
512
+var _model;
470 513
 async function main(): Promise<void>
471 514
 {
472 515
 	_conf = await fetch("conf.json").then(x => x.json());
... ...
@@ -479,6 +522,7 @@ async function main(): Promise<void>
479 522
 		"queries": {},
480 523
 		"active": null,
481 524
 	};
525
+_model = model;
482 526
 	view_setup(model);
483 527
 	control_setup(model);
484 528
 }
... ...
@@ -1,4 +1,4 @@
1
-@hue: 120;
1
+@hue: 150;
2 2
 
3 3
 body
4 4
 {
... ...
@@ -16,9 +16,11 @@ input,textarea,button
16 16
 
17 17
 button,input[type="submit"]
18 18
 {
19
-	background-color: hsl(@hue, 50%, 37.5%);
19
+	background-color: hsl(@hue, 37.5%, 37.5%);
20 20
 	color: hsl(@hue, 0%, 100%);
21 21
 	
22
+	font-size: 1.00em;
23
+	
22 24
 	border: none;
23 25
 	border-radius: 2px;
24 26
 	
... ...
@@ -52,49 +54,40 @@ label
52 54
 	
53 55
 	color: hsl(@hue, 0%, 75%);
54 56
 	
55
-	&:before
56
-	{
57
-		content: "<";
57
+	&:before {content: "<";}
58
+	&:after {content: ">";}
58 59
 }
59 60
 
60
-	&:after
61
-	{
62
-		content: ">";
63
-	}
64
-}
65
-
66
-.entry_type
61
+.entry_sender
67 62
 {
68 63
 	margin: 0 4px;
69 64
 	
70
-	color: hsl(@hue, 0%, 100%);
65
+	// font-weight: bold;
71 66
 	
72
-	&:before
73
-	{
74
-		content: "{";
67
+	&:before {content: "[";}
68
+	&:after {content: "]";}
75 69
 }
76 70
 
77
-	&:after
71
+.spot
78 72
 {
79
-		content: "}";
80
-	}
81
-}
73
+	cursor: pointer;
82 74
 	
83
-.entry_sender
84
-{
85 75
 	margin: 0 4px;
86 76
 	
87
-	// font-weight: bold;
88
-	
89
-	&:before
77
+	&.spot_active
90 78
 	{
91
-		content: "[";
79
+		font-weight: bold;
80
+	}
92 81
 }
93 82
 
94
-	&:after
83
+.spot_kind
95 84
 {
96
-		content: "]";
97
-	}
85
+	display: none;
86
+	
87
+	padding: 4px;
88
+	
89
+	&:before {content: "[";}
90
+	&:after {content: "]";}
98 91
 }
99 92
 
100 93
 .pane
... ...
@@ -212,7 +205,12 @@ body
212 205
 	flex-direction: row;
213 206
 	flex-wrap: wrap;
214 207
 	
215
-	& > #content {flex: 7;}
216
-	& > #send {flex: 1;}
208
+	& > #container_content {flex: 7;}
209
+	& > #container_send {flex: 1;}
210
+}
211
+
212
+#content
213
+{
214
+	width: 93.75%;
217 215
 }
218 216
 
219 217