mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-01-10 09:56:24 +00:00
make searching from modal work
This commit is contained in:
parent
f82cb5188b
commit
7c729de800
1 changed files with 93 additions and 11 deletions
|
@ -7,13 +7,14 @@
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
|
import { debounce } from "@shared/debounce";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
|
import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { wordsFromCamel, wordsToTitle } from "@utils/text";
|
import { wordsFromCamel, wordsToTitle } from "@utils/text";
|
||||||
import { OptionType, PluginOptionList } from "@utils/types";
|
import { OptionType, PluginOptionList } from "@utils/types";
|
||||||
import { findByCodeLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
||||||
import { Avatar, Button, ChannelStore, Forms, GuildStore, IconUtils, React, Text, TextInput, useEffect, useState } from "@webpack/common";
|
import { Avatar, Button, ChannelStore, Forms, GuildStore, IconUtils, React, Text, TextInput, useCallback, useEffect, useRef, useState } from "@webpack/common";
|
||||||
import { Channel, Guild } from "discord-types/general";
|
import { Channel, Guild } from "discord-types/general";
|
||||||
import { JSX } from "react";
|
|
||||||
|
|
||||||
import { ISettingElementProps } from ".";
|
import { ISettingElementProps } from ".";
|
||||||
|
|
||||||
|
@ -22,9 +23,9 @@ const cl = classNameFactory("vc-plugin-modal-");
|
||||||
const UserMentionComponent = findComponentByCodeLazy(".USER_MENTION)");
|
const UserMentionComponent = findComponentByCodeLazy(".USER_MENTION)");
|
||||||
const getDMChannelIcon = findByCodeLazy(".getChannelIconURL({");
|
const getDMChannelIcon = findByCodeLazy(".getChannelIconURL({");
|
||||||
const GroupDMAvatars = findComponentByCodeLazy(".AvatarSizeSpecs[", "getAvatarURL");
|
const GroupDMAvatars = findComponentByCodeLazy(".AvatarSizeSpecs[", "getAvatarURL");
|
||||||
|
const SearchBarModule = findByPropsLazy("SearchBar", "Checkbox");
|
||||||
const SearchBar = findComponentByCodeLazy("focus(){let{current:");
|
const SearchBarWrapper = findByPropsLazy("SearchBar", "Item");
|
||||||
|
const SearchHandler = findByCodeLazy("createSearchContext", "setLimit");
|
||||||
|
|
||||||
const CloseIcon = () => {
|
const CloseIcon = () => {
|
||||||
return <svg viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" width="18" height="18">
|
return <svg viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" width="18" height="18">
|
||||||
|
@ -65,6 +66,89 @@ export function SettingArrayComponent({
|
||||||
setItems(pluginSettings[id]);
|
setItems(pluginSettings[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SearchModal({ modalProps, close, val }: { modalProps: ModalProps; close(): void; val?: string; }) {
|
||||||
|
|
||||||
|
const [searchText, setSearchText] = useState<string>(val || "");
|
||||||
|
const [searchState, setSearchState] = useState({
|
||||||
|
results: [],
|
||||||
|
query: searchText
|
||||||
|
});
|
||||||
|
// channels:0, guilds:1, users:2
|
||||||
|
const [results, setResults] = useState<Record<string, any[]>>({
|
||||||
|
"channels": [],
|
||||||
|
"guilds": [],
|
||||||
|
"users": []
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchHandlerRef = useRef<typeof SearchHandler | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = new SearchHandler((results, query) => {
|
||||||
|
setSearchState({
|
||||||
|
results,
|
||||||
|
query
|
||||||
|
});
|
||||||
|
});
|
||||||
|
searchHandlerRef.current = handler;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
handler.destroy();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const search = useCallback(debounce(() => {
|
||||||
|
if (searchHandlerRef.current) {
|
||||||
|
searchHandlerRef.current.search(searchText.trim());
|
||||||
|
setResults({
|
||||||
|
"channels": [...searchHandlerRef.current._groupDMResults, ...searchHandlerRef.current._textChannelResults, ...searchHandlerRef.current._voiceChannelResults],
|
||||||
|
"guilds": searchHandlerRef.current._guildResults,
|
||||||
|
"users": searchHandlerRef.current._userResults
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 300), [searchText]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
search();
|
||||||
|
}, [searchText, search]);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalRoot {...modalProps} size={ModalSize.MEDIUM}>
|
||||||
|
<ModalHeader>
|
||||||
|
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>Search for {
|
||||||
|
option.type === OptionType.USERS ? "Users" : option.type === OptionType.CHANNELS ? "Channels" : "Guilds"
|
||||||
|
}</Text>
|
||||||
|
<ModalCloseButton onClick={close} />
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalContent>
|
||||||
|
<SearchBarWrapper.SearchBar
|
||||||
|
size={SearchBarModule.SearchBar.Sizes.MEDIUM}
|
||||||
|
placeholder={"Search for a" + (option.type === OptionType.USERS ? " user" : option.type === OptionType.CHANNELS ? " channel" : " guild")}
|
||||||
|
query={searchText}
|
||||||
|
onChange={setSearchText}
|
||||||
|
autofocus={true}
|
||||||
|
/>
|
||||||
|
</ModalContent>
|
||||||
|
|
||||||
|
<ModalFooter>
|
||||||
|
|
||||||
|
|
||||||
|
</ModalFooter>
|
||||||
|
|
||||||
|
</ModalRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openSearchModal(val?: string) {
|
||||||
|
const key = openModal(modalProps => (
|
||||||
|
<SearchModal
|
||||||
|
modalProps={modalProps}
|
||||||
|
close={() => closeModal(key)}
|
||||||
|
val={val}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
const removeButton = (index: number) => {
|
const removeButton = (index: number) => {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
@ -162,7 +246,7 @@ export function SettingArrayComponent({
|
||||||
// collapsible guild list with channels in it
|
// collapsible guild list with channels in it
|
||||||
const channels: Record<string, Channel[]> = {};
|
const channels: Record<string, Channel[]> = {};
|
||||||
const dmChannels: Channel[] = [];
|
const dmChannels: Channel[] = [];
|
||||||
const elements: JSX.Element[] = [];
|
const elements: React.JSX.Element[] = [];
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const channel = ChannelStore.getChannel(item);
|
const channel = ChannelStore.getChannel(item);
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
|
@ -259,7 +343,7 @@ export function SettingArrayComponent({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (option.type !== OptionType.ARRAY && !(text.length >= 18 && text.length <= 19 && !isNaN(Number(text)))) {
|
if (option.type !== OptionType.ARRAY && !(text.length >= 18 && text.length <= 19 && !isNaN(Number(text)))) {
|
||||||
// openSearchModal();
|
openSearchModal();
|
||||||
setText("");
|
setText("");
|
||||||
// FIXME
|
// FIXME
|
||||||
return;
|
return;
|
||||||
|
@ -330,9 +414,7 @@ export function SettingArrayComponent({
|
||||||
<Button
|
<Button
|
||||||
id={cl("search-button")}
|
id={cl("search-button")}
|
||||||
size={Button.Sizes.MIN}
|
size={Button.Sizes.MIN}
|
||||||
onClick={() => {
|
onClick={openSearchModal}
|
||||||
// openSearchModal();
|
|
||||||
}}
|
|
||||||
style={
|
style={
|
||||||
{ background: "none" }
|
{ background: "none" }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue