mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-01-11 02:16:23 +00:00
Setup render of Messages
This commit is contained in:
parent
72a8178501
commit
22def634ad
7 changed files with 277 additions and 19 deletions
50
src/plugins/holynotes/components/modals/Error.tsx
Normal file
50
src/plugins/holynotes/components/modals/Error.tsx
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { findByCodeLazy } from "@webpack";
|
||||
|
||||
const classes = findByCodeLazy("emptyResultsWrap");
|
||||
|
||||
export default ({ error }: { error?: Error; } = {}) => {
|
||||
if (error) {
|
||||
// Error
|
||||
console.log(error);
|
||||
return (
|
||||
<div className={classes.emptyResultsWrap}>
|
||||
<div className={classes.emptyResultsContent} style={{ paddingBottom: "0px" }}>
|
||||
<div className={classes.errorImage} />
|
||||
<div className={classes.emptyResultsText}>
|
||||
There was an error parsing your notes! The issue was logged in your console, press CTRL
|
||||
+ I to access it! Please visit the support server if you need extra help!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (Math.floor(Math.random() * 100) <= 10)
|
||||
// Easter egg
|
||||
return (
|
||||
<div className={classes.emptyResultsWrap}>
|
||||
<div className={classes.emptyResultsContent} style={{ paddingBottom: "0px" }}>
|
||||
<div className={`${classes.noResultsImage} ${classes.alt}`} />
|
||||
<div className={classes.emptyResultsText}>
|
||||
No notes were found. Empathy banana is here for you.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
// Empty notebook
|
||||
else
|
||||
return (
|
||||
<div className={classes.emptyResultsWrap}>
|
||||
<div className={classes.emptyResultsContent} style={{ paddingBottom: "0px" }}>
|
||||
<div className={classes.noResultsImage} />
|
||||
<div className={classes.emptyResultsText}>
|
||||
No notes were found saved in this notebook.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -9,8 +9,47 @@ import { Flex } from "@components/Flex";
|
|||
import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, openModal } from "@utils/modal";
|
||||
import { React, TabBar, Text, TextInput } from "@webpack/common";
|
||||
import noteHandler from "plugins/holynotes/noteHandler";
|
||||
import { HolyNotes } from "plugins/holynotes/types";
|
||||
|
||||
import HelpIcon from "../icons/HelpIcon";
|
||||
import Errors from "./Error";
|
||||
import RenderMessage from "./RenderMessage";
|
||||
|
||||
const renderNotebook = ({
|
||||
notes, notebook, updateParent, sortDirection, sortType, searchInput, closeModal
|
||||
}: {
|
||||
notes: Record<string, HolyNotes.Note>;
|
||||
notebook: string;
|
||||
updateParent: () => void;
|
||||
sortDirection: boolean;
|
||||
sortType: boolean;
|
||||
searchInput: string;
|
||||
closeModal: () => void;
|
||||
}) => {
|
||||
const messageArray = Object.values(notes).map((note) => {
|
||||
<RenderMessage
|
||||
note={note}
|
||||
notebook={notebook}
|
||||
updateParent={updateParent}
|
||||
fromDeleteModal={false}
|
||||
closeModal={closeModal}
|
||||
/>;
|
||||
});
|
||||
|
||||
if (sortType)
|
||||
messageArray.sort(
|
||||
(a, b) =>
|
||||
new Date(b.props.note?.timestamp)?.getTime() - new Date(a.props.note?.timestamp)?.getTime(),
|
||||
);
|
||||
|
||||
if (sortDirection) messageArray.reverse();
|
||||
console.log(messageArray);
|
||||
const filteredMessages = messageArray.filter((message) =>
|
||||
message.props.note.content.toLowerCase().includes(searchInput.toLowerCase()),
|
||||
);
|
||||
|
||||
return filteredMessages;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -19,9 +58,29 @@ export const NoteModal = (props) => {
|
|||
const [searchInput, setSearch] = React.useState("");
|
||||
const [sortDirection, setSortDirection] = React.useState(true);
|
||||
const [currentNotebook, setCurrentNotebook] = React.useState("Main");
|
||||
const [notes, setNotes] = React.useState({});
|
||||
const [notebooks, setNotebooks] = React.useState([]);
|
||||
|
||||
const forceUpdate = React.useReducer(() => ({}), {})[1] as () => void;
|
||||
const notes = noteHandler.getNotes(currentNotebook);
|
||||
|
||||
React.useEffect(() => {
|
||||
const update = async () => {
|
||||
const notes = await noteHandler.getNotes(currentNotebook);
|
||||
setNotes(notes);
|
||||
};
|
||||
update();
|
||||
}, [currentNotebook]);
|
||||
|
||||
React.useEffect(() => {
|
||||
async function fetchNotebooks() {
|
||||
console.log(await noteHandler.getNotebooks());
|
||||
const notebooks = await noteHandler.getNotebooks();
|
||||
setNotebooks(notebooks);
|
||||
}
|
||||
|
||||
fetchNotebooks();
|
||||
}, []);
|
||||
|
||||
|
||||
if (!notes) return <></>;
|
||||
|
||||
|
@ -56,7 +115,7 @@ export const NoteModal = (props) => {
|
|||
className="notebook-tabbar-Bar notebook-tabbar"
|
||||
selectedItem={currentNotebook}
|
||||
onItemSelect={setCurrentNotebook}>
|
||||
{Object.keys(noteHandler.getAllNotes()).map(notebook => (
|
||||
{notebooks.map(notebook => (
|
||||
<TabBar.Item key={notebook} id={notebook} className="notebook-tabbar-barItem notebook-tabbar-item">
|
||||
{notebook}
|
||||
</TabBar.Item>
|
||||
|
@ -66,7 +125,15 @@ export const NoteModal = (props) => {
|
|||
</div>
|
||||
<ModalContent style={{ marginTop: "20px" }}>
|
||||
<ErrorBoundary>
|
||||
{ }
|
||||
{renderNotebook({
|
||||
notes,
|
||||
notebook: currentNotebook,
|
||||
updateParent: () => forceUpdate(),
|
||||
sortDirection: sortDirection,
|
||||
sortType: sortType,
|
||||
searchInput: searchInput,
|
||||
closeModal: props.onClose,
|
||||
})}
|
||||
</ErrorBoundary>
|
||||
</ModalContent>
|
||||
</Flex>
|
||||
|
|
139
src/plugins/holynotes/components/modals/RenderMessage.tsx
Normal file
139
src/plugins/holynotes/components/modals/RenderMessage.tsx
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { findByCodeLazy, findByProps, findByPropsLazy } from "@webpack";
|
||||
import { ContextMenuApi, FluxDispatcher, Menu, NavigationRouter, React } from "@webpack/common";
|
||||
import noteHandler from "plugins/holynotes/noteHandler";
|
||||
import { HolyNotes } from "plugins/holynotes/types";
|
||||
|
||||
const { message, groupStart, cozyMessage } = findByPropsLazy("cozyMessage");
|
||||
const User = findByCodeLazy("isClyde(){");
|
||||
const Message = findByCodeLazy("isEdited(){");
|
||||
const Channel = findByCodeLazy("ChannelRecordBase");
|
||||
|
||||
export default ({
|
||||
note,
|
||||
notebook,
|
||||
updateParent,
|
||||
fromDeleteModal,
|
||||
closeModal,
|
||||
}: {
|
||||
note: HolyNotes.Note;
|
||||
notebook: string;
|
||||
updateParent?: () => void;
|
||||
fromDeleteModal: boolean;
|
||||
closeModal?: () => void;
|
||||
}) => {
|
||||
const ChannelMessage = findByProps("ThreadStarterChatMessage").default;
|
||||
|
||||
const [isHoldingDelete, setHoldingDelete] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
const deleteHandler = (e: { key: string; type: string; }) =>
|
||||
e.key.toLowerCase() === "delete" && setHoldingDelete(e.type.toLowerCase() === "keydown");
|
||||
|
||||
document.addEventListener("keydown", deleteHandler);
|
||||
document.addEventListener("keyup", deleteHandler);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keydown", deleteHandler);
|
||||
document.removeEventListener("keyup", deleteHandler);
|
||||
};
|
||||
}, []);
|
||||
|
||||
console.log(note, notebook, updateParent, fromDeleteModal, closeModal);
|
||||
|
||||
const render = (
|
||||
<div
|
||||
className="holy-note"
|
||||
style={{
|
||||
marginBottom: "8px",
|
||||
marginTop: "8px",
|
||||
paddingTop: "4px",
|
||||
paddingBottom: "4px",
|
||||
}}
|
||||
onClick={() => {
|
||||
if (isHoldingDelete && !fromDeleteModal) {
|
||||
noteHandler.deleteNote(note.id, notebook);
|
||||
updateParent?.();
|
||||
}
|
||||
}}
|
||||
onContextMenu={(event: any) => {
|
||||
if (!fromDeleteModal)
|
||||
// @ts-ignore
|
||||
return open(event, (props: any) => (
|
||||
// @ts-ignore
|
||||
<NoteContextMenu
|
||||
{...Object.assign({}, props, { onClose: close })}
|
||||
note={note}
|
||||
notebook={notebook}
|
||||
updateParent={updateParent}
|
||||
closeModal={closeModal}
|
||||
/>
|
||||
));
|
||||
}}
|
||||
>
|
||||
{/* <ChannelMessage
|
||||
className={`holy-render ${message} ${groupStart} ${cozyMessage}`}
|
||||
key={note.id}
|
||||
groupId={note.id}
|
||||
id={note.id}
|
||||
compact={false}
|
||||
isHighlight={false}
|
||||
isLastItem={false}
|
||||
renderContentOnly={false}
|
||||
// @ts-ignore
|
||||
channel={new Channel({ id: "holy-notes" })}
|
||||
message={
|
||||
new Message(
|
||||
Object.assign(
|
||||
{ ...note },
|
||||
{
|
||||
author: new User({ ...note.author }),
|
||||
timestamp: new Date(note.timestamp),
|
||||
embeds: note.embeds.map((embed: { timestamp: string | number | Date; }) =>
|
||||
embed.timestamp
|
||||
? Object.assign(embed, {
|
||||
// @ts-ignore
|
||||
timestamp: new Moment(new Date(embed.timestamp)),
|
||||
})
|
||||
: embed,
|
||||
),
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
/> */}
|
||||
|
||||
</div>
|
||||
);
|
||||
|
||||
console.log(render);
|
||||
};
|
||||
|
||||
const NoteContextMenu = (props) => {
|
||||
const { note, notebook, updateParent, closeModal } = props;
|
||||
|
||||
return (
|
||||
<div onContextMenu={e => {
|
||||
ContextMenuApi.openContextMenu(e, () =>
|
||||
<Menu.Menu
|
||||
navId="holynotes"
|
||||
onClose={() => FluxDispatcher.dispatch({ type: "CONTEXT_MENU_CLOSE" })}
|
||||
aria-label="Holy Notes"
|
||||
>
|
||||
<Menu.MenuItem
|
||||
label="Jump To Message"
|
||||
id="jump"
|
||||
action={() => {
|
||||
NavigationRouter.transitionTo(`/channels/${note.guild_id ?? "@me"}/${note.channel_id}/${note.id}`);
|
||||
closeModal?.();
|
||||
}}
|
||||
/>
|
||||
</Menu.Menu>);
|
||||
}}></div>
|
||||
);
|
||||
};
|
|
@ -32,7 +32,7 @@ import { HolyNoteStore } from "./utils";
|
|||
|
||||
const messageContextMenuPatch: NavContextMenuPatchCallback = async (children, { message }: { message: Message; }) => {
|
||||
|
||||
console.log(await noteHandler.getAllNotes());
|
||||
//console.log(await noteHandler.getAllNotes());
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -38,25 +38,26 @@ export default new (class NoteHandler {
|
|||
|
||||
|
||||
public async getNotes(notebook?: string): Promise<Record<string, HolyNotes.Note>> {
|
||||
if (await DataStore.keys(HolyNoteStore).then(keys => keys.includes(notebook))) {
|
||||
return await DataStore.get(notebook, HolyNoteStore) ?? {};
|
||||
if (await DataStore.keys().then(keys => keys.includes(notebook))) {
|
||||
return await DataStore.get(notebook) ?? {};
|
||||
} else {
|
||||
return this.newNoteBook(notebook).then(() => this.getNotes(notebook));
|
||||
}
|
||||
}
|
||||
|
||||
public async getAllNotes(): Promise<HolyNotes.Note[]> {
|
||||
const data = await DataStore.values(HolyNoteStore);
|
||||
const mainData = data[0];
|
||||
return mainData;
|
||||
return await DataStore.entries();
|
||||
}
|
||||
|
||||
public async getNotebooks(): Promise<string[]> {
|
||||
return await DataStore.keys();
|
||||
}
|
||||
|
||||
public addNote = async (message: Message, notebook: string) => {
|
||||
const notes = this.getNotes(notebook);
|
||||
const notes = await this.getNotes(notebook);
|
||||
const channel = ChannelStore.getChannel(message.channel_id);
|
||||
const newNotes = Object.assign({ [notebook]: { [message.id]: this._formatNote(channel, message) } }, notes);
|
||||
|
||||
await DataStore.set(notebook, newNotes, HolyNoteStore);
|
||||
const newNotes = Object.assign({ [message.id]: this._formatNote(channel, message) }, notes);
|
||||
await DataStore.set(notebook, newNotes);
|
||||
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
|
@ -68,7 +69,7 @@ export default new (class NoteHandler {
|
|||
public deleteNote = async (noteId: string, notebook: string) => {
|
||||
const notes = this.getNotes(notebook);
|
||||
|
||||
await DataStore.set(notebook, lodash.omit(notes, noteId), HolyNoteStore);
|
||||
await DataStore.set(notebook, lodash.omit(notes, noteId));
|
||||
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
|
@ -83,8 +84,8 @@ export default new (class NoteHandler {
|
|||
|
||||
newNoteBook[note.id] = note;
|
||||
|
||||
await DataStore.set(from, lodash.omit(origNotebook, note.id), HolyNoteStore);
|
||||
await DataStore.set(to, newNoteBook, HolyNoteStore);
|
||||
await DataStore.set(from, lodash.omit(origNotebook, note.id));
|
||||
await DataStore.set(to, newNoteBook);
|
||||
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
|
@ -102,8 +103,8 @@ export default new (class NoteHandler {
|
|||
});
|
||||
return;
|
||||
}
|
||||
await DataStore.set(notebookName, {}, HolyNoteStore);
|
||||
Toasts.show({
|
||||
await DataStore.set(notebookName, {});
|
||||
return Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
message: `Successfully created ${notebookName}.`,
|
||||
type: Toasts.Type.SUCCESS,
|
||||
|
|
|
@ -45,3 +45,5 @@ export declare namespace HolyNotes {
|
|||
stickerItems: Discord.Sticker[];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
import { createStore } from "@api/DataStore";
|
||||
import { Settings } from "@api/Settings";
|
||||
|
||||
|
||||
export const HolyNoteStore = createStore("HolyNotesData", "HolyNotesStore");
|
||||
|
|
Loading…
Reference in a new issue