move search logic to the search input component
This commit is contained in:
parent
44f61073dc
commit
40344bde52
|
@ -252,11 +252,7 @@
|
|||
"StartupWMClass": "Session"
|
||||
},
|
||||
"asarUnpack": "node_modules/spellchecker/vendor/hunspell_dictionaries",
|
||||
"target": [
|
||||
"deb",
|
||||
"rpm",
|
||||
"freebsd"
|
||||
],
|
||||
"target": ["deb", "rpm", "freebsd"],
|
||||
"icon": "build/icon.icns"
|
||||
},
|
||||
"asarUnpack": [
|
||||
|
|
|
@ -1,16 +1,40 @@
|
|||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { debounce } from 'lodash';
|
||||
import React, { Dispatch, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { clearSearch, search, updateSearchTerm } from '../state/ducks/search';
|
||||
import { getConversationsCount } from '../state/selectors/conversations';
|
||||
import { cleanSearchTerm } from '../util/cleanSearchTerm';
|
||||
import { SessionIconButton } from './icon';
|
||||
|
||||
type Props = {
|
||||
searchString: string;
|
||||
onChange: any;
|
||||
placeholder: string;
|
||||
const doTheSearch = (dispatch: Dispatch<any>, cleanedTerm: string) => {
|
||||
dispatch(search(cleanedTerm));
|
||||
};
|
||||
|
||||
export const SessionSearchInput = (props: Props) => {
|
||||
const { searchString, onChange, placeholder } = props;
|
||||
const debouncedSearch = debounce(doTheSearch, 50);
|
||||
|
||||
function updateSearch(dispatch: Dispatch<any>, searchTerm: string) {
|
||||
if (!searchTerm) {
|
||||
dispatch(clearSearch());
|
||||
return;
|
||||
}
|
||||
|
||||
// this updates our current state and text field.
|
||||
dispatch(updateSearchTerm(searchTerm));
|
||||
|
||||
if (searchTerm.length < 2) {
|
||||
return;
|
||||
}
|
||||
// this effectively trigger a search
|
||||
const cleanedTerm = cleanSearchTerm(searchTerm);
|
||||
if (!cleanedTerm) {
|
||||
return;
|
||||
}
|
||||
|
||||
debouncedSearch(dispatch, searchTerm);
|
||||
}
|
||||
export const SessionSearchInput = () => {
|
||||
const [currentSearchTerm, setCurrentSearchTerm] = useState('');
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const convoCount = useSelector(getConversationsCount);
|
||||
|
||||
|
@ -23,10 +47,24 @@ export const SessionSearchInput = (props: Props) => {
|
|||
<div className="session-search-input">
|
||||
<SessionIconButton iconSize="medium" iconType="search" />
|
||||
<input
|
||||
value={searchString}
|
||||
onChange={e => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
value={currentSearchTerm}
|
||||
onChange={e => {
|
||||
const inputValue = e.target.value;
|
||||
setCurrentSearchTerm(inputValue);
|
||||
updateSearch(dispatch, inputValue);
|
||||
}}
|
||||
placeholder={window.i18n('searchFor...')}
|
||||
/>
|
||||
{!!currentSearchTerm.length && (
|
||||
<SessionIconButton
|
||||
iconSize="tiny"
|
||||
iconType="exit"
|
||||
onClick={() => {
|
||||
setCurrentSearchTerm('');
|
||||
dispatch(clearSearch());
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useSelector } from 'react-redux';
|
|||
import { SectionType } from '../../state/ducks/section';
|
||||
import { SessionTheme } from '../../state/ducks/SessionTheme';
|
||||
import { getLeftPaneLists } from '../../state/selectors/conversations';
|
||||
import { getQuery, getSearchResults, isSearching } from '../../state/selectors/search';
|
||||
import { getSearchResults, isSearching } from '../../state/selectors/search';
|
||||
import { getFocusedSection, getOverlayMode } from '../../state/selectors/section';
|
||||
import { getIsMessageRequestsEnabled } from '../../state/selectors/userConfig';
|
||||
import { ActionsPanel } from './ActionsPanel';
|
||||
|
@ -24,7 +24,6 @@ export type RowRendererParamsType = {
|
|||
|
||||
const InnerLeftPaneMessageSection = () => {
|
||||
const showSearch = useSelector(isSearching);
|
||||
const searchTerm = useSelector(getQuery);
|
||||
|
||||
const searchResults = showSearch ? useSelector(getSearchResults) : undefined;
|
||||
|
||||
|
@ -38,7 +37,6 @@ const InnerLeftPaneMessageSection = () => {
|
|||
conversations={lists?.conversations || []}
|
||||
contacts={lists?.contacts || []}
|
||||
searchResults={searchResults}
|
||||
searchTerm={searchTerm}
|
||||
messageRequestsEnabled={messageRequestsEnabled}
|
||||
overlayMode={overlayMode}
|
||||
/>
|
||||
|
|
|
@ -6,14 +6,11 @@ import {
|
|||
} from './conversation-list-item/ConversationListItem';
|
||||
import { ReduxConversationType } from '../../state/ducks/conversations';
|
||||
import { SearchResults, SearchResultsProps } from '../search/SearchResults';
|
||||
import { UserUtils } from '../../session/utils';
|
||||
import { LeftPaneSectionHeader } from './LeftPaneSectionHeader';
|
||||
import autoBind from 'auto-bind';
|
||||
import { clearSearch, search, updateSearchTerm } from '../../state/ducks/search';
|
||||
import _ from 'lodash';
|
||||
import { MessageRequestsBanner } from './MessageRequestsBanner';
|
||||
|
||||
import { cleanSearchTerm } from '../../util/cleanSearchTerm';
|
||||
import { SessionButton, SessionButtonColor, SessionButtonType } from '../basic/SessionButton';
|
||||
import { SessionSearchInput } from '../SessionSearchInput';
|
||||
import { RowRendererParamsType } from './LeftPane';
|
||||
|
@ -24,8 +21,6 @@ import { OverlayClosedGroup } from './overlay/OverlayClosedGroup';
|
|||
import { OverlayMode, setOverlayMode } from '../../state/ducks/section';
|
||||
|
||||
export interface Props {
|
||||
searchTerm: string;
|
||||
|
||||
contacts: Array<ReduxConversationType>;
|
||||
conversations?: Array<ConversationListItemProps>;
|
||||
searchResults?: SearchResultsProps;
|
||||
|
@ -35,13 +30,10 @@ export interface Props {
|
|||
}
|
||||
|
||||
export class LeftPaneMessageSection extends React.Component<Props> {
|
||||
private readonly debouncedSearch: (searchTerm: string) => void;
|
||||
|
||||
public constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
autoBind(this);
|
||||
this.debouncedSearch = _.debounce(this.search.bind(this), 50);
|
||||
}
|
||||
|
||||
public renderRow = ({ index, key, style }: RowRendererParamsType): JSX.Element | null => {
|
||||
|
@ -117,11 +109,7 @@ export class LeftPaneMessageSection extends React.Component<Props> {
|
|||
public renderConversations() {
|
||||
return (
|
||||
<div className="module-conversations-list-content">
|
||||
<SessionSearchInput
|
||||
searchString={this.props.searchTerm}
|
||||
onChange={this.updateSearch}
|
||||
placeholder={window.i18n('searchFor...')}
|
||||
/>
|
||||
<SessionSearchInput />
|
||||
{window.lokiFeatureFlags.useMessageRequests ? (
|
||||
<MessageRequestsBanner
|
||||
handleOnClick={() => {
|
||||
|
@ -135,44 +123,6 @@ export class LeftPaneMessageSection extends React.Component<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
public updateSearch(searchTerm: string) {
|
||||
if (!searchTerm) {
|
||||
window.inboxStore?.dispatch(clearSearch());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// reset our pubKeyPasted, we can either have a pasted sessionID or a sessionID got from a search
|
||||
this.setState({ valuePasted: '' });
|
||||
|
||||
window.inboxStore?.dispatch(updateSearchTerm(searchTerm));
|
||||
|
||||
if (searchTerm.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cleanedTerm = cleanSearchTerm(searchTerm);
|
||||
if (!cleanedTerm) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.debouncedSearch(cleanedTerm);
|
||||
}
|
||||
|
||||
private clearSearch() {
|
||||
window.inboxStore?.dispatch(clearSearch());
|
||||
}
|
||||
|
||||
private search() {
|
||||
const { searchTerm } = this.props;
|
||||
window.inboxStore?.dispatch(
|
||||
search(searchTerm, {
|
||||
noteToSelf: window.i18n('noteToSelf').toLowerCase(),
|
||||
ourNumber: UserUtils.getOurPubKeyStrFromCache(),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private renderClosableOverlay() {
|
||||
const { overlayMode } = this.props;
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ const StyledSeparatorSection = styled.div`
|
|||
|
||||
color: var(--color-text);
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
`;
|
||||
|
||||
|
@ -41,7 +41,7 @@ const NoResults = styled.div`
|
|||
export const SearchResults = (props: SearchResultsProps) => {
|
||||
const { contactsAndGroups, messages, searchTerm } = props;
|
||||
|
||||
const haveContactsAndGroup = contactsAndGroups?.length;
|
||||
const haveContactsAndGroup = Boolean(contactsAndGroups?.length);
|
||||
const haveMessages = Boolean(messages?.length);
|
||||
const noResults = !haveContactsAndGroup && !haveMessages;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ export function useMembersAvatars(closedGroupPubkey: string | undefined) {
|
|||
return undefined;
|
||||
}
|
||||
// this must be a closed group
|
||||
const originalMembers = groupConvo.members;
|
||||
const originalMembers = _.cloneDeep(groupConvo.members);
|
||||
if (!originalMembers || originalMembers.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -465,7 +465,6 @@ function handleMessageChangedOrAdded(
|
|||
if (state.showScrollButton) {
|
||||
return state;
|
||||
}
|
||||
console.warn('messages should be added at the bottom only if it is in the current view');
|
||||
// sorting happens in the selector
|
||||
|
||||
state.messages.push(changedOrAddedMessageProps);
|
||||
|
|
|
@ -8,6 +8,7 @@ import { ConversationTypeEnum } from '../../models/conversation';
|
|||
import _ from 'lodash';
|
||||
import { getConversationController } from '../../session/conversations';
|
||||
import { MessageResultProps } from '../../components/search/MessageSearchResults';
|
||||
import { UserUtils } from '../../session/utils';
|
||||
|
||||
// State
|
||||
|
||||
|
@ -59,14 +60,18 @@ export const actions = {
|
|||
updateSearchTerm,
|
||||
};
|
||||
|
||||
export function search(query: string, options: SearchOptions): SearchResultsKickoffActionType {
|
||||
export function search(query: string): SearchResultsKickoffActionType {
|
||||
return {
|
||||
type: 'SEARCH_RESULTS',
|
||||
payload: doSearch(query, options), // this uses redux-promise-middleware
|
||||
payload: doSearch(query), // this uses redux-promise-middleware
|
||||
};
|
||||
}
|
||||
|
||||
async function doSearch(query: string, options: SearchOptions): Promise<SearchResultsPayloadType> {
|
||||
async function doSearch(query: string): Promise<SearchResultsPayloadType> {
|
||||
const options: SearchOptions = {
|
||||
noteToSelf: window.i18n('noteToSelf').toLowerCase(),
|
||||
ourNumber: UserUtils.getOurPubKeyStrFromCache(),
|
||||
};
|
||||
const advancedSearchOptions = getAdvancedSearchOptionsFromQuery(query);
|
||||
const processedQuery = advancedSearchOptions.query;
|
||||
// const isAdvancedQuery = query !== processedQuery;
|
||||
|
|
|
@ -196,6 +196,7 @@ export async function autoScale<T extends { contentType: string; blob: Blob }>(
|
|||
let i = 4;
|
||||
do {
|
||||
i -= 1;
|
||||
window.log.info('autoscale of ', attachment, i);
|
||||
readAndResizedBlob = dataURLToBlob(
|
||||
(canvas.image as HTMLCanvasElement).toDataURL('image/jpeg', quality)
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue