mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-01-11 10:26:21 +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 { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, openModal } from "@utils/modal";
|
||||||
import { React, TabBar, Text, TextInput } from "@webpack/common";
|
import { React, TabBar, Text, TextInput } from "@webpack/common";
|
||||||
import noteHandler from "plugins/holynotes/noteHandler";
|
import noteHandler from "plugins/holynotes/noteHandler";
|
||||||
|
import { HolyNotes } from "plugins/holynotes/types";
|
||||||
|
|
||||||
import HelpIcon from "../icons/HelpIcon";
|
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 [searchInput, setSearch] = React.useState("");
|
||||||
const [sortDirection, setSortDirection] = React.useState(true);
|
const [sortDirection, setSortDirection] = React.useState(true);
|
||||||
const [currentNotebook, setCurrentNotebook] = React.useState("Main");
|
const [currentNotebook, setCurrentNotebook] = React.useState("Main");
|
||||||
|
const [notes, setNotes] = React.useState({});
|
||||||
|
const [notebooks, setNotebooks] = React.useState([]);
|
||||||
|
|
||||||
const forceUpdate = React.useReducer(() => ({}), {})[1] as () => void;
|
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 <></>;
|
if (!notes) return <></>;
|
||||||
|
|
||||||
|
@ -56,7 +115,7 @@ export const NoteModal = (props) => {
|
||||||
className="notebook-tabbar-Bar notebook-tabbar"
|
className="notebook-tabbar-Bar notebook-tabbar"
|
||||||
selectedItem={currentNotebook}
|
selectedItem={currentNotebook}
|
||||||
onItemSelect={setCurrentNotebook}>
|
onItemSelect={setCurrentNotebook}>
|
||||||
{Object.keys(noteHandler.getAllNotes()).map(notebook => (
|
{notebooks.map(notebook => (
|
||||||
<TabBar.Item key={notebook} id={notebook} className="notebook-tabbar-barItem notebook-tabbar-item">
|
<TabBar.Item key={notebook} id={notebook} className="notebook-tabbar-barItem notebook-tabbar-item">
|
||||||
{notebook}
|
{notebook}
|
||||||
</TabBar.Item>
|
</TabBar.Item>
|
||||||
|
@ -66,7 +125,15 @@ export const NoteModal = (props) => {
|
||||||
</div>
|
</div>
|
||||||
<ModalContent style={{ marginTop: "20px" }}>
|
<ModalContent style={{ marginTop: "20px" }}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
{ }
|
{renderNotebook({
|
||||||
|
notes,
|
||||||
|
notebook: currentNotebook,
|
||||||
|
updateParent: () => forceUpdate(),
|
||||||
|
sortDirection: sortDirection,
|
||||||
|
sortType: sortType,
|
||||||
|
searchInput: searchInput,
|
||||||
|
closeModal: props.onClose,
|
||||||
|
})}
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Flex>
|
</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; }) => {
|
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>> {
|
public async getNotes(notebook?: string): Promise<Record<string, HolyNotes.Note>> {
|
||||||
if (await DataStore.keys(HolyNoteStore).then(keys => keys.includes(notebook))) {
|
if (await DataStore.keys().then(keys => keys.includes(notebook))) {
|
||||||
return await DataStore.get(notebook, HolyNoteStore) ?? {};
|
return await DataStore.get(notebook) ?? {};
|
||||||
} else {
|
} else {
|
||||||
return this.newNoteBook(notebook).then(() => this.getNotes(notebook));
|
return this.newNoteBook(notebook).then(() => this.getNotes(notebook));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAllNotes(): Promise<HolyNotes.Note[]> {
|
public async getAllNotes(): Promise<HolyNotes.Note[]> {
|
||||||
const data = await DataStore.values(HolyNoteStore);
|
return await DataStore.entries();
|
||||||
const mainData = data[0];
|
}
|
||||||
return mainData;
|
|
||||||
|
public async getNotebooks(): Promise<string[]> {
|
||||||
|
return await DataStore.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
public addNote = async (message: Message, notebook: string) => {
|
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 channel = ChannelStore.getChannel(message.channel_id);
|
||||||
const newNotes = Object.assign({ [notebook]: { [message.id]: this._formatNote(channel, message) } }, notes);
|
const newNotes = Object.assign({ [message.id]: this._formatNote(channel, message) }, notes);
|
||||||
|
await DataStore.set(notebook, newNotes);
|
||||||
await DataStore.set(notebook, newNotes, HolyNoteStore);
|
|
||||||
|
|
||||||
Toasts.show({
|
Toasts.show({
|
||||||
id: Toasts.genId(),
|
id: Toasts.genId(),
|
||||||
|
@ -68,7 +69,7 @@ export default new (class NoteHandler {
|
||||||
public deleteNote = async (noteId: string, notebook: string) => {
|
public deleteNote = async (noteId: string, notebook: string) => {
|
||||||
const notes = this.getNotes(notebook);
|
const notes = this.getNotes(notebook);
|
||||||
|
|
||||||
await DataStore.set(notebook, lodash.omit(notes, noteId), HolyNoteStore);
|
await DataStore.set(notebook, lodash.omit(notes, noteId));
|
||||||
|
|
||||||
Toasts.show({
|
Toasts.show({
|
||||||
id: Toasts.genId(),
|
id: Toasts.genId(),
|
||||||
|
@ -83,8 +84,8 @@ export default new (class NoteHandler {
|
||||||
|
|
||||||
newNoteBook[note.id] = note;
|
newNoteBook[note.id] = note;
|
||||||
|
|
||||||
await DataStore.set(from, lodash.omit(origNotebook, note.id), HolyNoteStore);
|
await DataStore.set(from, lodash.omit(origNotebook, note.id));
|
||||||
await DataStore.set(to, newNoteBook, HolyNoteStore);
|
await DataStore.set(to, newNoteBook);
|
||||||
|
|
||||||
Toasts.show({
|
Toasts.show({
|
||||||
id: Toasts.genId(),
|
id: Toasts.genId(),
|
||||||
|
@ -102,8 +103,8 @@ export default new (class NoteHandler {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await DataStore.set(notebookName, {}, HolyNoteStore);
|
await DataStore.set(notebookName, {});
|
||||||
Toasts.show({
|
return Toasts.show({
|
||||||
id: Toasts.genId(),
|
id: Toasts.genId(),
|
||||||
message: `Successfully created ${notebookName}.`,
|
message: `Successfully created ${notebookName}.`,
|
||||||
type: Toasts.Type.SUCCESS,
|
type: Toasts.Type.SUCCESS,
|
||||||
|
|
|
@ -45,3 +45,5 @@ export declare namespace HolyNotes {
|
||||||
stickerItems: Discord.Sticker[];
|
stickerItems: Discord.Sticker[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createStore } from "@api/DataStore";
|
import { createStore } from "@api/DataStore";
|
||||||
import { Settings } from "@api/Settings";
|
|
||||||
|
|
||||||
|
|
||||||
export const HolyNoteStore = createStore("HolyNotesData", "HolyNotesStore");
|
export const HolyNoteStore = createStore("HolyNotesData", "HolyNotesStore");
|
||||||
|
|
Loading…
Reference in a new issue