111 lines
2.8 KiB
JavaScript
111 lines
2.8 KiB
JavaScript
const {q} = require("./basic.js")
|
|
const {store} = require("./store/store.js")
|
|
const lsm = require("./lsm.js")
|
|
const {chat} = require("./chat.js")
|
|
const {toHTML} = require("discord-markdown")
|
|
|
|
const input = q("#c-chat-textarea")
|
|
|
|
class TypingManager {
|
|
constructor() {
|
|
/** How long to appear to type for. */
|
|
this.time = 20000
|
|
/** How long before the end of the timeout to send the request again. */
|
|
this.margin = 5000
|
|
/** The room that we're typing in. We can semantically only type in one room at a time. */
|
|
this.typingRoom = null
|
|
this.timeout = null
|
|
}
|
|
|
|
request(id, typing) {
|
|
const url = new URL(`${lsm.get("domain")}/_matrix/client/r0/rooms/${id}/typing/${lsm.get("mx_user_id")}`)
|
|
url.searchParams.set("access_token", lsm.get("access_token"))
|
|
const body = {typing}
|
|
if (typing) body.timeout = this.time
|
|
fetch(url.toString(), {
|
|
method: "PUT",
|
|
body: JSON.stringify(body)
|
|
})
|
|
}
|
|
|
|
schedule(id) {
|
|
this.request(id, true)
|
|
this.timeout = setTimeout(() => {
|
|
this.schedule(id)
|
|
}, this.time - this.margin)
|
|
}
|
|
|
|
update(id) {
|
|
if (id) { // typing somewhere
|
|
if (this.typingRoom === id) return // already typing, don't do anything
|
|
// state
|
|
this.typingRoom = id
|
|
// mark and schedule
|
|
this.schedule(id)
|
|
// add self to typing list now instead of waiting a round trip
|
|
const typing = store.rooms.get(id).value().timeline.typing
|
|
typing.edit(list => list.concat(lsm.get("mx_user_id")))
|
|
} else { // stopped typing
|
|
if (this.typingRoom) {
|
|
clearTimeout(this.timeout)
|
|
this.request(this.typingRoom, false)
|
|
}
|
|
this.typingRoom = null
|
|
}
|
|
}
|
|
}
|
|
|
|
const typingManager = new TypingManager()
|
|
|
|
store.activeRoom.subscribe("changeSelf", () => {
|
|
// stop typing. you semantically can't type in a room you're not in.
|
|
typingManager.update(null)
|
|
// focus input box
|
|
if (store.activeRoom.exists()) {
|
|
input.focus()
|
|
}
|
|
})
|
|
|
|
input.addEventListener("keydown", event => {
|
|
if (!store.activeRoom.exists()) return
|
|
// send message?
|
|
if (event.key === "Enter" && !event.shiftKey && !event.ctrlKey) {
|
|
event.preventDefault()
|
|
const body = input.value
|
|
send(input.value)
|
|
typingManager.update(null) // stop typing
|
|
input.value = ""
|
|
fixHeight()
|
|
return
|
|
}
|
|
})
|
|
|
|
input.addEventListener("input", () => {
|
|
fixHeight()
|
|
// set typing
|
|
if (input.value) {
|
|
typingManager.update(store.activeRoom.value().id)
|
|
} else {
|
|
typingManager.update(null)
|
|
}
|
|
})
|
|
|
|
function fixHeight() {
|
|
input.style.height = "0px"
|
|
// console.log(input.clientHeight, input.scrollHeight)
|
|
input.style.height = (input.scrollHeight + 1) + "px"
|
|
}
|
|
|
|
function send(body) {
|
|
if (!store.activeRoom.exists()) return
|
|
if (!body.trim().length) return
|
|
const content = {
|
|
msgtype: "m.text",
|
|
format: "org.matrix.custom.html",
|
|
body,
|
|
formatted_body: toHTML(body),
|
|
"chat.carbon.message.input_body": body
|
|
}
|
|
return store.activeRoom.value().timeline.send("m.room.message", content)
|
|
}
|