ServerDrawer: add DM tile to the drawer grid, with a settings screen
This commit is contained in:
parent
68e478d7ca
commit
8bbfd6d7a5
5 changed files with 113 additions and 0 deletions
45
plugins/server-drawer/src/components/DmTile.tsx
Normal file
45
plugins/server-drawer/src/components/DmTile.tsx
Normal file
|
|
@ -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 (
|
||||
<Pressable onPress={openDms} style={st.outer}>
|
||||
<View style={[st.icon, { backgroundColor: selected ? (colors?.BG_ACCENT ?? "#5865f2") : "rgba(128,128,128,0.24)" }]}>
|
||||
<Image source={ChatIcon} style={{ width: 24, height: 24, tintColor: "#fff" }} />
|
||||
</View>
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
|
||||
const st = StyleSheet.create({
|
||||
outer: { width: ICON, height: ICON },
|
||||
icon: { width: ICON, height: ICON, borderRadius: 16, alignItems: "center", justifyContent: "center" },
|
||||
});
|
||||
|
|
@ -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 && <DmTile />}
|
||||
{nodes.map((node) =>
|
||||
node.type === "folder"
|
||||
? <FolderItem key={node.id} node={node} onPick={pick} />
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
29
plugins/server-drawer/src/ui/NoteBox.tsx
Normal file
29
plugins/server-drawer/src/ui/NoteBox.tsx
Normal file
|
|
@ -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 (
|
||||
<View
|
||||
style={[
|
||||
{
|
||||
marginHorizontal: 16,
|
||||
marginVertical: 8,
|
||||
padding: 10,
|
||||
borderRadius: 8,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(128,128,128,0.25)"
|
||||
},
|
||||
style
|
||||
]}
|
||||
>
|
||||
<Text style={{ fontSize: 12.5, lineHeight: 18, opacity: 0.75, color: textColor }}>{children}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
28
plugins/server-drawer/src/ui/Settings.tsx
Normal file
28
plugins/server-drawer/src/ui/Settings.tsx
Normal file
|
|
@ -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 (
|
||||
<SettingsScaffold>
|
||||
<NoteBox>
|
||||
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.
|
||||
</NoteBox>
|
||||
<TableRowGroup title="Layout">
|
||||
<TableSwitchRow
|
||||
label="Hide the DMs tile"
|
||||
subLabel="Remove the DMs tile from the drawer entirely"
|
||||
value={!!storage.hideDmTile}
|
||||
onValueChange={(v: boolean) => { storage.hideDmTile = v; }}
|
||||
/>
|
||||
</TableRowGroup>
|
||||
</SettingsScaffold>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue