Revert "moved accelerator dir to equicordplugins dir"

This reverts commit 95dc23b6a2.
This commit is contained in:
arasseo. 2025-06-23 19:02:26 +07:00
parent 40e07392e1
commit acfa10992f
9 changed files with 0 additions and 2004 deletions

View file

@ -1,237 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { definePluginSettings } from "@api/Settings";
import { addMessageAccessory, removeMessageAccessory } from "@api/MessageAccessories";
import { EquicordDevs } from "@utils/constants";
import { Logger } from "@utils/Logger";
import definePlugin, { OptionType } from "@utils/types";
import { channelPreloader } from "./modules/preloader";
import { fastCache } from "./modules/fastcache";
import { intersectionOptimizer } from "./modules/intersection";
import { imagePreloader } from "./modules/imagepreloader";
import { CacheIndicatorAccessory } from "./modules/messageAccessory";
import { statsTracker, FloatingStats } from "./modules/stats";
const logger = new Logger("Accelerator");
const settings = definePluginSettings({
enablePreloading: {
type: OptionType.BOOLEAN,
description: "Preload adjacent channels and recent DMs for instant switching",
default: true,
restartNeeded: true
},
enableFastCache: {
type: OptionType.BOOLEAN,
description: "Thread-safe high-performance message and user caching",
default: true,
restartNeeded: true
},
enableImagePreloading: {
type: OptionType.BOOLEAN,
description: "Intelligent image preloading for smoother scrolling",
default: true,
restartNeeded: true
},
enableViewportOptimization: {
type: OptionType.BOOLEAN,
description: "Use intersection observers for efficient rendering",
default: true,
restartNeeded: true
},
showStatsWindow: {
type: OptionType.BOOLEAN,
description: "Show floating performance statistics window",
default: true,
restartNeeded: true
},
showCacheIndicators: {
type: OptionType.BOOLEAN,
description: "Show green dots on messages served instantly from cache",
default: true,
restartNeeded: true
},
preloadDistance: {
type: OptionType.SLIDER,
description: "How many adjacent channels to preload",
default: 3,
markers: [1, 2, 3, 4, 5],
stickToMarkers: true,
restartNeeded: true
},
cacheSize: {
type: OptionType.SLIDER,
description: "Cache size in MB (uses thread-safe buckets)",
default: 256,
markers: [128, 256, 384, 512, 640, 768, 896, 1024],
stickToMarkers: true,
restartNeeded: true
},
maxImagePreload: {
type: OptionType.SLIDER,
description: "Maximum images to preload ahead",
default: 10,
markers: [5, 10, 20, 50],
stickToMarkers: true,
restartNeeded: true
}
});
export default definePlugin({
name: "Accelerator",
description: "High-performance Discord optimization using thread-safe caching, intelligent preloading, and zero CSS interference",
authors: [EquicordDevs.galpt],
tags: ["performance", "optimization", "preload", "cache", "thread-safe"],
dependencies: ["MessageAccessoriesAPI"],
settings,
// Minimal patches - only for tracking performance, no CSS modifications
patches: [
{
find: "CONNECTION_OPEN:",
replacement: {
match: /(CONNECTION_OPEN:function\(\w+\)\{)/,
replace: "$1/* Accelerator: Performance tracking */"
}
}
],
flux: {
// Channel switching with immediate preloading
CHANNEL_SELECT({ channelId, guildId }) {
if (channelId) {
statsTracker.trackChannelSwitchStart(channelId);
if (settings.store.enablePreloading) {
channelPreloader.preloadAdjacent(guildId, channelId, settings.store.preloadDistance);
}
if (settings.store.enableImagePreloading) {
imagePreloader.preloadChannelImages(channelId, settings.store.maxImagePreload);
}
}
},
// Track message loading and fast cache integration
LOAD_MESSAGES_SUCCESS({ channelId, messages }) {
statsTracker.trackChannelSwitchEnd(channelId);
// Always track messages loaded for statistics
if (messages?.length) {
statsTracker.incrementMessagesLoaded(messages.length);
}
// Add to fast cache if enabled
if (settings.store.enableFastCache && messages?.length) {
fastCache.addMessageBatch(channelId, messages);
}
},
// Cache new messages atomically and track them
MESSAGE_CREATE({ message }) {
if (message) {
// Add to fast cache if enabled and track cached count
if (settings.store.enableFastCache) {
fastCache.addMessage(message.channel_id, message);
statsTracker.incrementMessagesCached(1);
}
}
},
// Track cache performance
LOAD_MESSAGES_START({ channelId }) {
if (settings.store.enableFastCache) {
const cached = fastCache.getMessages(channelId);
if (cached.length > 0) {
statsTracker.incrementCacheHit();
logger.debug(`Found ${cached.length} cached messages for channel ${channelId}`);
} else {
statsTracker.incrementCacheMiss();
}
}
},
// User data caching for profile optimization
USER_UPDATE({ user }) {
if (settings.store.enableFastCache && user) {
fastCache.addUser(user.id, user);
}
}
},
async start() {
// Initialize performance tracking
statsTracker.init();
// Initialize thread-safe cache system first
if (settings.store.enableFastCache) {
await fastCache.init(settings.store.cacheSize * 1024 * 1024); // Convert MB to bytes
}
// Initialize pure JavaScript optimizations
if (settings.store.enableViewportOptimization) {
intersectionOptimizer.init();
}
if (settings.store.enablePreloading) {
channelPreloader.init(settings.store.preloadDistance);
}
if (settings.store.enableImagePreloading) {
imagePreloader.init(settings.store.maxImagePreload);
}
// Initialize message accessories for cache indicators
if (settings.store.enableFastCache && settings.store.showCacheIndicators) {
addMessageAccessory("accelerator-cache-indicator", props =>
CacheIndicatorAccessory({ message: props.message })
);
}
// Show stats window (this is the ONLY UI/CSS component)
if (settings.store.showStatsWindow) {
FloatingStats.show();
}
// Set up periodic cache stats sync
if (settings.store.enableFastCache) {
setInterval(() => {
const totalCached = fastCache.getTotalMessagesCached();
if (totalCached !== statsTracker.getStats().messagesCached) {
statsTracker.updateCacheStats({
totalMessagesCached: totalCached
});
}
}, 5000); // Sync every 5 seconds
}
},
stop() {
// Clean shutdown of all systems
channelPreloader.cleanup();
fastCache.cleanup();
intersectionOptimizer.cleanup();
imagePreloader.cleanup();
statsTracker.cleanup();
FloatingStats.hide();
// Remove message accessories
if (settings.store.enableFastCache && settings.store.showCacheIndicators) {
removeMessageAccessory("accelerator-cache-indicator");
}
}
});

View file

@ -1,351 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { Logger } from "@utils/Logger";
import { statsTracker } from "./stats";
const logger = new Logger("Accelerator:FastCache");
// Inspired by VictoriaMetrics/fastcache - thread-safe cache with buckets
// Each bucket has its own lock (simulated with async operations) to reduce contention
interface CacheEntry {
key: string;
value: any;
timestamp: number;
size: number;
}
interface Bucket {
entries: Map<string, CacheEntry>;
totalSize: number;
lastCleanup: number;
}
class FastCache {
private buckets: Bucket[] = [];
private bucketCount = 256; // Power of 2 for fast modulo
private maxCacheSize = 256 * 1024 * 1024; // 256 MB default
private maxEntryAge = 30 * 60 * 1000; // 30 minutes
private cleanupInterval: any | null = null;
private stats = {
hits: 0,
misses: 0,
evictions: 0,
totalEntries: 0
};
async init(maxSizeBytes: number): Promise<void> {
this.maxCacheSize = maxSizeBytes;
this.buckets = [];
// Initialize buckets (like chunks in fastcache)
for (let i = 0; i < this.bucketCount; i++) {
this.buckets.push({
entries: new Map(),
totalSize: 0,
lastCleanup: Date.now()
});
}
// Start background cleanup (like GC in fastcache)
this.cleanupInterval = setInterval(() => {
this.performCleanup();
}, 60 * 1000); // Every minute
logger.info(`FastCache initialized with ${this.bucketCount} buckets, max size: ${Math.round(maxSizeBytes / 1024 / 1024)}MB`);
}
// Hash function to distribute keys across buckets
private hash(key: string): number {
let hash = 0;
for (let i = 0; i < key.length; i++) {
const char = key.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash; // Convert to 32-bit integer
}
return Math.abs(hash) % this.bucketCount;
}
// Estimate size of an object (simplified)
private estimateSize(obj: any): number {
if (obj === null || obj === undefined) return 8;
if (typeof obj === "string") return obj.length * 2; // UTF-16
if (typeof obj === "number") return 8;
if (typeof obj === "boolean") return 4;
if (Array.isArray(obj)) {
return 24 + obj.reduce((acc, item) => acc + this.estimateSize(item), 0);
}
if (typeof obj === "object") {
return 24 + Object.keys(obj).reduce((acc, key) => {
return acc + this.estimateSize(key) + this.estimateSize(obj[key]);
}, 0);
}
return 24; // Default object overhead
}
// Thread-safe set operation
set(key: string, value: any): void {
const bucketIndex = this.hash(key);
const bucket = this.buckets[bucketIndex];
const size = this.estimateSize(value);
const now = Date.now();
// Remove old entry if exists
const existing = bucket.entries.get(key);
if (existing) {
bucket.totalSize -= existing.size;
this.stats.totalEntries--;
}
// Add new entry
const entry: CacheEntry = {
key,
value,
timestamp: now,
size
};
bucket.entries.set(key, entry);
bucket.totalSize += size;
this.stats.totalEntries++;
// Evict if bucket is too large
this.evictFromBucketIfNeeded(bucket);
}
// Thread-safe get operation
get(key: string): any | null {
const bucketIndex = this.hash(key);
const bucket = this.buckets[bucketIndex];
const entry = bucket.entries.get(key);
if (!entry) {
this.stats.misses++;
return null;
}
// Check if entry is still fresh
const now = Date.now();
if (now - entry.timestamp > this.maxEntryAge) {
bucket.entries.delete(key);
bucket.totalSize -= entry.size;
this.stats.totalEntries--;
this.stats.evictions++;
this.stats.misses++;
return null;
}
this.stats.hits++;
return entry.value;
}
// Message-specific operations
addMessage(channelId: string, message: any): void {
if (!message?.id) return;
const key = `msg:${channelId}:${message.id}`;
this.set(key, message);
}
addMessageBatch(channelId: string, messages: any[]): void {
for (const message of messages) {
this.addMessage(channelId, message);
}
}
getMessage(channelId: string, messageId: string): any | null {
const key = `msg:${channelId}:${messageId}`;
return this.get(key);
}
getMessages(channelId: string): any[] {
const messages: any[] = [];
const prefix = `msg:${channelId}:`;
// Search across all buckets for this channel's messages
for (const bucket of this.buckets) {
for (const [key, entry] of bucket.entries) {
if (key.startsWith(prefix)) {
const now = Date.now();
if (now - entry.timestamp <= this.maxEntryAge) {
messages.push(entry.value);
}
}
}
}
return messages.sort((a, b) =>
new Date(a.timestamp || 0).getTime() - new Date(b.timestamp || 0).getTime()
);
}
getMessageCount(channelId: string): number {
const prefix = `msg:${channelId}:`;
let count = 0;
for (const bucket of this.buckets) {
for (const [key, entry] of bucket.entries) {
if (key.startsWith(prefix)) {
const now = Date.now();
if (now - entry.timestamp <= this.maxEntryAge) {
count++;
}
}
}
}
return count;
}
getTotalMessagesCached(): number {
let count = 0;
for (const bucket of this.buckets) {
for (const [key, entry] of bucket.entries) {
if (key.startsWith('msg:')) {
const now = Date.now();
if (now - entry.timestamp <= this.maxEntryAge) {
count++;
}
}
}
}
return count;
}
// User-specific operations
addUser(userId: string, user: any): void {
const key = `user:${userId}`;
this.set(key, user);
}
getUser(userId: string): any | null {
const key = `user:${userId}`;
return this.get(key);
}
// Channel data operations
addChannelData(channelId: string, data: any): void {
const key = `channel:${channelId}`;
this.set(key, data);
}
getChannelData(channelId: string): any | null {
const key = `channel:${channelId}`;
return this.get(key);
}
// Eviction policy (LRU-like but simplified for performance)
private evictFromBucketIfNeeded(bucket: Bucket): void {
const maxBucketSize = this.maxCacheSize / this.bucketCount;
while (bucket.totalSize > maxBucketSize && bucket.entries.size > 0) {
// Find oldest entry
let oldestKey = "";
let oldestTime = Date.now();
for (const [key, entry] of bucket.entries) {
if (entry.timestamp < oldestTime) {
oldestTime = entry.timestamp;
oldestKey = key;
}
}
if (oldestKey) {
const entry = bucket.entries.get(oldestKey);
if (entry) {
bucket.entries.delete(oldestKey);
bucket.totalSize -= entry.size;
this.stats.totalEntries--;
this.stats.evictions++;
}
} else {
break; // Safety break
}
}
}
// Background cleanup (like fastcache's background GC)
private performCleanup(): void {
const now = Date.now();
let totalCleaned = 0;
for (const bucket of this.buckets) {
// Only clean buckets that haven't been cleaned recently
if (now - bucket.lastCleanup < 30 * 1000) continue; // 30 seconds
const keysToDelete: string[] = [];
for (const [key, entry] of bucket.entries) {
if (now - entry.timestamp > this.maxEntryAge) {
keysToDelete.push(key);
}
}
for (const key of keysToDelete) {
const entry = bucket.entries.get(key);
if (entry) {
bucket.entries.delete(key);
bucket.totalSize -= entry.size;
this.stats.totalEntries--;
totalCleaned++;
}
}
bucket.lastCleanup = now;
}
if (totalCleaned > 0) {
logger.debug(`Cleanup removed ${totalCleaned} expired entries`);
}
// Update stats tracker
statsTracker.updateCacheStats({
hits: this.stats.hits,
misses: this.stats.misses,
evictions: this.stats.evictions,
totalEntries: this.stats.totalEntries,
totalSize: this.getTotalSize()
});
}
// Get cache statistics
getStats() {
return {
...this.stats,
totalSize: this.getTotalSize(),
bucketCount: this.bucketCount,
avgBucketSize: this.getTotalSize() / this.bucketCount
};
}
private getTotalSize(): number {
return this.buckets.reduce((total, bucket) => total + bucket.totalSize, 0);
}
cleanup(): void {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
this.cleanupInterval = null;
}
// Clear all buckets
for (const bucket of this.buckets) {
bucket.entries.clear();
bucket.totalSize = 0;
}
this.stats = {
hits: 0,
misses: 0,
evictions: 0,
totalEntries: 0
};
logger.debug("FastCache cleanup completed");
}
}
export const fastCache = new FastCache();

View file

@ -1,255 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { Logger } from "@utils/Logger";
import { MessageStore } from "@webpack/common";
const logger = new Logger("Accelerator:ImagePreloader");
class ImagePreloader {
private preloadedImages = new Set<string>();
private preloadQueue: string[] = [];
private isPreloading = false;
private maxPreload = 10;
private intersectionObserver: IntersectionObserver | null = null;
init(maxPreload: number): void {
this.maxPreload = maxPreload;
this.setupIntersectionObserver();
logger.info("Image preloader initialized");
}
// Set up intersection observer for intelligent preloading
private setupIntersectionObserver(): void {
this.intersectionObserver = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
this.preloadNearbyImages(entry.target);
}
}
},
{
rootMargin: "100px 0px 100px 0px", // Preload when 100px away
threshold: 0.1
}
);
// Observe existing images
this.observeExistingImages();
// Use MutationObserver to watch for new images
const mutationObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === "childList") {
for (const node of mutation.addedNodes) {
if (node.nodeType === Node.ELEMENT_NODE) {
this.observeImagesInElement(node as Element);
}
}
}
}
});
mutationObserver.observe(document.body, {
childList: true,
subtree: true
});
}
private observeExistingImages(): void {
const images = document.querySelectorAll('img, [style*="background-image"]');
for (const img of images) {
this.intersectionObserver?.observe(img);
}
}
private observeImagesInElement(element: Element): void {
// Observe the element itself if it's an image
if (element.tagName === "IMG" ||
(element as HTMLElement).style.backgroundImage) {
this.intersectionObserver?.observe(element);
}
// Observe child images
const images = element.querySelectorAll('img, [style*="background-image"]');
for (const img of images) {
this.intersectionObserver?.observe(img);
}
}
private preloadNearbyImages(target: Element): void {
// Find adjacent images to preload
const container = target.closest('[class*="message"], [class*="content"]');
if (!container) return;
const nearbyImages = this.findNearbyImageUrls(container);
this.addToPreloadQueue(nearbyImages);
}
private findNearbyImageUrls(container: Element): string[] {
const urls: string[] = [];
// Find images in current and adjacent messages
const messageElements = container.parentElement?.querySelectorAll('[class*="message"]') || [];
const currentIndex = Array.from(messageElements).indexOf(container as Element);
// Check current message and a few before/after
const start = Math.max(0, currentIndex - 2);
const end = Math.min(messageElements.length, currentIndex + 3);
for (let i = start; i < end; i++) {
const messageEl = messageElements[i];
// Find image URLs in this message
const images = messageEl.querySelectorAll('img');
for (const img of images) {
if (img.src && !this.preloadedImages.has(img.src)) {
urls.push(img.src);
}
}
// Find background images
const elementsWithBg = messageEl.querySelectorAll('[style*="background-image"]');
for (const el of elementsWithBg) {
const bgImage = (el as HTMLElement).style.backgroundImage;
const urlMatch = bgImage.match(/url\(['"]?(.*?)['"]?\)/);
if (urlMatch && urlMatch[1] && !this.preloadedImages.has(urlMatch[1])) {
urls.push(urlMatch[1]);
}
}
}
return urls.slice(0, this.maxPreload);
}
preloadChannelImages(channelId: string, maxImages: number): void {
try {
// Get messages from Discord's message store
const messages = MessageStore.getMessages(channelId);
if (!messages?._array) return;
const imageUrls: string[] = [];
// Extract image URLs from recent messages
for (const message of messages._array.slice(-20)) { // Last 20 messages
if (imageUrls.length >= maxImages) break;
// Check attachments
if (message.attachments) {
for (const attachment of message.attachments) {
if (attachment.content_type?.startsWith('image/') &&
attachment.url &&
!this.preloadedImages.has(attachment.url)) {
imageUrls.push(attachment.url);
}
}
}
// Check embeds
if (message.embeds) {
for (const embed of message.embeds) {
if (embed.image?.url && !this.preloadedImages.has(embed.image.url)) {
imageUrls.push(embed.image.url);
}
if (embed.thumbnail?.url && !this.preloadedImages.has(embed.thumbnail.url)) {
imageUrls.push(embed.thumbnail.url);
}
}
}
}
this.addToPreloadQueue(imageUrls.slice(0, maxImages));
} catch (error) {
logger.warn("Failed to preload channel images:", error);
}
}
private addToPreloadQueue(urls: string[]): void {
for (const url of urls) {
if (!this.preloadedImages.has(url) && !this.preloadQueue.includes(url)) {
this.preloadQueue.push(url);
}
}
if (!this.isPreloading) {
this.processPreloadQueue();
}
}
private async processPreloadQueue(): Promise<void> {
if (this.isPreloading || this.preloadQueue.length === 0) return;
this.isPreloading = true;
while (this.preloadQueue.length > 0 && this.preloadedImages.size < this.maxPreload * 2) {
const url = this.preloadQueue.shift();
if (!url || this.preloadedImages.has(url)) continue;
try {
await this.preloadImage(url);
this.preloadedImages.add(url);
} catch (error) {
logger.debug(`Failed to preload image: ${url}`, error);
}
// Add small delay to avoid blocking the main thread
await new Promise(resolve => setTimeout(resolve, 10));
}
this.isPreloading = false;
}
private preloadImage(url: string): Promise<void> {
return new Promise((resolve, reject) => {
const img = new Image();
const cleanup = () => {
img.onload = null;
img.onerror = null;
img.onabort = null;
};
img.onload = () => {
cleanup();
resolve();
};
img.onerror = () => {
cleanup();
reject(new Error(`Failed to load ${url}`));
};
img.onabort = () => {
cleanup();
reject(new Error(`Aborted loading ${url}`));
};
// Set timeout to avoid hanging
setTimeout(() => {
cleanup();
reject(new Error(`Timeout loading ${url}`));
}, 5000);
img.src = url;
});
}
cleanup(): void {
if (this.intersectionObserver) {
this.intersectionObserver.disconnect();
this.intersectionObserver = null;
}
this.preloadedImages.clear();
this.preloadQueue.length = 0;
this.isPreloading = false;
logger.debug("Image preloader cleanup completed");
}
}
export const imagePreloader = new ImagePreloader();

View file

@ -1,173 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { Logger } from "@utils/Logger";
import { statsTracker } from "./stats";
const logger = new Logger("Accelerator:IntersectionOptimizer");
class IntersectionOptimizer {
private imageObserver: IntersectionObserver | null = null;
private observedElements = new Set<Element>();
private imagePreloadQueue = new Set<string>();
private isEnabled = false;
init() {
this.setupImageObserver();
this.isEnabled = true;
logger.info("Intersection optimizer initialized (scroll-safe mode)");
}
private setupImageObserver() {
// Only handle image lazy loading - no layout modifications to avoid scroll issues
this.imageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target as HTMLImageElement;
this.optimizeImageLoading(img);
this.imageObserver?.unobserve(img);
}
});
}, {
rootMargin: '1000px 0px', // Preload images 1000px before they enter viewport
threshold: 0.01
});
this.observeExistingImages();
this.setupImageMutationObserver();
}
private observeExistingImages() {
if (!this.imageObserver) return;
// Only observe Discord CDN images to avoid interfering with other content
const images = document.querySelectorAll('img[src*="cdn.discordapp.com"], img[src*="media.discordapp.net"]');
images.forEach(img => {
if (!this.observedElements.has(img)) {
this.imageObserver!.observe(img);
this.observedElements.add(img);
}
});
}
private setupImageMutationObserver() {
if (!this.imageObserver) return;
const mutationObserver = new MutationObserver(mutations => {
if (!this.isEnabled) return;
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node instanceof HTMLElement) {
// Check for new Discord images only
const images = node.matches('img') ? [node] :
Array.from(node.querySelectorAll('img[src*="cdn.discordapp.com"], img[src*="media.discordapp.net"]'));
images.forEach(img => {
if (!this.observedElements.has(img) && this.imageObserver) {
this.imageObserver.observe(img);
this.observedElements.add(img);
}
});
}
});
});
});
mutationObserver.observe(document.body, {
childList: true,
subtree: true
});
}
private optimizeImageLoading(img: HTMLImageElement) {
try {
// Only apply safe image optimizations that don't affect layout
if (!img.loading) {
img.loading = 'lazy';
}
if (!img.decoding) {
img.decoding = 'async';
}
// Preload higher quality version if available
const src = img.src;
if (src && (src.includes('cdn.discordapp.com') || src.includes('media.discordapp.net'))) {
this.preloadHigherQuality(src);
}
logger.debug(`Optimized image loading: ${img.src}`);
statsTracker.incrementImagesOptimized();
} catch (error) {
logger.error("Failed to optimize image loading:", error);
}
}
private preloadHigherQuality(src: string) {
if (this.imagePreloadQueue.has(src)) return;
this.imagePreloadQueue.add(src);
try {
// Convert to higher quality if it's a Discord CDN image with quality params
let highQualitySrc = src;
if (src.includes('?')) {
const url = new URL(src);
// Remove width/height constraints for better quality
url.searchParams.delete('width');
url.searchParams.delete('height');
// Set higher quality if quality param exists
if (url.searchParams.has('quality')) {
url.searchParams.set('quality', '100');
}
// Remove format constraints to get original format
if (url.searchParams.has('format')) {
url.searchParams.delete('format');
}
highQualitySrc = url.toString();
}
// Preload the higher quality version
if (highQualitySrc !== src) {
const preloadImg = new Image();
preloadImg.onload = () => {
this.imagePreloadQueue.delete(src);
logger.debug(`Preloaded high quality image: ${highQualitySrc}`);
};
preloadImg.onerror = () => {
this.imagePreloadQueue.delete(src);
};
preloadImg.src = highQualitySrc;
} else {
this.imagePreloadQueue.delete(src);
}
} catch (error) {
this.imagePreloadQueue.delete(src);
logger.error("Failed to preload higher quality image:", error);
}
}
cleanup() {
this.isEnabled = false;
if (this.imageObserver) {
this.imageObserver.disconnect();
this.imageObserver = null;
}
this.observedElements.clear();
this.imagePreloadQueue.clear();
logger.debug("Intersection optimizer cleanup completed");
}
}
export const intersectionOptimizer = new IntersectionOptimizer();

View file

@ -1,86 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { Logger } from "@utils/Logger";
import { React } from "@webpack/common";
import { fastCache } from "./fastcache";
import { statsTracker } from "./stats";
const logger = new Logger("Accelerator:MessageAccessory");
interface MessageAccessoryProps {
message: any;
}
let processedMessages = new Set<string>();
export function CacheIndicatorAccessory({ message }: MessageAccessoryProps) {
const [showIndicator, setShowIndicator] = React.useState(false);
const indicatorRef = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
if (!message?.id || !message?.channel_id) return;
const messageKey = `${message.channel_id}:${message.id}`;
// Avoid processing the same message multiple times
if (processedMessages.has(messageKey)) return;
processedMessages.add(messageKey);
// Add slight delay to ensure cache has been checked
setTimeout(() => {
const cachedMessage = fastCache.getMessage(message.channel_id, message.id);
if (cachedMessage) {
setShowIndicator(true);
statsTracker.incrementMessagesServedFromCache(1);
logger.debug(`Message ${message.id} served from cache`);
}
}, 100);
}, [message?.id, message?.channel_id]);
// Ensure proper positioning after render
React.useEffect(() => {
if (showIndicator && indicatorRef.current) {
const indicator = indicatorRef.current;
const messageElement = indicator.closest('[class*="message"]') ||
indicator.closest('[id^="chat-messages-"]') ||
indicator.closest('[class*="messageListItem-"]');
if (messageElement) {
const messageRect = messageElement.getBoundingClientRect();
// Adjust position to be perfectly centered in the message highlight area
indicator.style.top = "50%";
indicator.style.right = "12px";
}
}
}, [showIndicator]);
if (!showIndicator) return null;
return (
<div
ref={indicatorRef}
style={{
position: "absolute",
top: "50%",
right: "12px",
width: "10px",
height: "10px",
backgroundColor: "#3ba55c",
borderRadius: "50%",
zIndex: 100,
transform: "translateY(-50%)",
boxShadow: "0 0 0 2px rgba(32, 34, 37, 0.95), 0 2px 8px rgba(0, 0, 0, 0.5)",
animation: "acceleratorCachePulse 2.5s ease-in-out infinite",
cursor: "help",
pointerEvents: "none" // Don't interfere with message interactions
}}
title="This message was served instantly from fastcache"
/>
);
}

View file

@ -1,214 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { FluxDispatcher, ChannelStore, GuildChannelStore, ChannelActionCreators, MessageActions } from "@webpack/common";
import { Logger } from "@utils/Logger";
const logger = new Logger("Accelerator:Preloader");
interface PreloadedChannel {
channelId: string;
timestamp: number;
messages: boolean;
}
class ChannelPreloader {
private preloadedChannels = new Map<string, PreloadedChannel>();
private preloadQueue = new Set<string>();
private maxPreloadAge = 5 * 60 * 1000; // 5 minutes
private preloadDistance = 3;
private isScrolling = false;
private scrollTimeout: number | null = null;
private lastScrollTime = 0;
init(distance: number) {
this.preloadDistance = distance;
this.setupScrollDetection();
logger.info("Channel preloader initialized (scroll-aware)");
}
private setupScrollDetection() {
// Detect when user is actively scrolling to avoid interference
const handleScroll = () => {
this.isScrolling = true;
this.lastScrollTime = Date.now();
if (this.scrollTimeout) {
clearTimeout(this.scrollTimeout);
}
// Consider scrolling finished after 150ms of no scroll events
this.scrollTimeout = setTimeout(() => {
this.isScrolling = false;
}, 150);
};
// Listen to scroll events on potential scroll containers
document.addEventListener('scroll', handleScroll, { passive: true, capture: true });
document.addEventListener('wheel', handleScroll, { passive: true, capture: true });
}
async preloadAdjacent(guildId: string | null, currentChannelId: string, distance: number) {
// Don't start new preloads while user is actively scrolling
if (this.isScrolling || (Date.now() - this.lastScrollTime) < 500) {
logger.debug("Skipping preload during scroll activity");
return;
}
try {
const adjacentChannels = this.getAdjacentChannels(guildId, currentChannelId, distance);
// More conservative preloading to avoid interfering with scroll
const batchSize = 1; // Reduced from 2 to 1
for (let i = 0; i < adjacentChannels.length; i += batchSize) {
// Check if user started scrolling during preload
if (this.isScrolling) {
logger.debug("Stopping preload due to scroll activity");
break;
}
const batch = adjacentChannels.slice(i, i + batchSize);
await Promise.all(batch.map(channelId => this.preloadChannel(channelId)));
// Longer delay between batches to be less aggressive
if (i + batchSize < adjacentChannels.length) {
await new Promise(resolve => setTimeout(resolve, 200));
}
}
// Cleanup old preloaded channels
this.cleanup();
} catch (error) {
logger.error("Failed to preload adjacent channels:", error);
}
}
private getAdjacentChannels(guildId: string | null, currentChannelId: string, distance: number): string[] {
const channels: string[] = [];
try {
if (guildId) {
// Guild channels
const guildChannels = GuildChannelStore.getChannels(guildId);
const selectableChannels = guildChannels.SELECTABLE || [];
const currentIndex = selectableChannels.findIndex(ch => ch.channel.id === currentChannelId);
if (currentIndex !== -1) {
// Get channels before and after current
for (let i = 1; i <= distance; i++) {
const beforeIndex = currentIndex - i;
const afterIndex = currentIndex + i;
if (beforeIndex >= 0) {
channels.push(selectableChannels[beforeIndex].channel.id);
}
if (afterIndex < selectableChannels.length) {
channels.push(selectableChannels[afterIndex].channel.id);
}
}
}
} else {
// DM channels - preload recent conversations
const recentChannels = this.getRecentDMChannels(currentChannelId, distance);
channels.push(...recentChannels);
}
} catch (error) {
logger.error("Failed to get adjacent channels:", error);
}
return channels.filter(id => id !== currentChannelId);
}
private getRecentDMChannels(excludeChannelId: string, count: number): string[] {
// Get recent DM channels from Discord's internal stores
try {
const privateChannels = ChannelStore.getSortedPrivateChannels();
return privateChannels
.filter(channel => channel.id !== excludeChannelId)
.slice(0, count)
.map(channel => channel.id);
} catch (error) {
logger.error("Failed to get recent DM channels:", error);
return [];
}
}
private async preloadChannel(channelId: string) {
if (this.preloadQueue.has(channelId)) return;
if (this.isScrolling) return; // Don't start new preloads during scroll
const existingPreload = this.preloadedChannels.get(channelId);
const now = Date.now();
// Skip if recently preloaded
if (existingPreload && (now - existingPreload.timestamp) < this.maxPreloadAge) {
return;
}
this.preloadQueue.add(channelId);
try {
const channel = ChannelStore.getChannel(channelId);
if (!channel) return;
// Check again if user started scrolling
if (this.isScrolling) {
this.preloadQueue.delete(channelId);
return;
}
// Use Discord's internal preload system - but be more conservative
if (channel.guild_id) {
await ChannelActionCreators.preload(channel.guild_id, channelId);
}
// Only preload messages for non-DM channels, and with smaller batch size
if (channel.type !== 1 && channel.type !== 3 && !this.isScrolling) {
await MessageActions.fetchMessages({
channelId,
limit: 25 // Reduced from 50 to 25
});
}
this.preloadedChannels.set(channelId, {
channelId,
timestamp: now,
messages: true
});
logger.debug(`Preloaded channel: ${channelId}`);
} catch (error) {
logger.error(`Failed to preload channel ${channelId}:`, error);
} finally {
this.preloadQueue.delete(channelId);
}
}
cleanup() {
const now = Date.now();
const toRemove: string[] = [];
for (const [channelId, preload] of this.preloadedChannels) {
if ((now - preload.timestamp) > this.maxPreloadAge) {
toRemove.push(channelId);
}
}
toRemove.forEach(channelId => this.preloadedChannels.delete(channelId));
if (toRemove.length > 0) {
logger.debug(`Cleaned up ${toRemove.length} old preloaded channels`);
}
// Cleanup scroll detection
if (this.scrollTimeout) {
clearTimeout(this.scrollTimeout);
this.scrollTimeout = null;
}
}
}
export const channelPreloader = new ChannelPreloader();

View file

@ -1,513 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { Logger } from "@utils/Logger";
const logger = new Logger("Accelerator:Stats");
interface AcceleratorStats {
channelSwitches: number;
messagesLoaded: number;
messagesCached: number;
messagesServedFromCache: number;
imagesOptimized: number;
imagesCached: number;
cacheHits: number;
cacheMisses: number;
averageLoadTime: number;
startTime: number;
lastUpdate: number;
}
interface ChannelSwitchTracking {
channelId: string;
startTime: number;
}
class StatsTracker {
private stats: AcceleratorStats;
private loadTimes: number[] = [];
private maxLoadTimeHistory = 50;
private currentChannelSwitch: ChannelSwitchTracking | null = null;
private imageLoadTimes = new Map<string, number>(); // Track when image requests start
private processedImages = new Set<string>(); // Track which images we've seen before
constructor() {
this.stats = this.getInitialStats();
}
private getInitialStats(): AcceleratorStats {
return {
channelSwitches: 0,
messagesLoaded: 0,
messagesCached: 0,
messagesServedFromCache: 0,
imagesOptimized: 0,
imagesCached: 0,
cacheHits: 0,
cacheMisses: 0,
averageLoadTime: 0,
startTime: Date.now(),
lastUpdate: Date.now()
};
}
init() {
this.stats = this.getInitialStats();
this.setupImageCacheTracking();
logger.info("Stats tracker initialized - tracking real Discord performance");
}
// Track real Discord channel switching performance like messageFetchTimer
trackChannelSwitchStart(channelId: string): void {
this.currentChannelSwitch = {
channelId,
startTime: performance.now()
};
logger.debug(`Channel switch started: ${channelId}`);
}
trackChannelSwitchEnd(channelId: string): void {
if (!this.currentChannelSwitch || this.currentChannelSwitch.channelId !== channelId) {
logger.debug(`Channel switch end without matching start: ${channelId}`);
return;
}
const loadTime = performance.now() - this.currentChannelSwitch.startTime;
this.recordLoadTime(loadTime);
this.incrementChannelSwitch();
this.currentChannelSwitch = null;
logger.debug(`Channel switch completed: ${channelId} in ${loadTime.toFixed(1)}ms`);
}
// Set up real image cache tracking by hooking into image loading
private setupImageCacheTracking() {
const statsTracker = this;
// Use MutationObserver to track all image elements added to DOM
const imageObserver = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
const element = node as Element;
// Check if it's an image or contains images
const images = element.tagName === 'IMG'
? [element as HTMLImageElement]
: Array.from(element.querySelectorAll('img'));
images.forEach(img => {
this.trackImageElement(img);
});
}
});
});
});
// Start observing
imageObserver.observe(document.body, {
childList: true,
subtree: true
});
// Track existing images
document.querySelectorAll('img').forEach(img => {
this.trackImageElement(img);
});
}
private trackImageElement(img: HTMLImageElement) {
const src = img.src || img.getAttribute('data-src') || '';
// Only track Discord CDN images
if (!src || (!src.includes('cdn.discordapp.com') && !src.includes('media.discordapp.net'))) {
return;
}
const startTime = performance.now();
this.imageLoadTimes.set(src, startTime);
// Check if we've seen this image before (cache scenario)
const wasProcessed = this.processedImages.has(src);
const onLoad = () => {
const endTime = performance.now();
const loadTime = endTime - (this.imageLoadTimes.get(src) || endTime);
if (wasProcessed) {
// Image was processed before, likely from cache
this.incrementImagesCached();
if (loadTime < 50) { // Very fast load likely means cache hit
this.incrementCacheHit();
}
} else {
// First time seeing this image
this.incrementImagesOptimized();
this.processedImages.add(src);
if (loadTime >= 50) { // Slower load likely means cache miss
this.incrementCacheMiss();
}
}
this.imageLoadTimes.delete(src);
logger.debug(`Image loaded: ${src} in ${loadTime.toFixed(1)}ms (cached: ${wasProcessed})`);
// Clean up listeners
img.removeEventListener('load', onLoad);
img.removeEventListener('error', onError);
};
const onError = () => {
this.imageLoadTimes.delete(src);
img.removeEventListener('load', onLoad);
img.removeEventListener('error', onError);
};
// If image is already loaded, track it immediately
if (img.complete && img.naturalWidth > 0) {
setTimeout(onLoad, 0);
} else {
img.addEventListener('load', onLoad);
img.addEventListener('error', onError);
}
}
incrementChannelSwitch() {
this.stats.channelSwitches++;
this.updateTimestamp();
logger.debug(`Channel switch tracked: ${this.stats.channelSwitches}`);
}
incrementMessagesLoaded(count: number) {
this.stats.messagesLoaded += count;
this.updateTimestamp();
logger.debug(`Messages loaded: +${count} (total: ${this.stats.messagesLoaded})`);
}
incrementMessagesCached(count: number) {
this.stats.messagesCached += count;
this.updateTimestamp();
logger.debug(`Messages cached: +${count} (total: ${this.stats.messagesCached})`);
}
incrementMessagesServedFromCache(count: number) {
this.stats.messagesServedFromCache += count;
this.updateTimestamp();
logger.debug(`Messages served from cache: +${count} (total: ${this.stats.messagesServedFromCache})`);
}
incrementImagesOptimized() {
this.stats.imagesOptimized++;
this.updateTimestamp();
logger.debug(`Images optimized: ${this.stats.imagesOptimized}`);
}
incrementImagesCached() {
this.stats.imagesCached++;
this.updateTimestamp();
logger.debug(`Images cached: ${this.stats.imagesCached}`);
}
incrementCacheHit() {
this.stats.cacheHits++;
this.updateTimestamp();
logger.debug(`Cache hit: ${this.stats.cacheHits}`);
}
incrementCacheMiss() {
this.stats.cacheMisses++;
this.updateTimestamp();
logger.debug(`Cache miss: ${this.stats.cacheMisses}`);
}
updateCacheStats(cacheStats: any): void {
if (cacheStats.hits !== undefined) this.stats.cacheHits = cacheStats.hits;
if (cacheStats.misses !== undefined) this.stats.cacheMisses = cacheStats.misses;
if (cacheStats.totalMessagesCached !== undefined) this.stats.messagesCached = cacheStats.totalMessagesCached;
this.updateTimestamp();
logger.debug(`Cache stats updated:`, cacheStats);
}
recordLoadTime(time: number) {
// Only record realistic load times (filter out obviously wrong values)
if (time > 0 && time < 30000) { // Between 0 and 30 seconds
this.loadTimes.push(time);
if (this.loadTimes.length > this.maxLoadTimeHistory) {
this.loadTimes.shift();
}
this.stats.averageLoadTime = this.loadTimes.reduce((a, b) => a + b, 0) / this.loadTimes.length;
this.updateTimestamp();
logger.debug(`Load time recorded: ${time.toFixed(1)}ms (avg: ${this.stats.averageLoadTime.toFixed(1)}ms)`);
}
}
private updateTimestamp() {
this.stats.lastUpdate = Date.now();
}
getStats(): AcceleratorStats {
return { ...this.stats };
}
getFormattedUptime(): string {
const uptime = Date.now() - this.stats.startTime;
const minutes = Math.floor(uptime / 60000);
const seconds = Math.floor((uptime % 60000) / 1000);
return `${minutes}m ${seconds}s`;
}
getCacheHitRate(): number {
const total = this.stats.cacheHits + this.stats.cacheMisses;
return total > 0 ? (this.stats.cacheHits / total) * 100 : 0;
}
cleanup() {
// Reset tracking state
this.currentChannelSwitch = null;
this.imageLoadTimes.clear();
this.processedImages.clear();
this.stats = this.getInitialStats();
this.loadTimes = [];
logger.debug("Stats tracker cleanup completed");
}
}
export const statsTracker = new StatsTracker();
// Floating Stats Window using vanilla DOM
export class FloatingStats {
private static container: HTMLDivElement | null = null;
private static isVisible = false;
private static updateInterval: number | null = null;
private static isDragging = false;
private static dragOffset = { x: 0, y: 0 };
private static position = { x: window.innerWidth - 320, y: 20 };
private static isMinimized = false;
static show() {
if (this.isVisible) return;
this.createContainer();
this.setupEventListeners();
this.startUpdating();
this.isVisible = true;
logger.info("Floating stats window shown");
}
static hide() {
if (!this.isVisible) return;
if (this.container) {
document.body.removeChild(this.container);
this.container = null;
}
if (this.updateInterval) {
clearInterval(this.updateInterval);
this.updateInterval = null;
}
this.isVisible = false;
logger.info("Floating stats window hidden");
}
static toggle() {
if (this.isVisible) {
this.hide();
} else {
this.show();
}
}
private static createContainer() {
this.container = document.createElement("div");
this.container.id = "accelerator-stats-container";
this.updateStyles();
this.updateContent();
document.body.appendChild(this.container);
}
private static updateStyles() {
if (!this.container) return;
Object.assign(this.container.style, {
position: "fixed",
top: `${this.position.y}px`,
left: `${this.position.x}px`,
width: "300px",
minHeight: this.isMinimized ? "40px" : "auto",
maxHeight: this.isMinimized ? "40px" : "500px",
backgroundColor: "var(--background-secondary)",
border: "1px solid var(--background-secondary-alt)",
borderRadius: "8px",
padding: "12px",
fontSize: "12px",
fontFamily: "var(--font-primary)",
color: "var(--text-normal)",
zIndex: "9999",
userSelect: "none",
boxShadow: "0 8px 24px rgba(0, 0, 0, 0.15)",
backdropFilter: "blur(10px)",
overflow: "hidden",
transition: "all 0.2s ease"
});
}
private static updateContent() {
if (!this.container) return;
const stats = statsTracker.getStats();
const uptime = statsTracker.getFormattedUptime();
const cacheRate = statsTracker.getCacheHitRate();
const formatNumber = (num: number): string => {
if (num >= 1000) return (num / 1000).toFixed(1) + "k";
return num.toString();
};
const formatLoadTime = (time: number): string => {
return time < 1000 ? `${Math.round(time)}ms` : `${(time / 1000).toFixed(1)}s`;
};
const formatCacheRate = (rate: number): string => {
return rate.toFixed(1) + "%";
};
const headerHTML = `
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: ${this.isMinimized ? '0' : '8px'}; padding-bottom: 4px; border-bottom: 1px solid var(--background-modifier-accent);">
<span style="font-weight: 600; color: var(--text-brand);">🚀 Accelerator Stats</span>
<div style="display: flex; gap: 8px;">
<button id="accelerator-minimize" style="background: none; border: none; color: var(--text-muted); cursor: pointer; padding: 2px; font-size: 14px;">${this.isMinimized ? '📈' : '📉'}</button>
<button id="accelerator-close" style="background: none; border: none; color: var(--text-muted); cursor: pointer; padding: 2px; font-size: 12px;"></button>
</div>
</div>
`;
const contentHTML = this.isMinimized ? '' : `
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; font-size: 11px;">
<div style="background: var(--background-tertiary); padding: 6px; border-radius: 4px;">
<div style="color: var(--text-muted); margin-bottom: 2px;">Channel Switches</div>
<div style="font-weight: 600; color: var(--text-brand);">${formatNumber(stats.channelSwitches)}</div>
</div>
<div style="background: var(--background-tertiary); padding: 6px; border-radius: 4px;">
<div style="color: var(--text-muted); margin-bottom: 2px;">Channel Load Time</div>
<div style="font-weight: 600; color: ${stats.averageLoadTime < 1000 ? 'var(--text-positive)' : stats.averageLoadTime < 2000 ? 'var(--text-warning)' : 'var(--text-danger)'};">${formatLoadTime(stats.averageLoadTime)}</div>
</div>
<div style="background: var(--background-tertiary); padding: 6px; border-radius: 4px;">
<div style="color: var(--text-muted); margin-bottom: 2px;">Messages from Discord</div>
<div style="font-weight: 600; color: var(--text-normal);">${formatNumber(stats.messagesLoaded)}</div>
</div>
<div style="background: var(--background-tertiary); padding: 6px; border-radius: 4px;">
<div style="color: var(--text-muted); margin-bottom: 2px;">Messages from Cache</div>
<div style="font-weight: 600; color: var(--text-positive);">${formatNumber(stats.messagesServedFromCache)}</div>
</div>
<div style="background: var(--background-tertiary); padding: 6px; border-radius: 4px;">
<div style="color: var(--text-muted); margin-bottom: 2px;">Messages Stored</div>
<div style="font-weight: 600; color: var(--text-brand);">${formatNumber(stats.messagesCached)}</div>
</div>
<div style="background: var(--background-tertiary); padding: 6px; border-radius: 4px;">
<div style="color: var(--text-muted); margin-bottom: 2px;">Message Cache Rate</div>
<div style="font-weight: 600; color: ${cacheRate > 70 ? 'var(--text-positive)' : cacheRate > 40 ? 'var(--text-warning)' : 'var(--text-danger)'};">${formatCacheRate(cacheRate)}</div>
</div>
<div style="background: var(--background-tertiary); padding: 6px; border-radius: 4px;">
<div style="color: var(--text-muted); margin-bottom: 2px;">Images Preloaded</div>
<div style="font-weight: 600; color: var(--text-positive);">${formatNumber(stats.imagesOptimized)}</div>
</div>
<div style="background: var(--background-tertiary); padding: 6px; border-radius: 4px;">
<div style="color: var(--text-muted); margin-bottom: 2px;">Images from Cache</div>
<div style="font-weight: 600; color: var(--text-positive);">${formatNumber(stats.imagesCached)}</div>
</div>
<div style="background: var(--background-tertiary); padding: 6px; border-radius: 4px;">
<div style="color: var(--text-muted); margin-bottom: 2px;">Uptime</div>
<div style="font-weight: 600; color: var(--text-muted);">${uptime}</div>
</div>
</div>
`;
this.container.innerHTML = headerHTML + contentHTML;
this.setupToggleButton();
}
private static setupToggleButton() {
const minimizeBtn = document.getElementById("accelerator-minimize");
const closeBtn = document.getElementById("accelerator-close");
if (minimizeBtn) {
minimizeBtn.onclick = (e) => {
e.stopPropagation();
this.isMinimized = !this.isMinimized;
this.updateStyles();
this.updateContent();
};
}
if (closeBtn) {
closeBtn.onclick = (e) => {
e.stopPropagation();
this.hide();
};
}
}
private static setupEventListeners() {
if (!this.container) return;
// Dragging functionality
this.container.onmousedown = (e) => {
if ((e.target as HTMLElement).tagName === "BUTTON") return;
this.isDragging = true;
this.dragOffset.x = e.clientX - this.position.x;
this.dragOffset.y = e.clientY - this.position.y;
if (this.container) {
this.container.style.cursor = "grabbing";
this.container.style.opacity = "0.8";
}
};
document.onmousemove = (e) => {
if (!this.isDragging || !this.container) return;
this.position.x = e.clientX - this.dragOffset.x;
this.position.y = e.clientY - this.dragOffset.y;
// Keep within screen bounds
this.position.x = Math.max(0, Math.min(window.innerWidth - 300, this.position.x));
this.position.y = Math.max(0, Math.min(window.innerHeight - 100, this.position.y));
this.container.style.left = `${this.position.x}px`;
this.container.style.top = `${this.position.y}px`;
};
document.onmouseup = () => {
if (!this.isDragging) return;
this.isDragging = false;
if (this.container) {
this.container.style.cursor = "default";
this.container.style.opacity = "1";
}
};
}
private static startUpdating() {
if (this.updateInterval) clearInterval(this.updateInterval);
this.updateInterval = setInterval(() => {
if (this.isVisible && this.container) {
this.updateContent();
}
}, 1000) as any;
}
}

View file

@ -1,171 +0,0 @@
/*
* Accelerator Stats Window - The ONLY CSS component
* This contains ONLY styles for the floating stats window
* NO performance CSS that could interfere with Discord's layout
*/
.accelerator-stats-window {
position: fixed;
z-index: 10000;
background: rgba(32, 34, 37, 0.95);
border: 1px solid #40444b;
border-radius: 8px;
backdrop-filter: blur(10px);
font-family: 'gg sans', 'Noto Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12px;
color: #dcddde;
min-width: 280px;
max-width: 400px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
user-select: none;
cursor: move;
}
.accelerator-stats-header {
padding: 12px 16px 8px;
border-bottom: 1px solid #40444b;
font-weight: 600;
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(90deg, #5865f2, #7289da);
color: white;
border-radius: 7px 7px 0 0;
cursor: move;
}
.accelerator-stats-content {
padding: 12px 16px;
max-height: 400px;
overflow-y: auto;
}
.accelerator-stats-content::-webkit-scrollbar {
width: 6px;
}
.accelerator-stats-content::-webkit-scrollbar-track {
background: transparent;
}
.accelerator-stats-content::-webkit-scrollbar-thumb {
background: #40444b;
border-radius: 3px;
}
.accelerator-stats-section {
margin-bottom: 12px;
}
.accelerator-stats-section h4 {
margin: 0 0 6px 0;
font-size: 11px;
font-weight: 600;
color: #b9bbbe;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.accelerator-stats-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.accelerator-stats-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 4px 0;
}
.accelerator-stats-label {
color: #b9bbbe;
font-size: 11px;
}
.accelerator-stats-value {
color: #dcddde;
font-weight: 500;
font-size: 12px;
}
.accelerator-stats-value.positive {
color: #3ba55c;
}
.accelerator-stats-value.neutral {
color: #faa61a;
}
.accelerator-stats-toggle {
background: none;
border: none;
color: #dcddde;
cursor: pointer;
font-size: 14px;
padding: 4px;
border-radius: 4px;
transition: background-color 0.2s;
}
.accelerator-stats-toggle:hover {
background: rgba(255, 255, 255, 0.1);
}
.accelerator-stats-window.minimized .accelerator-stats-content {
display: none;
}
.accelerator-stats-window.minimized {
min-width: auto;
}
/* Cache Indicator - Shows when a message was served from fastcache */
.accelerator-cache-indicator {
position: absolute;
top: 4px;
right: 4px;
width: 8px;
height: 8px;
background: #3ba55c;
border-radius: 50%;
z-index: 10;
box-shadow: 0 0 0 1px rgba(32, 34, 37, 0.9), 0 1px 3px rgba(0, 0, 0, 0.3);
animation: accelerator-cache-pulse 2s ease-out;
cursor: help;
}
@keyframes acceleratorCachePulse {
0% {
transform: translateY(-50%) scale(1);
opacity: 1;
box-shadow: 0 0 0 2px rgba(32, 34, 37, 0.95), 0 2px 8px rgba(0, 0, 0, 0.5), 0 0 0 0 rgba(59, 165, 92, 1);
}
50% {
transform: translateY(-50%) scale(1.4);
opacity: 0.6;
box-shadow: 0 0 0 2px rgba(32, 34, 37, 0.95), 0 2px 8px rgba(0, 0, 0, 0.5), 0 0 0 12px rgba(59, 165, 92, 0.6);
}
100% {
transform: translateY(-50%) scale(1);
opacity: 1;
box-shadow: 0 0 0 2px rgba(32, 34, 37, 0.95), 0 2px 8px rgba(0, 0, 0, 0.5), 0 0 0 0 rgba(59, 165, 92, 1);
}
}
/* Ensure the message container has relative positioning for the indicator */
[class*="message-"],
[id^="chat-messages-"],
[data-list-item-id^="chat-messages"] {
position: relative;
}
/* Additional support for Discord's message structure */
[class*="messageListItem-"],
[class*="groupStart-"],
[class*="wrapper-"] {
position: relative;
}

View file

@ -613,10 +613,6 @@ export const Devs = /* #__PURE__*/ Object.freeze({
} satisfies Record<string, Dev>);
export const EquicordDevs = Object.freeze({
galpt: {
name: "galpt",
id: 631418827841863712n
},
nobody: {
name: "nobody",
id: 0n