Files
desktop/app/components/DialogsSearch/DialogsSearch.tsx
rosetta 83f38dc63f 'init'
2026-01-30 05:01:05 +02:00

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>
);
}