From bcb36541f6d9a704e37b30bb81cf5081ba1694ba Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Wed, 11 Feb 2026 00:54:49 -0500 Subject: [PATCH] MessageLoggerEnhanced: Update --- package.json | 4 +- pnpm-lock.yaml | 45 ++++ .../components/FolderSelectInput.tsx | 14 +- .../components/LogsModal.tsx | 40 ++-- .../messageLoggerEnhanced/components/hooks.ts | 4 +- .../messageLoggerEnhanced/db.ts | 24 ++ .../messageLoggerEnhanced/index.tsx | 48 ++-- .../messageLoggerEnhanced/native/export.ts | 57 +++++ .../messageLoggerEnhanced/native/import.ts | 54 +++++ .../messageLoggerEnhanced/native/index.ts | 7 +- .../messageLoggerEnhanced/native/utils.ts | 4 - .../messageLoggerEnhanced/settings.tsx | 64 +++++- .../messageLoggerEnhanced/styles.css | 23 +- .../messageLoggerEnhanced/types.ts | 18 +- .../messageLoggerEnhanced/utils/LimitedMap.ts | 8 +- .../messageLoggerEnhanced/utils/cleanUp.ts | 4 +- .../utils/contextMenu.tsx | 100 +++++---- .../messageLoggerEnhanced/utils/index.ts | 12 +- .../messageLoggerEnhanced/utils/misc.ts | 10 +- .../messageLoggerEnhanced/utils/parseQuery.ts | 2 +- .../utils/saveImage/ImageManager.ts | 7 +- .../utils/saveImage/index.ts | 6 +- .../utils/settingsUtils.ts | 212 ++++++++++++++---- src/equicordplugins/messagePeek/style.css | 7 +- .../_api/memberListDecorators/index.tsx | 14 ++ .../_api/memberListDecorators/style.css | 7 + src/plugins/showMeYourName/index.tsx | 4 +- src/utils/misc.ts | 4 +- 28 files changed, 591 insertions(+), 212 deletions(-) create mode 100644 src/equicordplugins/messageLoggerEnhanced/native/export.ts create mode 100644 src/equicordplugins/messageLoggerEnhanced/native/import.ts diff --git a/package.json b/package.json index 68a44e4c1..e1d7f371e 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@ffmpeg/ffmpeg": "^0.12.10", "@ffmpeg/util": "^0.12.1", "@intrnl/xxhash64": "^0.1.2", + "@streamparser/json": "^0.0.22", "@types/less": "^3.0.8", "@types/stylus": "^0.48.42", "@types/tinycolor2": "^1.4.6", @@ -53,6 +54,7 @@ "jsqr": "1.4.0", "monaco-editor": "^0.54.0", "nanoid": "^5.1.6", + "native-file-system-adapter": "^3.0.1", "usercss-meta": "^0.12.0", "virtual-merge": "^1.0.1" }, @@ -92,7 +94,7 @@ "typescript-transform-paths": "^3.5.5", "zip-local": "^0.3.5" }, - "packageManager": "pnpm@10.26.2", + "packageManager": "pnpm@10.29.2", "pnpm": { "patchedDependencies": { "@types/less@3.0.8": "patches/@types__less@3.0.8.patch" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24393b75a..654192c0b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,6 +25,9 @@ importers: '@intrnl/xxhash64': specifier: ^0.1.2 version: 0.1.2 + '@streamparser/json': + specifier: ^0.0.22 + version: 0.0.22 '@types/less': specifier: ^3.0.8 version: 3.0.8(patch_hash=641e6c93bb737bac7fc283416857bd095cd85bcbcba63becb7a8bbcc78f73076) @@ -58,6 +61,9 @@ importers: nanoid: specifier: ^5.1.6 version: 5.1.6 + native-file-system-adapter: + specifier: ^3.0.1 + version: 3.0.1 usercss-meta: specifier: ^0.12.0 version: 0.12.0 @@ -712,6 +718,9 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@streamparser/json@0.0.22': + resolution: {integrity: sha512-b6gTSBjJ8G8SuO3Gbbj+zXbVx8NSs1EbpbMKpzGLWMdkR+98McH9bEjSz3+0mPJf68c5nxa3CrJHp5EQNXM6zQ==} + '@stylistic/eslint-plugin@5.6.0': resolution: {integrity: sha512-owEc4B8ME+O/xyZOkLVyLqPMsUgJXIM4XzCm5Vt3WvRXpyoOfYxgA+JkEiFqXPCI8+Nc2BzAT+KGAK7QleGs8Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1445,6 +1454,10 @@ packages: fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} @@ -1959,6 +1972,10 @@ packages: engines: {node: ^18 || >=20} hasBin: true + native-file-system-adapter@3.0.1: + resolution: {integrity: sha512-ocuhsYk2SY0906LPc3QIMW+rCV3MdhqGiy7wV5Bf0e8/5TsMjDdyIwhNiVPiKxzTJLDrLT6h8BoV9ERfJscKhw==} + engines: {node: '>=14.8.0'} + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -1969,6 +1986,11 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2143,6 +2165,7 @@ packages: engines: {node: '>=0.6.0', teleport: '>=0.2.0'} deprecated: |- You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. + (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) qified@0.5.2: @@ -2534,6 +2557,10 @@ packages: vscode-textmate@5.2.0: resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==} + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + webdriver-bidi-protocol@0.3.8: resolution: {integrity: sha512-21Yi2GhGntMc671vNBCjiAeEVknXjVRoyu+k+9xOMShu+ZQfpGQwnBqbNz/Sv4GXZ6JmutlPAi2nIJcrymAWuQ==} @@ -2968,6 +2995,8 @@ snapshots: '@rtsao/scc@1.1.0': {} + '@streamparser/json@0.0.22': {} + '@stylistic/eslint-plugin@5.6.0(eslint@9.39.1)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) @@ -3908,6 +3937,12 @@ snapshots: dependencies: pend: 1.2.0 + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + optional: true + fflate@0.8.2: {} file-entry-cache@10.1.4: @@ -4421,6 +4456,10 @@ snapshots: nanoid@5.1.6: {} + native-file-system-adapter@3.0.1: + optionalDependencies: + fetch-blob: 3.2.0 + natural-compare@1.4.0: {} netmask@2.0.2: {} @@ -4430,6 +4469,9 @@ snapshots: lower-case: 2.0.2 tslib: 2.6.2 + node-domexception@1.0.0: + optional: true + normalize-path@3.0.0: {} object-assign@4.1.1: {} @@ -5134,6 +5176,9 @@ snapshots: vscode-textmate@5.2.0: {} + web-streams-polyfill@3.3.3: + optional: true + webdriver-bidi-protocol@0.3.8: {} which-boxed-primitive@1.1.1: diff --git a/src/equicordplugins/messageLoggerEnhanced/components/FolderSelectInput.tsx b/src/equicordplugins/messageLoggerEnhanced/components/FolderSelectInput.tsx index c0d2ff937..0bcc6f641 100644 --- a/src/equicordplugins/messageLoggerEnhanced/components/FolderSelectInput.tsx +++ b/src/equicordplugins/messageLoggerEnhanced/components/FolderSelectInput.tsx @@ -16,15 +16,19 @@ * along with this program. If not, see . */ +import { Button } from "@components/Button"; import { Heading } from "@components/Heading"; -import { DEFAULT_IMAGE_CACHE_DIR } from "@equicordplugins/messageLoggerEnhanced/utils/constants"; import { classNameFactory } from "@utils/css"; import { copyWithToast } from "@utils/discord"; -import { Button, Toasts } from "@webpack/common"; +import { classes } from "@utils/misc"; +import { findCssClassesLazy } from "@webpack"; +import { Toasts } from "@webpack/common"; import { Native, settings } from ".."; +import { DEFAULT_IMAGE_CACHE_DIR } from "../utils/constants"; const cl = classNameFactory("folder-upload"); +const inputClasses = findCssClassesLazy("input", "inputWrapper", "editable") as Record; function createDirSelector(settingKey: "logsDir" | "imageCacheDir", successMessage: string) { return function DirSelector({ option }) { @@ -32,7 +36,7 @@ function createDirSelector(settingKey: "logsDir" | "imageCacheDir", successMessa return (
- {option.description} + {option.description} +
copyWithToast(path)} className={cl("-input")}> {path == null || path === DEFAULT_IMAGE_CACHE_DIR ? "Choose Folder" : getDirName(path)}
- + - + ); @@ -221,7 +223,7 @@ function LogsContent({ visibleMessages, canLoadMore, sortNewest, tab, reset, han canLoadMore && @@ -302,8 +304,6 @@ interface LMessageProps { function LMessage({ log, isGroupStart, reset, }: LMessageProps) { const message = useMemo(() => messageJsonToMessageClass(log), [log]); - // console.log(message); - if (!message) return null; const channel = ChannelStore.getChannel(message?.channel_id); diff --git a/src/equicordplugins/messageLoggerEnhanced/components/hooks.ts b/src/equicordplugins/messageLoggerEnhanced/components/hooks.ts index 23315ca83..a60b472f9 100644 --- a/src/equicordplugins/messageLoggerEnhanced/components/hooks.ts +++ b/src/equicordplugins/messageLoggerEnhanced/components/hooks.ts @@ -4,10 +4,10 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { countMessagesByStatusIDB, countMessagesIDB, DBMessageRecord, DBMessageStatus, getDateStortedMessagesByStatusIDB } from "@equicordplugins/messageLoggerEnhanced/db"; -import { doesMatch, tokenizeQuery } from "@equicordplugins/messageLoggerEnhanced/utils/parseQuery"; import { useEffect, useState } from "@webpack/common"; +import { countMessagesByStatusIDB, countMessagesIDB, DBMessageRecord, DBMessageStatus, getDateStortedMessagesByStatusIDB } from "../db"; +import { doesMatch, tokenizeQuery } from "../utils/parseQuery"; import { LogTabs } from "./LogsModal"; function useDebouncedValue(value: T, delay: number): T { diff --git a/src/equicordplugins/messageLoggerEnhanced/db.ts b/src/equicordplugins/messageLoggerEnhanced/db.ts index 21dcaa3a8..f0d7e03d3 100644 --- a/src/equicordplugins/messageLoggerEnhanced/db.ts +++ b/src/equicordplugins/messageLoggerEnhanced/db.ts @@ -110,6 +110,30 @@ export async function getOldestMessagesIDB(limit: number) { return cacheRecords(await db.getAllFromIndex("messages", "by_timestamp", undefined, limit)); } +export async function* iterateAllMessagesIDB(batchSize = 100) { + let lastId: string | undefined; + while (true) { + const batch: DBMessageRecord[] = []; + // new transaction for each batch to avoid timeouts during yield + const tx = db.transaction("messages"); + const range = lastId ? IDBKeyRange.lowerBound(lastId, true) : undefined; + let cursor = await tx.store.openCursor(range); + + while (cursor && batch.length < batchSize) { + batch.push(cursor.value); + cursor = await cursor.continue(); + } + + if (batch.length === 0) break; + + lastId = batch[batch.length - 1].message_id; + + yield await cacheRecords(batch); + + if (batch.length < batchSize) break; + } +} + export async function getOlderThanTimestampIDB(timestamp: string) { const tx = db.transaction("messages", "readonly"); const { store } = tx; diff --git a/src/equicordplugins/messageLoggerEnhanced/index.tsx b/src/equicordplugins/messageLoggerEnhanced/index.tsx index 3fde1f61a..38788a629 100644 --- a/src/equicordplugins/messageLoggerEnhanced/index.tsx +++ b/src/equicordplugins/messageLoggerEnhanced/index.tsx @@ -40,17 +40,20 @@ let oldGetMessage: typeof MessageStore.getMessage; const handledMessageIds = new Set(); async function messageDeleteHandler(payload: MessageDeletePayload & { isBulk: boolean; }) { - if (payload.mlDeleted) return; + if (payload.mlDeleted) { + if (settings.store.permanentlyRemoveLogByDefault) + await idb.deleteMessageIDB(payload.id); + + return; + } if (handledMessageIds.has(payload.id)) { - // Flogger.warn("skipping duplicate message", payload.id); return; } try { handledMessageIds.add(payload.id); - // @ts-ignore let message: LoggedMessage | LoggedMessageJSON | null = oldGetMessage?.(payload.channelId, payload.id); if (message == null) { @@ -75,7 +78,6 @@ async function messageDeleteHandler(payload: MessageDeletePayload & { isBulk: bo webhookId: message?.webhookId }) ) { - // Flogger.log("IGNORING", message, payload); return FluxDispatcher.dispatch({ type: "MESSAGE_DELETE", channelId: payload.channelId, @@ -85,7 +87,6 @@ async function messageDeleteHandler(payload: MessageDeletePayload & { isBulk: bo } if (message == null || message.channel_id == null || !message.deleted) return; - // Flogger.log("ADDING MESSAGE (DELETED)", message); if (payload.isBulk) return message; @@ -138,7 +139,7 @@ async function messageUpdateHandler(payload: MessageUpdatePayload) { message.editHistory = []; cacheThing.commit(cache); } - return;// Flogger.log("this message has been ignored", payload); + return; } let message = oldGetMessage?.(payload.message.channel_id, payload.message.id) as LoggedMessage | LoggedMessageJSON | null; @@ -158,14 +159,12 @@ async function messageUpdateHandler(payload: MessageUpdatePayload) { ] }; - // @ts-ignore cacheSentMessages.set(`${payload.message.channel_id},${payload.message.id}`, message); } } if (message == null || message.channel_id == null || message.editHistory == null || message.editHistory.length === 0) return; - // Flogger.log("ADDING MESSAGE (EDITED)", message, payload); const currentChannelId = SelectedChannelStore.getChannelId(); await addMessage(message, idb.DBMessageStatus.EDITED, currentChannelId); } @@ -184,7 +183,6 @@ function messageCreateHandler(payload: MessageCreatePayload) { } cacheSentMessages.set(`${payload.message.channel_id},${payload.message.id}`, cleanUpCachedMessage(payload.message)); - // Flogger.log(`cached\nkey:${payload.message.channel_id},${payload.message.id}\nvalue:`, payload.message); } async function processMessageFetch(response: FetchMessagesResponse) { @@ -195,13 +193,14 @@ async function processMessageFetch(response: FetchMessagesResponse) { } const firstMessage = response.body[response.body.length - 1]; - // console.time("fetching messages from idb"); const messages = await idb.getMessagesByChannelAndAfterTimestampIDB(firstMessage.channel_id, firstMessage.timestamp); - // console.timeEnd("fetching messages from idb"); if (!messages.length) return; - const deletedMessages = messages.filter(m => m.status === idb.DBMessageStatus.DELETED); + const deletedMessages = messages.filter(m => + m.status === idb.DBMessageStatus.DELETED || + m.status === idb.DBMessageStatus.GHOST_PINGED + ); for (const recivedMessage of response.body) { const record = messages.find(m => m.message_id === recivedMessage.id); @@ -223,7 +222,7 @@ async function processMessageFetch(response: FetchMessagesResponse) { for (let j = 0, len2 = message.mentions.length; j < len2; j++) { const user = message.mentions[j]; - const cachedUser = fetchUser(user); + const cachedUser = fetchUser((user as any).id || user); if (cachedUser) (message.mentions[j] as any) = cleanupUserObject(cachedUser); } @@ -267,14 +266,14 @@ export default definePlugin({ replace: "deleted:$self.getDeleted(...arguments), editHistory:$self.getEdited(...arguments)," } }, + // MessagePreview component in LogsModal { - find: "childrenMessageContent:null", + find: "=!0,disableInteraction:", replacement: { - match: /(\i\]:!\i.{1,50},)childrenHeader:/, - replace: "$1childrenAccessories:arguments[0].childrenAccessories || null,childrenHeader:" + match: /childrenHeader:.{0,100}childrenMessageContent/, + replace: "childrenAccessories:arguments[0].childrenAccessories || null,$&" } }, - // https://regex101.com/r/S3IVGm/1 // fix vidoes failing because there are no thumbnails { find: ".handleImageLoad)", @@ -370,9 +369,20 @@ export default definePlugin({ // we have to do this because the original message logger fetches the message from the store now MessageStore.getMessage = (channelId: string, messageId: string) => { const MLMessage = idb.cachedMessages.get(messageId); - if (MLMessage) return messageJsonToMessageClass({ message: MLMessage }); + if (!MLMessage) + return this.oldGetMessage(channelId, messageId); - return this.oldGetMessage(channelId, messageId); + if (MLMessage.deleted) + return messageJsonToMessageClass({ message: MLMessage }); + + // update the edited message with the latest data + const latestMessage = this.oldGetMessage(channelId, messageId); + return messageJsonToMessageClass({ + message: { + ...MLMessage, + ...(latestMessage ?? {}), + } + }); }; Native.init(); diff --git a/src/equicordplugins/messageLoggerEnhanced/native/export.ts b/src/equicordplugins/messageLoggerEnhanced/native/export.ts new file mode 100644 index 000000000..2a881f1b2 --- /dev/null +++ b/src/equicordplugins/messageLoggerEnhanced/native/export.ts @@ -0,0 +1,57 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { randomUUID } from "node:crypto"; +import { createWriteStream, WriteStream } from "node:fs"; + +import { dialog, IpcMainInvokeEvent } from "electron"; + +const activeStreams = new Map(); + +export async function startNativeLogExport(_event: IpcMainInvokeEvent, filename: string) { + const { filePath, canceled } = await dialog.showSaveDialog({ + defaultPath: filename ?? "message-logger-logs-idb.json", + filters: [{ name: "JSON", extensions: ["json"] }] + }); + + if (canceled || !filePath) + throw new Error("No file path selected"); + + const stream = createWriteStream(filePath, { flags: "w", encoding: "utf-8" }); + + const streamId = randomUUID(); + activeStreams.set(streamId, stream); + + stream.on("error", err => { + console.error("Stream error", err); + activeStreams.delete(streamId); + }); + + return streamId; +} + +export async function writeNativeLogChunk(_event: IpcMainInvokeEvent, streamId: string, chunk: string) { + const stream = activeStreams.get(streamId); + if (!stream) throw new Error("Stream not found or closed"); + + // if returns false, buffer is full; wait for drain to prevent RAM spike + const canContinue = stream.write(chunk); + if (!canContinue) { + await new Promise(resolve => stream.once("drain", resolve)); + } +} + +export async function finishNativeLogExport(_event: IpcMainInvokeEvent, streamId: string) { + const stream = activeStreams.get(streamId); + if (!stream) return; + + return new Promise(resolve => { + stream.end(() => { + activeStreams.delete(streamId); + resolve(); + }); + }); +} diff --git a/src/equicordplugins/messageLoggerEnhanced/native/import.ts b/src/equicordplugins/messageLoggerEnhanced/native/import.ts new file mode 100644 index 000000000..9db8d9d26 --- /dev/null +++ b/src/equicordplugins/messageLoggerEnhanced/native/import.ts @@ -0,0 +1,54 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { randomUUID } from "node:crypto"; +import { FileHandle, open } from "node:fs/promises"; + +import { dialog, IpcMainInvokeEvent } from "electron"; + +const activeFiles = new Map(); + +export async function startNativeLogImport(_event: IpcMainInvokeEvent, defaultPath?: string) { + const res = await dialog.showOpenDialog({ + title: "Import Logs", + filters: [{ name: "Logs", extensions: ["json"] }], + properties: ["openFile"], + defaultPath + }); + const [path] = res.filePaths; + + if (!path) throw Error("No file selected"); + + const fileHandle = await open(path, "r"); + const fileId = randomUUID(); + activeFiles.set(fileId, fileHandle); + + return fileId; +} + +export async function readNativeLogChunk(_event: IpcMainInvokeEvent, fileId: string, size: number = 64 * 1024): Promise { + const fileHandle = activeFiles.get(fileId); + if (!fileHandle) return null; + + const buffer = Buffer.alloc(size); + const { bytesRead } = await fileHandle.read(buffer, 0, size); + + if (bytesRead === 0) { + await fileHandle.close(); + activeFiles.delete(fileId); + return null; + } + + return buffer.toString("utf-8", 0, bytesRead); +} + +export async function closeNativeLogImport(_event: IpcMainInvokeEvent, fileId: string) { + const fileHandle = activeFiles.get(fileId); + if (fileHandle) { + await fileHandle.close(); + activeFiles.delete(fileId); + } +} diff --git a/src/equicordplugins/messageLoggerEnhanced/native/index.ts b/src/equicordplugins/messageLoggerEnhanced/native/index.ts index cfde35f03..08c763cea 100644 --- a/src/equicordplugins/messageLoggerEnhanced/native/index.ts +++ b/src/equicordplugins/messageLoggerEnhanced/native/index.ts @@ -7,12 +7,15 @@ import { readdir, readFile, unlink, writeFile } from "node:fs/promises"; import path from "node:path"; -import { LoggedAttachment } from "@equicordplugins/messageLoggerEnhanced/types"; -import { LOGS_DATA_FILENAME } from "@equicordplugins/messageLoggerEnhanced/utils/constants"; import { DATA_DIR } from "@main/utils/constants"; import { dialog, IpcMainInvokeEvent, shell } from "electron"; import { getSettings, saveSettings } from "./settings"; +export * from "./export"; +export * from "./import"; + +import { LoggedAttachment } from "../types"; +import { LOGS_DATA_FILENAME } from "../utils/constants"; import { ensureDirectoryExists, getAttachmentIdFromFilename, sleep } from "./utils"; export { getSettings }; diff --git a/src/equicordplugins/messageLoggerEnhanced/native/utils.ts b/src/equicordplugins/messageLoggerEnhanced/native/utils.ts index e29bdca0c..691747f04 100644 --- a/src/equicordplugins/messageLoggerEnhanced/native/utils.ts +++ b/src/equicordplugins/messageLoggerEnhanced/native/utils.ts @@ -25,8 +25,4 @@ export function getAttachmentIdFromFilename(filename: string) { return path.parse(filename).name; } -export function getAttachmentExtFromFilename(filename: string) { - return path.parse(filename).ext; -} - export const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); diff --git a/src/equicordplugins/messageLoggerEnhanced/settings.tsx b/src/equicordplugins/messageLoggerEnhanced/settings.tsx index fd54ebe2c..be5401ac5 100644 --- a/src/equicordplugins/messageLoggerEnhanced/settings.tsx +++ b/src/equicordplugins/messageLoggerEnhanced/settings.tsx @@ -5,9 +5,10 @@ */ import { definePluginSettings } from "@api/Settings"; +import { Button } from "@components/Button"; import ErrorBoundary from "@components/ErrorBoundary"; import { OptionType } from "@utils/types"; -import { Alerts, Button } from "@webpack/common"; +import { Alerts, useState } from "@webpack/common"; import { Settings } from "Vencord"; import { Native } from "."; @@ -18,6 +19,46 @@ import { blockedExts } from "./list"; import { DEFAULT_IMAGE_CACHE_DIR } from "./utils/constants"; import { exportLogs, importLogs } from "./utils/settingsUtils"; +function ImportLogsButton() { + const [loading, setLoading] = useState(false); + + return ( + + ); +} + +function ExportLogsButton() { + const [loading, setLoading] = useState(false); + + return ( + + ); +} + export const settings = definePluginSettings({ saveMessages: { default: true, @@ -98,6 +139,12 @@ export const settings = definePluginSettings({ description: "Always log current selected channel. Blacklisted channels/users will still be ignored.", }, + permanentlyRemoveLogByDefault: { + default: false, + type: OptionType.BOOLEAN, + description: "Vencord's base MessageLogger remove log button wiil delete logs permanently", + }, + hideMessageFromMessageLoggers: { default: false, type: OptionType.BOOLEAN, @@ -204,19 +251,13 @@ export const settings = definePluginSettings({ importLogs: { type: OptionType.COMPONENT, description: "Import Logs From File", - component: () => - + component: ImportLogsButton }, exportLogs: { type: OptionType.COMPONENT, description: "Export Logs From IndexedDB", - component: () => - + component: ExportLogsButton }, openLogs: { @@ -248,11 +289,12 @@ export const settings = definePluginSettings({ description: "Clear Logs", component: () =>