[UI] Overall overhaul
This commit is contained in:
parent
474aad2a47
commit
32b3a0295c
9 changed files with 81 additions and 78 deletions
38
src/ui/settings/components/AddonPage.tsx
Normal file
38
src/ui/settings/components/AddonPage.tsx
Normal file
|
@ -0,0 +1,38 @@
|
|||
import { Indexable } from "@types";
|
||||
import { ReactNative as RN } from "@metro/common";
|
||||
import { useProxy } from "@lib/storage";
|
||||
import { HelpMessage, ErrorBoundary, Search } from "@ui/components";
|
||||
import { CardWrapper } from "@ui/settings/components/Card";
|
||||
import settings from "@lib/settings";
|
||||
|
||||
interface AddonPageProps<T> {
|
||||
items: Indexable<T & { id: string }>;
|
||||
safeModeMessage: string;
|
||||
safeModeExtras?: JSX.Element | JSX.Element[];
|
||||
card: React.ComponentType<CardWrapper<T>>;
|
||||
}
|
||||
|
||||
export default function AddonPage<T>({ items, safeModeMessage, safeModeExtras, card: CardComponent }: AddonPageProps<T>) {
|
||||
useProxy(settings)
|
||||
useProxy(items);
|
||||
const [search, setSearch] = React.useState("");
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<RN.ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 10 }}>
|
||||
{settings.safeMode?.enabled && <RN.View style={{ marginBottom: 10 }}>
|
||||
<HelpMessage messageType={0}>{safeModeMessage}</HelpMessage>
|
||||
{safeModeExtras}
|
||||
</RN.View>}
|
||||
<Search
|
||||
style={{ marginBottom: 10 }}
|
||||
onChangeText={(v: string) => setSearch(v.toLowerCase())}
|
||||
placeholder="Search"
|
||||
/>
|
||||
{/* TODO: When I am more awake, implement better searching than just by ID */}
|
||||
{/* TODO: Also when I am more awake, make the search bar not scroll with the cards */}
|
||||
{Object.values(items).filter(i => i.id?.toLowerCase().includes(search)).map((i, id) => <CardComponent item={i} index={id} />)}
|
||||
</RN.ScrollView>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { Asset } from "@types";
|
||||
import { ReactNative as RN, stylesheet, clipboard } from "@metro/common";
|
||||
import { ReactNative as RN, clipboard } from "@metro/common";
|
||||
import { showToast } from "@ui/toasts";
|
||||
import { getAssetIDByName } from "@ui/assets";
|
||||
import { Forms } from "@ui/components";
|
||||
|
@ -10,18 +10,11 @@ interface AssetDisplayProps {
|
|||
|
||||
const { FormRow } = Forms;
|
||||
|
||||
const styles = stylesheet.createThemedStyleSheet({
|
||||
asset: {
|
||||
width: 32,
|
||||
height: 32,
|
||||
}
|
||||
});
|
||||
|
||||
export default function AssetDisplay({ asset }: AssetDisplayProps) {
|
||||
return (
|
||||
<FormRow
|
||||
label={`${asset.name} - ${asset.id}`}
|
||||
trailing={<RN.Image source={asset.id} style={styles.asset} />}
|
||||
trailing={<RN.Image source={asset.id} style={{ width: 32, height: 32 }} />}
|
||||
onPress={() => {
|
||||
clipboard.setString(asset.name);
|
||||
showToast("Copied asset name to clipboard.", getAssetIDByName("toast_copy_link"));
|
||||
|
|
|
@ -13,8 +13,6 @@ const styles = stylesheet.createThemedStyleSheet({
|
|||
card: {
|
||||
backgroundColor: semanticColors?.BACKGROUND_SECONDARY,
|
||||
borderRadius: 5,
|
||||
marginHorizontal: 10,
|
||||
marginBottom: 10,
|
||||
},
|
||||
header: {
|
||||
padding: 0,
|
||||
|
@ -44,6 +42,11 @@ interface OverflowAction extends Action {
|
|||
isDestructive?: boolean;
|
||||
}
|
||||
|
||||
export interface CardWrapper<T> {
|
||||
item: T;
|
||||
index: number;
|
||||
}
|
||||
|
||||
interface CardProps {
|
||||
index?: number;
|
||||
headerLabel: string | React.ComponentType;
|
||||
|
@ -61,7 +64,7 @@ export default function Card(props: CardProps) {
|
|||
let pressableState = props.toggleValue ?? false;
|
||||
|
||||
return (
|
||||
<RN.View style={[styles.card, { marginTop: props.index === 0 ? 10 : 0 }]}>
|
||||
<RN.View style={[styles.card, { marginTop: props.index !== 0 ? 10 : 0 }]}>
|
||||
<FormRow
|
||||
style={styles.header}
|
||||
label={props.headerLabel}
|
||||
|
|
|
@ -5,20 +5,15 @@ import { getAssetIDByName } from "@ui/assets";
|
|||
import { showToast } from "@ui/toasts";
|
||||
import { showConfirmationAlert } from "@ui/alerts";
|
||||
import { removePlugin, startPlugin, stopPlugin, getSettings, fetchPlugin } from "@lib/plugins";
|
||||
import Card from "@ui/settings/components/Card";
|
||||
import Card, { CardWrapper } from "@ui/settings/components/Card";
|
||||
|
||||
interface PluginCardProps {
|
||||
plugin: Plugin;
|
||||
index: number;
|
||||
}
|
||||
|
||||
async function stopThenStart(plugin: Plugin, func: Function) {
|
||||
async function stopThenStart(plugin: Plugin, callback: Function) {
|
||||
if (plugin.enabled) stopPlugin(plugin.id, false);
|
||||
func();
|
||||
callback();
|
||||
if (plugin.enabled) await startPlugin(plugin.id);
|
||||
}
|
||||
|
||||
export default function PluginCard({ plugin, index }: PluginCardProps) {
|
||||
export default function PluginCard({ item: plugin, index }: CardWrapper<Plugin>) {
|
||||
const settings = getSettings(plugin.id);
|
||||
const navigation = NavigationNative.useNavigation();
|
||||
const [removed, setRemoved] = React.useState(false);
|
||||
|
|
|
@ -12,7 +12,7 @@ export default function SettingsSection() {
|
|||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<FormSection key="Vendetta" title="Vendetta">
|
||||
<FormSection key="Vendetta" title={`Vendetta${settings.safeMode?.enabled ? " (Safe Mode)" : ""}`}>
|
||||
<FormRow
|
||||
label="General"
|
||||
leading={<FormRow.Icon source={getAssetIDByName("settings")} />}
|
||||
|
|
|
@ -7,19 +7,14 @@ import { getAssetIDByName } from "@ui/assets";
|
|||
import { showConfirmationAlert } from "@ui/alerts";
|
||||
import { showToast } from "@ui/toasts";
|
||||
import settings from "@lib/settings";
|
||||
import Card from "@ui/settings/components/Card";
|
||||
|
||||
interface ThemeCardProps {
|
||||
theme: Theme;
|
||||
index: number;
|
||||
}
|
||||
import Card, { CardWrapper } from "@ui/settings/components/Card";
|
||||
|
||||
async function selectAndReload(value: boolean, id: string) {
|
||||
await selectTheme(value ? id : "default");
|
||||
BundleUpdaterManager.reload();
|
||||
}
|
||||
|
||||
export default function ThemeCard({ theme, index }: ThemeCardProps) {
|
||||
export default function ThemeCard({ item: theme, index }: CardWrapper<Theme>) {
|
||||
useProxy(settings);
|
||||
const [removed, setRemoved] = React.useState(false);
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import AssetDisplay from "@ui/settings/components/AssetDisplay";
|
|||
|
||||
const { FormDivider } = Forms;
|
||||
|
||||
|
||||
export default function AssetBrowser() {
|
||||
const [search, setSearch] = React.useState("");
|
||||
|
||||
|
@ -14,17 +13,14 @@ export default function AssetBrowser() {
|
|||
<ErrorBoundary>
|
||||
<RN.View style={{ flex: 1 }}>
|
||||
<Search
|
||||
style={{ margin: 10 }}
|
||||
onChangeText={(v: string) => setSearch(v)}
|
||||
placeholder="Search"
|
||||
/>
|
||||
<RN.FlatList
|
||||
data={Object.values(all).filter(a => a.name.includes(search) || a.id.toString() === search)}
|
||||
renderItem={({ item }) => (
|
||||
<>
|
||||
<AssetDisplay asset={item} />
|
||||
<FormDivider />
|
||||
</>
|
||||
)}
|
||||
renderItem={({ item }) => <AssetDisplay asset={item} />}
|
||||
ItemSeparatorComponent={FormDivider}
|
||||
keyExtractor={item => item.name}
|
||||
/>
|
||||
</RN.View>
|
||||
|
|
|
@ -1,27 +1,18 @@
|
|||
import { ReactNative as RN } from "@metro/common";
|
||||
import { Plugin } from "@types";
|
||||
import { useProxy } from "@lib/storage";
|
||||
import { plugins } from "@lib/plugins";
|
||||
import { HelpMessage } from "@ui/components";
|
||||
import settings from "@lib/settings";
|
||||
import AddonPage from "@ui/settings/components/AddonPage";
|
||||
import PluginCard from "@ui/settings/components/PluginCard";
|
||||
import ErrorBoundary from "@ui/components/ErrorBoundary";
|
||||
|
||||
export default function Plugins() {
|
||||
useProxy(settings)
|
||||
useProxy(plugins);
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<RN.View style={{ flex: 1 }}>
|
||||
{settings.safeMode?.enabled && <RN.View style={{ margin: 10 }}>
|
||||
<HelpMessage messageType={0}>You are in Safe Mode, so plugins cannot be loaded. Disable any misbehaving plugins, then return to Normal Mode from the General settings page. </HelpMessage>
|
||||
</RN.View>}
|
||||
<RN.FlatList
|
||||
data={Object.values(plugins)}
|
||||
renderItem={({ item, index }) => <PluginCard plugin={item} index={index} />}
|
||||
keyExtractor={item => item.id}
|
||||
/>
|
||||
</RN.View>
|
||||
</ErrorBoundary>
|
||||
<AddonPage<Plugin>
|
||||
items={plugins}
|
||||
safeModeMessage="You are in Safe Mode, so plugins cannot be loaded. Disable any misbehaving plugins, then return to Normal Mode from the General settings page."
|
||||
card={PluginCard}
|
||||
/>
|
||||
)
|
||||
}
|
|
@ -1,36 +1,28 @@
|
|||
import { ButtonColors } from "@types";
|
||||
import { ReactNative as RN } from "@metro/common";
|
||||
import { themes } from "@lib/themes";
|
||||
import { Theme, ButtonColors } from "@types";
|
||||
import { useProxy } from "@lib/storage";
|
||||
import { ErrorBoundary, Button, HelpMessage } from "@ui/components";
|
||||
import { themes } from "@lib/themes";
|
||||
import { Button } from "@ui/components";
|
||||
import settings from "@lib/settings";
|
||||
import AddonPage from "@ui/settings/components/AddonPage";
|
||||
import ThemeCard from "@ui/settings/components/ThemeCard";
|
||||
|
||||
export default function Themes() {
|
||||
useProxy(settings);
|
||||
useProxy(themes);
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<RN.View style={{ flex: 1 }}>
|
||||
{settings.safeMode?.enabled && <RN.View style={{ margin: 10 }}>
|
||||
<HelpMessage messageType={0}>You are in Safe Mode, meaning themes have been temporarily disabled.{settings.safeMode?.currentThemeId && " If a theme appears to be causing the issue, you can press below to disable it persistently."}</HelpMessage>
|
||||
{settings.safeMode?.currentThemeId && <Button
|
||||
text="Disable Theme"
|
||||
color={ButtonColors.BRAND}
|
||||
size="small"
|
||||
onPress={() => {
|
||||
delete settings.safeMode?.currentThemeId;
|
||||
}}
|
||||
style={{ marginTop: 8 }}
|
||||
/>}
|
||||
</RN.View>}
|
||||
<RN.FlatList
|
||||
data={Object.values(themes)}
|
||||
renderItem={({ item, index }) => <ThemeCard theme={item} index={index} />}
|
||||
keyExtractor={item => item.id}
|
||||
/>
|
||||
</RN.View>
|
||||
</ErrorBoundary>
|
||||
<AddonPage<Theme>
|
||||
items={themes}
|
||||
safeModeMessage={`You are in Safe Mode, meaning themes have been temporarily disabled.${settings.safeMode?.currentThemeId ? " If a theme appears to be causing the issue, you can press below to disable it persistently." : ""}`}
|
||||
safeModeExtras={settings.safeMode?.currentThemeId ? <Button
|
||||
text="Disable Theme"
|
||||
color={ButtonColors.BRAND}
|
||||
size="small"
|
||||
onPress={() => {
|
||||
delete settings.safeMode?.currentThemeId;
|
||||
}}
|
||||
style={{ marginTop: 8 }}
|
||||
/> : undefined}
|
||||
card={ThemeCard}
|
||||
/>
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue