From ceb8eb097bc5028f11fa8561b730d39156319c17 Mon Sep 17 00:00:00 2001 From: bignutty <3515180-bignutty@users.noreply.gitlab.com> Date: Sat, 22 Feb 2025 19:02:44 +0100 Subject: [PATCH] [nextgen/cardstack] rework timeout logic --- labscore/cardstack/stack.js | 69 +++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/labscore/cardstack/stack.js b/labscore/cardstack/stack.js index cdc19b7..97edd1e 100644 --- a/labscore/cardstack/stack.js +++ b/labscore/cardstack/stack.js @@ -8,7 +8,7 @@ const {STATIC_ASSETS} = require("#utils/statics"); const {Context} = require("detritus-client/lib/command"); const {MessageComponentTypes, InteractionCallbackTypes, MessageFlags} = require("detritus-client/lib/constants"); const {Message} = require("detritus-client/lib/structures"); -const {ComponentContext, Components, ComponentActionRow, ComponentButton} = require("detritus-client/lib/utils"); +const {ComponentContext, ComponentActionRow, ComponentButton} = require("detritus-client/lib/utils"); const { STACK_CACHE_KEYS, @@ -55,7 +55,7 @@ class DynamicCardStack { this.interactive_components = options.interactive || {}; this.index = options.startingIndex || 0; this.loopPages = options.loop || true; - this.expires = options.expires || 3 * 60 * 1000; + this.expires = options.expires || 60 * 1000; this.pageNumbers = options.pageNumbers || true; this.pageNumberGenerator = options.pageNumberGenerator || ((pg) => `Page ${pg.index + 1}/${pg.activeCardStack.length}`); this.disableCloning = options.disableCloning || false; @@ -70,6 +70,9 @@ class DynamicCardStack { this.currentComponentsBatch = {}; + this.lastInteraction = Date.now(); + this.spawned = 0; + return this._spawn(); } @@ -77,6 +80,7 @@ class DynamicCardStack { * Kills the dynamic card stack. */ async kill(clearComponents) { + clearTimeout(this.timeout); if (clearComponents && !this.killed) await this._edit(this.getCurrentCard(), false, true); this.killed = true; @@ -85,6 +89,27 @@ class DynamicCardStack { activeStacks.delete(this.context.message || this.context.interaction); } + /** + * Creates a timeout for the paginator. + * @returns {number} Timeout + * @private + */ + _createTimeout() { + return setTimeout(async () => { + // If we have an interaction within the expiry window + // restart the expiry window with 30s + if((this.lastInteraction - this.spawned) >= 0){ + clearTimeout(this.timeout) + this.spawned = Date.now(); + // New expiry time is 30 seconds + this.expires = 30*1000; + this.timeout = this._createTimeout(); + } else { + await this.kill(true); + } + }, this.expires) + } + /** * Get a Stack from an attached reference (message/interaction). * @param {Message} ref Attached message/interaction @@ -120,18 +145,9 @@ class DynamicCardStack { this.updatePageState() - // Create internal component listener - this.listener = new Components({ - timeout: this.expires, - run: this._handleInteraction.bind(this), - onError: (e) => { - console.error("Component Handler Exception:") - console.error(e) - }, - onTimeout: async (_e)=> { - await this.kill(true); - } - }) + this.timeout = this._createTimeout() + this.spawned = Date.now() + if (createMessage) return this._edit({ ...this.getCurrentCard() @@ -241,22 +257,17 @@ class DynamicCardStack { * Automatically applies and re-renders components. * @param {Message} cardContent Card Content * @param {boolean, Array} components Custom Components Array + * @param killComponents Remove components */ async _edit(cardContent, components = false, killComponents = false) { let message = Object.assign({}, cardContent); - this._renderComponents(killComponents); - message.components = this.listener; + message.components = this._renderComponents(killComponents); if (components) { message.components = components; } - // This should detatch the listener. - if(killComponents) { - message.components = this.listener.components; - } - if (message["_meta"]) delete message["_meta"]; try { @@ -414,7 +425,15 @@ class DynamicCardStack { // Slot all components into their respective rows. while (components.length > 0) { - row.addButton(components.shift()); + let c = components.shift(); + + // Avoid adding listeners to disabled components + // for optimization's sake + if(c.disabled) row.addButton(c); + else row.addButton({ + ...c, + run: this._handleInteraction.bind(this) + }) // Create a new row for content to overflow in. if (row.isFull) { @@ -429,9 +448,7 @@ class DynamicCardStack { if (renderedSlots.length > 5) console.warn("Component Overflow - Limiting to 5.") - this.listener.components = renderedSlots.splice(0, 5); - - return this.listener; + return renderedSlots.splice(0, 5); } /** @@ -530,7 +547,7 @@ class DynamicCardStack { return; } - //this.lastInteraction = Date.now(); + this.lastInteraction = Date.now(); // Built-in Buttons if (Object.values(BuiltInButtonTypes).includes(ctx.data.customId)) {