Support writing messages

This commit is contained in:
Midgard 2021-02-17 18:15:57 +01:00
parent 26ebbcc190
commit 8983e0e504
Signed by: midgard
GPG key ID: 511C112F1331BBB4
5 changed files with 70 additions and 28 deletions

View file

@ -55,7 +55,7 @@
</div> </div>
<div class="centered compose-wrapper"> <div class="centered compose-wrapper">
<textarea id="compose" disabled="disabled" oninput="" rows="1"></textarea> <textarea id="compose" rows="1"></textarea>
</div> </div>
</div> </div>

View file

@ -139,3 +139,32 @@ function switchToChannel(client, team, channel) {
byId("channel_header").append(...elements); byId("channel_header").append(...elements);
byId("compose").setAttribute("placeholder", `Write to ${byId("channel_header").textContent}`); 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;
}

View file

@ -3,6 +3,13 @@
byId("server_selection_add").addEventListener("click", e => { e.stopPropagation(); e.preventDefault(); window.location = "#login"; return false; }); 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").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("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(); updateComposeHeight();
checkScrolledToBottom(); checkScrolledToBottom();

View file

@ -11,21 +11,24 @@ class MattermostClient {
console.info(`Created MattermostClient for ${this.endpoint}, ${this.token ? "found token" : "did not find token"}`); console.info(`Created MattermostClient for ${this.endpoint}, ${this.token ? "found token" : "did not find token"}`);
if (this.token) { if (this.token) {
this.websocket(); this.userMe().then(data => {
this.me = data;
this.websocket();
});
} }
} }
async get(path, token, queryParams) { async get(path, queryParams) {
const headers = token ? {"Authorization": `Bearer ${token}`} : {}; const headers = this.token ? {"Authorization": `Bearer ${this.token}`} : {};
const response = await ajax.getJson(`${this.endpoint}${path}`, {headers, queryParams}); const response = await ajax.getJson(`${this.endpoint}${path}`, {headers, queryParams});
if (!response.ok) { if (!response.ok) {
throw response; throw response;
} }
return response; return response.responseJson;
} }
async post(path, token, data) { async post(path, data) {
const headers = token ? {"Authorization": `Bearer ${token}`} : {}; const headers = this.token ? {"Authorization": `Bearer ${this.token}`} : {};
const response = await ajax.postJson(`${this.endpoint}${path}`, data, {headers}); const response = await ajax.postJson(`${this.endpoint}${path}`, data, {headers});
if (!response.ok) { if (!response.ok) {
throw response; throw response;
@ -33,14 +36,7 @@ class MattermostClient {
return response; return response;
} }
async authedGet(url, queryParams) { async paginatedGet(url, queryParams, perPage=200) {
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");
let data = []; let data = [];
let params = {page: 0, per_page: perPage}; let params = {page: 0, per_page: perPage};
@ -51,13 +47,13 @@ class MattermostClient {
let loadMore = true; let loadMore = true;
while (loadMore) { while (loadMore) {
if (params.page > 100) { 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); const response = await this.get(url, params);
data = data.concat(response.responseJson); data = data.concat(response);
loadMore = response.responseJson.length > 0; loadMore = response.length > 0;
params.page++; params.page++;
} }
@ -93,7 +89,10 @@ class MattermostClient {
this.credentials.store(this.endpoint, login_id, token); this.credentials.store(this.endpoint, login_id, token);
this.token = token; this.token = token;
let _ = this.getUsers(); let _ = this.getUsers();
this.websocket(); this.userMe().then(data => {
this.me = data;
this.websocket();
});
return response.responseJson; return response.responseJson;
} }
@ -119,28 +118,35 @@ class MattermostClient {
user(user_id) { user(user_id) {
assertIsMattermostId(user_id); assertIsMattermostId(user_id);
return this.authedGet(`/users/${user_id}`); return this.get(`/users/${user_id}`);
} }
userMe() { return this.authedGet("/users/me"); } userMe() { return this.get("/users/me"); }
myTeams() { return this.authedGet("/users/me/teams"); } myTeams() { return this.get("/users/me/teams"); }
myChannels(team_id) { myChannels(team_id) {
assertIsMattermostId(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) { channelPosts(channel_id, beforePost=null, afterPost=null, since=null) {
assertIsMattermostId(channel_id); assertIsMattermostId(channel_id);
assertIsNullOrMattermostId(beforePost); assertIsNullOrMattermostId(beforePost);
assertIsNullOrMattermostId(afterPost); assertIsNullOrMattermostId(afterPost);
return this.authedGet(`/channels/${channel_id}/posts`, { return this.get(`/channels/${channel_id}/posts`, {
before: beforePost, after: afterPost, since before: beforePost, after: afterPost, since
}); });
} }
writePost(channel_id, message) {
return this.post("/posts", {
"channel_id": channel_id,
"message": message
});
}
getUsers() { getUsers() {
if (!this.users) { if (!this.users) {
this.users = this.authedPaginatedGet("/users", {}).then(users => { this.users = this.paginatedGet("/users", {}).then(users => {
const newUsers = Object.create(null); const newUsers = Object.create(null);
for (let user_data of users) { for (let user_data of users) {
const user = user_data; const user = user_data;
@ -153,7 +159,7 @@ class MattermostClient {
} }
async filePublicLink(file_id) { 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; return response.link;
} }

View file

@ -90,7 +90,7 @@ async function createMessageElement(client, post, lastTime, lastAuthor) {
postDiv.appendChild(createAtDiv); postDiv.appendChild(createAtDiv);
postDiv.appendChild(messageDiv); postDiv.appendChild(messageDiv);
if ((post.metadata.files || []).length > 0) { if (post.metadata && (post.metadata.files || []).length > 0) {
const attachmentsUl = document.createElement("ul"); const attachmentsUl = document.createElement("ul");
attachmentsUl.className = "attachments"; attachmentsUl.className = "attachments";
for (let file of post.metadata.files || []) { for (let file of post.metadata.files || []) {