Turn update message into notification

Summary: Based on discussion in D25805957 (ffeb47ed75), instead of showing a warning icon in the siderail, Flipper now shows a notification if there is a version / launcher issue or an update available

Reviewed By: nikoant

Differential Revision: D25924534

fbshipit-source-id: 625e46e41d9aa58f49e8bb77e5c513de0ddfbd6a
This commit is contained in:
Michel Weststrate
2021-01-19 07:07:33 -08:00
committed by Facebook GitHub Bot
parent 6f75e39ca5
commit 84c05d441d

View File

@@ -7,123 +7,112 @@
* @format
*/
import {LauncherMsg} from '../reducers/application';
import {FlexRow, Glyph, styled} from '../ui';
import {Tooltip} from 'antd';
import {notification, Typography} from 'antd';
import isProduction from '../utils/isProduction';
import {
checkForUpdate,
VersionCheckResult,
} from '../utils/publicVersionChecker';
import {reportPlatformFailures} from '../utils/metrics';
import React from 'react';
import {shell} from 'electron';
import React, {useEffect, useState} from 'react';
import config from '../utils/processConfig';
import fbConfig from '../fb-stubs/config';
import {useStore} from '../utils/useStore';
import {remote} from 'electron';
import {theme} from 'flipper-plugin';
const version = remote.app.getVersion();
const Container = styled(FlexRow)({
alignItems: 'center',
export default function UpdateIndicator() {
const [versionCheckResult, setVersionCheckResult] = useState<
VersionCheckResult
>({kind: 'up-to-date'});
const launcherMsg = useStore((state) => state.application.launcherMsg);
// Effect to show notification if details change
useEffect(() => {
switch (versionCheckResult.kind) {
case 'up-to-date':
break;
case 'update-available':
console.log(
`Flipper update available: ${versionCheckResult.version} at ${versionCheckResult.url}`,
);
notification.info({
placement: 'bottomLeft',
key: 'flipperupdatecheck',
message: 'Update available',
description: (
<>
Flipper version {versionCheckResult.version} is now available.
{fbConfig.isFBBuild ? (
<>
{' '}
Pull <code>~/fbsource</code> and/or restart Flipper to update
to the latest version.
</>
) : (
<>
{' '}
Click to{' '}
<Typography.Link href={versionCheckResult.url}>
download
</Typography.Link>
.
</>
)}
</>
),
duration: null, // no auto close
});
type Props = {
launcherMsg: LauncherMsg;
version: string;
};
type State = {
versionCheckResult: VersionCheckResult;
};
function getSeverityColor(severity: 'warning' | 'error'): string {
switch (severity) {
case 'warning':
return theme.warningColor;
break;
case 'error':
return theme.errorColor;
}
}
class UpdateIndicatorImpl extends React.PureComponent<Props, State> {
state = {
versionCheckResult: {kind: 'up-to-date'} as VersionCheckResult,
};
renderMessage(): React.ReactNode {
if (this.props.launcherMsg.message.length == 0) {
return null;
}
return (
<Container>
<span title={this.props.launcherMsg.message}>
<Glyph
color={getSeverityColor(this.props.launcherMsg.severity)}
name="caution-triangle"
/>
</span>
</Container>
console.warn(
`Failed to check for Flipper update: ${versionCheckResult.msg}`,
);
break;
}
}, [versionCheckResult]);
renderUpdateIndicator(): React.ReactNode {
const result = this.state.versionCheckResult;
if (result.kind !== 'update-available') {
return null;
// trigger the update check, unless there is a launcher message already
useEffect(() => {
if (launcherMsg && launcherMsg.message) {
if (launcherMsg.severity === 'error') {
notification.error({
placement: 'bottomLeft',
key: 'launchermsg',
message: 'Launch problem',
description: launcherMsg.message,
duration: null,
});
} else {
notification.warning({
placement: 'bottomLeft',
key: 'launchermsg',
message: 'Flipper version warning',
description: launcherMsg.message,
duration: null,
});
}
const container = (
<Container>
<span
onClick={() => shell.openExternal(result.url)}
role="button"
tabIndex={0}>
<Glyph
color={getSeverityColor(this.props.launcherMsg.severity)}
name="caution-triangle"
/>
</span>
</Container>
);
return (
<Tooltip
placement="right"
title={`Update to Flipper v${result.version} available. Click to download.`}
children={container}
/>
);
}
componentDidMount() {
if (isProduction() && (config().launcherEnabled || !fbConfig.isFBBuild)) {
} else if (
isProduction() &&
(config().launcherEnabled || !fbConfig.isFBBuild)
) {
reportPlatformFailures(
checkForUpdate(this.props.version).then((res) => {
checkForUpdate(version).then((res) => {
if (res.kind === 'error') {
console.warn('Version check failure: ', res.msg);
throw new Error(res.msg);
console.warn('Version check failure: ', res);
setVersionCheckResult({
kind: 'error',
msg: res.msg,
});
} else {
setVersionCheckResult(res);
}
this.setState({versionCheckResult: res});
}),
'publicVersionCheck',
);
}
}
}, [launcherMsg]);
render(): React.ReactNode {
return (
<>
{this.renderMessage()}
{this.renderUpdateIndicator()}
</>
);
}
}
export default function UpdateIndicator() {
const launcherMsg = useStore((state) => state.application.launcherMsg);
return <UpdateIndicatorImpl launcherMsg={launcherMsg} version={version} />;
return null;
}