Refactor settings UI and improve long list handling
- Rewrite settings page using TableRowGroup and TableSwitchRow - Add commands overview and about sections to settings - Replace deprecated Forms components with updated UI components - Add dialogs for installing/enabling Split Large Messages plugin - Improve alerts for sending long plugin/theme lists
This commit is contained in:
parent
cd4d414a0c
commit
7c3a5bf31c
2 changed files with 170 additions and 73 deletions
|
|
@ -1,89 +1,153 @@
|
|||
import { ReactNative } from "@vendetta/metro/common";
|
||||
import { storage } from "@vendetta/plugin";
|
||||
import { useProxy } from "@vendetta/storage";
|
||||
import { plugin } from "@vendetta";
|
||||
import { getAssetIDByName } from "@vendetta/ui/assets";
|
||||
import { ErrorBoundary, Forms } from "@vendetta/ui/components";
|
||||
import { React } from "@vendetta/metro/common";
|
||||
import { findByProps } from "@vendetta/metro";
|
||||
|
||||
const { FormSwitchRow, FormIcon, FormSection, FormDivider } = Forms;
|
||||
const { ScrollView } = findByProps("ScrollView");
|
||||
const { TableRowGroup, TableSwitchRow, Stack } = findByProps(
|
||||
"TableSwitchRow",
|
||||
"TableRowGroup",
|
||||
"Stack",
|
||||
);
|
||||
|
||||
const Icons = {
|
||||
List: getAssetIDByName("ic_list"),
|
||||
Message: getAssetIDByName("ic_message"),
|
||||
Copy: getAssetIDByName("ic_copy_message_link"),
|
||||
Info: getAssetIDByName("ic_info"),
|
||||
Theme: getAssetIDByName("ic_theme"),
|
||||
Plugin: getAssetIDByName("ic_plugins"),
|
||||
};
|
||||
const get = (k: string, fallback: any = "") => plugin.storage[k] ?? fallback;
|
||||
const set = (k: string, v: any) => (plugin.storage[k] = v);
|
||||
|
||||
export default () => {
|
||||
useProxy(storage);
|
||||
|
||||
if (!storage.factSettings) {
|
||||
storage.factSettings = {
|
||||
sendAsReply: true,
|
||||
includeCitation: false,
|
||||
};
|
||||
}
|
||||
|
||||
if (!storage.listSettings) {
|
||||
storage.listSettings = {
|
||||
pluginListAlwaysDetailed: false,
|
||||
themeListAlwaysDetailed: false,
|
||||
};
|
||||
}
|
||||
export default function Settings() {
|
||||
const [_, forceUpdate] = React.useReducer((x) => ~x, 0);
|
||||
const update = () => forceUpdate();
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<ReactNative.ScrollView style={{ flex: 1 }}>
|
||||
{/* Fact Commands Settings */}
|
||||
<FormSection title="Fact Commands" titleStyleType="no_border">
|
||||
<FormSwitchRow
|
||||
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 10 }}>
|
||||
<Stack spacing={8}>
|
||||
{/* Facts Commands Settings */}
|
||||
<TableRowGroup title="Facts Settings">
|
||||
<TableSwitchRow
|
||||
label="Send as Reply"
|
||||
subLabel="Send facts as a reply to the command message"
|
||||
leading={<FormIcon source={Icons.Message} />}
|
||||
icon={getAssetIDByName("ic_reply_24px")}
|
||||
value={get("factSettings.sendAsReply", true)}
|
||||
onValueChange={(value: boolean) => {
|
||||
storage.factSettings.sendAsReply = value;
|
||||
set("factSettings", {
|
||||
...get("factSettings", {}),
|
||||
sendAsReply: value,
|
||||
});
|
||||
update();
|
||||
}}
|
||||
value={storage.factSettings.sendAsReply}
|
||||
/>
|
||||
<FormDivider />
|
||||
<FormSwitchRow
|
||||
<TableSwitchRow
|
||||
label="Include Source Citation"
|
||||
subLabel="Include the source of facts when available"
|
||||
leading={<FormIcon source={Icons.Info} />}
|
||||
icon={getAssetIDByName("ic_info")}
|
||||
value={get("factSettings.includeCitation", false)}
|
||||
onValueChange={(value: boolean) => {
|
||||
storage.factSettings.includeCitation = value;
|
||||
set("factSettings", {
|
||||
...get("factSettings", {}),
|
||||
includeCitation: value,
|
||||
});
|
||||
update();
|
||||
}}
|
||||
value={storage.factSettings.includeCitation}
|
||||
/>
|
||||
</FormSection>
|
||||
</TableRowGroup>
|
||||
|
||||
{/* Plugin List Settings */}
|
||||
<FormSection title="Plugin List" titleStyleType="no_border">
|
||||
<FormSwitchRow
|
||||
<TableRowGroup title="Plugin List Settings">
|
||||
<TableSwitchRow
|
||||
label="Always Send Detailed List"
|
||||
subLabel="Always use detailed mode when listing plugins"
|
||||
leading={<FormIcon source={Icons.Plugin} />}
|
||||
icon={getAssetIDByName("ic_message_copy")}
|
||||
value={get("listSettings.pluginListAlwaysDetailed", false)}
|
||||
onValueChange={(value: boolean) => {
|
||||
storage.listSettings.pluginListAlwaysDetailed = value;
|
||||
set("listSettings", {
|
||||
...get("listSettings", {}),
|
||||
pluginListAlwaysDetailed: value,
|
||||
});
|
||||
update();
|
||||
}}
|
||||
value={storage.listSettings.pluginListAlwaysDetailed}
|
||||
/>
|
||||
</FormSection>
|
||||
</TableRowGroup>
|
||||
|
||||
{/* Theme List Settings */}
|
||||
<FormSection title="Theme List" titleStyleType="no_border">
|
||||
<FormSwitchRow
|
||||
<TableRowGroup title="Theme List Settings">
|
||||
<TableSwitchRow
|
||||
label="Always Send Detailed List"
|
||||
subLabel="Always use detailed mode when listing themes"
|
||||
leading={<FormIcon source={Icons.Theme} />}
|
||||
icon={getAssetIDByName("ic_theme")}
|
||||
value={get("listSettings.themeListAlwaysDetailed", false)}
|
||||
onValueChange={(value: boolean) => {
|
||||
storage.listSettings.themeListAlwaysDetailed = value;
|
||||
set("listSettings", {
|
||||
...get("listSettings", {}),
|
||||
themeListAlwaysDetailed: value,
|
||||
});
|
||||
update();
|
||||
}}
|
||||
value={storage.listSettings.themeListAlwaysDetailed}
|
||||
/>
|
||||
</FormSection>
|
||||
</ReactNative.ScrollView>
|
||||
</ErrorBoundary>
|
||||
</TableRowGroup>
|
||||
|
||||
{/* Commands Overview */}
|
||||
<TableRowGroup title="Available Commands">
|
||||
<TableSwitchRow
|
||||
label="/catfact"
|
||||
subLabel="Get random cat facts"
|
||||
icon={getAssetIDByName("ic_info")}
|
||||
value={true}
|
||||
disabled={true}
|
||||
/>
|
||||
<TableSwitchRow
|
||||
label="/dogfact"
|
||||
subLabel="Get random dog facts"
|
||||
icon={getAssetIDByName("ic_info")}
|
||||
value={true}
|
||||
disabled={true}
|
||||
/>
|
||||
<TableSwitchRow
|
||||
label="/useless"
|
||||
subLabel="Get random useless facts"
|
||||
icon={getAssetIDByName("ic_info")}
|
||||
value={true}
|
||||
disabled={true}
|
||||
/>
|
||||
<TableSwitchRow
|
||||
label="/petpet"
|
||||
subLabel="Create pet-pet GIF of a user"
|
||||
icon={getAssetIDByName("ic_image")}
|
||||
value={true}
|
||||
disabled={true}
|
||||
/>
|
||||
<TableSwitchRow
|
||||
label="/plugin-list"
|
||||
subLabel="List all installed plugins"
|
||||
icon={getAssetIDByName("ic_plugins")}
|
||||
value={true}
|
||||
disabled={true}
|
||||
/>
|
||||
<TableSwitchRow
|
||||
label="/theme-list"
|
||||
subLabel="List all installed themes"
|
||||
icon={getAssetIDByName("ic_theme")}
|
||||
value={true}
|
||||
disabled={true}
|
||||
/>
|
||||
<TableSwitchRow
|
||||
label="/konoself, /konosend"
|
||||
subLabel="Get random images from KonoChan"
|
||||
icon={getAssetIDByName("ic_image")}
|
||||
value={true}
|
||||
disabled={true}
|
||||
/>
|
||||
</TableRowGroup>
|
||||
|
||||
{/* About Section */}
|
||||
<TableRowGroup title="About">
|
||||
<TableSwitchRow
|
||||
label="All-In-One Commands"
|
||||
subLabel="A collection of useful commands"
|
||||
icon={getAssetIDByName("ic_badge_staff")}
|
||||
value={true}
|
||||
disabled={true}
|
||||
/>
|
||||
</TableRowGroup>
|
||||
</Stack>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import { themes } from "@vendetta/themes";
|
|||
import { plugins } from "@vendetta/plugins";
|
||||
import { storage } from "@vendetta/plugin";
|
||||
import { alerts } from "@vendetta/ui";
|
||||
import { showAlert } from "../utils/messages";
|
||||
import { sendMessage } from "../utils/messages";
|
||||
import { openURL } from "@vendetta/metro/common";
|
||||
|
||||
const SPLIT_LARGE_MESSAGES_PLUGIN =
|
||||
"https://vd-plugins.github.io/proxy/actuallythesun.github.io/vendetta-plugins/SplitLargeMessages/";
|
||||
|
|
@ -30,6 +31,40 @@ const isSLMPluginEnabled = () =>
|
|||
Object.values(plugins).find((p) => p.id === SPLIT_LARGE_MESSAGES_PLUGIN)
|
||||
?.enabled ?? false;
|
||||
|
||||
const showSplitPluginDialog = () => {
|
||||
return alerts.showConfirmationAlert({
|
||||
title: "Large Message Warning",
|
||||
content:
|
||||
"This list is too long to send! Would you like to install the Split Large Messages plugin?",
|
||||
confirmText: "Install Plugin",
|
||||
cancelText: "Cancel",
|
||||
confirmColor: "brand",
|
||||
onConfirm: () => {
|
||||
openURL(SPLIT_LARGE_MESSAGES_PLUGIN);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const showEnablePluginDialog = () => {
|
||||
return alerts.showConfirmationAlert({
|
||||
title: "Plugin Disabled",
|
||||
content:
|
||||
"The Split Large Messages plugin is installed but disabled. Would you like to enable it now?",
|
||||
confirmText: "Enable Plugin",
|
||||
cancelText: "Cancel",
|
||||
confirmColor: "brand",
|
||||
onConfirm: () => {
|
||||
// Enable the plugin
|
||||
const slmPlugin = Object.values(plugins).find(
|
||||
(p) => p.id === SPLIT_LARGE_MESSAGES_PLUGIN,
|
||||
);
|
||||
if (slmPlugin) {
|
||||
slmPlugin.enabled = true;
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Command handlers
|
||||
async function handlePluginList(detailed: boolean, ctx: any) {
|
||||
const alwaysDetailed =
|
||||
|
|
@ -61,18 +96,17 @@ async function handlePluginList(detailed: boolean, ctx: any) {
|
|||
|
||||
if (getListLength(pluginList) > 2000) {
|
||||
if (!isSLMPluginInstalled()) {
|
||||
showAlert("List too long! Install Split Large Messages plugin");
|
||||
return { type: 4 };
|
||||
return showSplitPluginDialog();
|
||||
}
|
||||
if (!isSLMPluginEnabled()) {
|
||||
showAlert("Enable Split Large Messages plugin to send long lists!");
|
||||
return { type: 4 };
|
||||
return showEnablePluginDialog();
|
||||
}
|
||||
|
||||
return alerts.showConfirmationAlert({
|
||||
content: "Your list is over 2000 characters. Send anyway?",
|
||||
confirmText: "Yes",
|
||||
cancelText: "No",
|
||||
title: "Large Message",
|
||||
content: "This list is over 2000 characters. Send anyway?",
|
||||
confirmText: "Send",
|
||||
cancelText: "Cancel",
|
||||
onConfirm: () => sendMessage(ctx.channel.id, formatList(pluginList)),
|
||||
});
|
||||
}
|
||||
|
|
@ -114,18 +148,17 @@ async function handleThemeList(detailed: boolean, ctx: any) {
|
|||
|
||||
if (getListLength(themeList) > 2000) {
|
||||
if (!isSLMPluginInstalled()) {
|
||||
showAlert("List too long! Install Split Large Messages plugin");
|
||||
return { type: 4 };
|
||||
return showSplitPluginDialog();
|
||||
}
|
||||
if (!isSLMPluginEnabled()) {
|
||||
showAlert("Enable Split Large Messages plugin to send long lists!");
|
||||
return { type: 4 };
|
||||
return showEnablePluginDialog();
|
||||
}
|
||||
|
||||
return alerts.showConfirmationAlert({
|
||||
content: "Your list is over 2000 characters. Send anyway?",
|
||||
confirmText: "Yes",
|
||||
cancelText: "No",
|
||||
title: "Large Message",
|
||||
content: "This list is over 2000 characters. Send anyway?",
|
||||
confirmText: "Send",
|
||||
cancelText: "Cancel",
|
||||
onConfirm: () => sendMessage(ctx.channel.id, formatList(themeList)),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue