... | ... |
@@ -1,6 +1,19 @@ |
1 | 1 |
namespace ns_view |
2 | 2 |
{ |
3 |
- |
|
3 |
+ |
|
4 |
+ /** |
|
5 |
+ * clears the content and focus on the message content input |
|
6 |
+ */ |
|
7 |
+ function clear_content |
|
8 |
+ ( |
|
9 |
+ ): void |
|
10 |
+ { |
|
11 |
+ let dom_content: HTMLInputElement = document.querySelector<HTMLInputElement>("#content"); |
|
12 |
+ dom_content.value = ""; |
|
13 |
+ dom_content.focus(); |
|
14 |
+ } |
|
15 |
+ |
|
16 |
+ |
|
4 | 17 |
/** |
5 | 18 |
* updates the state (switches between login, connecting and regular "page") |
6 | 19 |
*/ |
... | ... |
@@ -51,6 +64,8 @@ namespace ns_view |
51 | 64 |
} |
52 | 65 |
// meeh… |
53 | 66 |
ns_control.setup(conf, model); |
67 |
+ |
|
68 |
+ clear_content(); |
|
54 | 69 |
} |
55 | 70 |
|
56 | 71 |
|
... | ... |
@@ -207,19 +222,6 @@ namespace ns_view |
207 | 222 |
} |
208 | 223 |
|
209 | 224 |
|
210 |
- /** |
|
211 |
- * clears the content and focus on the message content input |
|
212 |
- */ |
|
213 |
- function clear_content |
|
214 |
- ( |
|
215 |
- ): void |
|
216 |
- { |
|
217 |
- let dom_content: HTMLInputElement = document.querySelector<HTMLInputElement>("#content"); |
|
218 |
- dom_content.value = ""; |
|
219 |
- dom_content.focus(); |
|
220 |
- } |
|
221 |
- |
|
222 |
- |
|
223 | 225 |
/** |
224 | 226 |
* sets up the view |
225 | 227 |
*/ |
... | ... |
@@ -80,28 +80,61 @@ namespace ns_view |
80 | 80 |
dom_entries.textContent = ""; |
81 | 81 |
for (const entry of entries) |
82 | 82 |
{ |
83 |
- let dom_entry: HTMLLIElement = document.createElement("li"); |
|
84 |
- dom_entry.classList.add("entry"); |
|
83 |
+ switch (entry.kind) |
|
85 | 84 |
{ |
86 |
- let dom_time: HTMLSpanElement = document.createElement("span"); |
|
87 |
- dom_time.classList.add("entry_time"); |
|
88 |
- dom_time.textContent = (new Date(entry.timestamp*1000)).toISOString().slice(11, 19); |
|
89 |
- dom_entry.appendChild(dom_time); |
|
85 |
+ default: |
|
86 |
+ { |
|
87 |
+ console.warn(`unhandled entry kind '${entry.kind}'`); |
|
88 |
+ break; |
|
89 |
+ } |
|
90 |
+ case enum_entrykind.info: |
|
91 |
+ { |
|
92 |
+ let dom_entry: HTMLLIElement = document.createElement("li"); |
|
93 |
+ dom_entry.classList.add("entry"); |
|
94 |
+ dom_entry.classList.add("entry_info"); |
|
95 |
+ { |
|
96 |
+ let dom_time: HTMLSpanElement = document.createElement("span"); |
|
97 |
+ dom_time.classList.add("entry_time"); |
|
98 |
+ dom_time.textContent = (new Date(entry.timestamp*1000)).toISOString().slice(11, 19); |
|
99 |
+ dom_entry.appendChild(dom_time); |
|
100 |
+ } |
|
101 |
+ { |
|
102 |
+ let dom_content: HTMLSpanElement = document.createElement("span"); |
|
103 |
+ dom_content.classList.add("entry_content"); |
|
104 |
+ dom_content.textContent = `-- ${entry.content}`; |
|
105 |
+ dom_entry.appendChild(dom_content); |
|
106 |
+ } |
|
107 |
+ dom_entries.appendChild(dom_entry); |
|
108 |
+ break; |
|
109 |
+ } |
|
110 |
+ case enum_entrykind.message: |
|
111 |
+ { |
|
112 |
+ let dom_entry: HTMLLIElement = document.createElement("li"); |
|
113 |
+ dom_entry.classList.add("entry"); |
|
114 |
+ dom_entry.classList.add("entry_message"); |
|
115 |
+ { |
|
116 |
+ let dom_time: HTMLSpanElement = document.createElement("span"); |
|
117 |
+ dom_time.classList.add("entry_time"); |
|
118 |
+ dom_time.textContent = (new Date(entry.timestamp*1000)).toISOString().slice(11, 19); |
|
119 |
+ dom_entry.appendChild(dom_time); |
|
120 |
+ } |
|
121 |
+ { |
|
122 |
+ let dom_sender: HTMLSpanElement = document.createElement("span"); |
|
123 |
+ dom_sender.classList.add("entry_sender"); |
|
124 |
+ dom_sender.style.color = get_usercolor(entry.sender); |
|
125 |
+ dom_sender.textContent = entry.sender; |
|
126 |
+ dom_entry.appendChild(dom_sender); |
|
127 |
+ } |
|
128 |
+ { |
|
129 |
+ let dom_content: HTMLSpanElement = document.createElement("span"); |
|
130 |
+ dom_content.classList.add("entry_content"); |
|
131 |
+ dom_content.textContent = entry.content; |
|
132 |
+ dom_entry.appendChild(dom_content); |
|
133 |
+ } |
|
134 |
+ dom_entries.appendChild(dom_entry); |
|
135 |
+ break; |
|
136 |
+ } |
|
90 | 137 |
} |
91 |
- { |
|
92 |
- let dom_sender: HTMLSpanElement = document.createElement("span"); |
|
93 |
- dom_sender.classList.add("entry_sender"); |
|
94 |
- dom_sender.style.color = get_usercolor(entry.sender); |
|
95 |
- dom_sender.textContent = entry.sender; |
|
96 |
- dom_entry.appendChild(dom_sender); |
|
97 |
- } |
|
98 |
- { |
|
99 |
- let dom_content: HTMLSpanElement = document.createElement("span"); |
|
100 |
- dom_content.classList.add("entry_content"); |
|
101 |
- dom_content.textContent = entry.content; |
|
102 |
- dom_entry.appendChild(dom_content); |
|
103 |
- } |
|
104 |
- dom_entries.appendChild(dom_entry); |
|
105 | 138 |
} |
106 | 139 |
dom_entries.scrollTo(0, dom_entries["scrollTopMax"]); |
107 | 140 |
} |
... | ... |
@@ -112,6 +112,7 @@ namespace ns_view |
112 | 112 |
*/ |
113 | 113 |
function update_users |
114 | 114 |
( |
115 |
+ conf: type_conf, |
|
115 | 116 |
model: type_model |
116 | 117 |
): void |
117 | 118 |
{ |
... | ... |
@@ -165,8 +166,11 @@ namespace ns_view |
165 | 166 |
dom_name.style.color = get_usercolor(user.name); |
166 | 167 |
dom_user.appendChild(dom_name); |
167 | 168 |
} |
169 |
+ dom_user.setAttribute("rel", JSON.stringify(user.name)); |
|
168 | 170 |
dom_users.appendChild(dom_user); |
169 | 171 |
} |
172 |
+ // meeh… |
|
173 |
+ ns_control.setup(conf, model); |
|
170 | 174 |
} |
171 | 175 |
|
172 | 176 |
|
... | ... |
@@ -198,7 +202,7 @@ namespace ns_view |
198 | 202 |
ns_model.listen(model, "state_changed", () => {update_state(model);}); |
199 | 203 |
ns_model.listen(model, "spots_changed", () => {update_spots(conf, model);}); |
200 | 204 |
ns_model.listen(model, "entries_changed", () => {update_entries(model);}); |
201 |
- ns_model.listen(model, "users_changed", () => {update_users(model);}); |
|
205 |
+ ns_model.listen(model, "users_changed", () => {update_users(conf, model);}); |
|
202 | 206 |
ns_model.listen(model, "message_sent", () => {clear_content();}); |
203 | 207 |
} |
204 | 208 |
|
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,205 @@ |
1 |
+namespace ns_view |
|
2 |
+{ |
|
3 |
+ |
|
4 |
+ /** |
|
5 |
+ * updates the state (switches between login, connecting and regular "page") |
|
6 |
+ */ |
|
7 |
+ function update_state |
|
8 |
+ ( |
|
9 |
+ model: type_model |
|
10 |
+ ): void |
|
11 |
+ { |
|
12 |
+ document.querySelector("body").setAttribute("class", model.state); |
|
13 |
+ } |
|
14 |
+ |
|
15 |
+ |
|
16 |
+ /** |
|
17 |
+ * updates the spots (channels and queries) |
|
18 |
+ */ |
|
19 |
+ function update_spots |
|
20 |
+ ( |
|
21 |
+ conf: type_conf, |
|
22 |
+ model: type_model |
|
23 |
+ ): void |
|
24 |
+ { |
|
25 |
+ let dom_spots: HTMLUListElement = document.querySelector("#spots"); |
|
26 |
+ const spots: Array<type_spot> = ( |
|
27 |
+ [] |
|
28 |
+ .concat(Object.keys(model.channels).map((name) => ({"kind": "channel", "name": name}))) |
|
29 |
+ .concat(Object.keys(model.queries).map((name) => ({"kind": "query", "name": name}))) |
|
30 |
+ ); |
|
31 |
+ dom_spots.textContent = ""; |
|
32 |
+ for (const spot of spots) |
|
33 |
+ { |
|
34 |
+ let dom_spot: HTMLLIElement = document.createElement("li"); |
|
35 |
+ dom_spot.classList.add("spot"); |
|
36 |
+ { |
|
37 |
+ let dom_kind: HTMLSpanElement = document.createElement("span"); |
|
38 |
+ dom_kind.classList.add("spot_kind"); |
|
39 |
+ dom_kind.textContent = spot.kind; |
|
40 |
+ dom_spot.appendChild(dom_kind); |
|
41 |
+ } |
|
42 |
+ { |
|
43 |
+ let dom_name: HTMLSpanElement = document.createElement("span"); |
|
44 |
+ dom_name.classList.add("spot_sender"); |
|
45 |
+ dom_name.textContent = spot.name; |
|
46 |
+ dom_spot.appendChild(dom_name); |
|
47 |
+ } |
|
48 |
+ dom_spot.classList.toggle("spot_active", ((spot.kind === model.active.kind) && (spot.name === model.active.name))); |
|
49 |
+ dom_spot.setAttribute("rel", JSON.stringify(spot)); |
|
50 |
+ dom_spots.appendChild(dom_spot); |
|
51 |
+ } |
|
52 |
+ // meeh… |
|
53 |
+ ns_control.setup(conf, model); |
|
54 |
+ } |
|
55 |
+ |
|
56 |
+ |
|
57 |
+ /** |
|
58 |
+ * updates the chat entries |
|
59 |
+ */ |
|
60 |
+ function update_entries |
|
61 |
+ ( |
|
62 |
+ model: type_model |
|
63 |
+ ): void |
|
64 |
+ { |
|
65 |
+ let dom_entries: HTMLUListElement = document.querySelector("#entries"); |
|
66 |
+ let entries: Array<type_entry>; |
|
67 |
+ switch (model.active.kind) |
|
68 |
+ { |
|
69 |
+ case "channel": |
|
70 |
+ { |
|
71 |
+ entries = model.channels[model.active.name].entries; |
|
72 |
+ break; |
|
73 |
+ } |
|
74 |
+ case "query": |
|
75 |
+ { |
|
76 |
+ entries = model.queries[model.active.name].entries; |
|
77 |
+ break; |
|
78 |
+ } |
|
79 |
+ } |
|
80 |
+ dom_entries.textContent = ""; |
|
81 |
+ for (const entry of entries) |
|
82 |
+ { |
|
83 |
+ let dom_entry: HTMLLIElement = document.createElement("li"); |
|
84 |
+ dom_entry.classList.add("entry"); |
|
85 |
+ { |
|
86 |
+ let dom_time: HTMLSpanElement = document.createElement("span"); |
|
87 |
+ dom_time.classList.add("entry_time"); |
|
88 |
+ dom_time.textContent = (new Date(entry.timestamp*1000)).toISOString().slice(11, 19); |
|
89 |
+ dom_entry.appendChild(dom_time); |
|
90 |
+ } |
|
91 |
+ { |
|
92 |
+ let dom_sender: HTMLSpanElement = document.createElement("span"); |
|
93 |
+ dom_sender.classList.add("entry_sender"); |
|
94 |
+ dom_sender.style.color = get_usercolor(entry.sender); |
|
95 |
+ dom_sender.textContent = entry.sender; |
|
96 |
+ dom_entry.appendChild(dom_sender); |
|
97 |
+ } |
|
98 |
+ { |
|
99 |
+ let dom_content: HTMLSpanElement = document.createElement("span"); |
|
100 |
+ dom_content.classList.add("entry_content"); |
|
101 |
+ dom_content.textContent = entry.content; |
|
102 |
+ dom_entry.appendChild(dom_content); |
|
103 |
+ } |
|
104 |
+ dom_entries.appendChild(dom_entry); |
|
105 |
+ } |
|
106 |
+ dom_entries.scrollTo(0, dom_entries["scrollTopMax"]); |
|
107 |
+ } |
|
108 |
+ |
|
109 |
+ |
|
110 |
+ /** |
|
111 |
+ * updates the user list |
|
112 |
+ */ |
|
113 |
+ function update_users |
|
114 |
+ ( |
|
115 |
+ model: type_model |
|
116 |
+ ): void |
|
117 |
+ { |
|
118 |
+ let dom_users: HTMLUListElement = document.querySelector("#users"); |
|
119 |
+ dom_users.textContent = ""; |
|
120 |
+ let users: Array<type_user>; |
|
121 |
+ switch (model.active.kind) |
|
122 |
+ { |
|
123 |
+ default: |
|
124 |
+ { |
|
125 |
+ console.warn("unhandled kind: " + model.active.kind); |
|
126 |
+ users = []; |
|
127 |
+ break; |
|
128 |
+ } |
|
129 |
+ case "channel": |
|
130 |
+ { |
|
131 |
+ users = model.channels[model.active.name].users; |
|
132 |
+ break; |
|
133 |
+ } |
|
134 |
+ case "query": |
|
135 |
+ { |
|
136 |
+ users = [{"name": model.nickname, "role": ""}, {"name": model.active.name, "role": ""}]; |
|
137 |
+ break; |
|
138 |
+ } |
|
139 |
+ } |
|
140 |
+ const users_sorted: Array<type_user> = users.sort |
|
141 |
+ ( |
|
142 |
+ (x, y) => |
|
143 |
+ ( |
|
144 |
+ (x.role >= y.role) |
|
145 |
+ ? -1 |
|
146 |
+ : ( |
|
147 |
+ (x.role === y.role) |
|
148 |
+ ? ((x.name < y.name) ? -1 : +1) |
|
149 |
+ : +1 |
|
150 |
+ ) |
|
151 |
+ ) |
|
152 |
+ ); |
|
153 |
+ for (const user of users_sorted) |
|
154 |
+ { |
|
155 |
+ let dom_user: HTMLLIElement = document.createElement("li"); |
|
156 |
+ dom_user.classList.add("user"); |
|
157 |
+ { |
|
158 |
+ let dom_role: HTMLSpanElement = document.createElement("span"); |
|
159 |
+ dom_role.textContent = user.role; |
|
160 |
+ dom_user.appendChild(dom_role); |
|
161 |
+ } |
|
162 |
+ { |
|
163 |
+ let dom_name: HTMLSpanElement = document.createElement("span"); |
|
164 |
+ dom_name.textContent = user.name; |
|
165 |
+ dom_name.style.color = get_usercolor(user.name); |
|
166 |
+ dom_user.appendChild(dom_name); |
|
167 |
+ } |
|
168 |
+ dom_users.appendChild(dom_user); |
|
169 |
+ } |
|
170 |
+ } |
|
171 |
+ |
|
172 |
+ |
|
173 |
+ /** |
|
174 |
+ * clears the content and focus on the message content input |
|
175 |
+ */ |
|
176 |
+ function clear_content |
|
177 |
+ ( |
|
178 |
+ ): void |
|
179 |
+ { |
|
180 |
+ let dom_content: HTMLInputElement = document.querySelector<HTMLInputElement>("#content"); |
|
181 |
+ dom_content.value = ""; |
|
182 |
+ dom_content.focus(); |
|
183 |
+ } |
|
184 |
+ |
|
185 |
+ |
|
186 |
+ /** |
|
187 |
+ * sets up the view |
|
188 |
+ */ |
|
189 |
+ export function setup |
|
190 |
+ ( |
|
191 |
+ conf: type_conf, |
|
192 |
+ model: type_model |
|
193 |
+ ): void |
|
194 |
+ { |
|
195 |
+ document.querySelector<HTMLInputElement>("#channel").value = conf.irc.predefined_channel; |
|
196 |
+ document.querySelector<HTMLInputElement>("#nickname").value = (conf.irc.predefined_nickname_prefix + (Math.random()*100).toFixed(0)); |
|
197 |
+ |
|
198 |
+ ns_model.listen(model, "state_changed", () => {update_state(model);}); |
|
199 |
+ ns_model.listen(model, "spots_changed", () => {update_spots(conf, model);}); |
|
200 |
+ ns_model.listen(model, "entries_changed", () => {update_entries(model);}); |
|
201 |
+ ns_model.listen(model, "users_changed", () => {update_users(model);}); |
|
202 |
+ ns_model.listen(model, "message_sent", () => {clear_content();}); |
|
203 |
+ } |
|
204 |
+ |
|
205 |
+} |