import { plugin } from "@vendetta";
import { storage } from "@vendetta/plugin";
import { useProxy } from "@vendetta/storage";
import { React, ReactNative as RN, stylesheet } from "@vendetta/metro/common";
import { findByProps } from "@vendetta/metro";
import { semanticColors } from "@vendetta/ui";
import { getAssetIDByName } from "@vendetta/ui/assets";
import { Forms } from "@vendetta/ui/components";
import { alerts } from "@vendetta/ui";
const { ScrollView } = findByProps("ScrollView");
const { TableRowGroup, TableSwitchRow, Stack, TableRow } = findByProps(
"TableSwitchRow",
"TableRowGroup",
"Stack",
"TableRow",
);
const { FormRow, FormSwitchRow } = Forms;
// Better Table Row Group Component (inspired by nexpid's styling)
function BetterTableRowGroup({
title,
icon,
children,
padding = false,
}: React.PropsWithChildren<{
title?: string;
icon?: number;
padding?: boolean;
}>) {
const styles = stylesheet.createThemedStyleSheet({
main: {
backgroundColor: semanticColors.CARD_PRIMARY_BG,
borderColor: semanticColors.BORDER_FAINT,
borderWidth: 1,
borderRadius: 16,
overflow: "hidden",
flex: 1,
},
titleContainer: {
marginBottom: 8,
marginHorizontal: 0,
marginTop: 8,
gap: 4,
flexDirection: "row",
alignItems: "center",
},
icon: {
width: 16,
height: 16,
marginTop: 1.5,
tintColor: semanticColors.TEXT_MUTED,
},
titleText: {
fontSize: 14,
fontWeight: "600",
color: semanticColors.TEXT_MUTED,
},
});
return (
{title && (
{icon && (
)}
{title.toUpperCase()}
)}
{padding ? (
{children}
) : children}
);
}
// Header Component
function Header() {
const styles = stylesheet.createThemedStyleSheet({
container: {
flexDirection: "column",
alignItems: "center",
paddingVertical: 24,
paddingHorizontal: 16,
},
title: {
fontSize: 28,
fontWeight: "700",
color: semanticColors.TEXT_NORMAL,
marginBottom: 4,
},
subtitle: {
fontSize: 16,
fontWeight: "500",
color: semanticColors.TEXT_MUTED,
},
iconContainer: {
backgroundColor: semanticColors.BACKGROUND_SECONDARY,
borderRadius: 16,
padding: 12,
marginBottom: 16,
},
icon: {
width: 32,
height: 32,
tintColor: semanticColors.TEXT_NORMAL,
},
});
return (
Commands
A collection of useful commands
);
}
// Initialize storage with default values
if (!storage.factSettings) {
storage.factSettings = {
sendAsReply: true,
includeCitation: false,
};
}
if (!storage.listSettings) {
storage.listSettings = {
pluginListAlwaysDetailed: false,
themeListAlwaysDetailed: false,
};
}
if (!storage.garySettings) {
storage.garySettings = {
imageSource: "gary",
};
}
if (!storage.enabledCommands) {
storage.enabledCommands = {
catfact: true,
dogfact: true,
useless: true,
petpet: true,
pluginList: true,
themeList: true,
konoself: true,
konosend: true,
firstmessage: true,
sysinfo: true,
spotifyTrack: true,
spotifyAlbum: true,
spotifyArtists: true,
spotifyCover: true,
gary: true,
};
}
if (!storage.pendingRestart) {
storage.pendingRestart = false;
}
export default function Settings() {
useProxy(storage);
const [rerender, forceRerender] = React.useReducer((x) => x + 1, 0);
const styles = stylesheet.createThemedStyleSheet({
container: {
flex: 1,
backgroundColor: semanticColors.BACKGROUND_PRIMARY,
},
spacing: {
height: 16,
},
});
// Check for pending restart when unmounting
React.useEffect(() => {
return () => {
if (storage.pendingRestart) {
storage.pendingRestart = false;
alerts.showConfirmationAlert({
title: "Restart Required",
content:
"You have made changes to commands. Please restart Discord to apply these changes.",
confirmText: "Okay",
cancelText: null,
});
}
};
}, []);
const handleCommandToggle = (commandName: string, value: boolean) => {
storage.enabledCommands[commandName] = value;
storage.pendingRestart = true;
forceRerender();
};
const showGarySourceSelection = () => {
alerts.showConfirmationAlert({
title: "Choose Gary Image Source",
content: "Select an image source for the Gary command:",
confirmText: "Gary API",
cancelText: "Other Options",
confirmColor: "brand",
onConfirm: () => {
storage.garySettings.imageSource = "gary";
forceRerender();
},
onCancel: () => {
alerts.showConfirmationAlert({
title: "Choose Image Source",
content: "Select from remaining options:",
confirmText: "Cat API",
cancelText: "More Options",
confirmColor: "brand",
onConfirm: () => {
storage.garySettings.imageSource = "catapi";
forceRerender();
},
onCancel: () => {
alerts.showConfirmationAlert({
title: "Choose Image Source",
content: "Select from final options:",
confirmText: "Minker API",
cancelText: "Goober API",
confirmColor: "brand",
onConfirm: () => {
storage.garySettings.imageSource = "minker";
forceRerender();
},
onCancel: () => {
storage.garySettings.imageSource = "goober";
forceRerender();
},
});
},
});
},
});
};
return (
{/* Facts Commands */}
}
value={storage.factSettings?.sendAsReply ?? true}
onValueChange={(v: boolean) => {
storage.factSettings.sendAsReply = v;
forceRerender();
}}
/>
}
value={storage.factSettings?.includeCitation ?? false}
onValueChange={(v: boolean) => {
storage.factSettings.includeCitation = v;
forceRerender();
}}
/>
}
value={storage.enabledCommands?.catfact ?? true}
onValueChange={(v) => handleCommandToggle("catfact", v)}
/>
}
value={storage.enabledCommands?.dogfact ?? true}
onValueChange={(v) => handleCommandToggle("dogfact", v)}
/>
}
value={storage.enabledCommands?.useless ?? true}
onValueChange={(v) => handleCommandToggle("useless", v)}
/>
{/* List Commands */}
}
value={storage.listSettings?.pluginListAlwaysDetailed ?? false}
onValueChange={(v: boolean) => {
storage.listSettings.pluginListAlwaysDetailed = v;
forceRerender();
}}
/>
}
value={storage.listSettings?.themeListAlwaysDetailed ?? false}
onValueChange={(v: boolean) => {
storage.listSettings.themeListAlwaysDetailed = v;
forceRerender();
}}
/>
}
value={storage.enabledCommands?.pluginList ?? true}
onValueChange={(v) => handleCommandToggle("pluginList", v)}
/>
}
value={storage.enabledCommands?.themeList ?? true}
onValueChange={(v) => handleCommandToggle("themeList", v)}
/>
{/* Image Commands */}
}
value={storage.enabledCommands?.petpet ?? true}
onValueChange={(v) => handleCommandToggle("petpet", v)}
/>
{/* Gary Commands */}
}
value={storage.enabledCommands?.gary ?? true}
onValueChange={(v) => handleCommandToggle("gary", v)}
/>
}
trailing={}
onPress={showGarySourceSelection}
/>
{/* KonoChan Commands */}
}
value={storage.enabledCommands?.konoself ?? true}
onValueChange={(v) => handleCommandToggle("konoself", v)}
/>
}
value={storage.enabledCommands?.konosend ?? true}
onValueChange={(v) => handleCommandToggle("konosend", v)}
/>
{/* Message Commands */}
}
value={storage.enabledCommands?.firstmessage ?? true}
onValueChange={(v) => handleCommandToggle("firstmessage", v)}
/>
{/* System Commands */}
}
value={storage.enabledCommands?.sysinfo ?? true}
onValueChange={(v) => handleCommandToggle("sysinfo", v)}
/>
{/* Spotify Commands */}
}
value={storage.enabledCommands?.spotifyTrack ?? true}
onValueChange={(v) => handleCommandToggle("spotifyTrack", v)}
/>
}
value={storage.enabledCommands?.spotifyAlbum ?? true}
onValueChange={(v) => handleCommandToggle("spotifyAlbum", v)}
/>
}
value={storage.enabledCommands?.spotifyArtists ?? true}
onValueChange={(v) => handleCommandToggle("spotifyArtists", v)}
/>
}
value={storage.enabledCommands?.spotifyCover ?? true}
onValueChange={(v) => handleCommandToggle("spotifyCover", v)}
/>
{/* Credits */}
Facts Commands by jdev082{'\n'}
List Commands by Kitomanari{'\n'}
PetPet Command by wolfieeee{'\n'}
KonoChan Commands by btmc727 & Rico040{'\n'}
FirstMessage Command by sapphire{'\n'}
Sysinfo Command by mugman{'\n'}
Spotify Commands by Kitomanari{'\n'}
Gary Command by Zach Orange
);
}