[mod] pack model stuff into dedicated variable
Christian Fraß

Christian Fraß commited on 2021-11-19 13:04:04
Zeige 3 geänderte Dateien mit 183 Einfügungen und 95 Löschungen.

... ...
@@ -2,10 +2,11 @@
2 2
 <html>
3 3
 	<head>
4 4
 		<meta charset="utf-8"/>
5
-		<title>web-irc</title>
5
+		<meta name="viewport" content="width=device-width, initial-scale=1.0">
6 6
 		<link rel="stylesheet" type="text/css" href="style.css"/>
7 7
 		<script type="text/javascript" src="logic.js"></script>
8 8
 		<script type="text/javascript">init();</script>
9
+		<title>wirc</title>
9 10
 	</head>
10 11
 	<body class="offline">
11 12
 		<div id="connect">
... ...
@@ -26,15 +27,20 @@
26 27
 		</div>
27 28
 		<div id="main">
28 29
 			<div id="head">
30
+				<div id="head_left">
31
+					<h2>wirc</h2>
32
+				</div>
33
+				<div id="head_right">
29 34
 					<button id="disconnect">disconnect</button>
30 35
 				</div>
36
+			</div>
31 37
 			<div id="middle">
32
-				<ul class="pane" id="history"></ul>
38
+				<ul class="pane" id="events"></ul>
33 39
 				<ul class="pane" id="users"></ul>
34 40
 			</div>
35 41
 			<form action="#">
36 42
 				<input type="text" id="message" placeholder="…"/>
37
-				<input type="submit" value="send"/>
43
+				<input type="submit" id="send" value="send"/>
38 44
 			</form>
39 45
 		</template>
40 46
 	</body>
... ...
@@ -3,11 +3,6 @@ type float = number;
3 3
 
4 4
 
5 5
 var _conf: any = null;
6
-var _state: string = undefined;
7
-var _channel: string = undefined;
8
-var _nickname: string = undefined;
9
-var _userhash: string = undefined;
10
-var _id: (null | string) = null;
11 6
 
12 7
 
13 8
 function get_timestamp(): int
... ...
@@ -31,41 +26,76 @@ function get_usercolor(name: string): string
31 26
 
32 27
 async function backend_call(action: string, data: any): Promise<any>
33 28
 {
34
-	const response = await fetch(
29
+	const response = await fetch
30
+	(
35 31
 		`${_conf.backend.scheme}://${_conf.backend.host}:${_conf.backend.port.toFixed(0)}`,
36 32
 		{
37 33
 			"method": "POST",
38
-			"body": JSON.stringify({"action": action, "id": _id, "data": data}),
34
+			"body": JSON.stringify({"action": action, "id": _model.connection_id, "data": data}),
39 35
 		}
40 36
 	);
41
-	if (response.ok) {
37
+	if (response.ok)
38
+	{
42 39
 		return response.json();
43 40
 	}
44
-	else {
41
+	else
42
+	{
45 43
 		console.error(response.text());
46 44
 		return Promise.reject<any>(new Error("backend call failed"));
47 45
 	}
48 46
 }
49 47
 
48
+enum enum_state
49
+{
50
+	offline = "offline",
51
+	connecting = "connecting",
52
+	online = "online",
53
+}
54
+
55
+
56
+type type_model =
57
+{
58
+	state: enum_state;
59
+	channel: (null | string);
60
+	nickname: (null | string);
61
+	connection_id: (null | string);
62
+	usershash: (null | string);
63
+};
64
+
65
+
66
+var _model: type_model =
67
+{
68
+	"state": enum_state.offline,
69
+	"channel": null,
70
+	"nickname": null,
71
+	"connection_id": null,
72
+	"usershash": null,
73
+};
74
+
50 75
 
51 76
 function update_state(): void
52 77
 {
53
-	document.querySelector("body").setAttribute("class", _state);
78
+	document.querySelector("body").setAttribute("class", _model.state);
54 79
 }
55 80
 
56 81
 
57
-function update_history(events): void
82
+function update_events(events): void
83
+{
84
+	let dom_events: HTMLUListElement = document.querySelector("#events");
85
+	for (const event of events)
58 86
 	{
59
-	let dom_history: HTMLUListElement = document.querySelector("#history");
60
-	for (const event of events) {
61 87
 		const timestring: string = (new Date(event["timestamp"]*1000)).toISOString().slice(11, 19);
62 88
 		let dom_event: HTMLLIElement = document.createElement("li");
63 89
 		dom_event.classList.add("event");
64
-		switch (event["kind"]) {
90
+		switch (event["kind"])
91
+		{
65 92
 			default:
93
+			{
66 94
 				dom_event.textContent = ("-- unhandled event: " + JSON.stringify(event));
67 95
 				break;
96
+			}
68 97
 			case "channel_message":
98
+			{
69 99
 				{
70 100
 					let dom_time: HTMLDivElement = document.createElement("div");
71 101
 					dom_time.classList.add("event_time");
... ...
@@ -87,9 +117,10 @@ function update_history(events): void
87 117
 				}
88 118
 				break;
89 119
 			}
90
-		dom_history.appendChild(dom_event);
91 120
 		}
92
-	dom_history.scrollTo(0, dom_history["scrollTopMax"]);
121
+		dom_events.appendChild(dom_event);
122
+	}
123
+	dom_events.scrollTo(0, dom_events["scrollTopMax"]);
93 124
 }
94 125
 
95 126
 
... ...
@@ -97,8 +128,10 @@ function update_users(users: Array<{name: string; role: string;}>): void
97 128
 {
98 129
 	let dom_users: HTMLUListElement = document.querySelector("#users");
99 130
 	dom_users.textContent = "";
100
-	const users_sorted: Array<{name: string; role: string;}> = users.sort(
101
-		(x, y) => (
131
+	const users_sorted: Array<{name: string; role: string;}> = users.sort
132
+	(
133
+		(x, y) =>
134
+		(
102 135
 			(x.role >= y.role)
103 136
 			? -1
104 137
 			: (
... ...
@@ -108,7 +141,8 @@ function update_users(users: Array<{name: string; role: string;}>): void
108 141
 			)
109 142
 		)
110 143
 	);
111
-	for (const user of users_sorted) {
144
+	for (const user of users_sorted)
145
+	{
112 146
 		let dom_user: HTMLLIElement = document.createElement("li");
113 147
 		dom_user.classList.add("user");
114 148
 		{
... ...
@@ -122,15 +156,14 @@ function update_users(users: Array<{name: string; role: string;}>): void
122 156
 			dom_name.style.color = get_usercolor(user.name);
123 157
 			dom_user.appendChild(dom_name);
124 158
 		}
125
-		// dom_user.textContent = `${user.role}${user.name}`;
126 159
 		dom_users.appendChild(dom_user);
127 160
 	}
128 161
 }
129 162
 
130 163
 
131
-function set_state(state: string): void
164
+function set_state(state: enum_state): void
132 165
 {
133
-	_state = state;
166
+	_model.state = state;
134 167
 	update_state();
135 168
 }
136 169
 
... ...
@@ -139,45 +172,72 @@ function setup_view(): void
139 172
 {
140 173
 	document.querySelector<HTMLInputElement>("#channel").value = _conf["irc"]["predefined_channel"];
141 174
 	document.querySelector<HTMLInputElement>("#nickname").value = (_conf["irc"]["predefined_nickname_prefix"] + (Math.random()*100).toFixed(0));
142
-	setInterval(
143
-		async () => {
144
-			switch (_state) {
145
-				case "offline":
175
+	setInterval
176
+	(
177
+		async () =>
178
+		{
179
+			switch (_model.state)
180
+			{
181
+				default:
182
+				{
183
+					throw (new Error("invalid state: " + _model.state));
184
+					break;
185
+				}
186
+				case enum_state.offline:
187
+				{
146 188
 					// do nothing
147 189
 					break;
148
-				case "checking":
190
+				}
191
+				case enum_state.connecting:
192
+				{
149 193
 					const ready: boolean = await backend_call("check", null);
150
-					if (ready) {
151
-						set_state("online");
194
+					if (ready)
195
+					{
196
+						set_state(enum_state.online);
197
+					}
198
+					else
199
+					{
200
+						// do nothing
152 201
 					}
153 202
 					break;
154
-				case "online":
203
+				}
204
+				case enum_state.online:
205
+				{
155 206
 					const stuff: any = await backend_call("fetch", null);
156
-					update_history(stuff["events"]);
157
-					const userhash: string = btoa(JSON.stringify(stuff["users"]));
158
-					if (_userhash !== userhash) {
159
-						_userhash = userhash;
207
+					update_events(stuff["events"]);
208
+					const usershash: string = btoa(JSON.stringify(stuff["users"]));
209
+					if (_model.usershash !== usershash)
210
+					{
211
+						_model.usershash = usershash;
160 212
 						update_users(stuff["users"]);
161 213
 					}
214
+					else
215
+					{
216
+						// do nothing
217
+					}
162 218
 					break;
163 219
 				}
220
+			}
164 221
 		},
165 222
 		_conf["settings"]["poll_interval_in_milliseconds"]
166 223
 	);
167
-	set_state("offline");
224
+	set_state(enum_state.offline);
168 225
 }
169 226
 
170 227
 
171 228
 function setup_control(): void
172 229
 {
173
-	document.querySelector("#connect > form").addEventListener(
230
+	document.querySelector("#connect > form").addEventListener
231
+	(
174 232
 		"submit",
175
-		async (event) => {
233
+		async (event) =>
234
+		{
176 235
 			let dom_nickname: HTMLInputElement = document.querySelector<HTMLInputElement>("#nickname");
177 236
 			let dom_channel: HTMLInputElement = document.querySelector<HTMLInputElement>("#channel");
178 237
 			const nickname: string = dom_nickname.value;
179 238
 			const channel: string = dom_channel.value;
180
-			const id: string = await backend_call(
239
+			const connection_id: string = await backend_call
240
+			(
181 241
 				"connect",
182 242
 				{
183 243
 					"server": _conf["irc"]["server"],
... ...
@@ -185,45 +245,52 @@ function setup_control(): void
185 245
 					"nickname": nickname,
186 246
 				}
187 247
 			);
188
-			_id = id;
189
-			_channel = channel;
190
-			_nickname = nickname;
191
-			set_state("checking");
248
+			_model.connection_id = connection_id;
249
+			_model.channel = channel;
250
+			_model.nickname = nickname;
251
+			set_state(enum_state.connecting);
192 252
 		}
193 253
 	);
194
-	document.querySelector("#disconnect").addEventListener(
254
+	document.querySelector("#disconnect").addEventListener
255
+	(
195 256
 		"click",
196
-		async (event) => {
197
-			await backend_call(
257
+		async (event) =>
258
+		{
259
+			await backend_call
260
+			(
198 261
 				"disconnect",
199 262
 				null
200 263
 			);
201
-			set_state("offline");
202
-			_id = null;
264
+			set_state(enum_state.offline);
265
+			_model.connection_id = null;
203 266
 		}
204 267
 	);
205
-	document.querySelector("#main > form").addEventListener(
268
+	document.querySelector("#main > form").addEventListener
269
+	(
206 270
 		"submit",
207
-		async (event) => {
271
+		async (event) =>
272
+		{
208 273
 			event.preventDefault();
209 274
 			let dom_message: HTMLInputElement = document.querySelector<HTMLInputElement>("#message");
210 275
 			const message: string = dom_message.value;
211 276
 			dom_message.value = "";
212 277
 			dom_message.focus();
213
-			const event_: any = {
278
+			const event_: any =
279
+			{
214 280
 				"timestamp": get_timestamp(),
215 281
 				"kind": "channel_message",
216 282
 				"data": {
217
-					"from": _nickname,
218
-					"to": _channel,
283
+					"from": _model.nickname,
284
+					"to": _model.channel,
219 285
 					"message": message,
220 286
 				}
221 287
 			};
222
-			update_history([event_]);
223
-			await backend_call(
224
-				"say",
288
+			update_events([event_]);
289
+			await backend_call
290
+			(
291
+				"send",
225 292
 				{
226
-					"channel": _channel,
293
+					"channel": _model.channel,
227 294
 					"message": message,
228 295
 				}
229 296
 			);
... ...
@@ -242,11 +309,10 @@ async function main(): Promise<void>
242 309
 
243 310
 function init(): void
244 311
 {
245
-	document.addEventListener(
312
+	document.addEventListener
313
+	(
246 314
 		"DOMContentLoaded",
247
-		(event) => {
248
-			main();
249
-		}
315
+		(event) => {main();}
250 316
 	);
251 317
 }
252 318
 
... ...
@@ -32,7 +32,7 @@ label
32 32
 	display: block;
33 33
 	font-size: 1.0em;
34 34
 	font-weight: bold;
35
-	text-transform: capitalize;
35
+	// text-transform: capitalize;
36 36
 }
37 37
 
38 38
 .field
... ...
@@ -99,25 +99,62 @@ label
99 99
 	}
100 100
 }
101 101
 
102
+body
103
+{
104
+	&
105
+	{
106
+		& #connect {display: none;}
107
+		& #wait {display: none;}
108
+		& #main {display: none;}
109
+	}
110
+	
111
+	&.offline
112
+	{
113
+		& #connect {display: initial !important;}
114
+	}
115
+	
116
+	&.connecting
117
+	{
118
+		& #wait {display: initial !important;}
119
+	}
120
+	
121
+	&.online
122
+	{
123
+		& #main {display: initial !important;}
124
+	}
125
+}
126
+
102 127
 #head
103 128
 {
129
+	display: flex;
130
+	flex-direction: row;
131
+	flex-wrap: wrap;
132
+	
133
+	& > #head_left
134
+	{
135
+		flex: 1;
136
+		text-align: left;
137
+	}
138
+	
139
+	& > #head_right
140
+	{
141
+		flex: 1;
104 142
 		text-align: right;
105 143
 	}
144
+}
145
+
106 146
 
107 147
 #middle
108 148
 {
109 149
 	display: flex;
110 150
 	flex-direction: row;
111 151
 	
112
-	& #history {flex: 4;}	
152
+	& #events {flex: 4;}	
113 153
 	& #users {flex: 1;}
114 154
 }
115 155
 
116 156
 #message
117 157
 {
118
-	// height: 40px;
119
-	width: 80%;
120
-	
121 158
 	border: none;
122 159
 	
123 160
 	background-color: hsl(@hue, 0%, 25%);
... ...
@@ -127,34 +164,13 @@ label
127 164
 	margin: 4px;
128 165
 }
129 166
 
130
-body
131
-{
132
-	&:not(.offline):not(.checking):not(.online)
133
-	{
134
-		& #connect {display: none;}
135
-		& #wait {display: none;}
136
-		& #main {display: none;}
137
-	}
138
-	
139
-	&.offline
167
+#main > form
140 168
 {
141
-		& #connect {}
142
-		& #wait {display: none;}
143
-		& #main {display: none;}
144
-	}
145
-	
146
-	&.checking
147
-	{
148
-		& #connect {display: none;}
149
-		& #wait {}
150
-		& #main {display: none;}
151
-	}
169
+	display: flex;
170
+	flex-direction: row;
171
+	flex-wrap: wrap;
152 172
 	
153
-	&.online
154
-	{
155
-		& #connect {display: none;}
156
-		& #wait {display: none;}
157
-		& #main {}
158
-	}
173
+	& > #message {flex: 7;}
174
+	& > #send {flex: 1;}
159 175
 }
160 176
 
161 177