
* Use downloads location as default when clicking "Save as". Remove update from downloads after upgrade when application starts * Fix issue where "addedAt" was extracted from undefined object * Fix tests
135 lines
4.5 KiB
TypeScript
135 lines
4.5 KiB
TypeScript
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import React from 'react';
|
|
import ReactDOM from 'react-dom';
|
|
import classNames from 'classnames';
|
|
import {FormattedMessage} from 'react-intl';
|
|
|
|
import {DownloadedItem} from 'types/downloads';
|
|
|
|
import {
|
|
CLOSE_DOWNLOADS_DROPDOWN,
|
|
REQUEST_CLEAR_DOWNLOADS_DROPDOWN,
|
|
REQUEST_DOWNLOADS_DROPDOWN_INFO,
|
|
SEND_DOWNLOADS_DROPDOWN_SIZE,
|
|
UPDATE_DOWNLOADS_DROPDOWN,
|
|
} from 'common/communication';
|
|
|
|
import IntlProvider from './intl_provider';
|
|
import DownloadsDropdownItem from './components/DownloadsDropdown/DownloadsDropdownItem';
|
|
|
|
import './css/downloadsDropdown.scss';
|
|
|
|
type State = {
|
|
downloads: DownloadedItem[];
|
|
darkMode?: boolean;
|
|
windowBounds?: Electron.Rectangle;
|
|
item?: DownloadedItem;
|
|
}
|
|
|
|
class DownloadsDropdown extends React.PureComponent<Record<string, never>, State> {
|
|
constructor(props: Record<string, never>) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
downloads: [],
|
|
};
|
|
|
|
window.addEventListener('message', this.handleMessageEvent);
|
|
}
|
|
|
|
componentDidMount() {
|
|
window.postMessage({type: REQUEST_DOWNLOADS_DROPDOWN_INFO}, window.location.href);
|
|
}
|
|
|
|
componentDidUpdate() {
|
|
window.postMessage({type: SEND_DOWNLOADS_DROPDOWN_SIZE, data: {width: document.body.scrollWidth, height: document.body.scrollHeight}}, window.location.href);
|
|
}
|
|
|
|
handleMessageEvent = (event: MessageEvent) => {
|
|
if (event.data.type === UPDATE_DOWNLOADS_DROPDOWN) {
|
|
const {downloads, darkMode, windowBounds, item} = event.data.data;
|
|
const newDownloads = Object.values<DownloadedItem>(downloads);
|
|
newDownloads.sort((a, b) => {
|
|
// Show App update first
|
|
if (a.type === 'update') {
|
|
return -1;
|
|
} else if (b.type === 'update') {
|
|
return 1;
|
|
}
|
|
return b?.addedAt - a?.addedAt;
|
|
});
|
|
this.setState({
|
|
downloads: newDownloads,
|
|
darkMode,
|
|
windowBounds,
|
|
item,
|
|
});
|
|
}
|
|
}
|
|
|
|
closeMenu = () => {
|
|
window.postMessage({type: CLOSE_DOWNLOADS_DROPDOWN}, window.location.href);
|
|
}
|
|
|
|
clearAll = () => {
|
|
if (!this.clearAllButtonDisabled()) {
|
|
window.postMessage({type: REQUEST_CLEAR_DOWNLOADS_DROPDOWN}, window.location.href);
|
|
}
|
|
}
|
|
|
|
clearAllButtonDisabled = () => {
|
|
return this.state.downloads?.length === 1 && this.state.downloads[0]?.type === 'update';
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<IntlProvider>
|
|
<div
|
|
className={classNames('DownloadsDropdown', {
|
|
darkMode: this.state.darkMode,
|
|
})}
|
|
>
|
|
<div className='DownloadsDropdown__header'>
|
|
<div className='DownloadsDropdown__Downloads'>
|
|
<FormattedMessage
|
|
id='renderer.downloadsDropdown.Downloads'
|
|
defaultMessage='Downloads'
|
|
/>
|
|
</div>
|
|
<div
|
|
className={classNames('DownloadsDropdown__clearAllButton', {
|
|
disabled: this.clearAllButtonDisabled(),
|
|
})}
|
|
onClick={this.clearAll}
|
|
>
|
|
<FormattedMessage
|
|
id='renderer.downloadsDropdown.ClearAll'
|
|
defaultMessage='Clear All'
|
|
/>
|
|
</div>
|
|
</div>
|
|
<hr className='DownloadsDropdown__divider'/>
|
|
<div className='DownloadsDropdown__list'>
|
|
{(this.state.downloads || []).map((downloadItem: DownloadedItem) => {
|
|
return (
|
|
<DownloadsDropdownItem
|
|
item={downloadItem}
|
|
key={downloadItem.filename}
|
|
activeItem={this.state.item}
|
|
/>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</IntlProvider>
|
|
);
|
|
}
|
|
}
|
|
|
|
ReactDOM.render(
|
|
<DownloadsDropdown/>,
|
|
document.getElementById('app'),
|
|
);
|