From 07b4c5a7427b87aa2111e5eb416178179340f82b Mon Sep 17 00:00:00 2001 From: kmmiio99o Date: Thu, 2 Oct 2025 14:43:06 +0200 Subject: [PATCH] Include new settings --- plugins/Commands/settings.tsx | 39 +- plugins/Commands/src/commands/konochan.ts | 1121 ++++++++++++++++++--- 2 files changed, 1038 insertions(+), 122 deletions(-) diff --git a/plugins/Commands/settings.tsx b/plugins/Commands/settings.tsx index 96b3c96..8aa40e9 100644 --- a/plugins/Commands/settings.tsx +++ b/plugins/Commands/settings.tsx @@ -47,10 +47,11 @@ storage.enabledCommands ??= { storage.pendingRestart ??= false; -// Hidden settings storage +// Hidden settings storage with NSFW bypass option storage.hiddenSettings ??= { enabled: false, visible: false, + konochanBypassNsfw: false, // New bypass option - disabled by default }; // Better Table Row Group Component @@ -206,7 +207,7 @@ function Header({ onHiddenUnlock }: { onHiddenUnlock?: () => void }) { ); } -// Hidden Commands Settings Page +// Hidden Commands Settings Page with NSFW bypass option function HiddenSettingsPage() { useProxy(storage); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); @@ -258,6 +259,35 @@ function HiddenSettingsPage() { /> + + } + value={storage.hiddenSettings.konochanBypassNsfw} + onValueChange={(v) => { + if (v) { + alerts.showConfirmationAlert({ + title: "⚠️ NSFW Bypass Warning", + content: "Enabling this allows NSFW content from KonoChan to be sent in any channel, including non-NSFW channels. This could violate server rules or Discord ToS. Use responsibly!", + confirmText: "I Understand", + cancelText: "Cancel", + onConfirm: () => { + storage.hiddenSettings.konochanBypassNsfw = true; + forceUpdate(); + }, + onCancel: () => { + // Do nothing - keep it disabled + }, + }); + } else { + storage.hiddenSettings.konochanBypassNsfw = false; + forceUpdate(); + } + }} + /> + + { storage.hiddenSettings.enabled = false; storage.hiddenSettings.visible = false; + storage.hiddenSettings.konochanBypassNsfw = false; // Reset bypass option storage.enabledCommands.lovefemboys = false; storage.pendingRestart = true; showToast("Hidden settings reset", getAssetIDByName("CheckmarkIcon")); @@ -587,7 +618,7 @@ function ImageSettingsPage() { ); } -// Spotify Settings Page - FIXED with proper text styling +// Spotify Settings Page function SpotifySettingsPage() { useProxy(storage); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); @@ -701,7 +732,7 @@ function OtherSettingsPage() { ); } -// Credits Page - UPDATED VERSION TO 1.0.1 +// Credits Page function CreditsPage() { const styles = stylesheet.createThemedStyleSheet({ container: { diff --git a/plugins/Commands/src/commands/konochan.ts b/plugins/Commands/src/commands/konochan.ts index 2e55204..8aa40e9 100644 --- a/plugins/Commands/src/commands/konochan.ts +++ b/plugins/Commands/src/commands/konochan.ts @@ -1,131 +1,1016 @@ -import { findByProps } from "@vendetta/metro"; +import { storage } from "@vendetta/plugin"; +import { useProxy } from "@vendetta/storage"; +import { React, ReactNative as RN, stylesheet } from "@vendetta/metro/common"; +import { NavigationNative } from "@vendetta/metro/common"; +import { semanticColors } from "@vendetta/ui"; +import { getAssetIDByName } from "@vendetta/ui/assets"; +import { Forms } from "@vendetta/ui/components"; import { alerts } from "@vendetta/ui"; +import { showToast } from "@vendetta/ui/toasts"; -const MessageActions = findByProps("sendMessage"); -const messageUtil = findByProps("sendBotMessage", "sendMessage", "receiveMessage"); +const { ScrollView } = RN; +const { FormRow, FormSwitchRow } = Forms; -/** - * Fetches a random image from KonoChan. - * @param isNSFW - Whether to include NSFW content. - * @returns The URL of the fetched image or null if none are found. - */ -const fetchImage = async (isNSFW: boolean): Promise => { - const baseURL = "https://konachan.com/post.json"; - const tag = isNSFW ? "rating:explicit" : "rating:safe"; - const randomPage = Math.floor(Math.random() * 100); - - try { - const response = await fetch(`${baseURL}?tags=${tag}&limit=1&page=${randomPage}`); - const data = await response.json(); - - if (!Array.isArray(data) || data.length === 0) { - return null; - } - - return data[0].file_url; - } catch (error) { - console.error("[KonoChan Randomizer] Error fetching image:", error); - return null; - } +// Initialize storage with default values +storage.factSettings ??= { + sendAsReply: true, + includeCitation: false, }; -const showNSFWWarning = () => { - return alerts.showConfirmationAlert({ - title: "NSFW Content Warning", - content: "NSFW content can only be sent in NSFW channels!", - confirmText: "Okay", - cancelText: null, - confirmColor: "brand", - isDismissable: true, +storage.listSettings ??= { + pluginListAlwaysDetailed: false, + themeListAlwaysDetailed: false, +}; + +storage.garySettings ??= { + imageSource: "gary", +}; + +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, + lovefemboys: false, // Hidden command - disabled by default +}; + +storage.pendingRestart ??= false; + +// Hidden settings storage with NSFW bypass option +storage.hiddenSettings ??= { + enabled: false, + visible: false, + konochanBypassNsfw: false, // New bypass option - disabled by default +}; + +// Better Table Row Group Component +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, + }, }); -}; -// Common options for both commands -const nsfwOption = { - name: "nsfw", - description: "Include NSFW content?", - type: 5, - required: false, - displayName: "nsfw", - displayDescription: "Include NSFW content?", -}; + return ( + + {title && ( + + {icon && ( + + )} + + {title.toUpperCase()} + + + )} + + {padding ? ( + + {children} + + ) : children} + + + ); +} -export const konoSelfCommand = { - name: "konoself", - displayName: "konoself", - description: "Fetch a random image from KonoChan for yourself.", - displayDescription: "Fetch a random image from KonoChan for yourself.", - options: [nsfwOption], - execute: async (args: any, ctx: any) => { - try { - const options = new Map(args.map((option: any) => [option.name, option])); - const isNSFW = options.get("nsfw")?.value || false; +// Header Component with secret unlock +function Header({ onHiddenUnlock }: { onHiddenUnlock?: () => void }) { + const [clickCounter, setClickCounter] = React.useState(0); + const [clickTimeout, setClickTimeout] = React.useState(null); + + 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, + }, + }); - // Check if channel is NSFW for NSFW content - if (isNSFW && !ctx.channel.nsfw) { - showNSFWWarning(); - return { type: 4 }; - } - - const imageUrl = await fetchImage(isNSFW); - - if (!imageUrl) { - // Silent fail - no error message - return { type: 4 }; - } - - messageUtil.sendBotMessage( - ctx.channel.id, - `Here's your random image: ${imageUrl}`, + const handleIconPress = () => { + if (storage.hiddenSettings.enabled) { + storage.hiddenSettings.visible = !storage.hiddenSettings.visible; + showToast( + `Hidden settings ${storage.hiddenSettings.visible ? "visible" : "hidden"}`, + getAssetIDByName("SettingsIcon") ); - return { type: 4 }; - } catch (error) { - console.error('[KonoSelf] Error:', error); - // Silent fail - no error message in chat - return { type: 4 }; + onHiddenUnlock?.(); + return; } - }, - applicationId: "-1", - inputType: 1, - type: 1, -}; -export const konoSendCommand = { - name: "konosend", - displayName: "konosend", - description: "Fetch a random image from KonoChan and send it to the channel.", - displayDescription: "Fetch a random image from KonoChan and send it to the channel.", - options: [nsfwOption], - execute: async (args: any, ctx: any) => { - try { - const options = new Map(args.map((option: any) => [option.name, option])); - const isNSFW = options.get("nsfw")?.value || false; - - // Check if channel is NSFW for NSFW content - if (isNSFW && !ctx.channel.nsfw) { - showNSFWWarning(); - return { type: 4 }; - } - - const imageUrl = await fetchImage(isNSFW); - - if (!imageUrl) { - // Silent fail - no error message - return { type: 4 }; - } - - const fixNonce = Date.now().toString(); - MessageActions.sendMessage(ctx.channel.id, { content: imageUrl }, void 0, { - nonce: fixNonce, - }); - return { type: 4 }; - } catch (error) { - console.error('[KonoSend] Error:', error); - // Silent fail - no error message in chat - return { type: 4 }; + if (clickTimeout) { + clearTimeout(clickTimeout); } - }, - applicationId: "-1", - inputType: 1, - type: 1, -}; + + const newTimeout = setTimeout(() => { + setClickCounter(0); + }, 1000); + setClickTimeout(newTimeout); + + const newCounter = clickCounter + 1; + setClickCounter(newCounter); + + if (newCounter < 10) { + return; + } + + showToast("🔓 Hidden settings unlocked!", getAssetIDByName("CheckmarkIcon")); + storage.hiddenSettings.enabled = true; + storage.hiddenSettings.visible = true; + setClickCounter(0); + + onHiddenUnlock?.(); + }; + + return ( + + + + + Commands + A collection of useful commands + + ); +} + +// Hidden Commands Settings Page with NSFW bypass option +function HiddenSettingsPage() { + useProxy(storage); + const [, forceUpdate] = React.useReducer((x) => x + 1, 0); + + const styles = stylesheet.createThemedStyleSheet({ + container: { + flex: 1, + backgroundColor: semanticColors.BACKGROUND_PRIMARY, + }, + warningText: { + fontSize: 14, + color: semanticColors.TEXT_DANGER, + textAlign: "center", + lineHeight: 20, + fontWeight: "600", + }, + infoText: { + fontSize: 14, + color: semanticColors.TEXT_MUTED, + textAlign: "center", + lineHeight: 20, + marginTop: 8, + }, + }); + + return ( + + + + + These are hidden commands that may contain mature content or experimental features. + + + Use at your own discretion. Commands in this section are disabled by default. + + + + + } + value={storage.enabledCommands.lovefemboys} + onValueChange={(v) => { + storage.enabledCommands.lovefemboys = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + + + + } + value={storage.hiddenSettings.konochanBypassNsfw} + onValueChange={(v) => { + if (v) { + alerts.showConfirmationAlert({ + title: "⚠️ NSFW Bypass Warning", + content: "Enabling this allows NSFW content from KonoChan to be sent in any channel, including non-NSFW channels. This could violate server rules or Discord ToS. Use responsibly!", + confirmText: "I Understand", + cancelText: "Cancel", + onConfirm: () => { + storage.hiddenSettings.konochanBypassNsfw = true; + forceUpdate(); + }, + onCancel: () => { + // Do nothing - keep it disabled + }, + }); + } else { + storage.hiddenSettings.konochanBypassNsfw = false; + forceUpdate(); + } + }} + /> + + + + } + value={storage.hiddenSettings.visible} + onValueChange={(v) => { + storage.hiddenSettings.visible = v; + }} + /> + } + onPress={() => { + alerts.showConfirmationAlert({ + title: "Reset Hidden Settings", + content: "This will hide the hidden settings section and disable all hidden commands. Are you sure?", + confirmText: "Reset", + onConfirm: () => { + storage.hiddenSettings.enabled = false; + storage.hiddenSettings.visible = false; + storage.hiddenSettings.konochanBypassNsfw = false; // Reset bypass option + storage.enabledCommands.lovefemboys = false; + storage.pendingRestart = true; + showToast("Hidden settings reset", getAssetIDByName("CheckmarkIcon")); + }, + cancelText: "Cancel", + }); + }} + /> + + + + ); +} + +// Facts Commands Settings Page +function FactsSettingsPage() { + useProxy(storage); + const [, forceUpdate] = React.useReducer((x) => x + 1, 0); + + return ( + + + + } + value={storage.factSettings.sendAsReply} + onValueChange={(v) => { + storage.factSettings.sendAsReply = v; + }} + /> + } + value={storage.factSettings.includeCitation} + onValueChange={(v) => { + storage.factSettings.includeCitation = v; + }} + /> + + + + } + value={storage.enabledCommands.catfact} + onValueChange={(v) => { + storage.enabledCommands.catfact = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + } + value={storage.enabledCommands.dogfact} + onValueChange={(v) => { + storage.enabledCommands.dogfact = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + } + value={storage.enabledCommands.useless} + onValueChange={(v) => { + storage.enabledCommands.useless = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + + + + ); +} + +// Gary API Settings Page +function GaryAPIPage() { + useProxy(storage); + const [, forceUpdate] = React.useReducer((x) => x + 1, 0); + + const styles = stylesheet.createThemedStyleSheet({ + container: { + flex: 1, + backgroundColor: semanticColors.BACKGROUND_PRIMARY, + }, + infoText: { + fontSize: 14, + color: semanticColors.TEXT_MUTED, + marginBottom: 16, + textAlign: "center", + }, + currentText: { + fontSize: 14, + color: semanticColors.TEXT_NORMAL, + textAlign: "center", + fontWeight: "600", + }, + }); + + const currentSource = storage.garySettings.imageSource; + + return ( + + + + } + value={storage.enabledCommands.gary} + onValueChange={(v) => { + storage.enabledCommands.gary = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + + + + + Choose which API the /gary command should use to fetch images. + + + + + } + value={currentSource === "gary"} + onValueChange={(v) => { + if (v) { + storage.garySettings.imageSource = "gary"; + forceUpdate(); + } + }} + /> + } + value={currentSource === "catapi"} + onValueChange={(v) => { + if (v) { + storage.garySettings.imageSource = "catapi"; + forceUpdate(); + } + }} + /> + } + value={currentSource === "minker"} + onValueChange={(v) => { + if (v) { + storage.garySettings.imageSource = "minker"; + forceUpdate(); + } + }} + /> + } + value={currentSource === "goober"} + onValueChange={(v) => { + if (v) { + storage.garySettings.imageSource = "goober"; + forceUpdate(); + } + }} + /> + + + + + Currently using: { + currentSource === "gary" ? "Gary API" : + currentSource === "catapi" ? "Cat API" : + currentSource === "minker" ? "Minker API" : + currentSource === "goober" ? "Goober API" : "Gary API" + } + + + + + ); +} + +// List Settings Page +function ListSettingsPage() { + useProxy(storage); + const [, forceUpdate] = React.useReducer((x) => x + 1, 0); + + return ( + + + + } + value={storage.listSettings.pluginListAlwaysDetailed} + onValueChange={(v) => { + storage.listSettings.pluginListAlwaysDetailed = v; + }} + /> + } + value={storage.listSettings.themeListAlwaysDetailed} + onValueChange={(v) => { + storage.listSettings.themeListAlwaysDetailed = v; + }} + /> + + + + } + value={storage.enabledCommands.pluginList} + onValueChange={(v) => { + storage.enabledCommands.pluginList = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + } + value={storage.enabledCommands.themeList} + onValueChange={(v) => { + storage.enabledCommands.themeList = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + + + + ); +} + +// Image Settings Page +function ImageSettingsPage() { + useProxy(storage); + const [, forceUpdate] = React.useReducer((x) => x + 1, 0); + + return ( + + + + } + value={storage.enabledCommands.petpet} + onValueChange={(v) => { + storage.enabledCommands.petpet = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + + + + } + value={storage.enabledCommands.konoself} + onValueChange={(v) => { + storage.enabledCommands.konoself = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + } + value={storage.enabledCommands.konosend} + onValueChange={(v) => { + storage.enabledCommands.konosend = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + + + + ); +} + +// Spotify Settings Page +function SpotifySettingsPage() { + useProxy(storage); + const [, forceUpdate] = React.useReducer((x) => x + 1, 0); + + const styles = stylesheet.createThemedStyleSheet({ + infoText: { + fontSize: 14, + color: semanticColors.TEXT_MUTED, + textAlign: "center", + lineHeight: 20, + }, + }); + + return ( + + + + } + value={storage.enabledCommands.spotifyTrack} + onValueChange={(v) => { + storage.enabledCommands.spotifyTrack = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + } + value={storage.enabledCommands.spotifyAlbum} + onValueChange={(v) => { + storage.enabledCommands.spotifyAlbum = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + } + value={storage.enabledCommands.spotifyArtists} + onValueChange={(v) => { + storage.enabledCommands.spotifyArtists = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + } + value={storage.enabledCommands.spotifyCover} + onValueChange={(v) => { + storage.enabledCommands.spotifyCover = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + + + + + These commands allow you to share your current Spotify activity in Discord. Make sure you have Spotify connected to Discord for these commands to work properly. + + + + + ); +} + +// Other Settings Page +function OtherSettingsPage() { + useProxy(storage); + const [, forceUpdate] = React.useReducer((x) => x + 1, 0); + + return ( + + + + } + value={storage.enabledCommands.firstmessage} + onValueChange={(v) => { + storage.enabledCommands.firstmessage = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + + + + } + value={storage.enabledCommands.sysinfo} + onValueChange={(v) => { + storage.enabledCommands.sysinfo = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + + + + ); +} + +// Credits Page +function CreditsPage() { + const styles = stylesheet.createThemedStyleSheet({ + container: { + flex: 1, + backgroundColor: semanticColors.BACKGROUND_PRIMARY, + }, + creditItem: { + flexDirection: "row", + alignItems: "center", + paddingVertical: 16, + paddingHorizontal: 20, + backgroundColor: semanticColors.CARD_PRIMARY_BG, + borderRadius: 12, + marginHorizontal: 16, + marginVertical: 6, + shadowColor: semanticColors.BLACK, + shadowOffset: { width: 0, height: 1 }, + shadowOpacity: 0.1, + shadowRadius: 2, + elevation: 2, + }, + avatar: { + width: 48, + height: 48, + borderRadius: 24, + marginRight: 16, + backgroundColor: semanticColors.BACKGROUND_SECONDARY, + }, + textContainer: { + flex: 1, + }, + commandText: { + fontSize: 17, + fontWeight: "600", + color: semanticColors.TEXT_NORMAL, + marginBottom: 4, + }, + authorText: { + fontSize: 15, + color: semanticColors.TEXT_MUTED, + marginBottom: 2, + }, + linkText: { + fontSize: 13, + color: semanticColors.TEXT_BRAND, + fontWeight: "500", + }, + infoText: { + fontSize: 14, + color: semanticColors.TEXT_MUTED, + marginBottom: 20, + textAlign: "center", + lineHeight: 20, + }, + versionText: { + fontSize: 15, + color: semanticColors.TEXT_NORMAL, + textAlign: "center", + fontWeight: "600", + lineHeight: 22, + }, + }); + + const credits = [ + { + command: "Facts Commands", + author: "jdev082", + avatar: "https://github.com/jdev082.png", + github: "https://github.com/jdev082" + }, + { + command: "List Commands", + author: "Kitomanari", + avatar: "https://github.com/Kitosight.png", + github: "https://github.com/Kitosight" + }, + { + command: "PetPet", + author: "wolfieeee", + avatar: "https://github.com/WolfPlugs.png", + github: "https://github.com/WolfPlugs" + }, + { + command: "KonoChan Commands", + author: "btmc727 & Rico040", + avatar: "https://github.com/OTKUSteyler.png", + github: "https://github.com/OTKUSteyler" + }, + { + command: "FirstMessage Command", + author: "sapphire", + avatar: "https://github.com/aeongdesu.png", + github: "https://github.com/aeongdesu" + }, + { + command: "Sysinfo Command", + author: "mugman", + avatar: "https://github.com/mugman174.png", + github: "https://github.com/mugman174" + }, + { + command: "Spotify Commands", + author: "Kitomanari", + avatar: "https://github.com/Kitosight.png", + github: "https://github.com/Kitosight" + }, + { + command: "Gary Command", + author: "Zach Orange", + avatar: "https://github.com/Zach11111.png", + github: "https://github.com/Zach11111" + }, + ]; + + const handleProfilePress = (githubUrl: string) => { + RN.Linking.openURL(githubUrl); + }; + + return ( + + + + + Thanks to this developers for creating such a nice plugins!{'\n'} + Tap on any developer to visit their GitHub profile. + + + + {credits.map((credit, index) => ( + handleProfilePress(credit.github)} + android_ripple={{ color: semanticColors.ANDROID_RIPPLE, radius: 200 }} + > + + + {credit.command} + by {credit.author} + {credit.github.replace('https://github.com/', '@')} + + + ))} + + + + Commands Plugin Collection{'\n'} + Version 1.0.1 + + + + + ); +} + +// MAIN SETTINGS COMPONENT +export default function Settings() { + useProxy(storage); + const navigation = NavigationNative.useNavigation(); + const [, forceUpdate] = React.useReducer((x) => x + 1, 0); + + 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, + }); + } + }; + }, []); + + return ( + +
+ + + } + trailing={} + onPress={() => navigation.push("VendettaCustomPage", { + title: "Facts Commands", + render: FactsSettingsPage, + })} + /> + } + trailing={} + onPress={() => navigation.push("VendettaCustomPage", { + title: "List Commands", + render: ListSettingsPage, + })} + /> + } + trailing={} + onPress={() => navigation.push("VendettaCustomPage", { + title: "Image Commands", + render: ImageSettingsPage, + })} + /> + } + trailing={} + onPress={() => navigation.push("VendettaCustomPage", { + title: "Gary Commands", + render: GaryAPIPage, + })} + /> + } + trailing={} + onPress={() => navigation.push("VendettaCustomPage", { + title: "Spotify Commands", + render: SpotifySettingsPage, + })} + /> + } + trailing={} + onPress={() => navigation.push("VendettaCustomPage", { + title: "Other Commands", + render: OtherSettingsPage, + })} + /> + + + {storage.hiddenSettings?.enabled && storage.hiddenSettings?.visible && ( + + } + trailing={} + onPress={() => navigation.push("VendettaCustomPage", { + title: "Hidden Settings", + render: HiddenSettingsPage, + })} + /> + + )} + + + } + trailing={} + onPress={() => navigation.push("VendettaCustomPage", { + title: "Credits", + render: CreditsPage, + })} + /> + + + + + ); +}