deck headers and saving (closing is broken though)

This commit is contained in:
Sqaaakoi 2025-02-26 04:52:51 +13:00
parent 54fe9f17bf
commit 7b1da05aa3
No known key found for this signature in database
5 changed files with 82 additions and 16 deletions

View file

@ -1,6 +1,7 @@
import { proxyLazyWebpack, findByProps, findByPropsLazy } from "@webpack";
import { Flux, FluxDispatcher, PopoutActions, PopoutWindowStore, SnowflakeUtils } from "@webpack/common";
import DeckPopout from "./components/DeckPopout";
import { DataStore } from "@api/index";
export interface ChannelDeck {
id: string;
@ -21,7 +22,10 @@ export const ChannelDeckStore = proxyLazyWebpack(() => {
public _decks = new Map<string, ChannelDeck>();
public windowKeyPrefix = "DISCORD_CHANNELDECK_DECK_";
public loaded = false;
public windowKeyPrefix = "DISCORD_VC_CHANNELDECK_";
public dataStoreKey = "ChannelDeck_Decks";
public createDeck(deckState: Partial<Omit<ChannelDeck, "id">>) {
const deck = {
@ -31,8 +35,7 @@ export const ChannelDeckStore = proxyLazyWebpack(() => {
open: false,
...deckState
};
this._decks.set(deck.id, deck);
this.updateDeck(deck.id);
this.setDeck(deck);
return deck;
}
@ -40,23 +43,54 @@ export const ChannelDeckStore = proxyLazyWebpack(() => {
return this._decks.get(id);
}
public updateDeck(id: string) {
const deck = this.getDeck(id);
if (deck?.open && !PopoutWindowStore.getWindowKeys().includes(this.windowKeyPrefix + id))
public setDeck(deck: ChannelDeck, noWrite?: boolean) {
this._decks.set(deck.id, deck);
const { id } = deck;
const windowKey = this.windowKeyPrefix + id;
if (deck?.open && !PopoutWindowStore.getWindowKeys().includes(windowKey)) {
PopoutActions.open(
this.windowKeyPrefix + id,
windowKey,
(key) => <DeckPopout deckId={id} windowKey={key} />, {
defaultWidth: 1200,
defaultHeight: 960
});
if (!deck?.open && PopoutWindowStore.getWindowKeys().includes(this.windowKeyPrefix + id))
const deckWindow = this.getDeckWindow(id);
debugger;
deckWindow.addEventListener("beforeunload", () => {
const deck_ = this.getDeck(id);
if (deck_?.open) this.setDeck({ ...deck, open: false });
});
}
if (!deck?.open && PopoutWindowStore.getWindowKeys().includes(windowKey))
this.getDeckWindow(id).close();
if (noWrite) return;
this.emitChange();
this.writeData();
};
public getDeckWindow(id: string) {
return PopoutWindowStore.getWindow(this.windowKeyPrefix + id);
}
public async loadData() {
this.loaded = true;
const decks: Map<string, ChannelDeck> | undefined = await DataStore.get(this.dataStoreKey);
if (decks) {
this._decks.clear();
decks.forEach(deck => this.setDeck(deck, true));
}
}
public async unloadData() {
// closes all decks
this.loaded = false;
this._decks.forEach(deck => this.setDeck({ ...deck, open: false }, true));
this._decks.clear();
}
public async writeData() {
await DataStore.set(this.dataStoreKey, this._decks);
}
}
const store = new ChannelDeckStore(FluxDispatcher, {

View file

@ -1,23 +1,52 @@
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
import { filters, findByPropsLazy, findComponentByCodeLazy, mapMangledModuleLazy } from "@webpack";
import "./DeckColumn.css";
import { cl } from "./util";
import { DeckColumn } from "../ChannelDeckStore";
import { ChannelStore, GuildStore } from "@webpack/common";
import { ChannelDeck, ChannelDeckStore, DeckColumn } from "../ChannelDeckStore";
import { ChannelStore, GuildStore, useMemo } from "@webpack/common";
const { HeaderBar, HeaderBarIcon } = mapMangledModuleLazy(".themedMobile]:", {
HeaderBarIcon: filters.byCode('size:"custom",'),
HeaderBar: filters.byCode(".themedMobile]:"),
});
const ChannelHeader = findComponentByCodeLazy(".forumPostTitle]:", '"channel-".concat');
const XSmallIcon = findComponentByCodeLazy("1.4L12 13.42l5.3 5.3Z");
const Chat = findComponentByCodeLazy("filterAfterTimestamp:", "chatInputType");
const ChatInputTypes = findByPropsLazy("FORM", "NORMAL");
export default function DeckColumn({ column }: { column: DeckColumn; }) {
export default function DeckColumn({ column, deck, index }: { column: DeckColumn; deck: ChannelDeck; index: number; }) {
const channel = ChannelStore.getChannel(column.channelId);
const guild = GuildStore.getGuild(channel.guild_id);
const chatInputType = useMemo(() => ({ ...ChatInputTypes.SIDEBAR }), []);
return <div className={cl("column")} style={{
width: column.width
}}>
<HeaderBar
toolbar={
<>
<HeaderBarIcon
icon={XSmallIcon}
tooltip="Close Column"
onClick={() => {
const newColumns = deck.columns;
newColumns.splice(index, 1);
ChannelDeckStore.setDeck({ ...deck, columns: newColumns });
}}
/>
</>
}
>
<ChannelHeader
channel={channel}
channelName={channel?.name}
guild={guild}
parentChannel={ChannelStore.getChannel(channel?.parent_id)}
/>
</HeaderBar>
<Chat
channel={channel}
guild={guild}
chatInputType={ChatInputTypes.SIDEBAR}
chatInputType={chatInputType}
/>
</div>;
};

View file

@ -6,6 +6,6 @@ import DeckColumn from "./DeckColumn";
export default function DeckContent() {
const deck = useDeck();
return <div className={cl("content")}>
{deck?.columns.map(column => <DeckColumn key={column.channelId} column={column} />)}
{deck?.columns.map((column, i) => <DeckColumn key={column.channelId} deck={deck} index={i} column={column} />)}
</div>;
};

View file

@ -7,8 +7,6 @@ import { DeckContext } from "./util";
const PopoutWindow = findComponentByCodeLazy("Missing guestWindow reference");
export default function DeckPopout({ deckId, windowKey }: { deckId: string; windowKey?: string; }) {
// Copy from an unexported function of the one they use in the experiment
// right click a channel and search withTitleBar:!0,windowKey
const deck = useStateFromStores([ChannelDeckStore], () => ChannelDeckStore.getDeck(deckId));
return <PopoutWindow

View file

@ -10,6 +10,11 @@ export default definePlugin({
start() {
if (!Vencord?.Api?.Styles?.createStyle) return showUnsupportedMessage();
ChannelDeckStore.loadData();
},
stop() {
ChannelDeckStore.unloadData();
},
ChannelDeckStore