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
|
id
|
||||||
}: ISettingElementProps<PluginOptionArray>) {
|
}: ISettingElementProps<PluginOptionArray>) {
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [items, setItems] = useState<string[]>([]);
|
const [items, setItems] = useState<string[]>(pluginSettings[id] || []);
|
||||||
const [text, setText] = useState<string>("");
|
const [text, setText] = useState<string>("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -87,16 +87,12 @@ export function SettingArrayComponent({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
pluginSettings[id] = items;
|
pluginSettings[id] = items;
|
||||||
onChange(items);
|
onChange(items);
|
||||||
}, [items, pluginSettings, id]);
|
}, [items]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onError(error !== null);
|
onError(error !== null);
|
||||||
}, [error]);
|
}, [error]);
|
||||||
|
|
||||||
if (items.length === 0 && pluginSettings[id].length !== 0) {
|
|
||||||
setItems(pluginSettings[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function openSearchModal(val?: string) {
|
function openSearchModal(val?: string) {
|
||||||
return openModal(modalProps => (
|
return openModal(modalProps => (
|
||||||
<SearchModal
|
<SearchModal
|
||||||
|
@ -105,16 +101,17 @@ export function SettingArrayComponent({
|
||||||
subText={"All selected items will be added to " + wordsToTitle(wordsFromCamel(id))}
|
subText={"All selected items will be added to " + wordsToTitle(wordsFromCamel(id))}
|
||||||
searchType={option.type === OptionType.USERS ? "USERS" : option.type === OptionType.CHANNELS ? "CHANNELS" : "GUILDS"}
|
searchType={option.type === OptionType.USERS ? "USERS" : option.type === OptionType.CHANNELS ? "CHANNELS" : "GUILDS"}
|
||||||
onSubmit={values => setItems([...items, ...values.map(v => v.id)])}
|
onSubmit={values => setItems([...items, ...values.map(v => v.id)])}
|
||||||
|
excludeIds={items}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeButton = (index: number) => {
|
const removeButton = (id: string) => {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
id={cl("remove-button")}
|
id={cl("remove-button")}
|
||||||
size={Button.Sizes.MIN}
|
size={Button.Sizes.MIN}
|
||||||
onClick={() => removeItem(index)}
|
onClick={() => removeItem(id)}
|
||||||
style={
|
style={
|
||||||
{ background: "none", color: "red" }
|
{ background: "none", color: "red" }
|
||||||
}
|
}
|
||||||
|
@ -134,17 +131,16 @@ export function SettingArrayComponent({
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeItem = (index: number) => {
|
const removeItem = (itemId: string) => {
|
||||||
if (items.length === 1) {
|
if (items.length === 1) {
|
||||||
setItems([]);
|
setItems([]);
|
||||||
pluginSettings[id] = [];
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setItems(items.filter((_, i) => i !== index));
|
setItems(items.filter(item => item !== itemId));
|
||||||
};
|
};
|
||||||
|
|
||||||
function renderGuildView() {
|
function renderGuildView() {
|
||||||
return items.map(item => GuildStore.getGuild(item))
|
return items.map(item => GuildStore.getGuild(item) || item)
|
||||||
.map((guild, index) => (
|
.map((guild, index) => (
|
||||||
<Flex
|
<Flex
|
||||||
flexDirection="row"
|
flexDirection="row"
|
||||||
|
@ -154,15 +150,15 @@ export function SettingArrayComponent({
|
||||||
marginBottom: "8px"
|
marginBottom: "8px"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{guild ? (
|
{typeof guild !== "string" ? (
|
||||||
<div className={cl("name")} style={{ color: "var(--text-normal)" }}>
|
<div className={cl("name")} style={{ color: "var(--text-normal)" }}>
|
||||||
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
||||||
{guildIcon(guild)}
|
{guildIcon(guild)}
|
||||||
<Text variant="text-sm/semibold" style={{ marginLeft: "4px" }}>{guild.name}</Text>
|
<Text variant="text-sm/semibold" style={{ marginLeft: "4px" }}>{guild.name}</Text>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : <Text variant="text-sm/semibold">{"Unknown Guild"}</Text>}
|
) : <Text variant="text-sm/semibold">{`Unknown Guild (${guild})`}</Text>}
|
||||||
{removeButton(index)}
|
{removeButton(typeof guild !== "string" ? guild.id : guild)}
|
||||||
</Flex>
|
</Flex>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -206,9 +202,14 @@ export function SettingArrayComponent({
|
||||||
const channels: Record<string, Channel[]> = {};
|
const channels: Record<string, Channel[]> = {};
|
||||||
const dmChannels: Channel[] = [];
|
const dmChannels: Channel[] = [];
|
||||||
const elements: React.JSX.Element[] = [];
|
const elements: React.JSX.Element[] = [];
|
||||||
|
|
||||||
|
// to not remove items while iterating
|
||||||
|
const invalidChannels: string[] = [];
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const channel = ChannelStore.getChannel(item);
|
const channel = ChannelStore.getChannel(item);
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
|
invalidChannels.push(item);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (channel.isDM() || channel.isGroupDM()) {
|
if (channel.isDM() || channel.isGroupDM()) {
|
||||||
|
@ -221,6 +222,10 @@ export function SettingArrayComponent({
|
||||||
channels[channel.guild_id].push(channel);
|
channels[channel.guild_id].push(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const channel of invalidChannels) {
|
||||||
|
removeItem(channel);
|
||||||
|
}
|
||||||
|
|
||||||
const userMention = (channel: Channel) => {
|
const userMention = (channel: Channel) => {
|
||||||
return <UserMentionComponent
|
return <UserMentionComponent
|
||||||
userId={channel.recipients[0]}
|
userId={channel.recipients[0]}
|
||||||
|
@ -239,33 +244,40 @@ export function SettingArrayComponent({
|
||||||
</span>;
|
</span>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let idx = -1;
|
||||||
|
|
||||||
if (dmChannels.length > 0) {
|
if (dmChannels.length > 0) {
|
||||||
elements.push(
|
elements.push(
|
||||||
<details>
|
<details>
|
||||||
<summary style={{ color: "var(--text-normal)", marginBottom: "8px" }}>DMs</summary>
|
<summary style={{ color: "var(--text-normal)", marginBottom: "8px" }}>DMs</summary>
|
||||||
<div style={{ paddingLeft: "16px" }}>
|
<div style={{ paddingLeft: "16px" }}>
|
||||||
{dmChannels.map((channel, index) => (
|
{dmChannels.map(channel => {
|
||||||
<Flex
|
idx += 1;
|
||||||
|
return <Flex
|
||||||
flexDirection="row"
|
flexDirection="row"
|
||||||
key={index}
|
key={idx}
|
||||||
style={{
|
style={{
|
||||||
gap: "1px",
|
gap: "1px",
|
||||||
marginBottom: "8px",
|
marginBottom: "8px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{channel.recipients.length === 1 ? userMention(channel) : gdmComponent(channel)}
|
{channel.recipients.length === 1 ? userMention(channel) : gdmComponent(channel)}
|
||||||
{removeButton(index)}
|
{removeButton(channel.id)}
|
||||||
</Flex>
|
</Flex>;
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</details >
|
</details >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const guilds: { name: string; guild: React.JSX.Element }[] = [];
|
||||||
|
|
||||||
Object.keys(channels).forEach(guildId => {
|
Object.keys(channels).forEach(guildId => {
|
||||||
const guild = GuildStore.getGuild(guildId);
|
const guild = GuildStore.getGuild(guildId);
|
||||||
elements.push(
|
guilds.push(
|
||||||
|
{ name: guild?.name ?? `Unknown Guild (${guildId})`, guild: (
|
||||||
<details>
|
<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" }}>
|
<summary style={{ color: "var(--text-normal)", marginBottom: "8px" }}>
|
||||||
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
||||||
{guildIcon(guild)}
|
{guildIcon(guild)}
|
||||||
|
@ -274,26 +286,33 @@ export function SettingArrayComponent({
|
||||||
</summary>
|
</summary>
|
||||||
)}
|
)}
|
||||||
<div style={{ paddingLeft: "16px", color: "var(--text-normal)" }}>
|
<div style={{ paddingLeft: "16px", color: "var(--text-normal)" }}>
|
||||||
{channels[guildId].map((channel, index) => (
|
{channels[guildId].map(channel => {
|
||||||
<Flex
|
idx += 1;
|
||||||
|
return <Flex
|
||||||
flexDirection="row"
|
flexDirection="row"
|
||||||
key={index}
|
key={idx}
|
||||||
style={{
|
style={{
|
||||||
gap: "1px",
|
gap: "1px",
|
||||||
marginBottom: "8px"
|
marginBottom: "8px"
|
||||||
}}
|
}}>
|
||||||
>
|
|
||||||
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
||||||
{getChannelSymbol(channel.type)}
|
{getChannelSymbol(channel.type)}
|
||||||
<Text variant="text-sm/semibold" style={{ marginLeft: "4px" }}>{channel.name}</Text>
|
<Text variant="text-sm/semibold" style={{ marginLeft: "4px" }}>{channel.name}</Text>
|
||||||
{removeButton(index)}
|
{removeButton(channel.id)}
|
||||||
</span>
|
</span>
|
||||||
</Flex>
|
</Flex>;
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>) }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
guilds.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
|
for (const guild of guilds) {
|
||||||
|
elements.push(guild.guild);
|
||||||
|
}
|
||||||
|
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +353,7 @@ export function SettingArrayComponent({
|
||||||
) : (
|
) : (
|
||||||
<span style={{ color: "var(--text-normal)" }}>{item}</span>
|
<span style={{ color: "var(--text-normal)" }}>{item}</span>
|
||||||
)}
|
)}
|
||||||
{removeButton(index)}
|
{removeButton(item)}
|
||||||
</Flex>
|
</Flex>
|
||||||
)) : option.type === OptionType.CHANNELS ?
|
)) : option.type === OptionType.CHANNELS ?
|
||||||
renderChannelView() : renderGuildView()
|
renderChannelView() : renderGuildView()
|
||||||
|
|
|
@ -147,14 +147,16 @@ function searchTypeToText(type: string | string[]) {
|
||||||
* @param {string} [props.input] - The initial input value for the search bar.
|
* @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 {("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.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.
|
* @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;
|
modalProps: ModalProps;
|
||||||
onSubmit(selected: DestinationItem[]): void;
|
onSubmit(selected: DestinationItem[]): void;
|
||||||
input?: string;
|
input?: string;
|
||||||
searchType?: ("USERS" | "CHANNELS" | "GUILDS")[] | "USERS" | "CHANNELS" | "GUILDS" | "ALL";
|
searchType?: ("USERS" | "CHANNELS" | "GUILDS")[] | "USERS" | "CHANNELS" | "GUILDS" | "ALL";
|
||||||
subText?: string
|
subText?: string
|
||||||
|
excludeIds?: string[],
|
||||||
}) {
|
}) {
|
||||||
const UserIcon = React.memo(function ({
|
const UserIcon = React.memo(function ({
|
||||||
user,
|
user,
|
||||||
|
@ -384,7 +386,7 @@ export default function SearchModal({ modalProps, onSubmit, input, searchType =
|
||||||
|
|
||||||
const filterItems = (items: any[]) => {
|
const filterItems = (items: any[]) => {
|
||||||
return items.filter(
|
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