diff --git a/plugins/server-drawer/src/components/DmTile.tsx b/plugins/server-drawer/src/components/DmTile.tsx
new file mode 100644
index 0000000..e6a238e
--- /dev/null
+++ b/plugins/server-drawer/src/components/DmTile.tsx
@@ -0,0 +1,45 @@
+import React from "react";
+import { View, Pressable, Image, StyleSheet } from "react-native";
+import { getAssetIDByName } from "@vendetta/ui/assets";
+import { findByProps, findByName } from "@vendetta/metro";
+
+const ICON = 48;
+
+const ChatIcon = getAssetIDByName("ChatIcon");
+const Haptic = findByProps("triggerHapticFeedback", "HapticFeedbackTypes");
+const ChannelActions = findByProps("selectPrivateChannel");
+const SelectedChannelStore = findByName("SelectedChannelStore");
+const Flux = findByProps("useStateFromStores");
+const NavContext = findByProps("getGuildId");
+const colors = findByProps("colors", "unsafe_rawColors")?.colors;
+
+function openDms() {
+ Haptic?.triggerHapticFeedback?.(Haptic.HapticFeedbackTypes.SOFT);
+ if (ChannelActions?.selectPrivateChannel) {
+ const lastChannelId = SelectedChannelStore?.getLastSelectedChannelId?.();
+ ChannelActions.selectPrivateChannel(lastChannelId);
+ }
+}
+
+// Was previously only reachable via the native left server rail's own DM shortcut icon - moved
+// into the drawer's own grid instead, as the first tile, so DMs live in the same place as every
+// other server rather than in a spot that only exists on the rail this plugin otherwise hides.
+export default function DmTile() {
+ const selected = Flux?.useStateFromStores?.(
+ [NavContext],
+ () => NavContext?.getGuildId?.() == null,
+ ) ?? false;
+
+ return (
+
+
+
+
+
+ );
+}
+
+const st = StyleSheet.create({
+ outer: { width: ICON, height: ICON },
+ icon: { width: ICON, height: ICON, borderRadius: 16, alignItems: "center", justifyContent: "center" },
+});
diff --git a/plugins/server-drawer/src/components/ServerDrawerSheet.tsx b/plugins/server-drawer/src/components/ServerDrawerSheet.tsx
index ca07a14..5a4dbb6 100644
--- a/plugins/server-drawer/src/components/ServerDrawerSheet.tsx
+++ b/plugins/server-drawer/src/components/ServerDrawerSheet.tsx
@@ -1,9 +1,12 @@
import React from "react";
import { View, Text, Pressable, Animated, Dimensions, StyleSheet, BackHandler } from "react-native";
import { find, findByProps, findByStoreName } from "@vendetta/metro";
+import { storage } from "@vendetta/plugin";
+import { useProxy } from "@vendetta/storage";
import { GuildNode } from "../utils/theme";
import GuildItem from "./GuildItem";
import FolderItem from "./FolderItem";
+import DmTile from "./DmTile";
const Flux = findByProps("useStateFromStores");
const SortedGuildStore = findByStoreName("SortedGuildStore");
@@ -54,6 +57,8 @@ function CreateJoinButton() {
}
export default function ServerDrawerSheet({ gestureContext }: { gestureContext: any }) {
+ useProxy(storage);
+
const pick = React.useCallback((id: string) => {
Haptic?.triggerHapticFeedback(Haptic.HapticFeedbackTypes.SOFT);
if (Routing?.transitionToGuild) {
@@ -110,6 +115,7 @@ export default function ServerDrawerSheet({ gestureContext }: { gestureContext:
style={[st.grid, { paddingHorizontal: padX, gap: GAP }]}
onLayout={onLayout}
>
+ {!storage.hideDmTile && }
{nodes.map((node) =>
node.type === "folder"
?
diff --git a/plugins/server-drawer/src/index.tsx b/plugins/server-drawer/src/index.tsx
index d88cde9..e52ae20 100644
--- a/plugins/server-drawer/src/index.tsx
+++ b/plugins/server-drawer/src/index.tsx
@@ -5,12 +5,16 @@ import { patchGetQuestAsset } from "./patches/getQuestAsset";
import { patchExpanded, patchEmpty } from "./patches/contentPatch";
import { patchHideGuildsBar } from "./patches/hideGuildsBar";
import { patchCreateElement } from "./patches/createElementIntercept";
+import { storage } from "@vendetta/plugin";
+import Settings from "./ui/Settings";
const TAG = "[ServerDrawer]";
const cleanups: (() => void)[] = [];
export default {
onLoad() {
+ storage.hideDmTile ??= false;
+
console.log(TAG, "onLoad");
let patched = 0;
@@ -37,4 +41,5 @@ export default {
for (const fn of cleanups) fn();
cleanups.length = 0;
},
+ settings: Settings,
};
diff --git a/plugins/server-drawer/src/ui/NoteBox.tsx b/plugins/server-drawer/src/ui/NoteBox.tsx
new file mode 100644
index 0000000..50a5055
--- /dev/null
+++ b/plugins/server-drawer/src/ui/NoteBox.tsx
@@ -0,0 +1,29 @@
+import { React, ReactNative } from "@vendetta/metro/common";
+import { findByProps } from "@vendetta/metro";
+
+const { View, Text } = ReactNative;
+
+const colors = findByProps("colors", "unsafe_rawColors")?.colors;
+
+/** Small bordered callout for explanatory text in a settings screen. */
+export default function NoteBox({ children, style }: { children: any; style?: any }) {
+ const textColor = colors?.TEXT_MUTED ?? colors?.TEXT_NORMAL ?? "#96989d";
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/plugins/server-drawer/src/ui/Settings.tsx b/plugins/server-drawer/src/ui/Settings.tsx
new file mode 100644
index 0000000..8a3f50d
--- /dev/null
+++ b/plugins/server-drawer/src/ui/Settings.tsx
@@ -0,0 +1,28 @@
+import { React } from "@vendetta/metro/common";
+import { storage } from "@vendetta/plugin";
+import { useProxy } from "@vendetta/storage";
+import { TableRowGroup, TableSwitchRow } from "@shared/ui/table";
+import SettingsScaffold from "@shared/ui/SettingsScaffold";
+import NoteBox from "./NoteBox";
+
+export default function Settings() {
+ useProxy(storage);
+
+ return (
+
+
+ Server Drawer takes over the Quest Dock (the strip above the tab bar) to show your
+ servers as a grid instead - tap to expand, long-press a server for its usual context
+ menu, and the + button creates or joins a server through Discord's own modal.
+
+
+ { storage.hideDmTile = v; }}
+ />
+
+
+ );
+}