diff --git a/package.json b/package.json index 43248d2..3d392c5 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "immer": "^9.0.7", "nanoid": "^3.1.30", "react-reconciler": "^0.26.2", - "react-tree-reconciler": "^1.2.0" + "rxjs": "^7.4.0" }, "peerDependencies": { "discord.js": "^13.3", diff --git a/playground/main.tsx b/playground/main.tsx index c423e88..8972418 100644 --- a/playground/main.tsx +++ b/playground/main.tsx @@ -17,6 +17,7 @@ createCommandHandler(client, [ description: "shows a counter button", run: (interaction) => { manager.create(interaction).render() + manager.create(interaction).render() }, }, ]) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 603b9a7..0d5c6ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,7 +30,7 @@ importers: prettier: ^2.5.1 react: ^17.0.2 react-reconciler: ^0.26.2 - react-tree-reconciler: ^1.2.0 + rxjs: ^7.4.0 tsup: ^5.11.7 typescript: ^4.5.4 vite: ^2.7.6 @@ -42,7 +42,7 @@ importers: immer: 9.0.7 nanoid: 3.1.30 react-reconciler: 0.26.2_react@17.0.2 - react-tree-reconciler: 1.2.0_cfedea9b3ed0faf0dded75c187406c5e + rxjs: 7.4.0 devDependencies: '@itsmapleleaf/configs': 1.1.2 '@typescript-eslint/eslint-plugin': 5.8.0_836011a006f4f5d67178564baf2b6d34 @@ -4830,18 +4830,6 @@ packages: scheduler: 0.20.2 dev: false - /react-tree-reconciler/1.2.0_cfedea9b3ed0faf0dded75c187406c5e: - resolution: {integrity: sha512-DmILQhig+Nnh1tOrYFn7Tary077qW943vdjYqRUWLpYLMP5vS/+k0ICNTPQVNaLQJhh4nDCvVUhFxcSSTzYvHA==} - engines: {node: '>=12'} - peerDependencies: - '@types/react': '*' - dependencies: - '@types/react': 17.0.37 - react-reconciler: 0.26.2_react@17.0.2 - transitivePeerDependencies: - - react - dev: false - /react/17.0.2: resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} engines: {node: '>=0.10.0'} @@ -5050,7 +5038,6 @@ packages: resolution: {integrity: sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==} dependencies: tslib: 2.1.0 - dev: true /safe-buffer/5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -5536,7 +5523,6 @@ packages: /tslib/2.1.0: resolution: {integrity: sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==} - dev: true /tslib/2.3.1: resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==} diff --git a/src.new/renderer.ts b/src.new/renderer.ts index 9cac1dc..7c8282c 100644 --- a/src.new/renderer.ts +++ b/src.new/renderer.ts @@ -3,25 +3,29 @@ import type { MessageComponentInteraction, MessageOptions, } from "discord.js" +import { Subject } from "rxjs" +import { concatMap } from "rxjs/operators" import { Container } from "./container.js" import type { Node } from "./node.js" +// keep track of interaction ids which have replies, +// so we know whether to call reply() or followUp() +const repliedInteractionIds = new Set() + export class Renderer { readonly nodes = new Container>() private componentInteraction?: MessageComponentInteraction + private messageId?: string + private updates = new Subject() - constructor(private interaction: CommandInteraction) {} + constructor(private interaction: CommandInteraction) { + this.updates + .pipe(concatMap((options) => this.updateMessage(options))) + .subscribe() + } render() { - const options = this.getMessageOptions() - if (this.componentInteraction) { - this.componentInteraction.update(options).catch(console.error) - this.componentInteraction = undefined - } else if (this.interaction.replied) { - this.interaction.editReply(options).catch(console.error) - } else { - this.interaction.reply(options).catch(console.error) - } + this.updates.next(this.getMessageOptions()) } handleInteraction(interaction: MessageComponentInteraction) { @@ -44,4 +48,34 @@ export class Renderer { } return options } + + private async updateMessage(options: MessageOptions) { + if (this.componentInteraction) { + const promise = this.componentInteraction.update(options) + this.componentInteraction = undefined + await promise + return + } + + if (this.messageId) { + await this.interaction.channel?.messages.edit(this.messageId, options) + return + } + + if (repliedInteractionIds.has(this.interaction.id)) { + const message = await this.interaction.followUp({ + ...options, + fetchReply: true, + }) + this.messageId = message.id + return + } + + repliedInteractionIds.add(this.interaction.id) + const message = await this.interaction.reply({ + ...options, + fetchReply: true, + }) + this.messageId = message.id + } }