remove MainHeader class no longer used
parent
71c47ba87a
commit
2335dbab93
@ -1,419 +0,0 @@
|
||||
import React from 'react';
|
||||
import { debounce } from 'lodash';
|
||||
import classNames from 'classnames';
|
||||
|
||||
// Use this to trigger whisper events
|
||||
import { trigger } from '../shims/events';
|
||||
|
||||
// Use this to check for password
|
||||
import { hasPassword } from '../shims/Signal';
|
||||
|
||||
import { Avatar } from './Avatar';
|
||||
import { ContactName } from './conversation/ContactName';
|
||||
|
||||
import { cleanSearchTerm } from '../util/cleanSearchTerm';
|
||||
import { LocalizerType } from '../types/Util';
|
||||
import { SearchOptions } from '../types/Search';
|
||||
import { clipboard } from 'electron';
|
||||
|
||||
import { validateNumber } from '../types/PhoneNumber';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
lokiFeatureFlags: any;
|
||||
}
|
||||
}
|
||||
|
||||
interface MenuItem {
|
||||
id: string;
|
||||
name: string;
|
||||
onClick?: () => void;
|
||||
}
|
||||
export interface Props {
|
||||
searchTerm: string;
|
||||
|
||||
// To be used as an ID
|
||||
ourNumber: string;
|
||||
regionCode: string;
|
||||
|
||||
// For display
|
||||
phoneNumber: string;
|
||||
isMe: boolean;
|
||||
name?: string;
|
||||
color: string;
|
||||
verified: boolean;
|
||||
profileName?: string;
|
||||
avatarPath?: string;
|
||||
isSecondaryDevice: boolean;
|
||||
|
||||
i18n: LocalizerType;
|
||||
updateSearchTerm: (searchTerm: string) => void;
|
||||
search: (query: string, options: SearchOptions) => void;
|
||||
clearSearch: () => void;
|
||||
|
||||
onClick?: () => void;
|
||||
onCopyPublicKey?: () => void;
|
||||
}
|
||||
|
||||
export class MainHeader extends React.Component<Props, any> {
|
||||
private readonly updateSearchBound: (
|
||||
event: React.FormEvent<HTMLInputElement>
|
||||
) => void;
|
||||
private readonly clearSearchBound: () => void;
|
||||
private readonly copyFromClipboardBound: () => void;
|
||||
private readonly handleKeyUpBound: (
|
||||
event: React.KeyboardEvent<HTMLInputElement>
|
||||
) => void;
|
||||
private readonly setFocusBound: () => void;
|
||||
private readonly inputRef: React.RefObject<HTMLInputElement>;
|
||||
private readonly debouncedSearch: (searchTerm: string) => void;
|
||||
private readonly timerId: any;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
expanded: false,
|
||||
hasPass: null,
|
||||
clipboardText: '',
|
||||
menuItems: [],
|
||||
};
|
||||
|
||||
this.updateSearchBound = this.updateSearch.bind(this);
|
||||
this.clearSearchBound = this.clearSearch.bind(this);
|
||||
this.copyFromClipboardBound = this.copyFromClipboard.bind(this);
|
||||
this.handleKeyUpBound = this.handleKeyUp.bind(this);
|
||||
this.setFocusBound = this.setFocus.bind(this);
|
||||
this.inputRef = React.createRef();
|
||||
|
||||
this.debouncedSearch = debounce(this.search.bind(this), 20);
|
||||
|
||||
this.timerId = setInterval(() => {
|
||||
const clipboardText = clipboard.readText();
|
||||
if (this.state.clipboardText !== clipboardText) {
|
||||
this.setState({ clipboardText });
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
public componentWillMount() {
|
||||
// tslint:disable-next-line
|
||||
this.updateHasPass();
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
// tslint:disable-next-line
|
||||
clearInterval(this.timerId);
|
||||
}
|
||||
|
||||
public componentDidUpdate(_prevProps: Props, prevState: any) {
|
||||
if (
|
||||
prevState.hasPass !== this.state.hasPass ||
|
||||
_prevProps.isSecondaryDevice !== this.props.isSecondaryDevice
|
||||
) {
|
||||
this.updateMenuItems();
|
||||
}
|
||||
}
|
||||
|
||||
public search() {
|
||||
const {
|
||||
searchTerm,
|
||||
search,
|
||||
i18n,
|
||||
ourNumber,
|
||||
regionCode,
|
||||
isSecondaryDevice,
|
||||
} = this.props;
|
||||
if (search) {
|
||||
search(searchTerm, {
|
||||
noteToSelf: i18n('noteToSelf').toLowerCase(),
|
||||
ourNumber,
|
||||
regionCode,
|
||||
isSecondaryDevice,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public updateSearch(event: React.FormEvent<HTMLInputElement>) {
|
||||
const { updateSearchTerm, clearSearch } = this.props;
|
||||
const searchTerm = event.currentTarget.value;
|
||||
|
||||
if (!searchTerm) {
|
||||
clearSearch();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateSearchTerm) {
|
||||
updateSearchTerm(searchTerm);
|
||||
}
|
||||
|
||||
if (searchTerm.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cleanedTerm = cleanSearchTerm(searchTerm);
|
||||
if (!cleanedTerm) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.debouncedSearch(cleanedTerm);
|
||||
}
|
||||
|
||||
public clearSearch() {
|
||||
const { clearSearch } = this.props;
|
||||
|
||||
clearSearch();
|
||||
this.setFocus();
|
||||
}
|
||||
|
||||
public copyFromClipboard() {
|
||||
const { clipboardText } = this.state;
|
||||
|
||||
this.props.updateSearchTerm(clipboardText);
|
||||
this.debouncedSearch(clipboardText);
|
||||
}
|
||||
|
||||
public handleKeyUp(event: React.KeyboardEvent<HTMLInputElement>) {
|
||||
const { clearSearch } = this.props;
|
||||
|
||||
if (event.key === 'Escape') {
|
||||
clearSearch();
|
||||
}
|
||||
}
|
||||
|
||||
public setFocus() {
|
||||
if (this.inputRef.current) {
|
||||
// @ts-ignore
|
||||
this.inputRef.current.focus();
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { onClick } = this.props;
|
||||
|
||||
return (
|
||||
<div role="button" className="module-main-header" onClick={onClick}>
|
||||
<div className="module-main-header__container">
|
||||
{this.renderName()}
|
||||
{this.renderMenu()}
|
||||
</div>
|
||||
{this.renderSearch()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderName() {
|
||||
const {
|
||||
avatarPath,
|
||||
i18n,
|
||||
color,
|
||||
name,
|
||||
phoneNumber,
|
||||
profileName,
|
||||
} = this.props;
|
||||
|
||||
const { expanded } = this.state;
|
||||
|
||||
return (
|
||||
<div
|
||||
role="button"
|
||||
className="module-main-header__title"
|
||||
onClick={() => {
|
||||
this.setState({ expanded: !expanded });
|
||||
}}
|
||||
>
|
||||
<Avatar
|
||||
avatarPath={avatarPath}
|
||||
color={color}
|
||||
conversationType="direct"
|
||||
i18n={i18n}
|
||||
name={name}
|
||||
phoneNumber={phoneNumber}
|
||||
profileName={profileName}
|
||||
size={28}
|
||||
/>
|
||||
<div className="module-main-header__contact-name">
|
||||
<ContactName
|
||||
phoneNumber={phoneNumber}
|
||||
profileName={profileName}
|
||||
i18n={i18n}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={classNames(
|
||||
'module-main-header-content-toggle',
|
||||
expanded && 'module-main-header-content-toggle-visible'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderMenu() {
|
||||
const { expanded, menuItems } = this.state;
|
||||
|
||||
return (
|
||||
<div className="module-main-header__menu">
|
||||
<div className={classNames('accordian', expanded && 'expanded')}>
|
||||
{menuItems.map((item: MenuItem) => (
|
||||
<div
|
||||
role="button"
|
||||
className="menu-item"
|
||||
key={item.id}
|
||||
onClick={item.onClick}
|
||||
>
|
||||
{item.name}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private shouldShowPaste() {
|
||||
const { searchTerm, i18n } = this.props;
|
||||
const { clipboardText } = this.state;
|
||||
|
||||
const error = validateNumber(clipboardText, i18n);
|
||||
|
||||
return !searchTerm && !error;
|
||||
}
|
||||
|
||||
private renderSearch() {
|
||||
const { searchTerm, i18n } = this.props;
|
||||
|
||||
return (
|
||||
<div className="module-main-header__search">
|
||||
<input
|
||||
type="text"
|
||||
ref={this.inputRef}
|
||||
className="module-main-header__search__input"
|
||||
placeholder={i18n('search')}
|
||||
dir="auto"
|
||||
onKeyUp={this.handleKeyUpBound}
|
||||
value={searchTerm}
|
||||
onChange={this.updateSearchBound}
|
||||
/>
|
||||
{this.shouldShowPaste() ? (
|
||||
<span
|
||||
role="button"
|
||||
className="module-main-header__search__copy-from-clipboard"
|
||||
onClick={this.copyFromClipboardBound}
|
||||
/>
|
||||
) : null}
|
||||
<span
|
||||
role="button"
|
||||
className="module-main-header__search__icon"
|
||||
onClick={this.setFocusBound}
|
||||
/>
|
||||
{searchTerm ? (
|
||||
<span
|
||||
role="button"
|
||||
className="module-main-header__search__cancel-icon"
|
||||
onClick={this.clearSearchBound}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private async updateHasPass() {
|
||||
const hasPass = await hasPassword();
|
||||
this.setState({ hasPass });
|
||||
}
|
||||
|
||||
private updateMenuItems() {
|
||||
const { i18n, onCopyPublicKey, isSecondaryDevice } = this.props;
|
||||
const { hasPass } = this.state;
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
id: 'copyPublicKey',
|
||||
name: i18n('copyPublicKey'),
|
||||
onClick: onCopyPublicKey,
|
||||
},
|
||||
{
|
||||
id: 'showSeed',
|
||||
name: i18n('showSeed'),
|
||||
onClick: () => {
|
||||
trigger('showSeedDialog');
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'showQRCode',
|
||||
name: i18n('showQRCode'),
|
||||
onClick: () => {
|
||||
trigger('showQRDialog');
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'showAddServer',
|
||||
name: i18n('showAddServer'),
|
||||
onClick: () => {
|
||||
trigger('showAddServerDialog');
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (window.lokiFeatureFlags.privateGroupChats) {
|
||||
menuItems.push({
|
||||
id: 'createPrivateGroup',
|
||||
name: i18n('createPrivateGroup'),
|
||||
onClick: () => {
|
||||
trigger('createNewGroup');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const passItem = (type: string) => ({
|
||||
id: `${type}Password`,
|
||||
name: i18n(`${type}Password`),
|
||||
onClick: () => {
|
||||
trigger('showPasswordDialog', {
|
||||
type,
|
||||
resolve: () => {
|
||||
trigger('showToast', {
|
||||
message: i18n(`${type}PasswordSuccess`),
|
||||
});
|
||||
setTimeout(async () => this.updateHasPass(), 100);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
if (hasPass) {
|
||||
menuItems.push(passItem('change'), passItem('remove'));
|
||||
} else {
|
||||
menuItems.push(passItem('set'));
|
||||
}
|
||||
|
||||
if (!isSecondaryDevice) {
|
||||
// insert as second element
|
||||
menuItems.splice(1, 0, {
|
||||
id: 'editProfile',
|
||||
name: i18n('editProfile'),
|
||||
onClick: () => {
|
||||
trigger('onEditProfile');
|
||||
},
|
||||
});
|
||||
menuItems.push({
|
||||
id: 'pairNewDevice',
|
||||
name: 'Device Pairing',
|
||||
onClick: () => {
|
||||
trigger('showDevicePairingDialog');
|
||||
},
|
||||
});
|
||||
} else {
|
||||
menuItems.push({
|
||||
id: 'showPairingWords',
|
||||
name: 'Show Pairing Words',
|
||||
onClick: () => {
|
||||
trigger('showDevicePairingWordsDialog');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({ menuItems });
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { mapDispatchToProps } from '../actions';
|
||||
|
||||
import { MainHeader } from '../../components/MainHeader';
|
||||
import { StateType } from '../reducer';
|
||||
|
||||
import { getQuery } from '../selectors/search';
|
||||
import {
|
||||
getIntl,
|
||||
getIsSecondaryDevice,
|
||||
getRegionCode,
|
||||
getUserNumber,
|
||||
} from '../selectors/user';
|
||||
import { getMe } from '../selectors/conversations';
|
||||
|
||||
const mapStateToProps = (state: StateType) => {
|
||||
return {
|
||||
searchTerm: getQuery(state),
|
||||
regionCode: getRegionCode(state),
|
||||
ourNumber: getUserNumber(state),
|
||||
isSecondaryDevice: getIsSecondaryDevice(state),
|
||||
...getMe(state),
|
||||
i18n: getIntl(state),
|
||||
};
|
||||
};
|
||||
|
||||
const smart = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
export const SmartMainHeader = smart(MainHeader);
|
Loading…
Reference in New Issue