136 lines
5.8 KiB
TypeScript
136 lines
5.8 KiB
TypeScript
import { useRosettaColors } from "@/app/hooks/useRosettaColors";
|
|
import { PacketSearch, PacketSearchUser } from "@/app/providers/ProtocolProvider/protocol/packets/packet.search";
|
|
import { Avatar, Box, Flex, Loader, Popover, Text } from "@mantine/core";
|
|
import { IconBookmark } from "@tabler/icons-react";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { usePublicKey } from "@/app/providers/AccountProvider/usePublicKey";
|
|
import { usePrivateKeyHash } from "@/app/providers/AccountProvider/usePrivateKeyHash";
|
|
import { useSender } from "@/app/providers/ProtocolProvider/useSender";
|
|
import { usePacket } from "@/app/providers/ProtocolProvider/usePacket";
|
|
import { DEVTOOLS_CHEATCODE } from "@/app/constants";
|
|
import { useRosettaBreakpoints } from "@/app/hooks/useRosettaBreakpoints";
|
|
import { useViewPanelsState, ViewPanelsState } from "@/app/hooks/useViewPanelsState";
|
|
import InputCustomPlaceholder from "../InputCustomPlaceholder/InputCustomPlaceholder";
|
|
import { SearchRow } from "../SearchRow/SearchRow";
|
|
|
|
export function DialogsSearch() {
|
|
const publicKey = usePublicKey();
|
|
const privateKey = usePrivateKeyHash();
|
|
const [opened, setOpened] = useState(false);
|
|
const [loading, setLoading] = useState(false);
|
|
const timeout = useRef<NodeJS.Timeout | null>(null);
|
|
const [searchValue, setSearchValue] = useState("");
|
|
const navigate = useNavigate();
|
|
const send = useSender();
|
|
const {lg} = useRosettaBreakpoints();
|
|
const [viewState] = useViewPanelsState();
|
|
const [searchResults, setSearchResults] = useState<PacketSearchUser[]>([]);
|
|
const colors = useRosettaColors();
|
|
|
|
useEffect(() => {
|
|
if(searchValue.trim() == DEVTOOLS_CHEATCODE){
|
|
window.electron.ipcRenderer.invoke('open-dev-tools');
|
|
}
|
|
}, [searchValue]);
|
|
|
|
|
|
const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const value = event.currentTarget.value.
|
|
replace("@", "");
|
|
if (timeout.current) {
|
|
clearTimeout(timeout.current);
|
|
}
|
|
if (value.trim() === "") {
|
|
if(timeout.current) {
|
|
clearTimeout(timeout.current);
|
|
}
|
|
setSearchResults([]);
|
|
setOpened(false);
|
|
setSearchValue(value);
|
|
return;
|
|
}
|
|
setOpened(true);
|
|
setLoading(true);
|
|
setSearchValue(value);
|
|
timeout.current = setTimeout(() => {
|
|
let packetSearch = new PacketSearch();
|
|
packetSearch.setSearch(value);
|
|
packetSearch.setPrivateKey(privateKey);
|
|
send(packetSearch);
|
|
}, 1000);
|
|
|
|
}
|
|
|
|
usePacket(0x03, (packet : PacketSearch) => {
|
|
setSearchResults(packet.getUsers());
|
|
setLoading(false);
|
|
});
|
|
|
|
const onDialogClick = (publicKey : string) => {
|
|
setOpened(false);
|
|
navigate(`/main/chat/${publicKey}`);
|
|
setSearchValue("");
|
|
}
|
|
|
|
return (
|
|
<Box style={{
|
|
borderRadius: 8,
|
|
}} bg={colors.mainColor} w={'100%'}>
|
|
<Popover
|
|
opened={(lg || viewState == ViewPanelsState.DIALOGS_PANEL_ONLY) && opened}
|
|
onClose={() => setOpened(false)}
|
|
width={'target'}
|
|
shadow="md"
|
|
clickOutsideEvents={['mouseup', 'touchend']}
|
|
//withOverlay
|
|
withArrow
|
|
overlayProps={{ zIndex: 10000, blur: '3px' }}
|
|
zIndex={10001}
|
|
position="bottom"
|
|
>
|
|
<Popover.Target>
|
|
<InputCustomPlaceholder onBlur={() => setOpened(false)} onChange={handleSearch}></InputCustomPlaceholder>
|
|
</Popover.Target>
|
|
<Popover.Dropdown p={0}>
|
|
{!loading && searchResults.length === 0 && (
|
|
<Text fz={12} c="dimmed" p={'sm'} ta={'center'}>
|
|
You can search by username or public key.
|
|
</Text>
|
|
)}
|
|
{loading && (
|
|
<Flex align={'center'} justify={'center'} p={10}>
|
|
<Loader size={20} color={colors.chevrons.active}></Loader>
|
|
</Flex>
|
|
)}
|
|
{searchResults.length > 0 && !loading &&
|
|
(<Flex direction={'column'} p={0}>
|
|
{searchResults.map((user, index) => (
|
|
<div key={index}>
|
|
{user.publicKey !== publicKey && (
|
|
<SearchRow user={user} onDialogClick={onDialogClick}></SearchRow>
|
|
)}
|
|
{user.publicKey === publicKey && (
|
|
<Flex onClick={() => onDialogClick(user.publicKey)} p={'sm'} direction={'row'} gap={'sm'}>
|
|
<Avatar
|
|
size={'md'}
|
|
color={'blue'}
|
|
variant={'filled'}
|
|
>
|
|
<IconBookmark stroke={2} size={20}></IconBookmark>
|
|
</Avatar>
|
|
<Flex direction={'column'}>
|
|
<Text fz={12}>Saved messages</Text>
|
|
<Text fz={10} c="dimmed">Notes</Text>
|
|
</Flex>
|
|
</Flex>
|
|
)}
|
|
</div>
|
|
))}
|
|
</Flex>)
|
|
}
|
|
</Popover.Dropdown>
|
|
</Popover>
|
|
</Box>
|
|
);
|
|
} |