From a0cb4624bc1bec8b2784b5f0f8dbefe0543bbe62 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Sat, 22 Feb 2025 22:30:17 -0500 Subject: [PATCH] Im Over ChannelTabs --- README.md | 3 +- .../components/BookmarkContainer.tsx | 311 ---------------- .../channelTabs/components/ChannelTab.tsx | 275 -------------- .../components/ChannelTabsContainer.tsx | 121 ------ .../channelTabs/components/ContextMenus.tsx | 348 ------------------ src/equicordplugins/channelTabs/index.tsx | 117 ------ src/equicordplugins/channelTabs/style.css | 262 ------------- .../channelTabs/util/bookmarks.ts | 117 ------ .../channelTabs/util/constants.tsx | 77 ---- src/equicordplugins/channelTabs/util/index.ts | 10 - src/equicordplugins/channelTabs/util/tabs.tsx | 274 -------------- src/equicordplugins/channelTabs/util/types.ts | 46 --- 12 files changed, 1 insertion(+), 1960 deletions(-) delete mode 100644 src/equicordplugins/channelTabs/components/BookmarkContainer.tsx delete mode 100644 src/equicordplugins/channelTabs/components/ChannelTab.tsx delete mode 100644 src/equicordplugins/channelTabs/components/ChannelTabsContainer.tsx delete mode 100644 src/equicordplugins/channelTabs/components/ContextMenus.tsx delete mode 100644 src/equicordplugins/channelTabs/index.tsx delete mode 100644 src/equicordplugins/channelTabs/style.css delete mode 100644 src/equicordplugins/channelTabs/util/bookmarks.ts delete mode 100644 src/equicordplugins/channelTabs/util/constants.tsx delete mode 100644 src/equicordplugins/channelTabs/util/index.ts delete mode 100644 src/equicordplugins/channelTabs/util/tabs.tsx delete mode 100644 src/equicordplugins/channelTabs/util/types.ts diff --git a/README.md b/README.md index c32a94f3..4eabf67b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch ### Extra included plugins
-151 additional plugins +150 additional plugins ### All Platforms - AllCallTimers by MaxHerbold & D3SOX @@ -30,7 +30,6 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch - BlockKrsip by D3SOX - BypassStatus by Inbestigator & thororen - ChannelBadges by Creations -- ChannelTabs by TheSun, TheKodeToad, keifufu, Nickyux - CharacterCounter by Creations & Panniku - CleanChannelName by AutumnVN - ClientSideBlock by Samwich diff --git a/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx b/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx deleted file mode 100644 index 8c97f625..00000000 --- a/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { classNameFactory } from "@api/Styles"; -import { getIntlMessage } from "@utils/discord"; -import { classes } from "@utils/misc"; -import { closeModal, openModal } from "@utils/modal"; -import { findComponentByCodeLazy } from "@webpack"; -import { Avatar, ChannelStore, ContextMenuApi, FluxDispatcher, GuildStore, Menu, ReadStateStore, ReadStateUtils, Text, Tooltip, useDrag, useDrop, useEffect, useRef, UserStore } from "@webpack/common"; - -import { BasicChannelTabsProps, Bookmark, BookmarkFolder, BookmarkProps, CircleQuestionIcon, isBookmarkFolder, settings, switchChannel, useBookmarks } from "../util"; -import { NotificationDot } from "./ChannelTab"; -import { BookmarkContextMenu, EditModal } from "./ContextMenus"; - -const cl = classNameFactory("vc-channeltabs-"); - -const StarIcon = findComponentByCodeLazy(".73-2.25h6.12l1.9-5.83Z"); - -function FolderIcon({ fill }: { fill: string; }) { - return ( - - ); -} - -function BookmarkIcon({ bookmark }: { bookmark: Bookmark | BookmarkFolder; }) { - if (isBookmarkFolder(bookmark)) return ( - - - - ); - - const channel = ChannelStore.getChannel(bookmark.channelId); - const guild = GuildStore.getGuild(bookmark.guildId); - if (guild) return guild.icon - ? - :
- {guild.acronym} -
; - - if (channel?.recipients?.length) { - if (channel.recipients.length === 1) return ( - - ); - else return ( - - ); - } - - return ( - - ); -} - -function BookmarkFolderOpenMenu(props: BookmarkProps) { - const { bookmarks, index, methods } = props; - const bookmark = bookmarks[index] as BookmarkFolder; - const { bookmarkNotificationDot } = settings.use(["bookmarkNotificationDot"]); - - return ( - FluxDispatcher.dispatch({ type: "CONTEXT_MENU_CLOSE" })} - aria-label="Bookmark Folder Menu" - > - {bookmark.bookmarks.map((b, i) => ( - - - {b.name} - - {bookmarkNotificationDot && } - - } - icon={() => } - showIconFirst={true} - action={() => switchChannel(b)} - > - {bookmarkNotificationDot && ( - - ReadStateUtils.ackChannel(ChannelStore.getChannel(b.channelId))} - /> - - )} - - { - const key = openModal(modalProps => - { - const newBookmarks = [...bookmark.bookmarks]; - newBookmarks[i].name = name; - methods.editBookmark(index, { bookmarks: newBookmarks }); - closeModal(key); - }} - /> - ); - }} - /> - { - methods.deleteBookmark(i, index); - }} - /> - { - const newBookmarks = [...bookmark.bookmarks]; - newBookmarks.splice(i, 1); - methods.addBookmark(b); - methods.editBookmark(index, { bookmarks: newBookmarks }); - }} - /> - - - ))} - - ); -} - -function Bookmark(props: BookmarkProps) { - const { bookmarks, index, methods } = props; - const bookmark = bookmarks[index]; - const { bookmarkNotificationDot } = settings.use(["bookmarkNotificationDot"]); - - const ref = useRef(null); - - const [, drag] = useDrag(() => ({ - type: "vc_Bookmark", - item: () => { - return { index }; - }, - collect: monitor => ({ - isDragging: !!monitor.isDragging() - }), - })); - - const [, drop] = useDrop(() => ({ - accept: "vc_Bookmark", - hover: (item, monitor) => { - if (!ref.current) return; - - const dragIndex = item.index; - const hoverIndex = index; - if (dragIndex === hoverIndex) return; - - const hoverBoundingRect = ref.current?.getBoundingClientRect(); - const hoverMiddleX = - (hoverBoundingRect.right - hoverBoundingRect.left) / 2; - const clientOffset = monitor.getClientOffset(); - const hoverClientX = clientOffset.x - hoverBoundingRect.left; - if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX - || dragIndex > hoverIndex && hoverClientX > hoverMiddleX) { - return; - } - - methods.moveDraggedBookmarks(dragIndex, hoverIndex); - item.index = hoverIndex; - }, - }), []); - drag(drop(ref)); - - return ( -
isBookmarkFolder(bookmark) - ? ContextMenuApi.openContextMenu(e, () => ) - : switchChannel(bookmark) - } - onContextMenu={e => ContextMenuApi.openContextMenu(e, () => - - )} - > - - - {bookmark.name} - - {bookmarkNotificationDot && b.channelId) - : [bookmark.channelId] - } />} -
- ); -} - -function HorizontalScroller({ children, className }: React.PropsWithChildren<{ className?: string; }>) { - const ref = useRef(null); - useEffect(() => { - ref.current!.addEventListener("wheel", e => { - e.preventDefault(); - ref.current!.scrollLeft += e.deltaY; - }); - }, []); - - return ( -
- {children} -
- ); -} - -export default function BookmarkContainer(props: BasicChannelTabsProps & { userId: string; }) { - const { guildId, channelId, userId } = props; - const [bookmarks, methods] = useBookmarks(userId); - - let isCurrentChannelBookmarked = false, currentChannelFolderIndex = -1; - bookmarks?.forEach((bookmark, i) => { - if (isBookmarkFolder(bookmark)) { - if (bookmark.bookmarks.some(b => b.channelId === channelId)) { - isCurrentChannelBookmarked = true; - currentChannelFolderIndex = i; - } - } - else if (bookmark.channelId === channelId) isCurrentChannelBookmarked = true; - }); - - return ( -
- - {!bookmarks && - Loading bookmarks... - } - {bookmarks && !bookmarks.length && - You have no bookmarks. You can add an open tab or hide this by right clicking it - } - {Array.isArray(bookmarks) && bookmarks.length > 0 && - bookmarks.map((_, i) => ( - - )) - } - - - - {p => } - -
- ); -} diff --git a/src/equicordplugins/channelTabs/components/ChannelTab.tsx b/src/equicordplugins/channelTabs/components/ChannelTab.tsx deleted file mode 100644 index f8350ef4..00000000 --- a/src/equicordplugins/channelTabs/components/ChannelTab.tsx +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { classNameFactory } from "@api/Styles"; -import { getIntlMessage, getUniqueUsername } from "@utils/discord"; -import { classes } from "@utils/misc"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; -import { Avatar, ChannelStore, ContextMenuApi, GuildStore, PresenceStore, ReadStateStore, Text, TypingStore, useDrag, useDrop, useRef, UserStore, useStateFromStores } from "@webpack/common"; -import { Channel, Guild, User } from "discord-types/general"; - -import { ChannelTabsProps, CircleQuestionIcon, closeTab, isTabSelected, moveDraggedTabs, moveToTab, openedTabs, settings } from "../util"; -import { TabContextMenu } from "./ContextMenus"; - -const ThreeDots = findComponentByCodeLazy(".dots,", "dotRadius:"); -const dotStyles = findByPropsLazy("numberBadge", "textBadge"); - -const FriendsIcon = findComponentByCodeLazy("12h1a8"); -const ChannelTypeIcon = findComponentByCodeLazy(".iconContainerWithGuildIcon,"); - -const cl = classNameFactory("vc-channeltabs-"); - -function XIcon({ size, fill }: { size: number, fill: string; }) { - return - - ; -} - -const GuildIcon = ({ guild }: { guild: Guild; }) => { - return guild.icon - ? - :
- {guild.acronym} -
; -}; - -const ChannelIcon = ({ channel }: { channel: Channel; }) => - ; - -function TypingIndicator({ isTyping }: { isTyping: boolean; }) { - return isTyping - ? - : null; -} - -export const NotificationDot = ({ channelIds }: { channelIds: string[]; }) => { - const [unreadCount, mentionCount] = useStateFromStores( - [ReadStateStore], - () => [ - channelIds.reduce((count, channelId) => count + ReadStateStore.getUnreadCount(channelId), 0), - channelIds.reduce((count, channelId) => count + ReadStateStore.getMentionCount(channelId), 0), - ] - ); - - return unreadCount > 0 ? -
node?.style.setProperty("background-color", - mentionCount ? "var(--red-400)" : "var(--brand-500)", "important" - )} - > - {mentionCount || unreadCount} -
: null; -}; - -function ChannelTabContent(props: ChannelTabsProps & { - guild?: Guild, - channel?: Channel; -}) { - const { guild, guildId, channel, channelId, compact } = props; - const userId = UserStore.getCurrentUser()?.id; - const recipients = channel?.recipients; - const { - noPomeloNames, - showStatusIndicators - } = settings.use(["noPomeloNames", "showStatusIndicators"]); - - const [isTyping, status, isMobile] = useStateFromStores( - [TypingStore, PresenceStore], - () => [ - !!((Object.keys(TypingStore.getTypingUsers(props.channelId)) as string[]).filter(id => id !== userId).length), - PresenceStore.getStatus(recipients?.[0]) as string, - PresenceStore.isMobileOnline(recipients?.[0]) as boolean - ] - ); - - if (guild) { - if (channel) - return ( - <> - - - {!compact && {channel.name}} - - - - ); - else { - let name = `${getIntlMessage("UNKNOWN_CHANNEL")} (${channelId})`; - switch (channelId) { - case "customize-community": - name = getIntlMessage("CHANNELS_AND_ROLES"); - break; - case "channel-browser": - name = getIntlMessage("GUILD_SIDEBAR_CHANNEL_BROWSER"); - break; - case "shop": - name = getIntlMessage("GUILD_SHOP_CHANNEL_LABEL"); - break; - case "member-safety": - name = getIntlMessage("MEMBER_SAFETY_CHANNEL_TITLE"); - break; - case "@home": - name = getIntlMessage("SERVER_GUIDE"); - break; - } - return ( - <> - - {!compact && {name}} - - ); - } - } - - if (channel && recipients?.length) { - if (recipients.length === 1) { - const user = UserStore.getUser(recipients[0]) as User & { globalName: string, isPomelo(): boolean; }; - const username = noPomeloNames - ? user.globalName || user.username - : getUniqueUsername(user); - - return ( - <> - - {!compact && - {username} - } - - {!showStatusIndicators && } - - ); - } else { - // Group DM - return ( - <> - - {!compact && {channel?.name || getIntlMessage("GROUP_DM")}} - - - - ); - } - } - - if (guildId === "@me" || guildId === undefined) - return ( - <> - - {!compact && {getIntlMessage("FRIENDS")}} - - ); - - return ( - <> - - {!compact && {getIntlMessage("UNKNOWN_CHANNEL")}} - - ); -} - -export default function ChannelTab(props: ChannelTabsProps & { index: number; }) { - const { channelId, guildId, id, index, compact } = props; - const guild = GuildStore.getGuild(guildId); - const channel = ChannelStore.getChannel(channelId); - - const ref = useRef(null); - const [, drag] = useDrag(() => ({ - type: "vc_ChannelTab", - item: () => { - return { id, index }; - }, - collect: monitor => ({ - isDragging: !!monitor.isDragging() - }), - })); - const [, drop] = useDrop(() => ({ - accept: "vc_ChannelTab", - hover: (item, monitor) => { - if (!ref.current) return; - - const dragIndex = item.index; - const hoverIndex = index; - if (dragIndex === hoverIndex) return; - - const hoverBoundingRect = ref.current?.getBoundingClientRect(); - const hoverMiddleX = - (hoverBoundingRect.right - hoverBoundingRect.left) / 2; - const clientOffset = monitor.getClientOffset(); - const hoverClientX = clientOffset.x - hoverBoundingRect.left; - if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX - || dragIndex > hoverIndex && hoverClientX > hoverMiddleX) { - return; - } - - moveDraggedTabs(dragIndex, hoverIndex); - item.index = hoverIndex; - }, - }), []); - drag(drop(ref)); - - return
{ - if (e.button === 1 /* middle click */) - closeTab(id); - }} - onContextMenu={e => ContextMenuApi.openContextMenu(e, () => )} - > - - - {openedTabs.length > 1 && (compact ? isTabSelected(id) : true) && } -
; -} - -export const PreviewTab = (props: ChannelTabsProps) => { - const guild = GuildStore.getGuild(props.guildId); - const channel = ChannelStore.getChannel(props.channelId); - - return ( -
- -
- ); -}; diff --git a/src/equicordplugins/channelTabs/components/ChannelTabsContainer.tsx b/src/equicordplugins/channelTabs/components/ChannelTabsContainer.tsx deleted file mode 100644 index 4fd26e76..00000000 --- a/src/equicordplugins/channelTabs/components/ChannelTabsContainer.tsx +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { classNameFactory } from "@api/Styles"; -import { useForceUpdater } from "@utils/react"; -import { findComponentByCodeLazy } from "@webpack"; -import { Button, ContextMenuApi, Flex, FluxDispatcher, Forms, useCallback, useEffect, useRef, UserStore, useState } from "@webpack/common"; - -import { BasicChannelTabsProps, ChannelTabsProps, createTab, handleChannelSwitch, openedTabs, openStartupTabs, saveTabs, settings, setUpdaterFunction, useGhostTabs } from "../util"; -import BookmarkContainer from "./BookmarkContainer"; -import ChannelTab, { PreviewTab } from "./ChannelTab"; -import { BasicContextMenu } from "./ContextMenus"; - -type TabSet = Record; - -const PlusSmallIcon = findComponentByCodeLazy("0v-5h5a1"); - -const cl = classNameFactory("vc-channeltabs-"); - -export default function ChannelsTabsContainer(props: BasicChannelTabsProps) { - const [userId, setUserId] = useState(""); - const { showBookmarkBar, widerTabsAndBookmarks } = settings.use(["showBookmarkBar", "widerTabsAndBookmarks"]); - const GhostTabs = useGhostTabs(); - - const _update = useForceUpdater(); - const update = useCallback((save = true) => { - _update(); - if (save) saveTabs(userId); - }, [userId]); - - const ref = useRef(null); - - useEffect(() => { - setUpdaterFunction(update); - const onLogin = () => { - const { id } = UserStore.getCurrentUser(); - if (id === userId && openedTabs.length) return; - setUserId(id); - - openStartupTabs({ ...props, userId: id }, setUserId); - }; - - FluxDispatcher.subscribe("CONNECTION_OPEN_SUPPLEMENTAL", onLogin); - return () => { - FluxDispatcher.unsubscribe("CONNECTION_OPEN_SUPPLEMENTAL", onLogin); - }; - }, []); - - useEffect(() => { - (Vencord.Plugins.plugins.ChannelTabs as any).containerHeight = ref.current?.clientHeight; - }, [userId, showBookmarkBar]); - - useEffect(() => { - _update(); - }, [widerTabsAndBookmarks]); - - if (!userId) return null; - handleChannelSwitch(props); - saveTabs(userId); - - return ( -
ContextMenuApi.openContextMenu(e, () => )} - > -
- {openedTabs.map((tab, i) => - - )} - - - - {GhostTabs} -
- {showBookmarkBar && <> -
- - } - -
- ); -} - -export function ChannelTabsPreview(p) { - const id = UserStore.getCurrentUser()?.id; - if (!id) return there's no logged in account?????; - - const { setValue }: { setValue: (v: TabSet) => void; } = p; - const { tabSet }: { tabSet: TabSet; } = settings.use(["tabSet"]); - - const placeholder = [{ guildId: "@me", channelId: undefined as any }]; - const [currentTabs, setCurrentTabs] = useState(tabSet?.[id] ?? placeholder); - - return ( - <> - Startup tabs - - {currentTabs.map(t => <> - - )} - - - - - - ); -} diff --git a/src/equicordplugins/channelTabs/components/ContextMenus.tsx b/src/equicordplugins/channelTabs/components/ContextMenus.tsx deleted file mode 100644 index d29cc09a..00000000 --- a/src/equicordplugins/channelTabs/components/ContextMenus.tsx +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { getIntlMessage } from "@utils/discord"; -import { Margins } from "@utils/margins"; -import { closeModal, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal"; -import { Button, ChannelStore, FluxDispatcher, Forms, Menu, ReadStateStore, ReadStateUtils, Select, Text, TextInput, useState } from "@webpack/common"; - -import { bookmarkFolderColors, bookmarkPlaceholderName, closeOtherTabs, closeTab, closeTabsToTheLeft, closeTabsToTheRight, createTab, hasClosedTabs, isBookmarkFolder, openedTabs, reopenClosedTab, settings, toggleCompactTab } from "../util"; -import { Bookmark, BookmarkFolder, Bookmarks, ChannelTabsProps, UseBookmarkMethods } from "../util/types"; - -export function BasicContextMenu() { - const { showBookmarkBar } = settings.use(["showBookmarkBar"]); - - return ( - FluxDispatcher.dispatch({ type: "CONTEXT_MENU_CLOSE" })} - aria-label="ChannelTabs Context Menu" - > - - { - settings.store.showBookmarkBar = !settings.store.showBookmarkBar; - }} - /> - - - ); -} - -export function EditModal({ modalProps, modalKey, bookmark, onSave }: { - modalProps: ModalProps, - modalKey: string, - bookmark: Bookmark | BookmarkFolder, - onSave: (name: string, color: string) => void; -}) { - const [name, setName] = useState(bookmark.name); - const [color, setColor] = useState(isBookmarkFolder(bookmark) ? bookmark.iconColor : undefined); - const placeholder = bookmarkPlaceholderName(bookmark); - - return ( - - - Edit Bookmark - - - Bookmark Name - setName(v)} - /> - {isBookmarkFolder(bookmark) && <> - Folder Color - isBookmarkFolder(bookmark)) - .map(([index, bookmark]) => ({ - label: bookmark.name, - value: parseInt(index, 10) - })), - { - label: "Create one", - value: -1, - default: true - }]} - isSelected={v => v === folderIndex} - select={setIndex} - serialize={String} - /> - - - - - - - ); -} - -function DeleteFolderConfirmationModal({ modalProps, modalKey, onConfirm }) { - return ( - - - Are you sure? - - - - Deleting a bookmark folder will also delete all bookmarks within it. - - - - - - - - ); -} - -export function BookmarkContextMenu({ bookmarks, index, methods }: { bookmarks: Bookmarks, index: number, methods: UseBookmarkMethods; }) { - const { showBookmarkBar, bookmarkNotificationDot } = settings.use(["showBookmarkBar", "bookmarkNotificationDot"]); - const bookmark = bookmarks[index]; - const isFolder = isBookmarkFolder(bookmark); - - return ( - FluxDispatcher.dispatch({ type: "CONTEXT_MENU_CLOSE" })} - aria-label="ChannelTabs Bookmark Context Menu" - > - - {bookmarkNotificationDot && !isFolder && - ReadStateUtils.ackChannel(ChannelStore.getChannel(bookmark.channelId))} - /> - } - {isFolder - ? bookmark.bookmarks.forEach(b => createTab(b))} - /> - : < Menu.MenuItem - id="open-in-tab" - label={"Open in New Tab"} - action={() => createTab(bookmark)} - /> - } - - - { - const key = openModal(modalProps => - { - methods.editBookmark(index, { name }); - if (color) methods.editBookmark(index, { iconColor: color }); - closeModal(key); - } - } - /> - ); - }} - /> - { - if (isFolder) { - const key = openModal(modalProps => - { - methods.deleteBookmark(index); - closeModal(key); - }} - />); - } - else methods.deleteBookmark(index); - }} - /> - { - const key = openModal(modalProps => - { - if (index === -1) { - const folderIndex = methods.addFolder(); - methods.addBookmark(bookmark as Bookmark, folderIndex); - } - else methods.addBookmark(bookmark as Bookmark, index); - methods.deleteBookmark(bookmarks.indexOf(bookmark)); - closeModal(key); - } - } - /> - ); - }} - /> - - - { - settings.store.showBookmarkBar = !settings.store.showBookmarkBar; - }} - /> - - - ); -} - -export function TabContextMenu({ tab }: { tab: ChannelTabsProps; }) { - const channel = ChannelStore.getChannel(tab.channelId); - const [compact, setCompact] = useState(tab.compact); - const { showBookmarkBar } = settings.use(["showBookmarkBar"]); - - return ( - FluxDispatcher.dispatch({ type: "CONTEXT_MENU_CLOSE" })} - aria-label="ChannelTabs Tab Context Menu" - > - - {channel && - ReadStateUtils.ackChannel(channel)} - /> - } - { - setCompact(compact => !compact); - toggleCompactTab(tab.id); - }} - /> - - {openedTabs.length !== 1 && - closeTab(tab.id)} - /> - closeOtherTabs(tab.id)} - /> - closeTabsToTheRight(tab.id)} - /> - closeTabsToTheLeft(tab.id)} - /> - reopenClosedTab()} - /> - } - - { - settings.store.showBookmarkBar = !settings.store.showBookmarkBar; - }} - /> - - - ); -} diff --git a/src/equicordplugins/channelTabs/index.tsx b/src/equicordplugins/channelTabs/index.tsx deleted file mode 100644 index a69104ac..00000000 --- a/src/equicordplugins/channelTabs/index.tsx +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import "./style.css"; - -import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; -import ErrorBoundary from "@components/ErrorBoundary"; -import { Devs, EquicordDevs } from "@utils/constants"; -import definePlugin from "@utils/types"; -import { ChannelStore, Menu } from "@webpack/common"; -import { Channel, Message } from "discord-types/general"; -import { JSX } from "react"; - -import ChannelsTabsContainer from "./components/ChannelTabsContainer"; -import { BasicChannelTabsProps, createTab, settings } from "./util"; -import * as ChannelTabsUtils from "./util"; - -const contextMenuPatch: NavContextMenuPatchCallback = (children, props: { channel: Channel, messageId?: string; }) => - () => { - const { channel, messageId } = props; - const group = findGroupChildrenByChildId("channel-copy-link", children); - group?.push( - createTab({ - guildId: channel.guild_id, - channelId: channel.id - }, true, messageId)} - /> - ); - }; - -export default definePlugin({ - name: "ChannelTabs", - description: "Group your commonly visited channels in tabs, like a browser", - authors: [Devs.TheSun, Devs.TheKodeToad, EquicordDevs.keifufu, Devs.Nickyux], - dependencies: ["ContextMenuAPI"], - contextMenus: { - "channel-mention-context": contextMenuPatch, - "channel-context": contextMenuPatch - }, - patches: [ - // add the channel tab container at the top - { - find: ".COLLECTIBLES_SHOP_FULLSCREEN))", - replacement: { - match: /(\?void 0:(\i)\.channelId.{0,300})\i\.Fragment,{/, - replace: "$1$self.render,{currentChannel:$2," - } - }, - // ctrl click to open in new tab in inbox unread - { - find: ".messageContainer,onKeyDown", - replacement: { - match: /.jumpButton,onJump:\i=>(\i)\(\i,(\i)\.id\)/, - replace: ".jumpButton,onJump: event => { if (event.ctrlKey) $self.open($2); else $1(event, $2.id) }" - } - }, - // ctrl click to open in new tab in inbox mentions - { - find: ".deleteRecentMention(", - replacement: { - match: /(?<=.jumpMessageButton,onJump:)(\i)(?=.{0,20}message:(\i))/, - replace: "event => { if (event.ctrlKey) $self.open($2); else $1(event) }" - } - }, - // ctrl click to open in new tab in search results - { - find: "(this,\"handleMessageClick\"", - replacement: { - match: /(?<=(\i)\.isSearchHit\));(?=null!=(\i))/, - replace: ";if ($1.ctrlKey) return $self.open($2);" - } - }, - // prevent issues with the pins/inbox popouts being too tall - { - find: ".messagesPopoutWrap", - replacement: { - match: /\i&&\((\i).maxHeight.{0,5}\)/, - replace: "$&;$1.maxHeight-=$self.containerHeight" - } - } - ], - - settings, - - containerHeight: 0, - - render({ currentChannel, children }: { - currentChannel: BasicChannelTabsProps, - children: JSX.Element; - }) { - return ( - <> - - - - {children} - - ); - }, - - open(message: Message) { - const tab = { - channelId: message.channel_id, - guildId: ChannelStore.getChannel(message.channel_id)?.guild_id, - compact: false - }; - createTab(tab, false, message.id); - }, - - util: ChannelTabsUtils, -}); diff --git a/src/equicordplugins/channelTabs/style.css b/src/equicordplugins/channelTabs/style.css deleted file mode 100644 index 2d4f187a..00000000 --- a/src/equicordplugins/channelTabs/style.css +++ /dev/null @@ -1,262 +0,0 @@ -.vc-channeltabs-icon { - height: 1.5rem; - width: 1.5rem; - border-radius: 50%; -} - -.vc-channeltabs-guild-acronym-icon { - height: 1.25rem; - width: 1.5rem; - min-width: 1.5rem; - border-radius: 50%; - padding-top: 0.25rem; - background-color: var(--background-primary); - overflow: hidden; -} - -/* user avatars */ -.vc-channeltabs-tab [class^="wrapper_"] { - min-width: 1.5rem; -} - -.vc-channeltabs-name-text { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin-left: 0.125rem; -} - -.vc-channeltabs-tab-inner { - border-radius: 0.5rem; - padding: 0.25rem 0 0.25rem 0.25rem; - display: flex; - flex-direction: row; - align-items: center; - gap: 0.25rem; -} - -.vc-channeltabs-tab-container, -.vc-channeltabs-bookmark-container { - display: flex; - flex-direction: row; - align-items: flex-start; -} - -.platform-osx .vc-channeltabs-tab-container { - padding-left: 66px; -} - -.vc-channeltabs-container { - --channeltabs-red: #f23f42; - --channeltabs-blue: #0052b6; - --channeltabs-yellow: #f0b132; - --channeltabs-green: #24934f; - --channeltabs-black: #000; - --channeltabs-white: #fff; - --channeltabs-orange: #e67e22; - --channeltabs-pink: #ff73fa; - - padding: 0.35rem; - display: flex; - flex-direction: column; -} - -.vc-channeltabs-separator { - width: 98vw; - height: 0.075rem; - background: var(--bg-overlay-5); - background-color: var(--background-secondary); - margin: 0.25rem 1vw; -} - -.vc-channeltabs-scroller { - display: flex; - flex-direction: row; - align-items: flex-start; - overflow-x: auto; - white-space: nowrap; -} - -.vc-channeltabs-scroller::-webkit-scrollbar { - display: none; -} - -.vc-channeltabs-bookmarks { - flex-grow: 1; - overflow: hidden; -} - -.vc-channeltabs-bookmark-placeholder-text { - color: var(--text-muted); - padding: 0.25rem 0 0 0.25rem; -} - -.vc-channeltabs-bookmark-star { - fill: none; - stroke: var(--text-muted); - stroke-width: 0.075rem; -} - -.vc-channeltabs-bookmark-star-checked { - fill: var(--yellow-300); -} - -.vc-channeltabs-bookmark { - display: flex; - flex-direction: row; - max-width: 8rem; - padding: 0.25rem 0.5rem; - border-radius: 0.25rem; -} - -.vc-channeltabs-bookmark.vc-channeltabs-wider { - max-width: 12rem; -} - -.vc-channeltabs-bookmark .vc-channeltabs-name-text { - margin-left: 0.25rem; - margin-right: 0.25rem; -} - -.vc-channeltabs-bookmark-icon { - height: 1rem; - width: 1rem; - border-radius: 50%; - background-color: var(--background-primary); - text-align: center; -} - -.vc-channeltabs-bookmark-notification { - height: 1rem; - width: 1rem; -} - -.vc-channeltabs-channel-info { - flex-grow: 1; - overflow: hidden; -} - -.vc-channeltabs-tab { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - border-radius: 0.25rem; - width: 12rem; - min-width: 0; - margin-right: 0.25rem; -} - -.vc-channeltabs-tab.vc-channeltabs-wider:not(.vc-channeltabs-tab-compact) { - width: 16rem; -} - -.vc-channeltabs-tab-compact { - width: unset; - min-width: unset; -} - -.vc-channeltabs-tab-selected { - background: var(--bg-overlay-selected); - background-color: var(--background-modifier-selected); -} - -/* channel type container */ -.vc-channeltabs-container [class^="iconContainer_"] { - margin: 0 -0.25rem 0 0; - pointer-events: none; - height: 1rem; - transform: scale(0.8); -} - -.vc-channeltabs-ghost-tab { - visibility: hidden; -} - -.vc-channeltabs-hoverable:hover, -.vc-channeltabs-tab:hover:not(.vc-channeltabs-tab-selected) { - background: var(--bg-overlay-hover); - background-color: var(--background-modifier-hover); -} - -.vc-channeltabs-button { - background-color: transparent; - color: var(--text-normal); -} - -.vc-channeltabs-new-button { - padding: 0.375rem 0.5rem; - border-radius: 0.25rem; -} - -.vc-channeltabs-close-button { - height: 1rem; - padding: 0; - margin-right: 0.5rem; -} - -.vc-channeltabs-close-button-compact { - position: absolute; - opacity: 0; - width: 2rem; - height: 2rem; - margin-left: 0.35rem; - display: flex; - align-items: center; - justify-content: center; - border-radius: 50%; -} - -.vc-channeltabs-close-button-compact:hover { - background-color: black; - opacity: 0.5; -} - -.vc-channeltabs-emoji-container { - display: flex; - align-items: center; - justify-content: center; - height: 1.25rem; - width: 1.25rem; - min-width: 1.25rem; - border-radius: 50%; -} - -.vc-channeltabs-emoji { - height: 0.75rem; - width: 0.75rem; -} - -.vc-channeltabs-favorites-star { - margin: 0 -0.25rem -1rem -0.75rem; - height: 0.75rem; - width: 0.75rem; -} - -.vc-channeltabs-preview-tab { - display: flex; - flex-direction: row; - align-items: center; - width: 12rem; - padding: 0.125rem 0; - min-width: 0; - border-radius: 0.25rem; - border: 1px solid var(--background-modifier-accent); -} - -.vc-channeltabs-preview-tab-compact { - width: unset; - min-width: unset; -} - -.vc-channeltabs-preview-tab> :is(.vc-channeltabs-emoji-container, -.vc-channeltabs-typing-indicator, -[data-has-mention]) { - display: none; -} - -.vc-channeltabs-preview-text { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} diff --git a/src/equicordplugins/channelTabs/util/bookmarks.ts b/src/equicordplugins/channelTabs/util/bookmarks.ts deleted file mode 100644 index 98854c88..00000000 --- a/src/equicordplugins/channelTabs/util/bookmarks.ts +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { DataStore } from "@api/index"; -import { useAwaiter } from "@utils/react"; -import { ChannelStore, useCallback, UserStore, useState } from "@webpack/common"; - -import { bookmarkFolderColors, logger } from "./constants"; -import { Bookmark, BookmarkFolder, Bookmarks, UseBookmark, UseBookmarkMethods } from "./types"; - -export function isBookmarkFolder(bookmark: Bookmark | BookmarkFolder): bookmark is BookmarkFolder { - return "bookmarks" in bookmark; -} - -export function bookmarkPlaceholderName(bookmark: Omit) { - if (isBookmarkFolder(bookmark as Bookmark | BookmarkFolder)) return "Folder"; - const channel = ChannelStore.getChannel((bookmark as Bookmark).channelId); - - if (!channel) return "Bookmark"; - if (channel.name) return `#${channel.name}`; - if (channel.recipients) return UserStore.getUser(channel.recipients?.[0])?.username - ?? "Unknown User"; - return "Bookmark"; -} - -export function useBookmarks(userId: string): UseBookmark { - const [bookmarks, _setBookmarks] = useState<{ [k: string]: Bookmarks; }>({}); - const setBookmarks = useCallback((bookmarks: { [k: string]: Bookmarks; }) => { - _setBookmarks(bookmarks); - DataStore.update("ChannelTabs_bookmarks", old => ({ - ...old, - [userId]: bookmarks[userId] - })); - }, [userId]); - - useAwaiter(() => DataStore.get("ChannelTabs_bookmarks"), { - fallbackValue: undefined, - onSuccess(bookmarks: { [k: string]: Bookmarks; }) { - if (!bookmarks) { - bookmarks = { [userId]: [] }; - DataStore.set("ChannelTabs_bookmarks", { [userId]: [] }); - } - if (!bookmarks[userId]) bookmarks[userId] = []; - - setBookmarks(bookmarks); - }, - }); - - const methods = { - addBookmark: (bookmark, folderIndex) => { - if (!bookmarks) return; - - if (typeof folderIndex === "number" && !(isBookmarkFolder(bookmarks[userId][folderIndex]))) - return logger.error("Attempted to add bookmark to non-folder " + folderIndex, bookmarks); - - const name = bookmark.name ?? bookmarkPlaceholderName(bookmark); - if (typeof folderIndex === "number") - (bookmarks[userId][folderIndex] as BookmarkFolder).bookmarks.push({ ...bookmark, name }); - else bookmarks[userId].push({ ...bookmark, name }); - - setBookmarks({ - ...bookmarks - }); - }, - addFolder() { - if (!bookmarks) return; - const length = bookmarks[userId].push({ - name: "Folder", - iconColor: bookmarkFolderColors.Black, - bookmarks: [] - }); - - setBookmarks({ - ...bookmarks - }); - return length - 1; - }, - editBookmark(index, newBookmark) { - if (!bookmarks) return; - Object.entries(newBookmark).forEach(([k, v]) => { - bookmarks[userId][index][k] = v; - }); - setBookmarks({ - ...bookmarks - }); - }, - deleteBookmark(index, folderIndex) { - if (!bookmarks) return; - if (index < 0 || index > (bookmarks[userId].length - 1)) - return logger.error("Attempted to delete bookmark at index " + index, bookmarks); - - if (typeof folderIndex === "number") - (bookmarks[userId][folderIndex] as BookmarkFolder).bookmarks.splice(index, 1); - else bookmarks[userId].splice(index, 1); - - setBookmarks({ - ...bookmarks - }); - }, - moveDraggedBookmarks(index1, index2) { - if (index1 < 0 || index2 > bookmarks[userId].length) - return logger.error(`Out of bounds drag (swap between indexes ${index1} and ${index2})`, bookmarks); - - const firstItem = bookmarks[userId].splice(index1, 1)[0]; - bookmarks[userId].splice(index2, 0, firstItem); - - setBookmarks({ - ...bookmarks - }); - } - } as UseBookmarkMethods; - - return [bookmarks[userId], methods]; -} diff --git a/src/equicordplugins/channelTabs/util/constants.tsx b/src/equicordplugins/channelTabs/util/constants.tsx deleted file mode 100644 index 04e2b078..00000000 --- a/src/equicordplugins/channelTabs/util/constants.tsx +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { definePluginSettings } from "@api/Settings"; -import { Logger } from "@utils/Logger"; -import { OptionType } from "@utils/types"; -import { findComponentByCodeLazy } from "@webpack"; - -import { ChannelTabsPreview } from "../components/ChannelTabsContainer"; - -export const logger = new Logger("ChannelTabs"); - -export const bookmarkFolderColors = { - Red: "var(--channeltabs-red)", - Blue: "var(--channeltabs-blue)", - Yellow: "var(--channeltabs-yellow)", - Green: "var(--channeltabs-green)", - Black: "var(--channeltabs-black)", - White: "var(--channeltabs-white)", - Orange: "var(--channeltabs-orange)", - Pink: "var(--channeltabs-pink)" -} as const; - -export const settings = definePluginSettings({ - onStartup: { - type: OptionType.SELECT, - description: "On startup", - options: [{ - label: "Do nothing (open on the friends tab)", - value: "nothing", - default: true - }, { - label: "Remember tabs from last session", - value: "remember" - }, { - label: "Open on a specific set of tabs", - value: "preset" - }], - }, - tabSet: { - component: ChannelTabsPreview, - description: "Select which tabs to open at startup", - type: OptionType.COMPONENT, - default: {} - }, - noPomeloNames: { - description: "Use display names instead of usernames for DM's", - type: OptionType.BOOLEAN, - default: false - }, - showStatusIndicators: { - description: "Show status indicators for DM's", - type: OptionType.BOOLEAN, - default: true - }, - showBookmarkBar: { - description: "", - type: OptionType.BOOLEAN, - default: true - }, - bookmarkNotificationDot: { - description: "Show notification dot for bookmarks", - type: OptionType.BOOLEAN, - default: true - }, - widerTabsAndBookmarks: { - description: "Extend the length of tabs and bookmarks for larger monitors", - type: OptionType.BOOLEAN, - default: false, - restartNeeded: false - } -}); - -export const CircleQuestionIcon = findComponentByCodeLazy("10.58l-3.3-3.3a1"); diff --git a/src/equicordplugins/channelTabs/util/index.ts b/src/equicordplugins/channelTabs/util/index.ts deleted file mode 100644 index 3cfe7f44..00000000 --- a/src/equicordplugins/channelTabs/util/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -export * from "./bookmarks"; -export * from "./constants"; -export * from "./tabs"; -export * from "./types"; diff --git a/src/equicordplugins/channelTabs/util/tabs.tsx b/src/equicordplugins/channelTabs/util/tabs.tsx deleted file mode 100644 index 3deb257f..00000000 --- a/src/equicordplugins/channelTabs/util/tabs.tsx +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { DataStore } from "@api/index"; -import { classNameFactory } from "@api/Styles"; -import { NavigationRouter, SelectedChannelStore, SelectedGuildStore, showToast, Toasts, useState } from "@webpack/common"; -import { JSX } from "react"; - -import { logger, settings } from "./constants"; -import { BasicChannelTabsProps, ChannelTabsProps, PersistedTabs } from "./types"; - -const cl = classNameFactory("vc-channeltabs-"); - -function replaceArray(array: T[], ...values: T[]) { - const len = array.length; - for (let i = 0; i < len; i++) array.pop(); - array.push(...values); -} - -let highestIdIndex = 0; -const genId = () => highestIdIndex++; - -const openTabs: ChannelTabsProps[] = []; -const closedTabs: ChannelTabsProps[] = []; -let currentlyOpenTab: number; -const openTabHistory: number[] = []; -let persistedTabs: Promise; - -// horror -const _ = { - get openedTabs() { - return openTabs; - } -}; -export const { openedTabs } = _; - -let update = (save = true) => { - logger.warn("Update function not set"); -}; -let bumpGhostTabCount = () => { - logger.warn("Set ghost tab function not set"); -}; -let clearGhostTabs = () => { - logger.warn("Clear ghost tab function not set"); -}; - -export function createTab(props: BasicChannelTabsProps | ChannelTabsProps, switchToTab?: boolean, messageId?: string, save = true) { - const id = genId(); - openTabs.push({ ...props, id, messageId, compact: "compact" in props ? props.compact : false }); - if (switchToTab) moveToTab(id); - clearGhostTabs(); - update(save); -} - -export function closeTab(id: number) { - if (openTabs.length <= 1) return; - const i = openTabs.findIndex(v => v.id === id); - if (i === -1) return logger.error("Couldn't find channel tab with ID " + id, openTabs); - - const closed = openTabs.splice(i, 1); - closedTabs.push(...closed); - - if (id === currentlyOpenTab) { - if (openTabHistory.length) { - openTabHistory.pop(); - let newTab: ChannelTabsProps | undefined = undefined; - while (!newTab) { - const maybeNewTabId = openTabHistory.at(-1); - openTabHistory.pop(); - if (!maybeNewTabId) { - moveToTab(openTabs[Math.max(i - 1, 0)].id); - } - const maybeNewTab = openTabs.find(t => t.id === maybeNewTabId); - if (maybeNewTab) newTab = maybeNewTab; - } - - moveToTab(newTab.id); - openTabHistory.pop(); - } - else moveToTab(openTabs[Math.max(i - 1, 0)].id); - } - if (i !== openTabs.length) bumpGhostTabCount(); - else clearGhostTabs(); - update(); -} - -export function closeOtherTabs(id: number) { - const tab = openTabs.find(v => v.id === id); - if (tab === undefined) return logger.error("Couldn't find channel tab with ID " + id, openTabs); - - const removedTabs = openTabs.filter(v => v.id !== id); - closedTabs.push(...removedTabs.reverse()); - const lastTab = openTabs.find(v => v.id === currentlyOpenTab)!; - replaceArray(openTabs, tab); - setOpenTab(id); - replaceArray(openTabHistory, id); - - if (tab.channelId !== lastTab.channelId) moveToTab(id); - else update(); -} - -export function closeTabsToTheRight(id: number) { - const i = openTabs.findIndex(v => v.id === id); - if (i === -1) return logger.error("Couldn't find channel tab with ID " + id, openTabs); - - const tabsToTheRight = openTabs.filter((_, ind) => ind > i); - closedTabs.push(...tabsToTheRight.reverse()); - const tabsToTheLeft = openTabs.filter((_, ind) => ind <= i); - replaceArray(openTabs, ...tabsToTheLeft); - - if (!tabsToTheLeft.some(v => v.id === currentlyOpenTab)) moveToTab(openTabs.at(-1)!.id); - else update(); -} - -export function closeTabsToTheLeft(id: number) { - const i = openTabs.findIndex(v => v.id === id); - if (i === -1) return logger.error("Couldn't find channel tab with ID " + id, openTabs); - - const tabsToTheLeft = openTabs.filter((_, ind) => ind < i); - closedTabs.push(...tabsToTheLeft.reverse()); - const tabsToTheRight = openTabs.filter((_, ind) => ind >= i); - replaceArray(openTabs, ...tabsToTheRight); - - if (!tabsToTheRight.some(v => v.id === currentlyOpenTab)) moveToTab(openTabs[0].id); - else update(); -} - -export function handleChannelSwitch(ch: BasicChannelTabsProps) { - const tab = openTabs.find(c => c.id === currentlyOpenTab); - if (tab === undefined) return logger.error("Couldn't find the currently open channel " + currentlyOpenTab, openTabs); - - if (tab.channelId !== ch.channelId) openTabs[openTabs.indexOf(tab)] = { id: tab.id, compact: tab.compact, ...ch }; -} - -export function hasClosedTabs() { - return !!closedTabs.length; -} - -export function isTabSelected(id: number) { - return id === currentlyOpenTab; -} - -export function moveDraggedTabs(index1: number, index2: number) { - if (index1 < 0 || index2 > openTabs.length) - return logger.error(`Out of bounds drag (swap between indexes ${index1} and ${index2})`, openTabs); - - const firstItem = openTabs.splice(index1, 1)[0]; - openTabs.splice(index2, 0, firstItem); - update(); -} - -export function moveToTab(id: number) { - const tab = openTabs.find(v => v.id === id); - if (tab === undefined) return logger.error("Couldn't find channel tab with ID " + id, openTabs); - - setOpenTab(id); - if (tab.messageId) { - NavigationRouter.transitionTo(`/channels/${tab.guildId}/${tab.channelId}/${tab.messageId}`); - delete openTabs[openTabs.indexOf(tab)].messageId; - } - else if (tab.channelId !== SelectedChannelStore.getChannelId() || tab.guildId !== SelectedGuildStore.getGuildId()) - NavigationRouter.transitionToGuild(tab.guildId, tab.channelId); - else update(); -} - -export function openStartupTabs(props: BasicChannelTabsProps & { userId: string; }, setUserId: (id: string) => void) { - const { userId } = props; - persistedTabs ??= DataStore.get("ChannelTabs_openChannels_v2"); - replaceArray(openTabs); - replaceArray(openTabHistory); - highestIdIndex = 0; - - if (settings.store.onStartup !== "nothing" && Vencord.Plugins.isPluginEnabled("KeepCurrentChannel")) - return showToast("Not restoring tabs as KeepCurrentChannel is enabled", Toasts.Type.FAILURE); - - switch (settings.store.onStartup) { - case "remember": { - persistedTabs.then(tabs => { - const t = tabs?.[userId]; - if (!t) { - createTab({ channelId: props.channelId, guildId: props.guildId }, true); - return showToast("Failed to restore tabs", Toasts.Type.FAILURE); - } - replaceArray(openTabs); // empty the array - t.openTabs.forEach(tab => createTab(tab)); - currentlyOpenTab = openTabs[t.openTabIndex]?.id ?? 0; - - setUserId(userId); - moveToTab(currentlyOpenTab); - }); - break; - } - case "preset": { - const tabs = settings.store.tabSet?.[userId]; - if (!tabs) break; - tabs.forEach(t => createTab(t)); - setOpenTab(0); - setUserId(userId); - break; - } - default: { - setUserId(userId); - } - } - - if (!openTabs.length) createTab({ channelId: props.channelId, guildId: props.guildId }, true, undefined, false); - for (let i = 0; i < openTabHistory.length; i++) openTabHistory.pop(); - moveToTab(currentlyOpenTab); -} - -export function reopenClosedTab() { - if (!closedTabs.length) return; - const tab = closedTabs.pop()!; - createTab(tab, true); -} - -export const saveTabs = async (userId: string) => { - if (!userId) return; - - DataStore.update("ChannelTabs_openChannels_v2", old => { - return { - ...(old ?? {}), - [userId]: { openTabs, openTabIndex: openTabs.findIndex(t => t.id === currentlyOpenTab) } - }; - }); -}; - -export function setOpenTab(id: number) { - const i = openTabs.findIndex(v => v.id === id); - if (i === -1) return logger.error("Couldn't find channel tab with ID " + id, openTabs); - - currentlyOpenTab = id; - openTabHistory.push(id); -} - -export function setUpdaterFunction(fn: () => void) { - update = fn; -} - -export function switchChannel(ch: BasicChannelTabsProps) { - handleChannelSwitch(ch); - moveToTab(openTabs.find(t => t.id === currentlyOpenTab)!.id); -} - -export function toggleCompactTab(id: number) { - const i = openTabs.findIndex(v => v.id === id); - if (i === -1) return logger.error("Couldn't find channel tab with ID " + id, openTabs); - - openTabs[i] = { - ...openTabs[i], - compact: !openTabs[i].compact - }; - update(); -} - -export function useGhostTabs() { - let timeout; - const [count, setCount] = useState(0); - bumpGhostTabCount = () => { - setCount(count + 1); - clearTimeout(timeout); - timeout = setTimeout(() => { - setCount(0); - }, 3000); - }; - clearGhostTabs = () => { - clearTimeout(timeout); - setCount(0); - }; - return new Array(count).fill(
); -} diff --git a/src/equicordplugins/channelTabs/util/types.ts b/src/equicordplugins/channelTabs/util/types.ts deleted file mode 100644 index 01bc3a88..00000000 --- a/src/equicordplugins/channelTabs/util/types.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -export type BasicChannelTabsProps = { - guildId: string; - channelId: string; -}; -export interface ChannelTabsProps extends BasicChannelTabsProps { - compact: boolean; - messageId?: string; - id: number; -} -export interface PersistedTabs { - [userId: string]: { - openTabs: ChannelTabsProps[], - openTabIndex: number; - }; -} - -export interface Bookmark { - channelId: string; - guildId: string; - name: string; -} -export interface BookmarkFolder { - bookmarks: Bookmark[]; - name: string; - iconColor: string; -} -export interface BookmarkProps { - bookmarks: Bookmarks, - index: number, - methods: UseBookmarkMethods; -} -export type Bookmarks = (Bookmark | BookmarkFolder)[]; -export type UseBookmarkMethods = { - addBookmark: (bookmark: Omit & { name?: string; }, folderIndex?: number) => void; - addFolder: () => number; - deleteBookmark: (index: number, folderIndex?: number) => void; - editBookmark: (index: number, bookmark: Partial, modalKey?) => void; - moveDraggedBookmarks: (index1: number, index2: number) => void; -}; -export type UseBookmark = [Bookmarks | undefined, UseBookmarkMethods];