do not show search input if we only got a single conversation

This commit is contained in:
audric 2021-08-26 16:44:58 +10:00
parent 714024fb1f
commit 985a5d92bc
7 changed files with 54 additions and 164 deletions

View File

@ -131,7 +131,7 @@
"deleteForEveryone": "Delete for Everyone",
"deleteConversationConfirmation": "Permanently delete the messages in this conversation?",
"clearAllData": "Clear All Data",
"deleteAccountWarning": "This will permanently delete your messages, sessions, and contacts.",
"deleteAccountWarning": "This will permanently delete your messages and contacts.",
"deleteContactConfirmation": "Are you sure you want to delete this conversation?",
"quoteThumbnailAlt": "Thumbnail of image from quoted message",
"imageAttachmentAlt": "Image attached to message",
@ -337,6 +337,8 @@
"onlyAdminCanRemoveMembersDesc": "Only the creator of the group can remove users",
"createAccount": "Create account",
"signIn": "Sign In",
"startInTrayTitle": "Start in Tray",
"startInTrayDescription": "Start Session as a minified app ",
"yourUniqueSessionID": "Say hello to your Session ID",
"allUsersAreRandomly...": "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.",
"getStarted": "Get started",
@ -419,5 +421,15 @@
"latestUnreadIsAbove": "First unread message is above",
"sendRecoveryPhraseTitle": "Sending Recovery Phrase",
"sendRecoveryPhraseMessage": "You are attempting to send your recovery phrase which can be used to access your account. Are you sure you want to send this message?",
"dialogClearAllDataDeletionFailedTitle": "Data not deleted",
"dialogClearAllDataDeletionFailedDesc": "Data not deleted with an unknown error. Do you want to delete data from just this device?",
"dialogClearAllDataDeletionFailedTitleQuestion": "Do you want to delete data from just this device?",
"dialogClearAllDataDeletionFailedMultiple": "Data not deleted by those Service Nodes: $snodes$",
"dialogClearAllDataDeletionQuestion": "Would you like to clear only this device, or delete your entire account?",
"deviceOnly": "Device Only",
"entireAccount": "Entire Account",
"recoveryPhraseSecureTitle": "You're almost finished!",
"recoveryPhraseRevealMessage": "Secure your account by saving your recovery phrase. Reveal your recovery phrase then store it safely to secure it.",
"recoveryPhraseRevealButtonText": "Reveal Recovery Phrase",
"notificationSubtitle": "Notifications - $setting$"
}

View File

@ -8,6 +8,8 @@ import { disableRecoveryPhrasePrompt } from '../../state/ducks/userConfig';
import { getShowRecoveryPhrasePrompt } from '../../state/selectors/userConfig';
import { recoveryPhraseModal } from '../../state/ducks/modalDialog';
import { Flex } from '../basic/Flex';
import { getFocusedSection } from '../../state/selectors/section';
import { SectionType } from '../../state/ducks/section';
const Tab = ({
isSelected,
@ -71,6 +73,8 @@ export const LeftPaneSectionHeader = (props: Props) => {
export const LeftPaneBanner = () => {
const dispatch = useDispatch();
const section = useSelector(getFocusedSection);
const showRecoveryPhraseModal = () => {
dispatch(
recoveryPhraseModal({
@ -81,6 +85,10 @@ export const LeftPaneBanner = () => {
);
};
if (section !== SectionType.Message) {
return null;
}
const BannerInner = () => {
return (
<StyledBannerInner>

View File

@ -2,7 +2,6 @@ import React from 'react';
import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
import { SessionIdEditable } from './SessionIdEditable';
import { UserSearchDropdown } from './UserSearchDropdown';
import { ContactType, SessionMemberListItem } from './SessionMemberListItem';
import { ReduxConversationType } from '../../state/ducks/conversations';
import { SessionButton, SessionButtonColor, SessionButtonType } from './SessionButton';
@ -100,16 +99,7 @@ export class SessionClosableOverlay extends React.Component<Props, State> {
// tslint:disable-next-line max-func-body-length cyclomatic-complexity */
public render(): JSX.Element {
const {
overlayMode,
onCloseClick,
onChangeSessionID,
showSpinner,
searchTerm,
updateSearch,
searchResults,
onButtonClick,
} = this.props;
const { overlayMode, onCloseClick, onChangeSessionID, showSpinner, onButtonClick } = this.props;
const { groupName, selectedMembers } = this.state;
@ -218,16 +208,7 @@ export class SessionClosableOverlay extends React.Component<Props, State> {
{descriptionLong && <div className="session-description-long">{descriptionLong}</div>}
{isMessageView && false && <h4>{window.i18n('or')}</h4>}
{/* FIXME enable back those two items when they are working */}
{isOpenGroupView && <SessionJoinableRooms onRoomClicked={this.props.onCloseClick} />}
{isMessageView && false && (
<UserSearchDropdown
searchTerm={searchTerm || ''}
updateSearch={updateSearch}
placeholder={window.i18n('searchFor...')}
searchResults={searchResults}
/>
)}
<SessionButton
buttonColor={SessionButtonColor.Green}

View File

@ -1,65 +1,32 @@
import React from 'react';
import { animation, contextMenu, Item, Menu } from 'react-contexify';
import { useSelector } from 'react-redux';
import { getConversationsCount } from '../../state/selectors/conversations';
import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
interface Props {
searchString: string;
onChange: any;
handleNavigation?: any;
placeholder: string;
}
export class SessionSearchInput extends React.Component<Props> {
public constructor(props: Props) {
super(props);
this.handleKeyDown = this.handleKeyDown.bind(this);
export const SessionSearchInput = (props: Props) => {
const { searchString, onChange, placeholder } = props;
const convoCount = useSelector(getConversationsCount);
// just after onboard we only have a conversation with ourself
if (convoCount <= 1) {
return null;
}
public render() {
const { searchString } = this.props;
const triggerId = 'session-search-input-context';
return (
<>
<div
className="session-search-input"
onContextMenu={(e: any) => {
contextMenu.show({
id: triggerId,
event: e,
});
}}
>
<SessionIconButton iconSize={SessionIconSize.Medium} iconType={SessionIconType.Search} />
<input
value={searchString}
onChange={e => this.props.onChange(e.target.value)}
onKeyDown={this.handleKeyDown}
placeholder={this.props.placeholder}
/>
</div>
<Menu id={triggerId} animation={animation.fade}>
<Item onClick={() => document.execCommand('undo')}>{window.i18n('editMenuUndo')}</Item>
<Item onClick={() => document.execCommand('redo')}>{window.i18n('editMenuRedo')}</Item>
<hr />
<Item onClick={() => document.execCommand('cut')}>{window.i18n('editMenuCut')}</Item>
<Item onClick={() => document.execCommand('copy')}>{window.i18n('editMenuCopy')}</Item>
<Item onClick={() => document.execCommand('paste')}>{window.i18n('editMenuPaste')}</Item>
<Item onClick={() => document.execCommand('selectAll')}>
{window.i18n('editMenuSelectAll')}
</Item>
</Menu>
</>
);
}
public handleKeyDown(e: any) {
if (e.keyCode === 38 || e.keyCode === 40 || e.key === 'Enter') {
// Up or Bottom arrow pressed
if (this.props.handleNavigation) {
e.stopPropagation();
this.props.handleNavigation(e);
}
}
}
}
return (
<div className="session-search-input">
<SessionIconButton iconSize={SessionIconSize.Medium} iconType={SessionIconType.Search} />
<input
value={searchString}
onChange={e => onChange(e.target.value)}
placeholder={placeholder}
/>
</div>
);
};

View File

@ -1,86 +0,0 @@
import React from 'react';
import { UserSearchResults } from '../UserSearchResults';
import { SessionSearchInput } from './SessionSearchInput';
import { SearchResultsProps } from '../SearchResults';
import autoBind from 'auto-bind';
export interface Props {
searchTerm: string;
placeholder: string;
searchResults?: SearchResultsProps;
updateSearch: (searchTerm: string) => void;
}
interface State {
selectedContact: number;
}
export class UserSearchDropdown extends React.Component<Props, State> {
public constructor(props: Props) {
super(props);
autoBind(this);
this.state = {
selectedContact: -1,
};
}
public handleNavigation(e: any) {
const { selectedContact } = this.state;
const { searchResults } = this.props;
// arrow up/down button should select next/previous list element
if (
e.keyCode === 38 &&
selectedContact > 0 &&
searchResults &&
searchResults.contacts.length > 0
) {
this.setState(prevState => ({
selectedContact: +prevState.selectedContact - 1,
}));
} else if (
e.keyCode === 40 &&
searchResults &&
selectedContact < searchResults.contacts.length - 1
) {
this.setState(prevState => ({
selectedContact: +prevState.selectedContact + 1,
}));
} else if (e.key === 'Enter' && searchResults && searchResults.contacts.length > 0) {
this.handleContactSelected(searchResults.contacts[selectedContact].phoneNumber);
}
}
public render() {
const { searchResults, placeholder } = this.props;
const { selectedContact } = this.state;
return (
<div className="user-search-dropdown">
<SessionSearchInput
searchString={this.props.searchTerm}
onChange={this.updateSearch}
placeholder={placeholder}
handleNavigation={this.handleNavigation}
/>
{searchResults && (
<UserSearchResults
{...searchResults}
selectedContact={selectedContact}
onContactSelected={this.handleContactSelected}
/>
)}
</div>
);
}
public updateSearch(data: string) {
this.setState({ selectedContact: -1 });
this.props.updateSearch(data);
}
public handleContactSelected(key: string) {
this.updateSearch(key);
}
}

View File

@ -33,12 +33,16 @@ export const persistConfig = {
const persistedReducer = persistReducer(persistConfig, rootReducer);
// Exclude logger if we're in production mode
const disableLogging = env === 'production' || true; // ALWAYS TURNED OFF
const middlewareList = disableLogging ? [promise] : [promise, logger];
const disableLogging = true; //; env === 'production' || true; // ALWAYS TURNED OFF
const middlewareList = disableLogging ? [] : [logger];
export const createStore = (initialState: any) =>
configureStore({
reducer: persistedReducer,
preloadedState: initialState,
middleware: (getDefaultMiddleware: any) => getDefaultMiddleware().concat(middlewareList),
middleware: (getDefaultMiddleware: any) =>
getDefaultMiddleware({
serializableCheck: false,
immutableCheck: false,
}).concat(middlewareList),
});

View File

@ -46,6 +46,10 @@ export const getConversationLookup = createSelector(
}
);
export const getConversationsCount = createSelector(getConversationLookup, (state): number => {
return Object.values(state).length;
});
export const getSelectedConversationKey = createSelector(
getConversations,
(state: ConversationsStateType): string | undefined => {