diff --git a/integration/text.test.tsx b/integration/text.test.tsx index 90484e0..1bb0c94 100644 --- a/integration/text.test.tsx +++ b/integration/text.test.tsx @@ -85,7 +85,7 @@ test("state", async (t) => { await assertSomeMessageHasContent(t, initialMessage) setMessage!(newMessage) - await root.awaitActions() + await root.completion() await assertSomeMessageHasContent(t, newMessage) diff --git a/src/container.ts b/src/container.ts index f712c6a..99959c2 100644 --- a/src/container.ts +++ b/src/container.ts @@ -5,56 +5,45 @@ type Action = | { type: "deleteMessage" } export class ReacordContainer { - channel: TextBasedChannels - message?: Message - actions: Action[] = [] - runningPromise?: Promise + private channel: TextBasedChannels + private message?: Message + private actions: Action[] = [] + private runningPromise?: Promise constructor(channel: TextBasedChannels) { this.channel = channel } - async render(instances: string[]) { + render(instances: string[]) { const messageOptions: MessageOptions = { content: instances.join("") || undefined, // empty strings are not allowed } const hasContent = messageOptions.content !== undefined - await this.addAction( + this.addAction( hasContent ? { type: "updateMessage", options: messageOptions } : { type: "deleteMessage" }, ) } - private async addAction(action: Action) { + 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) } - await this.runActions() + this.runActions() } - private async runActions() { - if (this.runningPromise) { - return this.runningPromise - } - - const runAction = async (action: Action) => { - if (action.type === "updateMessage") { - this.message = await (this.message - ? this.message.edit(action.options) - : this.channel.send(action.options)) - } - - if (action.type === "deleteMessage") { - await this.message?.delete() - this.message = undefined - } - } + private runActions() { + if (this.runningPromise) return this.runningPromise = new Promise((resolve) => { // using a microtask to allow multiple actions to be added synchronously @@ -62,21 +51,28 @@ export class ReacordContainer { let action: Action | undefined while ((action = this.actions.shift())) { try { - await runAction(action) + await this.runAction(action) } catch (error) { console.error(`Failed to run action:`, action) console.error(error) } } resolve() + this.runningPromise = undefined }) }) - - await this.runningPromise - this.runningPromise = undefined } - awaitActions() { - return this.runningPromise ?? Promise.resolve() + private async runAction(action: Action) { + if (action.type === "updateMessage") { + this.message = await (this.message + ? this.message.edit(action.options) + : this.channel.send(action.options)) + } + + if (action.type === "deleteMessage") { + await this.message?.delete() + this.message = undefined + } } } diff --git a/src/root.ts b/src/root.ts index cfa6b7a..4658f9a 100644 --- a/src/root.ts +++ b/src/root.ts @@ -12,12 +12,12 @@ export function createRoot(target: ReacordRenderTarget) { return { render: (content: ReactNode) => { reconciler.updateContainer(content, containerId) - return container.awaitActions() + return container.completion() }, destroy: () => { reconciler.updateContainer(null, containerId) - return container.awaitActions() + return container.completion() }, - awaitActions: () => container.awaitActions(), + completion: () => container.completion(), } }