feat(ChatboxAvatar): add Settings page with options

This commit is contained in:
kmmiio99o 2026-07-02 12:28:24 +02:00
parent 4435065c06
commit 4414c2d291
No known key found for this signature in database
GPG key ID: AC9D7747D423B9BF
2 changed files with 121 additions and 5 deletions

View file

@ -1,8 +1,11 @@
import { after } from "@vendetta/patcher"; import { after } from "@vendetta/patcher";
import { find, findByName, findByProps, findByStoreName } from "@vendetta/metro"; import { find, findByName, findByProps, findByStoreName } from "@vendetta/metro";
import { ReactNative } from "@vendetta/metro/common"; import { ReactNative } from "@vendetta/metro/common";
import { plugin } from "@vendetta";
import React from "react"; import React from "react";
import Settings from "./settings";
const Flux = findByProps("useStateFromStores"); const Flux = findByProps("useStateFromStores");
const { Pressable, View } = ReactNative; const { Pressable, View } = ReactNative;
@ -24,11 +27,15 @@ function openAccountSheet(userId: string, channelId: string) {
try { try {
fn(true, true); fn(true, true);
return; return;
} catch (_) {} } catch {
// fall through to showUserProfileActionSheet
}
} }
showUserProfileActionSheet?.({ userId, channelId }); showUserProfileActionSheet?.({ userId, channelId });
} }
const getSetting = (key: string, fallback: any) => plugin.storage[key] ?? fallback;
function AvatarAction() { function AvatarAction() {
const self = Flux?.useStateFromStores?.([UserStore], () => UserStore?.getCurrentUser?.()); const self = Flux?.useStateFromStores?.([UserStore], () => UserStore?.getCurrentUser?.());
const status = Flux?.useStateFromStores?.([SelfPresenceStore], () => SelfPresenceStore?.getStatus?.()); const status = Flux?.useStateFromStores?.([SelfPresenceStore], () => SelfPresenceStore?.getStatus?.());
@ -37,16 +44,44 @@ function AvatarAction() {
if (!self || !Avatar) return null; if (!self || !Avatar) return null;
const pressAction = getSetting("pressAction", "profile");
const longPressAction = getSetting("longPressAction", "server");
const showStatusCutout = getSetting("showStatusCutout", true);
const profileType = getSetting("profileType", "server");
const showInDms = getSetting("showInDms", true);
const isDm = channel?.type === 1 || channel?.type === 3;
if (isDm && !showInDms) return null;
const guildId = profileType === "server" ? channel?.guild_id : undefined;
const profileChannelId = profileType === "server" ? (channel?.id ?? channelId) : undefined;
const handlePress = () => {
if (pressAction === "server") {
openAccountSheet(self.id, channel?.id ?? channelId);
} else {
showUserProfileActionSheet?.({ userId: self.id, channelId: profileChannelId });
}
};
const handleLongPress = () => {
if (longPressAction === "server") {
openAccountSheet(self.id, channel?.id ?? channelId);
} else {
showUserProfileActionSheet?.({ userId: self.id, channelId: profileChannelId });
}
};
return ( return (
<Pressable <Pressable
onPress={() => showUserProfileActionSheet?.({ userId: self.id, channelId: channel?.id ?? channelId })} onPress={handlePress}
onLongPress={() => openAccountSheet(self.id, channel?.id ?? channelId)} onLongPress={handleLongPress}
style={{ justifyContent: "center", alignItems: "center", marginHorizontal: 4 }} style={{ justifyContent: "center", alignItems: "center", marginHorizontal: 4 }}
> >
<Avatar <Avatar
user={self} user={self}
guildId={channel?.guild_id} guildId={guildId}
status={status} status={showStatusCutout ? status : undefined}
avatarDecoration={self?.avatarDecoration} avatarDecoration={self?.avatarDecoration}
animate={true} animate={true}
/> />
@ -58,6 +93,17 @@ const patches: (() => void)[] = [];
export default { export default {
onLoad() { onLoad() {
const defaults: Record<string, any> = {
pressAction: "profile",
longPressAction: "server",
showStatusCutout: true,
profileType: "server",
showInDms: true,
};
for (const key in defaults) {
plugin.storage[key] = plugin.storage[key] ?? defaults[key];
}
if (!ChatInputActions) return; if (!ChatInputActions) return;
if (ChatInputActions.type) { if (ChatInputActions.type) {
@ -90,4 +136,5 @@ export default {
} }
patches.length = 0; patches.length = 0;
}, },
settings: Settings,
}; };

View file

@ -0,0 +1,69 @@
import { plugin } from "@vendetta";
import { findByProps } from "@vendetta/metro";
import { React } from "@vendetta/metro/common";
const { ScrollView } = findByProps("ScrollView");
const { TableRowGroup, TableRadioGroup, TableRadioRow, TableSwitchRow, Stack } = findByProps(
"TableRadioGroup",
"TableRadioRow",
"TableSwitchRow",
"TableRowGroup",
"Stack",
);
const get = (key: string, fallback: any) => plugin.storage[key] ?? fallback;
const set = (key: string, value: any) => { plugin.storage[key] = value; };
export default function ChatboxAvatarSettings() {
const [, forceUpdate] = React.useReducer((x: number) => ~x, 0);
return (
<ScrollView style={{ flex: 1 }}>
<Stack style={{ padding: 16 }} spacing={16}>
<TableRowGroup title="Press Action">
<TableRadioGroup
value={get("pressAction", "profile")}
onChange={(v: string) => { set("pressAction", v); forceUpdate(); }}
>
<TableRadioRow value="profile" label="Open Profile" />
<TableRadioRow value="server" label="Open Account Sheet" />
</TableRadioGroup>
</TableRowGroup>
<TableRowGroup title="Long Press Action">
<TableRadioGroup
value={get("longPressAction", "server")}
onChange={(v: string) => { set("longPressAction", v); forceUpdate(); }}
>
<TableRadioRow value="profile" label="Open Profile" />
<TableRadioRow value="server" label="Open Account Sheet" />
</TableRadioGroup>
</TableRowGroup>
<TableRowGroup title="Profile Type">
<TableRadioGroup
value={get("profileType", "server")}
onChange={(v: string) => { set("profileType", v); forceUpdate(); }}
>
<TableRadioRow value="server" label="Prefer Server Profile" />
<TableRadioRow value="main" label="Prefer Main Profile" />
</TableRadioGroup>
</TableRowGroup>
<TableRowGroup title="Status Icon">
<TableRadioGroup
value={get("showStatusCutout", true) ? "true" : "false"}
onChange={(v: string) => { set("showStatusCutout", v === "true"); forceUpdate(); }}
>
<TableRadioRow value="true" label="Show" />
<TableRadioRow value="false" label="Hide" />
</TableRadioGroup>
</TableRowGroup>
<TableRowGroup title="Visibility">
<TableSwitchRow
label="Show in DMs"
value={get("showInDms", true)}
onValueChange={(v: boolean) => { set("showInDms", v); forceUpdate(); }}
/>
</TableRowGroup>
</Stack>
</ScrollView>
);
}