Bugfixes for v1.29
* If focus was set to document.body during archive, focus left pane * Shortcut Guide: Add space between text and shortcut highlight * Ensure that draft attachment can be closed with click on X button * Move to keyDown event for user idle checking * Additional resiliency around avatars; check for them on on-disk * Increase timeouts to preserve websocket connection * On startup, be resilient to malformed JSON in log files * Don't crash if shell.openExternal returns an error * Whenever we request a contact/group sync, also request block list * Avatar popup: Ensure styling is mouse- and keyboard-appropriate * MainHeader: Create popperRoot on demand, not on mount * CompositionInput: Disable default Ctrl-/ shortcut * Update libphonenumber
This commit is contained in:
parent
ee9e86ab7a
commit
e9f08c3da9
19 changed files with 300 additions and 128 deletions
|
@ -24,6 +24,7 @@ export interface Props {
|
|||
|
||||
interface State {
|
||||
imageBroken: boolean;
|
||||
lastAvatarPath?: string;
|
||||
}
|
||||
|
||||
export class Avatar extends React.Component<Props, State> {
|
||||
|
@ -35,10 +36,23 @@ export class Avatar extends React.Component<Props, State> {
|
|||
this.handleImageErrorBound = this.handleImageError.bind(this);
|
||||
|
||||
this.state = {
|
||||
lastAvatarPath: props.avatarPath,
|
||||
imageBroken: false,
|
||||
};
|
||||
}
|
||||
|
||||
public static getDerivedStateFromProps(props: Props, state: State): State {
|
||||
if (props.avatarPath !== state.lastAvatarPath) {
|
||||
return {
|
||||
...state,
|
||||
lastAvatarPath: props.avatarPath,
|
||||
imageBroken: false,
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public handleImageError() {
|
||||
// tslint:disable-next-line no-console
|
||||
console.log('Avatar: Image failed to load; failing over to placeholder');
|
||||
|
|
|
@ -700,6 +700,13 @@ export const CompositionInput = ({
|
|||
return null;
|
||||
}
|
||||
|
||||
// Get rid of Ctrl-/, which on GNOME is bound to 'select all'
|
||||
if (e.key === '/' && !e.shiftKey && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return getDefaultKeyBinding(e);
|
||||
},
|
||||
[emojiResults, large]
|
||||
|
|
|
@ -70,15 +70,6 @@ export class MainHeader extends React.Component<PropsType, StateType> {
|
|||
};
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
const popperRoot = document.createElement('div');
|
||||
document.body.appendChild(popperRoot);
|
||||
|
||||
this.setState({
|
||||
popperRoot,
|
||||
});
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps: PropsType) {
|
||||
const { searchConversationId, startSearchCounter } = this.props;
|
||||
|
||||
|
@ -114,28 +105,41 @@ export class MainHeader extends React.Component<PropsType, StateType> {
|
|||
};
|
||||
|
||||
public showAvatarPopup = () => {
|
||||
const popperRoot = document.createElement('div');
|
||||
document.body.appendChild(popperRoot);
|
||||
|
||||
this.setState({
|
||||
showingAvatarPopup: true,
|
||||
popperRoot,
|
||||
});
|
||||
document.addEventListener('click', this.handleOutsideClick);
|
||||
document.addEventListener('keydown', this.handleOutsideKeyDown);
|
||||
};
|
||||
|
||||
public hideAvatarPopup = () => {
|
||||
const { popperRoot } = this.state;
|
||||
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
document.removeEventListener('keydown', this.handleOutsideKeyDown);
|
||||
|
||||
this.setState({
|
||||
showingAvatarPopup: false,
|
||||
popperRoot: null,
|
||||
});
|
||||
|
||||
if (popperRoot) {
|
||||
document.body.removeChild(popperRoot);
|
||||
}
|
||||
};
|
||||
|
||||
public componentWillUnmount() {
|
||||
const { popperRoot } = this.state;
|
||||
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
document.removeEventListener('keydown', this.handleOutsideKeyDown);
|
||||
|
||||
if (popperRoot) {
|
||||
document.body.removeChild(popperRoot);
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
document.removeEventListener('keydown', this.handleOutsideKeyDown);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -162,20 +162,6 @@ export class Image extends React.Component<Props> {
|
|||
alt={i18n('imageCaptionIconAlt')}
|
||||
/>
|
||||
) : null}
|
||||
{closeButton ? (
|
||||
<button
|
||||
onClick={(e: React.MouseEvent<{}>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (onClickClose) {
|
||||
onClickClose(attachment);
|
||||
}
|
||||
}}
|
||||
className="module-image__close-button"
|
||||
title={i18n('remove-attachment')}
|
||||
/>
|
||||
) : null}
|
||||
{bottomOverlay ? (
|
||||
<div
|
||||
className={classNames(
|
||||
|
@ -199,6 +185,20 @@ export class Image extends React.Component<Props> {
|
|||
</div>
|
||||
) : null}
|
||||
{overlay}
|
||||
{closeButton ? (
|
||||
<button
|
||||
onClick={(e: React.MouseEvent<{}>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (onClickClose) {
|
||||
onClickClose(attachment);
|
||||
}
|
||||
}}
|
||||
className="module-image__close-button"
|
||||
title={i18n('remove-attachment')}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue