Revert "MLEnhanced Update"

This reverts commit 163c35ff87.
This commit is contained in:
thororen1234 2024-11-18 22:15:50 -05:00
parent 163c35ff87
commit b56e03fd2f
34 changed files with 1076 additions and 3010 deletions

View file

@ -1,26 +1,37 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { classNameFactory } from "@api/Styles";
import { Flex } from "@components/Flex";
import { InfoIcon } from "@components/Icons";
import { openUserProfile } from "@utils/discord";
import { copyWithToast } from "@utils/misc";
import { closeAllModals, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
import { LazyComponent } from "@utils/react";
import { LazyComponent, useAwaiter } from "@utils/react";
import { find, findByCode, findByCodeLazy } from "@webpack";
import { Alerts, Button, ChannelStore, ContextMenuApi, FluxDispatcher, Menu, NavigationRouter, React, TabBar, Text, TextInput, Tooltip, useMemo, useRef, useState } from "@webpack/common";
import { Alerts, Button, ChannelStore, ContextMenuApi, FluxDispatcher, Menu, NavigationRouter, React, TabBar, Text, TextInput, useCallback, useMemo, useRef, useState } from "@webpack/common";
import { User } from "discord-types/general";
import { clearMessagesIDB, DBMessageRecord, deleteMessageIDB, deleteMessagesBulkIDB } from "../db";
import { settings } from "../index";
import { LoggedMessage, LoggedMessageJSON } from "../types";
import { messageJsonToMessageClass } from "../utils";
import { importLogs } from "../utils/settingsUtils";
import { useMessages } from "./hooks";
import { clearLogs, defaultLoggedMessages, removeLog, removeLogs, savedLoggedMessages } from "../LoggedMessageManager";
import { LoggedMessage, LoggedMessageJSON, LoggedMessages } from "../types";
import { isGhostPinged, messageJsonToMessageClass, sortMessagesByDate } from "../utils";
import { doesMatch, parseQuery } from "../utils/parseQuery";
export interface MessagePreviewProps {
className: string;
@ -56,7 +67,7 @@ const ChildrenAccessories = LazyComponent<ChildrenAccProops>(() => findByCode("c
const cl = classNameFactory("msg-logger-modal-");
export enum LogTabs {
enum LogTabs {
DELETED = "Deleted",
EDITED = "Edited",
GHOST_PING = "Ghost Pinged"
@ -68,14 +79,73 @@ interface Props {
}
export function LogsModal({ modalProps, initalQuery }: Props) {
const [x, setX] = useState(0);
const forceUpdate = () => setX(e => e + 1);
const [logs, _, pending] = useAwaiter(async () => savedLoggedMessages, {
fallbackValue: defaultLoggedMessages as LoggedMessages,
deps: [x]
});
const [currentTab, setCurrentTab] = useState(LogTabs.DELETED);
const [queryEh, setQuery] = useState(initalQuery ?? "");
const [sortNewest, setSortNewest] = useState(settings.store.sortNewest);
const [numDisplayedMessages, setNumDisplayedMessages] = useState(settings.store.messagesToDisplayAtOnceInLogs);
const [numDisplayedMessages, setNumDisplayedMessages] = useState(50);
const contentRef = useRef<HTMLDivElement | null>(null);
const { messages, total, statusTotal, pending, reset } = useMessages(queryEh, currentTab, sortNewest, numDisplayedMessages);
const handleLoadMore = useCallback(() => {
setNumDisplayedMessages(prevNum => prevNum + 50);
}, []);
// Flogger.log(logs, _, pending, contentRef);
// Flogger.time("hi");
const messages: string[][] = currentTab === LogTabs.DELETED || currentTab === LogTabs.GHOST_PING
? Object.values(logs?.deletedMessages ?? {})
: Object.values(logs?.editedMessages ?? {});
const flattendAndfilteredAndSortedMessages = useMemo(() => {
const { success, type, id, negate, query } = parseQuery(queryEh);
if (query === "" && !success) {
const result = messages
.flat()
.filter(m => currentTab === LogTabs.GHOST_PING ? isGhostPinged(logs[m].message!) : true)
.sort(sortMessagesByDate);
return sortNewest ? result : result.reverse();
}
const result = messages
.flat()
.filter(m =>
currentTab === LogTabs.GHOST_PING
? isGhostPinged(logs[m].message)
: true
)
.filter(m =>
logs[m]?.message != null &&
(
success === false
? true
: negate
? !doesMatch(type!, id!, logs[m].message!)
: doesMatch(type!, id!, logs[m].message!)
)
)
.filter(m =>
logs[m]?.message?.content?.toLowerCase()?.includes(query.toLowerCase()) ??
logs[m].message?.editHistory?.map(m => m.content?.toLowerCase()).includes(query.toLowerCase())
)
.sort(sortMessagesByDate);
return sortNewest ? result : result.reverse();
}, [currentTab, logs, queryEh, sortNewest]);
const visibleMessages = flattendAndfilteredAndSortedMessages.slice(0, numDisplayedMessages);
const canLoadMore = numDisplayedMessages < flattendAndfilteredAndSortedMessages.length;
// Flogger.timeEnd("hi");
return (
<ModalRoot className={cl("root")} {...modalProps} size={ModalSize.LARGE}>
<ModalHeader className={cl("header")}>
@ -87,7 +157,7 @@ export function LogsModal({ modalProps, initalQuery }: Props) {
selectedItem={currentTab}
onItemSelect={e => {
setCurrentTab(e);
setNumDisplayedMessages(settings.store.messagesToDisplayAtOnceInLogs);
setNumDisplayedMessages(50);
contentRef.current?.firstElementChild?.scrollTo(0, 0);
// forceUpdate();
}}
@ -118,23 +188,21 @@ export function LogsModal({ modalProps, initalQuery }: Props) {
<ModalContent
className={cl("content")}
>
{messages != null && total === 0 && (
<EmptyLogs
hasQuery={queryEh.length !== 0}
reset={reset}
/>
)}
{!pending && messages != null && (
<LogsContentMemo
visibleMessages={messages}
canLoadMore={messages.length < statusTotal && messages.length >= settings.store.messagesToDisplayAtOnceInLogs}
tab={currentTab}
sortNewest={sortNewest}
reset={reset}
handleLoadMore={() => setNumDisplayedMessages(e => e + settings.store.messagesToDisplayAtOnceInLogs)}
/>
)}
{
pending || logs == null || messages.length === 0
? <EmptyLogs />
: (
<LogsContentMemo
visibleMessages={visibleMessages}
canLoadMore={canLoadMore}
tab={currentTab}
logs={logs}
sortNewest={sortNewest}
forceUpdate={forceUpdate}
handleLoadMore={handleLoadMore}
/>
)
}
</ModalContent>
}
</div>
@ -148,8 +216,8 @@ export function LogsModal({ modalProps, initalQuery }: Props) {
confirmColor: Button.Colors.RED,
cancelText: "Cancel",
onConfirm: async () => {
await clearMessagesIDB();
reset();
await clearLogs();
forceUpdate();
}
})}
@ -159,16 +227,16 @@ export function LogsModal({ modalProps, initalQuery }: Props) {
<Button
style={{ marginRight: "16px" }}
color={Button.Colors.YELLOW}
disabled={messages?.length === 0}
disabled={visibleMessages.length === 0}
onClick={() => Alerts.show({
title: "Clear Logs",
body: `Are you sure you want to clear ${messages.length} logs`,
body: `Are you sure you want to clear ${visibleMessages.length} logs`,
confirmText: "Clear",
confirmColor: Button.Colors.RED,
cancelText: "Cancel",
onConfirm: async () => {
await deleteMessagesBulkIDB(messages.map(e => e.message_id));
reset();
await removeLogs(visibleMessages);
forceUpdate();
}
})}
>
@ -194,27 +262,28 @@ export function LogsModal({ modalProps, initalQuery }: Props) {
}
interface LogContentProps {
logs: LoggedMessages,
sortNewest: boolean;
tab: LogTabs;
visibleMessages: DBMessageRecord[];
visibleMessages: string[];
canLoadMore: boolean;
reset: () => void;
forceUpdate: () => void;
handleLoadMore: () => void;
}
function LogsContent({ visibleMessages, canLoadMore, sortNewest, tab, reset, handleLoadMore }: LogContentProps) {
function LogsContent({ logs, visibleMessages, canLoadMore, sortNewest, tab, forceUpdate, handleLoadMore }: LogContentProps) {
if (visibleMessages.length === 0)
return <NoResults tab={tab} />;
return (
<div className={cl("content-inner")}>
{visibleMessages
.map(({ message }, i) => (
.map((id, i) => (
<LMessage
key={message.id}
log={{ message }}
reset={reset}
isGroupStart={isGroupStart(message, visibleMessages[i - 1]?.message, sortNewest)}
key={id}
log={logs[id] as { message: LoggedMessageJSON; }}
forceUpdate={forceUpdate}
isGroupStart={isGroupStart(logs[id]?.message, logs[visibleMessages[i - 1]]?.message, sortNewest)}
/>
))}
{
@ -261,35 +330,12 @@ function NoResults({ tab }: { tab: LogTabs; }) {
);
}
function EmptyLogs({ hasQuery, reset: forceUpdate }: { hasQuery: boolean; reset: () => void; }) {
function EmptyLogs() {
return (
<div className={cl("empty-logs", "content-inner")} style={{ textAlign: "center" }}>
<Flex flexDirection="column" style={{ position: "relative" }}>
<Text variant="text-lg/normal">
Empty eh
</Text>
{!hasQuery && (
<>
<Tooltip text="ML Enhanced now stores logs in indexeddb. You need to import your old logs from the logs directory. Importing wont overwrite existing logs">
{({ onMouseEnter, onMouseLeave }) => (
<div
className={cl("info-icon")}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<InfoIcon />
</div>
)}
</Tooltip>
<Button onClick={() => importLogs().then(() => forceUpdate())}>
Import Logs
</Button>
</>
)}
</Flex>
<Text variant="text-lg/normal">
Empty eh
</Text>
</div>
);
@ -298,13 +344,11 @@ function EmptyLogs({ hasQuery, reset: forceUpdate }: { hasQuery: boolean; reset:
interface LMessageProps {
log: { message: LoggedMessageJSON; };
isGroupStart: boolean,
reset: () => void;
forceUpdate: () => void;
}
function LMessage({ log, isGroupStart, reset, }: LMessageProps) {
function LMessage({ log, isGroupStart, forceUpdate, }: LMessageProps) {
const message = useMemo(() => messageJsonToMessageClass(log), [log]);
// console.log(message);
if (!message) return null;
return (
@ -326,6 +370,7 @@ function LMessage({ log, isGroupStart, reset, }: LMessageProps) {
closeAllModals();
}}
/>
<Menu.MenuItem
key="open-user-profile"
id="open-user-profile"
@ -382,7 +427,10 @@ function LMessage({ log, isGroupStart, reset, }: LMessageProps) {
label="Delete Log"
color="danger"
action={() =>
deleteMessageIDB(log.message.id).then(() => reset())
removeLog(log.message.id)
.then(() => {
forceUpdate();
})
}
/>
@ -430,8 +478,6 @@ function isGroupStart(
) {
if (!currentMessage || !previousMessage) return true;
if (currentMessage.id === previousMessage.id) return true;
const [newestMessage, oldestMessage] = sortNewest
? [previousMessage, currentMessage]
: [currentMessage, previousMessage];

View file

@ -1,109 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
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<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
// this is so shit
export function useMessages(query: string, currentTab: LogTabs, sortNewest: boolean, numDisplayedMessages: number) {
// only for initial load
const [pending, setPending] = useState(true);
const [messages, setMessages] = useState<DBMessageRecord[]>([]);
const [statusTotal, setStatusTotal] = useState<number>(0);
const [total, setTotal] = useState<number>(0);
const debouncedQuery = useDebouncedValue(query, 300);
useEffect(() => {
countMessagesIDB().then(x => setTotal(x));
}, [pending]);
useEffect(() => {
let isMounted = true;
const loadMessages = async () => {
const status = getStatus(currentTab);
if (debouncedQuery === "") {
const [messages, statusTotal] = await Promise.all([
getDateStortedMessagesByStatusIDB(sortNewest, numDisplayedMessages, status),
countMessagesByStatusIDB(status),
]);
if (isMounted) {
setMessages(messages);
setStatusTotal(statusTotal);
}
setPending(false);
} else {
const allMessages = await getDateStortedMessagesByStatusIDB(sortNewest, Number.MAX_SAFE_INTEGER, status);
const { queries, rest } = tokenizeQuery(debouncedQuery);
const filteredMessages = allMessages.filter(record => {
for (const query of queries) {
const matching = doesMatch(query.key, query.value, record.message);
if (query.negate ? matching : !matching) {
return false;
}
}
return rest.every(r =>
record.message.content.toLowerCase().includes(r.toLowerCase())
);
});
if (isMounted) {
setMessages(filteredMessages);
setStatusTotal(Number.MAX_SAFE_INTEGER);
}
setPending(false);
}
};
loadMessages();
return () => {
isMounted = false;
};
}, [debouncedQuery, sortNewest, numDisplayedMessages, currentTab, pending]);
return { messages, statusTotal, total, pending, reset: () => setPending(true) };
}
function getStatus(currentTab: LogTabs) {
switch (currentTab) {
case LogTabs.DELETED:
return DBMessageStatus.DELETED;
case LogTabs.EDITED:
return DBMessageStatus.EDITED;
default:
return DBMessageStatus.GHOST_PINGED;
}
}