[nextgen/cardstack] rework timeout logic

This commit is contained in:
bignutty 2025-02-22 19:02:44 +01:00
parent 99c9af9a5d
commit ceb8eb097b

View file

@ -8,7 +8,7 @@ const {STATIC_ASSETS} = require("#utils/statics");
const {Context} = require("detritus-client/lib/command"); const {Context} = require("detritus-client/lib/command");
const {MessageComponentTypes, InteractionCallbackTypes, MessageFlags} = require("detritus-client/lib/constants"); const {MessageComponentTypes, InteractionCallbackTypes, MessageFlags} = require("detritus-client/lib/constants");
const {Message} = require("detritus-client/lib/structures"); 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 { const {
STACK_CACHE_KEYS, STACK_CACHE_KEYS,
@ -55,7 +55,7 @@ class DynamicCardStack {
this.interactive_components = options.interactive || {}; this.interactive_components = options.interactive || {};
this.index = options.startingIndex || 0; this.index = options.startingIndex || 0;
this.loopPages = options.loop || true; this.loopPages = options.loop || true;
this.expires = options.expires || 3 * 60 * 1000; this.expires = options.expires || 60 * 1000;
this.pageNumbers = options.pageNumbers || true; this.pageNumbers = options.pageNumbers || true;
this.pageNumberGenerator = options.pageNumberGenerator || ((pg) => `Page ${pg.index + 1}/${pg.activeCardStack.length}`); this.pageNumberGenerator = options.pageNumberGenerator || ((pg) => `Page ${pg.index + 1}/${pg.activeCardStack.length}`);
this.disableCloning = options.disableCloning || false; this.disableCloning = options.disableCloning || false;
@ -70,6 +70,9 @@ class DynamicCardStack {
this.currentComponentsBatch = {}; this.currentComponentsBatch = {};
this.lastInteraction = Date.now();
this.spawned = 0;
return this._spawn(); return this._spawn();
} }
@ -77,6 +80,7 @@ class DynamicCardStack {
* Kills the dynamic card stack. * Kills the dynamic card stack.
*/ */
async kill(clearComponents) { async kill(clearComponents) {
clearTimeout(this.timeout);
if (clearComponents && !this.killed) await this._edit(this.getCurrentCard(), false, true); if (clearComponents && !this.killed) await this._edit(this.getCurrentCard(), false, true);
this.killed = true; this.killed = true;
@ -85,6 +89,27 @@ class DynamicCardStack {
activeStacks.delete(this.context.message || this.context.interaction); 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). * Get a Stack from an attached reference (message/interaction).
* @param {Message} ref Attached message/interaction * @param {Message} ref Attached message/interaction
@ -120,18 +145,9 @@ class DynamicCardStack {
this.updatePageState() this.updatePageState()
// Create internal component listener this.timeout = this._createTimeout()
this.listener = new Components({ this.spawned = Date.now()
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);
}
})
if (createMessage) return this._edit({ if (createMessage) return this._edit({
...this.getCurrentCard() ...this.getCurrentCard()
@ -241,22 +257,17 @@ class DynamicCardStack {
* Automatically applies and re-renders components. * Automatically applies and re-renders components.
* @param {Message} cardContent Card Content * @param {Message} cardContent Card Content
* @param {boolean, Array} components Custom Components Array * @param {boolean, Array} components Custom Components Array
* @param killComponents Remove components
*/ */
async _edit(cardContent, components = false, killComponents = false) { async _edit(cardContent, components = false, killComponents = false) {
let message = Object.assign({}, cardContent); let message = Object.assign({}, cardContent);
this._renderComponents(killComponents); message.components = this._renderComponents(killComponents);
message.components = this.listener;
if (components) { if (components) {
message.components = components; message.components = components;
} }
// This should detatch the listener.
if(killComponents) {
message.components = this.listener.components;
}
if (message["_meta"]) delete message["_meta"]; if (message["_meta"]) delete message["_meta"];
try { try {
@ -414,7 +425,15 @@ class DynamicCardStack {
// Slot all components into their respective rows. // Slot all components into their respective rows.
while (components.length > 0) { 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. // Create a new row for content to overflow in.
if (row.isFull) { if (row.isFull) {
@ -429,9 +448,7 @@ class DynamicCardStack {
if (renderedSlots.length > 5) console.warn("Component Overflow - Limiting to 5.") if (renderedSlots.length > 5) console.warn("Component Overflow - Limiting to 5.")
this.listener.components = renderedSlots.splice(0, 5); return renderedSlots.splice(0, 5);
return this.listener;
} }
/** /**
@ -530,7 +547,7 @@ class DynamicCardStack {
return; return;
} }
//this.lastInteraction = Date.now(); this.lastInteraction = Date.now();
// Built-in Buttons // Built-in Buttons
if (Object.values(BuiltInButtonTypes).includes(ctx.data.customId)) { if (Object.values(BuiltInButtonTypes).includes(ctx.data.customId)) {