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 class="centered compose-wrapper">
<textarea id="compose" disabled="disabled" oninput="" rows="1"></textarea>
<textarea id="compose" rows="1"></textarea>
</div>
</div>

View file

@ -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;
}

View file

@ -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();

View file

@ -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;
}

View file

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