mirror of
https://github.com/lux-tel/session-desktop.git
synced 2026-10-30 20:33:24 +00:00
132 lines
4.0 KiB
TypeScript
132 lines
4.0 KiB
TypeScript
import { Dispatch } from '@reduxjs/toolkit';
|
|
import { debounce } from 'lodash';
|
|
import { useRef, useState } from 'react';
|
|
import { useSelector } from 'react-redux';
|
|
import styled from 'styled-components';
|
|
import { getAppDispatch } from '../state/dispatch';
|
|
import { searchActions, type DoSearchActionType, type SearchType } from '../state/ducks/search';
|
|
import { getConversationsCount } from '../state/selectors/conversations';
|
|
import { useLeftOverlayMode } from '../state/selectors/section';
|
|
import { useHotkey } from '../hooks/useHotkey';
|
|
import { tr } from '../localization/localeTools';
|
|
import { SessionLucideIconButton } from './icon/SessionIconButton';
|
|
import { LUCIDE_ICONS_UNICODE } from './icon/lucide';
|
|
import { LucideIcon } from './icon/LucideIcon';
|
|
|
|
const StyledSearchInput = styled.div`
|
|
height: var(--search-input-height);
|
|
background-color: var(--background-tertiary-color);
|
|
width: 100%;
|
|
// max width because it doesn't look good on a wide dialog otherwise
|
|
max-width: 300px;
|
|
margin-inline-end: 1px;
|
|
margin-bottom: 10px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
flex-shrink: 0;
|
|
padding-inline: var(--margins-sm);
|
|
border-radius: 100px;
|
|
`;
|
|
|
|
const StyledInput = styled.input`
|
|
width: inherit;
|
|
height: inherit;
|
|
border: none;
|
|
flex-grow: 1;
|
|
font-size: var(--font-size-sm);
|
|
font-family: var(--font-default);
|
|
text-overflow: ellipsis;
|
|
background: none;
|
|
color: var(--search-bar-text-control-color);
|
|
|
|
&:focus {
|
|
color: var(--search-bar-text-user-color);
|
|
outline: none !important;
|
|
}
|
|
`;
|
|
|
|
const doTheSearch = (dispatch: Dispatch<any>, searchOpts: DoSearchActionType) => {
|
|
dispatch(searchActions.search(searchOpts));
|
|
};
|
|
|
|
const debouncedSearch = debounce(doTheSearch, 50);
|
|
|
|
function updateSearch(dispatch: Dispatch<any>, searchOpts: DoSearchActionType) {
|
|
if (!searchOpts.query) {
|
|
dispatch(searchActions.clearSearch());
|
|
return;
|
|
}
|
|
|
|
// this updates our current state and text field.
|
|
dispatch(searchActions.updateSearchTerm(searchOpts));
|
|
|
|
debouncedSearch(dispatch, searchOpts);
|
|
}
|
|
|
|
export const SessionSearchInput = ({ searchType }: { searchType: SearchType }) => {
|
|
const [currentSearchTerm, setCurrentSearchTerm] = useState('');
|
|
const dispatch = getAppDispatch();
|
|
const isGroupCreationSearch = useLeftOverlayMode() === 'closed-group';
|
|
const convoCount = useSelector(getConversationsCount);
|
|
|
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
|
|
useHotkey('Escape', () => {
|
|
if (inputRef.current !== null && inputRef.current === document.activeElement) {
|
|
setCurrentSearchTerm('');
|
|
dispatch(searchActions.clearSearch());
|
|
}
|
|
});
|
|
|
|
// just after onboard we only have a conversation with ourself
|
|
if (convoCount <= 1) {
|
|
return null;
|
|
}
|
|
|
|
const iconSize = 'medium';
|
|
|
|
const placeholder = isGroupCreationSearch ? tr('searchContacts') : tr('search');
|
|
|
|
const isInMainScreen = searchType === 'global' || searchType === 'create-group';
|
|
|
|
const backgroundColor = isInMainScreen ? 'transparent' : undefined;
|
|
|
|
return (
|
|
<StyledSearchInput
|
|
data-testid={isGroupCreationSearch ? 'search-contacts-field' : undefined}
|
|
style={{ backgroundColor }}
|
|
>
|
|
<LucideIcon
|
|
iconColor="var(--search-bar-icon-color)"
|
|
iconSize={iconSize}
|
|
unicode={LUCIDE_ICONS_UNICODE.SEARCH}
|
|
/>
|
|
<StyledInput
|
|
ref={inputRef}
|
|
value={currentSearchTerm}
|
|
onChange={e => {
|
|
const inputValue = e.target.value;
|
|
setCurrentSearchTerm(inputValue);
|
|
updateSearch(dispatch, {
|
|
query: inputValue,
|
|
searchType,
|
|
});
|
|
}}
|
|
placeholder={placeholder}
|
|
style={{ borderWidth: '0' }}
|
|
/>
|
|
{Boolean(currentSearchTerm.length) && (
|
|
<SessionLucideIconButton
|
|
iconColor="var(--search-bar-icon-color)"
|
|
iconSize={iconSize}
|
|
unicode={LUCIDE_ICONS_UNICODE.X}
|
|
onClick={() => {
|
|
setCurrentSearchTerm('');
|
|
dispatch(searchActions.clearSearch());
|
|
}}
|
|
/>
|
|
)}
|
|
</StyledSearchInput>
|
|
);
|
|
};
|