mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-02-24 15:35:11 +00:00
minor fixes
- switch from indices to IDs - make indexes for the channel view unique - Fix guilds shuffling around in the channel view by sorting them alphabetically - Fix possibility to add elements twice from search modal by allowing to hide already added items from the search modal - Remove invalid channels instead of just not rendering them.
This commit is contained in:
parent
de2f1d5159
commit
9cee56e379
2 changed files with 56 additions and 35 deletions
|
@ -68,7 +68,7 @@ export function SettingArrayComponent({
|
|||
id
|
||||
}: ISettingElementProps<PluginOptionArray>) {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [items, setItems] = useState<string[]>([]);
|
||||
const [items, setItems] = useState<string[]>(pluginSettings[id] || []);
|
||||
const [text, setText] = useState<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -87,16 +87,12 @@ export function SettingArrayComponent({
|
|||
useEffect(() => {
|
||||
pluginSettings[id] = items;
|
||||
onChange(items);
|
||||
}, [items, pluginSettings, id]);
|
||||
}, [items]);
|
||||
|
||||
useEffect(() => {
|
||||
onError(error !== null);
|
||||
}, [error]);
|
||||
|
||||
if (items.length === 0 && pluginSettings[id].length !== 0) {
|
||||
setItems(pluginSettings[id]);
|
||||
}
|
||||
|
||||
function openSearchModal(val?: string) {
|
||||
return openModal(modalProps => (
|
||||
<SearchModal
|
||||
|
@ -105,16 +101,17 @@ export function SettingArrayComponent({
|
|||
subText={"All selected items will be added to " + wordsToTitle(wordsFromCamel(id))}
|
||||
searchType={option.type === OptionType.USERS ? "USERS" : option.type === OptionType.CHANNELS ? "CHANNELS" : "GUILDS"}
|
||||
onSubmit={values => setItems([...items, ...values.map(v => v.id)])}
|
||||
excludeIds={items}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
const removeButton = (index: number) => {
|
||||
const removeButton = (id: string) => {
|
||||
return (
|
||||
<Button
|
||||
id={cl("remove-button")}
|
||||
size={Button.Sizes.MIN}
|
||||
onClick={() => removeItem(index)}
|
||||
onClick={() => removeItem(id)}
|
||||
style={
|
||||
{ background: "none", color: "red" }
|
||||
}
|
||||
|
@ -134,17 +131,16 @@ export function SettingArrayComponent({
|
|||
|
||||
};
|
||||
|
||||
const removeItem = (index: number) => {
|
||||
const removeItem = (itemId: string) => {
|
||||
if (items.length === 1) {
|
||||
setItems([]);
|
||||
pluginSettings[id] = [];
|
||||
return;
|
||||
}
|
||||
setItems(items.filter((_, i) => i !== index));
|
||||
setItems(items.filter(item => item !== itemId));
|
||||
};
|
||||
|
||||
function renderGuildView() {
|
||||
return items.map(item => GuildStore.getGuild(item))
|
||||
return items.map(item => GuildStore.getGuild(item) || item)
|
||||
.map((guild, index) => (
|
||||
<Flex
|
||||
flexDirection="row"
|
||||
|
@ -154,15 +150,15 @@ export function SettingArrayComponent({
|
|||
marginBottom: "8px"
|
||||
}}
|
||||
>
|
||||
{guild ? (
|
||||
{typeof guild !== "string" ? (
|
||||
<div className={cl("name")} style={{ color: "var(--text-normal)" }}>
|
||||
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
||||
{guildIcon(guild)}
|
||||
<Text variant="text-sm/semibold" style={{ marginLeft: "4px" }}>{guild.name}</Text>
|
||||
</span>
|
||||
</div>
|
||||
) : <Text variant="text-sm/semibold">{"Unknown Guild"}</Text>}
|
||||
{removeButton(index)}
|
||||
) : <Text variant="text-sm/semibold">{`Unknown Guild (${guild})`}</Text>}
|
||||
{removeButton(typeof guild !== "string" ? guild.id : guild)}
|
||||
</Flex>
|
||||
));
|
||||
}
|
||||
|
@ -206,9 +202,14 @@ export function SettingArrayComponent({
|
|||
const channels: Record<string, Channel[]> = {};
|
||||
const dmChannels: Channel[] = [];
|
||||
const elements: React.JSX.Element[] = [];
|
||||
|
||||
// to not remove items while iterating
|
||||
const invalidChannels: string[] = [];
|
||||
|
||||
for (const item of items) {
|
||||
const channel = ChannelStore.getChannel(item);
|
||||
if (!channel) {
|
||||
invalidChannels.push(item);
|
||||
continue;
|
||||
}
|
||||
if (channel.isDM() || channel.isGroupDM()) {
|
||||
|
@ -221,6 +222,10 @@ export function SettingArrayComponent({
|
|||
channels[channel.guild_id].push(channel);
|
||||
}
|
||||
|
||||
for (const channel of invalidChannels) {
|
||||
removeItem(channel);
|
||||
}
|
||||
|
||||
const userMention = (channel: Channel) => {
|
||||
return <UserMentionComponent
|
||||
userId={channel.recipients[0]}
|
||||
|
@ -239,33 +244,40 @@ export function SettingArrayComponent({
|
|||
</span>;
|
||||
};
|
||||
|
||||
let idx = -1;
|
||||
|
||||
if (dmChannels.length > 0) {
|
||||
elements.push(
|
||||
<details>
|
||||
<summary style={{ color: "var(--text-normal)", marginBottom: "8px" }}>DMs</summary>
|
||||
<div style={{ paddingLeft: "16px" }}>
|
||||
{dmChannels.map((channel, index) => (
|
||||
<Flex
|
||||
{dmChannels.map(channel => {
|
||||
idx += 1;
|
||||
return <Flex
|
||||
flexDirection="row"
|
||||
key={index}
|
||||
key={idx}
|
||||
style={{
|
||||
gap: "1px",
|
||||
marginBottom: "8px",
|
||||
}}
|
||||
>
|
||||
{channel.recipients.length === 1 ? userMention(channel) : gdmComponent(channel)}
|
||||
{removeButton(index)}
|
||||
</Flex>
|
||||
))}
|
||||
{removeButton(channel.id)}
|
||||
</Flex>;
|
||||
})}
|
||||
</div>
|
||||
</details >
|
||||
);
|
||||
}
|
||||
|
||||
const guilds: { name: string; guild: React.JSX.Element }[] = [];
|
||||
|
||||
Object.keys(channels).forEach(guildId => {
|
||||
const guild = GuildStore.getGuild(guildId);
|
||||
elements.push(
|
||||
guilds.push(
|
||||
{ name: guild?.name ?? `Unknown Guild (${guildId})`, guild: (
|
||||
<details>
|
||||
{!guild ? <summary style={{ color: "var(--text-normal)", marginBottom: "8px" }}>Unknown Guild</summary> : (
|
||||
{!guild ? <summary style={{ color: "var(--text-normal)", marginBottom: "8px" }}>{`Unknown Guild (${guildId})`}</summary> : (
|
||||
<summary style={{ color: "var(--text-normal)", marginBottom: "8px" }}>
|
||||
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
||||
{guildIcon(guild)}
|
||||
|
@ -274,26 +286,33 @@ export function SettingArrayComponent({
|
|||
</summary>
|
||||
)}
|
||||
<div style={{ paddingLeft: "16px", color: "var(--text-normal)" }}>
|
||||
{channels[guildId].map((channel, index) => (
|
||||
<Flex
|
||||
{channels[guildId].map(channel => {
|
||||
idx += 1;
|
||||
return <Flex
|
||||
flexDirection="row"
|
||||
key={index}
|
||||
key={idx}
|
||||
style={{
|
||||
gap: "1px",
|
||||
marginBottom: "8px"
|
||||
}}
|
||||
>
|
||||
}}>
|
||||
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
||||
{getChannelSymbol(channel.type)}
|
||||
<Text variant="text-sm/semibold" style={{ marginLeft: "4px" }}>{channel.name}</Text>
|
||||
{removeButton(index)}
|
||||
{removeButton(channel.id)}
|
||||
</span>
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>;
|
||||
})}
|
||||
</div>
|
||||
</details>
|
||||
</details>) }
|
||||
);
|
||||
});
|
||||
|
||||
guilds.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
for (const guild of guilds) {
|
||||
elements.push(guild.guild);
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
|
@ -334,7 +353,7 @@ export function SettingArrayComponent({
|
|||
) : (
|
||||
<span style={{ color: "var(--text-normal)" }}>{item}</span>
|
||||
)}
|
||||
{removeButton(index)}
|
||||
{removeButton(item)}
|
||||
</Flex>
|
||||
)) : option.type === OptionType.CHANNELS ?
|
||||
renderChannelView() : renderGuildView()
|
||||
|
|
|
@ -147,14 +147,16 @@ function searchTypeToText(type: string | string[]) {
|
|||
* @param {string} [props.input] - The initial input value for the search bar.
|
||||
* @param {("USERS" | "CHANNELS" | "GUILDS")[] | "USERS" | "CHANNELS" | "GUILDS" | "ALL"} [props.searchType="ALL"] - The type of items to search for.
|
||||
* @param {string} [props.subText] - Additional text to display below the heading.
|
||||
* @param {string[]} [props.excludeIds] - An array of IDs to exclude from the search results.
|
||||
* @returns The rendered SearchModal component.
|
||||
*/
|
||||
export default function SearchModal({ modalProps, onSubmit, input, searchType = "ALL", subText }: {
|
||||
export default function SearchModal({ modalProps, onSubmit, input, searchType = "ALL", subText, excludeIds }: {
|
||||
modalProps: ModalProps;
|
||||
onSubmit(selected: DestinationItem[]): void;
|
||||
input?: string;
|
||||
searchType?: ("USERS" | "CHANNELS" | "GUILDS")[] | "USERS" | "CHANNELS" | "GUILDS" | "ALL";
|
||||
subText?: string
|
||||
excludeIds?: string[],
|
||||
}) {
|
||||
const UserIcon = React.memo(function ({
|
||||
user,
|
||||
|
@ -384,7 +386,7 @@ export default function SearchModal({ modalProps, onSubmit, input, searchType =
|
|||
|
||||
const filterItems = (items: any[]) => {
|
||||
return items.filter(
|
||||
item => item != null && resultTypes.includes(item.type)
|
||||
item => item != null && resultTypes.includes(item.type) && (excludeIds != null && !excludeIds.includes(item.record.id))
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue