refactor and simplify things

This commit is contained in:
MapleLeaf
2021-12-22 10:35:55 -06:00
parent 7b3ce42138
commit 765c6fadbb
26 changed files with 351 additions and 441 deletions

84
src/renderer.ts Normal file
View File

@@ -0,0 +1,84 @@
import type { Message, MessageOptions, TextBasedChannels } from "discord.js"
import type { MessageNode } from "./node-tree.js"
import { getMessageOptions } from "./node-tree.js"
type Action =
| { type: "updateMessage"; options: MessageOptions }
| { type: "deleteMessage" }
export class MessageRenderer {
private channel: TextBasedChannels
private message?: Message
private actions: Action[] = []
private runningPromise?: Promise<void>
constructor(channel: TextBasedChannels) {
this.channel = channel
}
render(node: MessageNode) {
this.addAction({
type: "updateMessage",
options: getMessageOptions(node),
})
}
destroy() {
this.actions = []
this.addAction({ type: "deleteMessage" })
}
completion() {
return this.runningPromise ?? Promise.resolve()
}
private addAction(action: Action) {
const lastAction = this.actions[this.actions.length - 1]
if (lastAction?.type === action.type) {
this.actions[this.actions.length - 1] = action
} else {
this.actions.push(action)
}
this.runActions()
}
private runActions() {
if (this.runningPromise) return
this.runningPromise = new Promise((resolve) => {
// using a microtask to allow multiple actions to be added synchronously
queueMicrotask(async () => {
let action: Action | undefined
while ((action = this.actions.shift())) {
try {
await this.runAction(action)
} catch (error) {
console.error(`Failed to run action:`, action)
console.error(error)
}
}
resolve()
this.runningPromise = undefined
})
})
}
private async runAction(action: Action) {
if (action.type === "updateMessage") {
this.message = await (this.message
? this.message.edit({
...action.options,
// need to ensure that, if there's no text, it's erased
// eslint-disable-next-line unicorn/no-null
content: action.options.content ?? null,
})
: this.channel.send(action.options))
}
if (action.type === "deleteMessage") {
await this.message?.delete()
this.message = undefined
}
}
}