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 || []) {