From 8983e0e5040b0888b6c2f4fa06152828cc6a1dc1 Mon Sep 17 00:00:00 2001 From: Midgard Date: Wed, 17 Feb 2021 18:15:57 +0100 Subject: [PATCH] Support writing messages --- index.html | 2 +- js/controller.js | 29 ++++++++++++++++++++++++ js/main.js | 7 ++++++ js/mm_client.js | 58 ++++++++++++++++++++++++++---------------------- js/view/view.js | 2 +- 5 files changed, 70 insertions(+), 28 deletions(-) diff --git a/index.html b/index.html index abf4881..840239a 100644 --- a/index.html +++ b/index.html @@ -55,7 +55,7 @@
- +
diff --git a/js/controller.js b/js/controller.js index 5e7dbb1..2f29ec9 100644 --- a/js/controller.js +++ b/js/controller.js @@ -139,3 +139,32 @@ function switchToChannel(client, team, channel) { byId("channel_header").append(...elements); byId("compose").setAttribute("placeholder", `Write to ${byId("channel_header").textContent}`); } + +function sendMessage(endpoint, channel_id, message) { + const client = mm_client.get(endpoint); + client.writePost(channel_id, message); + pubsub.publish("MESSAGES_NEW", { + endpoint, + channel_id: channel_id, + create_at: (new Date()).getTime(), + user_id: client.me.id, + message + }); +} + +function checkKeyPress(event) { + console.debug(event); + // Battle tested for many years in several browsers + if ((event.keyCode === event.DOM_VK_RETURN || event.keyCode === 13 || event.keyCode === 10 || event.key === "Enter" || event.keyIdentifier === "U+000A") && !event.shiftKey && !event.ctrlKey) { + if (byId("compose").value.length > 0) { + sendMessage( + byId("channel_contents").dataset["server"], + byId("channel_contents").dataset["id"], + byId("compose").value + ); + byId("compose").value = ""; + } + return true; + } + return false; +} diff --git a/js/main.js b/js/main.js index 3452cf8..3cdca13 100644 --- a/js/main.js +++ b/js/main.js @@ -3,6 +3,13 @@ byId("server_selection_add").addEventListener("click", e => { e.stopPropagation(); e.preventDefault(); window.location = "#login"; return false; }); byId("login").addEventListener("submit", e => { logIn(); e.stopPropagation(); e.preventDefault(); return false; }); byId("login_no_button").addEventListener("click", e => { e.stopPropagation(); e.preventDefault(); window.location = "#"; return false; }); +byId("compose").addEventListener("keydown", e => { + if (checkKeyPress(e)) { + e.stopPropagation(); e.preventDefault(); + return false; + } + return true; +}); updateComposeHeight(); checkScrolledToBottom(); diff --git a/js/mm_client.js b/js/mm_client.js index 33c7dd3..a1a4200 100644 --- a/js/mm_client.js +++ b/js/mm_client.js @@ -11,21 +11,24 @@ class MattermostClient { console.info(`Created MattermostClient for ${this.endpoint}, ${this.token ? "found token" : "did not find token"}`); if (this.token) { - this.websocket(); + this.userMe().then(data => { + this.me = data; + this.websocket(); + }); } } - async get(path, token, queryParams) { - const headers = token ? {"Authorization": `Bearer ${token}`} : {}; + async get(path, queryParams) { + const headers = this.token ? {"Authorization": `Bearer ${this.token}`} : {}; const response = await ajax.getJson(`${this.endpoint}${path}`, {headers, queryParams}); if (!response.ok) { throw response; } - return response; + return response.responseJson; } - async post(path, token, data) { - const headers = token ? {"Authorization": `Bearer ${token}`} : {}; + async post(path, data) { + const headers = this.token ? {"Authorization": `Bearer ${this.token}`} : {}; const response = await ajax.postJson(`${this.endpoint}${path}`, data, {headers}); if (!response.ok) { throw response; @@ -33,14 +36,7 @@ class MattermostClient { return response; } - async authedGet(url, queryParams) { - assert(this.token, "logged in"); - const response = await this.get(url, this.token, queryParams); - return response.responseJson; - } - - async authedPaginatedGet(url, queryParams, perPage=200) { - assert(this.token, "logged in"); + async paginatedGet(url, queryParams, perPage=200) { let data = []; let params = {page: 0, per_page: perPage}; @@ -51,13 +47,13 @@ class MattermostClient { let loadMore = true; while (loadMore) { if (params.page > 100) { - throw new Error("Requesting more than 100 pages, something looks wrong"); + throw new Error("Requesting more than 100 pages, something looks wrong or the response is massive (>20,000 items)"); } - const response = await this.get(url, this.token, params); - data = data.concat(response.responseJson); + const response = await this.get(url, params); + data = data.concat(response); - loadMore = response.responseJson.length > 0; + loadMore = response.length > 0; params.page++; } @@ -93,7 +89,10 @@ class MattermostClient { this.credentials.store(this.endpoint, login_id, token); this.token = token; let _ = this.getUsers(); - this.websocket(); + this.userMe().then(data => { + this.me = data; + this.websocket(); + }); return response.responseJson; } @@ -119,28 +118,35 @@ class MattermostClient { user(user_id) { assertIsMattermostId(user_id); - return this.authedGet(`/users/${user_id}`); + return this.get(`/users/${user_id}`); } - userMe() { return this.authedGet("/users/me"); } - myTeams() { return this.authedGet("/users/me/teams"); } + userMe() { return this.get("/users/me"); } + myTeams() { return this.get("/users/me/teams"); } myChannels(team_id) { assertIsMattermostId(team_id); - return this.authedGet(`/users/me/teams/${team_id}/channels`); + return this.get(`/users/me/teams/${team_id}/channels`); } channelPosts(channel_id, beforePost=null, afterPost=null, since=null) { assertIsMattermostId(channel_id); assertIsNullOrMattermostId(beforePost); assertIsNullOrMattermostId(afterPost); - return this.authedGet(`/channels/${channel_id}/posts`, { + return this.get(`/channels/${channel_id}/posts`, { before: beforePost, after: afterPost, since }); } + writePost(channel_id, message) { + return this.post("/posts", { + "channel_id": channel_id, + "message": message + }); + } + getUsers() { if (!this.users) { - this.users = this.authedPaginatedGet("/users", {}).then(users => { + this.users = this.paginatedGet("/users", {}).then(users => { const newUsers = Object.create(null); for (let user_data of users) { const user = user_data; @@ -153,7 +159,7 @@ class MattermostClient { } async filePublicLink(file_id) { - const response = await this.authedGet(`/files/${file_id}/link`, {}); + const response = await this.get(`/files/${file_id}/link`, {}); return response.link; } diff --git a/js/view/view.js b/js/view/view.js index 9688c41..9026b9a 100644 --- a/js/view/view.js +++ b/js/view/view.js @@ -90,7 +90,7 @@ async function createMessageElement(client, post, lastTime, lastAuthor) { postDiv.appendChild(createAtDiv); postDiv.appendChild(messageDiv); - if ((post.metadata.files || []).length > 0) { + if (post.metadata && (post.metadata.files || []).length > 0) { const attachmentsUl = document.createElement("ul"); attachmentsUl.className = "attachments"; for (let file of post.metadata.files || []) {