[MM-63224] Add incompatible server screen (#3348)
* [MM-63224] Add incompatible server screen * Fixed issue where init isn't called on no server case * Amend check
This commit is contained in:
@@ -169,9 +169,13 @@
|
||||
"renderer.components.developerModeIndicator.tooltip": "Developer mode is enabled. You should only have this enabled if a Mattermost developer has instructed you to.",
|
||||
"renderer.components.errorView.cannotConnectToThisServer": "Couldn't connect to this server",
|
||||
"renderer.components.errorView.contactAdmin": "If the issue persists, please contact your admin",
|
||||
"renderer.components.errorView.contactAdminUpgrade": "If the issue persists, contact your {appName} Administrator or IT department to upgrade this {appName} Server.",
|
||||
"renderer.components.errorView.havingTroubleConnecting": "We're having trouble connecting to this {appName} server. We'll keep trying to establish a connection.",
|
||||
"renderer.components.errorView.incompatibleServerVersion": "Incompatible server version",
|
||||
"renderer.components.errorView.refreshThenVerify": "If refreshing this page (Ctrl+R or Command+R) doesn't help, please check the following:",
|
||||
"renderer.components.errorView.serverVersionIsIncompatible": "The {appName} Server you are accessing is incompatible with this version of the {appName} Desktop App. To connect to this server, please try the following:",
|
||||
"renderer.components.errorView.troubleshooting.computerIsConnected": "Ensure your computer is connected to the internet.",
|
||||
"renderer.components.errorView.troubleshooting.downgradeApp": "<link>Downgrade your {appName} Desktop App</link> to version v5.10 or earlier.",
|
||||
"renderer.components.errorView.troubleshooting.urlIsCorrect.appNameIsCorrect": "Verify that the URL <link>{url}</link> is correct.",
|
||||
"renderer.components.errorView.troubleshooting.webContentsView.canReachFromBrowserWindow": "Try opening <link>{url}</link> in a browser window.",
|
||||
"renderer.components.input.required": "This field is required",
|
||||
|
@@ -59,6 +59,11 @@ export class ServerViewState {
|
||||
}
|
||||
|
||||
init = () => {
|
||||
// Don't need to init twice
|
||||
if (this.currentServerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const orderedServers = ServerManager.getOrderedServers();
|
||||
if (orderedServers.length) {
|
||||
if (Config.lastActiveServer && orderedServers[Config.lastActiveServer]) {
|
||||
|
@@ -30,6 +30,7 @@ export const APP_MENU_WILL_CLOSE = 'app-menu-will-close';
|
||||
export const LOAD_RETRY = 'load_retry';
|
||||
export const LOAD_SUCCESS = 'load_success';
|
||||
export const LOAD_FAILED = 'load_fail';
|
||||
export const LOAD_INCOMPATIBLE_SERVER = 'load_incompatible_server';
|
||||
|
||||
export const MAXIMIZE_CHANGE = 'maximized_change';
|
||||
|
||||
@@ -102,6 +103,7 @@ export const UPDATE_PATHS = 'update-paths';
|
||||
export const UPDATE_URL_VIEW_WIDTH = 'update-url-view-width';
|
||||
|
||||
export const OPEN_SERVER_EXTERNALLY = 'open-server-externally';
|
||||
export const OPEN_SERVER_UPGRADE_LINK = 'open-server-upgrade-link';
|
||||
|
||||
export const PING_DOMAIN = 'ping-domain';
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
import type {BuildConfig} from 'types/config';
|
||||
|
||||
import {DEFAULT_ACADEMY_LINK, DEFAULT_HELP_LINK} from '../../common/constants';
|
||||
import {DEFAULT_ACADEMY_LINK, DEFAULT_HELP_LINK, DEFAULT_UPGRADE_LINK} from '../../common/constants';
|
||||
|
||||
// For detailed guides, please refer to https://docs.mattermost.com/deployment/desktop-app-deployment.html
|
||||
|
||||
@@ -31,6 +31,7 @@ const buildConfig: BuildConfig = {
|
||||
*/],
|
||||
helpLink: DEFAULT_HELP_LINK,
|
||||
academyLink: DEFAULT_ACADEMY_LINK,
|
||||
upgradeLink: DEFAULT_UPGRADE_LINK,
|
||||
enableServerManagement: true,
|
||||
enableAutoUpdater: true,
|
||||
managedResources: ['trusted'],
|
||||
|
@@ -219,6 +219,9 @@ export class Config extends EventEmitter {
|
||||
get academyLink() {
|
||||
return this.combinedData?.academyLink;
|
||||
}
|
||||
get upgradeLink() {
|
||||
return this.combinedData?.upgradeLink;
|
||||
}
|
||||
get minimizeToTray() {
|
||||
return this.combinedData?.minimizeToTray;
|
||||
}
|
||||
|
@@ -48,3 +48,4 @@ export const DEFAULT_HELP_LINK = 'https://docs.mattermost.com/guides/collaborate
|
||||
export const DEFAULT_ACADEMY_LINK = 'https://academy.mattermost.com/';
|
||||
export const DEFAULT_TE_REPORT_PROBLEM_LINK = 'https://mattermost.com/pl/report-a-bug';
|
||||
export const DEFAULT_EE_REPORT_PROBLEM_LINK = 'https://support.mattermost.com/hc/en-us/requests/new';
|
||||
export const DEFAULT_UPGRADE_LINK = 'https://forum.mattermost.com/t/mattermost-desktop-app-5-11-important-compatibility-notice/22599';
|
||||
|
@@ -308,7 +308,6 @@ async function initializeAfterAppReady() {
|
||||
});
|
||||
|
||||
ServerManager.reloadFromConfig();
|
||||
updateServerInfos(ServerManager.getAllServers());
|
||||
ServerManager.on(SERVERS_URL_MODIFIED, (serverIds?: string[]) => {
|
||||
if (serverIds && serverIds.length) {
|
||||
updateServerInfos(serverIds.map((srvId) => ServerManager.getServer(srvId)!));
|
||||
|
@@ -93,6 +93,8 @@ import {
|
||||
IS_DEVELOPER_MODE_ENABLED,
|
||||
METRICS_REQUEST,
|
||||
METRICS_RECEIVE,
|
||||
LOAD_INCOMPATIBLE_SERVER,
|
||||
OPEN_SERVER_UPGRADE_LINK,
|
||||
} from 'common/communication';
|
||||
|
||||
console.log('Preload initialized');
|
||||
@@ -120,6 +122,7 @@ contextBridge.exposeInMainWorld('desktop', {
|
||||
doubleClickOnWindow: (windowName) => ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW, windowName),
|
||||
focusCurrentView: () => ipcRenderer.send(FOCUS_BROWSERVIEW),
|
||||
openServerExternally: () => ipcRenderer.send(OPEN_SERVER_EXTERNALLY),
|
||||
openServerUpgradeLink: () => ipcRenderer.send(OPEN_SERVER_UPGRADE_LINK),
|
||||
closeDownloadsDropdown: () => ipcRenderer.send(CLOSE_DOWNLOADS_DROPDOWN),
|
||||
closeDownloadsDropdownMenu: () => ipcRenderer.send(CLOSE_DOWNLOADS_DROPDOWN_MENU),
|
||||
openDownloadsDropdown: () => ipcRenderer.send(OPEN_DOWNLOADS_DROPDOWN),
|
||||
@@ -154,6 +157,7 @@ contextBridge.exposeInMainWorld('desktop', {
|
||||
onLoadRetry: (listener) => ipcRenderer.on(LOAD_RETRY, (_, viewId, retry, err, loadUrl) => listener(viewId, retry, err, loadUrl)),
|
||||
onLoadSuccess: (listener) => ipcRenderer.on(LOAD_SUCCESS, (_, viewId) => listener(viewId)),
|
||||
onLoadFailed: (listener) => ipcRenderer.on(LOAD_FAILED, (_, viewId, err, loadUrl) => listener(viewId, err, loadUrl)),
|
||||
onLoadIncompatibleServer: (listener) => ipcRenderer.on(LOAD_INCOMPATIBLE_SERVER, (_, viewId, loadUrl) => listener(viewId, loadUrl)),
|
||||
onSetActiveView: (listener) => ipcRenderer.on(SET_ACTIVE_VIEW, (_, serverId, viewId) => listener(serverId, viewId)),
|
||||
onMaximizeChange: (listener) => ipcRenderer.on(MAXIMIZE_CHANGE, (_, maximize) => listener(maximize)),
|
||||
onEnterFullScreen: (listener) => ipcRenderer.on('enter-full-screen', () => listener()),
|
||||
|
@@ -6,6 +6,7 @@
|
||||
import AppState from 'common/appState';
|
||||
import {LOAD_FAILED, UPDATE_TARGET_URL} from 'common/communication';
|
||||
import {MattermostServer} from 'common/servers/MattermostServer';
|
||||
import ServerManager from 'common/servers/serverManager';
|
||||
import MessagingView from 'common/views/MessagingView';
|
||||
|
||||
import {MattermostWebContentsView} from './MattermostWebContentsView';
|
||||
@@ -68,6 +69,16 @@ jest.mock('main/performanceMonitor', () => ({
|
||||
registerServerView: jest.fn(),
|
||||
unregisterView: jest.fn(),
|
||||
}));
|
||||
jest.mock('common/servers/serverManager', () => ({
|
||||
getRemoteInfo: jest.fn(),
|
||||
getViewLog: jest.fn().mockReturnValue({
|
||||
verbose: jest.fn(),
|
||||
info: jest.fn(),
|
||||
error: jest.fn(),
|
||||
silly: jest.fn(),
|
||||
}),
|
||||
on: jest.fn(),
|
||||
}));
|
||||
|
||||
const server = new MattermostServer({name: 'server_name', url: 'http://server-1.com'});
|
||||
const view = new MessagingView(server, true);
|
||||
@@ -268,6 +279,7 @@ describe('main/views/MattermostWebContentsView', () => {
|
||||
mattermostView.setInitialized = jest.fn();
|
||||
mattermostView.updateMentionsFromTitle = jest.fn();
|
||||
mattermostView.findUnreadState = jest.fn();
|
||||
ServerManager.getRemoteInfo.mockReturnValue({serverVersion: '10.0.0'});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
|
@@ -4,6 +4,7 @@
|
||||
import {WebContentsView, app, ipcMain} from 'electron';
|
||||
import type {WebContentsViewConstructorOptions, Event, Input} from 'electron/main';
|
||||
import {EventEmitter} from 'events';
|
||||
import semver from 'semver';
|
||||
|
||||
import AppState from 'common/appState';
|
||||
import {
|
||||
@@ -16,6 +17,7 @@ import {
|
||||
BROWSER_HISTORY_STATUS_UPDATED,
|
||||
CLOSE_SERVERS_DROPDOWN,
|
||||
CLOSE_DOWNLOADS_DROPDOWN,
|
||||
LOAD_INCOMPATIBLE_SERVER,
|
||||
} from 'common/communication';
|
||||
import type {Logger} from 'common/log';
|
||||
import ServerManager from 'common/servers/serverManager';
|
||||
@@ -426,6 +428,8 @@ export class MattermostWebContentsView extends EventEmitter {
|
||||
|
||||
private loadSuccess = (loadURL: string) => {
|
||||
return () => {
|
||||
const serverInfo = ServerManager.getRemoteInfo(this.view.server.id);
|
||||
if (serverInfo?.serverVersion && semver.gte(serverInfo.serverVersion, '9.4.0')) {
|
||||
this.log.verbose(`finished loading ${loadURL}`);
|
||||
MainWindow.sendToRenderer(LOAD_SUCCESS, this.id);
|
||||
this.maxRetries = MAX_SERVER_RETRIES;
|
||||
@@ -436,6 +440,11 @@ export class MattermostWebContentsView extends EventEmitter {
|
||||
if (mainWindow && this.currentURL) {
|
||||
this.setBounds(getWindowBoundaries(mainWindow));
|
||||
}
|
||||
} else {
|
||||
MainWindow.sendToRenderer(LOAD_INCOMPATIBLE_SERVER, this.id, loadURL.toString());
|
||||
this.emit(LOAD_FAILED, this.id, 'Incompatible server version', loadURL.toString());
|
||||
this.status = Status.ERROR;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
@@ -31,6 +31,7 @@ import {
|
||||
UNREADS_AND_MENTIONS,
|
||||
TAB_LOGIN_CHANGED,
|
||||
DEVELOPER_MODE_UPDATED,
|
||||
OPEN_SERVER_UPGRADE_LINK,
|
||||
} from 'common/communication';
|
||||
import Config from 'common/config';
|
||||
import {Logger} from 'common/log';
|
||||
@@ -42,7 +43,7 @@ import Utils from 'common/utils/util';
|
||||
import type {MattermostView} from 'common/views/View';
|
||||
import {TAB_MESSAGING} from 'common/views/View';
|
||||
import {handleWelcomeScreenModal} from 'main/app/intercom';
|
||||
import {flushCookiesStore} from 'main/app/utils';
|
||||
import {flushCookiesStore, updateServerInfos} from 'main/app/utils';
|
||||
import DeveloperMode from 'main/developerMode';
|
||||
import performanceMonitor from 'main/performanceMonitor';
|
||||
import PermissionsManager from 'main/permissionsManager';
|
||||
@@ -82,6 +83,7 @@ export class ViewManager {
|
||||
ipcMain.on(BROWSER_HISTORY_PUSH, this.handleBrowserHistoryPush);
|
||||
ipcMain.on(TAB_LOGIN_CHANGED, this.handleTabLoginChanged);
|
||||
ipcMain.on(OPEN_SERVER_EXTERNALLY, this.handleOpenServerExternally);
|
||||
ipcMain.on(OPEN_SERVER_UPGRADE_LINK, this.handleOpenServerUpgradeLink);
|
||||
ipcMain.on(UNREADS_AND_MENTIONS, this.handleUnreadsAndMentionsChanged);
|
||||
ipcMain.on(SESSION_EXPIRED, this.handleSessionExpired);
|
||||
|
||||
@@ -91,8 +93,11 @@ export class ViewManager {
|
||||
DeveloperMode.on(DEVELOPER_MODE_UPDATED, this.handleDeveloperModeUpdated);
|
||||
}
|
||||
|
||||
private init = () => {
|
||||
private init = async () => {
|
||||
if (ServerManager.hasServers()) {
|
||||
// TODO: This init should be happening elsewhere, future refactor will fix this
|
||||
ServerViewState.init();
|
||||
await updateServerInfos(ServerManager.getAllServers());
|
||||
LoadingScreen.show();
|
||||
ServerManager.getAllServers().forEach((server) => this.loadServer(server));
|
||||
this.showInitial();
|
||||
@@ -303,7 +308,6 @@ export class ViewManager {
|
||||
private showInitial = () => {
|
||||
log.verbose('showInitial');
|
||||
|
||||
// TODO: This init should be happening elsewhere, future refactor will fix this
|
||||
ServerViewState.init();
|
||||
if (ServerManager.hasServers()) {
|
||||
const lastActiveServer = ServerViewState.getCurrentServer();
|
||||
@@ -577,6 +581,12 @@ export class ViewManager {
|
||||
shell.openExternal(view.view.server.url.toString());
|
||||
};
|
||||
|
||||
private handleOpenServerUpgradeLink = () => {
|
||||
if (Config.upgradeLink) {
|
||||
shell.openExternal(Config.upgradeLink);
|
||||
}
|
||||
};
|
||||
|
||||
private handleUnreadsAndMentionsChanged = (e: IpcMainEvent, isUnread: boolean, mentionCount: number) => {
|
||||
log.silly('handleUnreadsAndMentionsChanged', {webContentsId: e.sender.id, isUnread, mentionCount});
|
||||
|
||||
|
90
src/renderer/components/ConnectionErrorView.tsx
Normal file
90
src/renderer/components/ConnectionErrorView.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
import ErrorView from './ErrorView';
|
||||
|
||||
type Props = {
|
||||
darkMode: boolean;
|
||||
appName?: string;
|
||||
url?: string;
|
||||
errorInfo?: string;
|
||||
handleLink: () => void;
|
||||
};
|
||||
|
||||
export default function ConnectionErrorView({darkMode, appName, url, handleLink, errorInfo}: Props) {
|
||||
const header = (
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.cannotConnectToThisServer'
|
||||
defaultMessage="Couldn't connect to this server"
|
||||
/>
|
||||
);
|
||||
|
||||
const subHeader = (
|
||||
<>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.havingTroubleConnecting'
|
||||
defaultMessage={'We\'re having trouble connecting to this {appName} server. We\'ll keep trying to establish a connection.'}
|
||||
values={{
|
||||
appName,
|
||||
}}
|
||||
/>
|
||||
<br/>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.refreshThenVerify'
|
||||
defaultMessage="If refreshing this page (Ctrl+R or Command+R) doesn't help, please check the following:"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
const bullets = (
|
||||
<>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.troubleshooting.computerIsConnected'
|
||||
defaultMessage='Ensure your computer is connected to the internet.'
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.troubleshooting.urlIsCorrect.appNameIsCorrect'
|
||||
defaultMessage='Verify that the URL <link>{url}</link> is correct.'
|
||||
values={{
|
||||
appName,
|
||||
url,
|
||||
link: (msg: React.ReactNode) => (
|
||||
<a
|
||||
onClick={handleLink}
|
||||
href='#'
|
||||
>
|
||||
{msg}
|
||||
</a>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
|
||||
const contactAdmin = (
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.contactAdmin'
|
||||
defaultMessage='If the issue persists, please contact your admin'
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<ErrorView
|
||||
darkMode={darkMode}
|
||||
header={header}
|
||||
subHeader={subHeader}
|
||||
bullets={bullets}
|
||||
contactAdmin={contactAdmin}
|
||||
handleLink={handleLink}
|
||||
errorInfo={errorInfo}
|
||||
url={url}
|
||||
/>
|
||||
);
|
||||
}
|
@@ -12,72 +12,47 @@ import AlertImage from './Images/alert';
|
||||
|
||||
import 'renderer/css/components/ErrorView.scss';
|
||||
|
||||
type Props = {
|
||||
type ErrorViewProps = {
|
||||
darkMode: boolean;
|
||||
header: React.ReactNode;
|
||||
subHeader: React.ReactNode;
|
||||
bullets: React.ReactNode;
|
||||
contactAdmin: React.ReactNode;
|
||||
errorInfo?: string;
|
||||
url?: string;
|
||||
appName?: string;
|
||||
handleLink: () => void;
|
||||
};
|
||||
|
||||
export default function ErrorView(props: Props) {
|
||||
export default function ErrorView({
|
||||
darkMode,
|
||||
header,
|
||||
subHeader,
|
||||
bullets,
|
||||
contactAdmin,
|
||||
errorInfo,
|
||||
url,
|
||||
handleLink,
|
||||
}: ErrorViewProps) {
|
||||
return (
|
||||
<div className={classNames('ErrorView', {darkMode: props.darkMode})}>
|
||||
<div className={classNames('ErrorView', {darkMode})}>
|
||||
<AlertImage/>
|
||||
<span className='ErrorView-header'>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.cannotConnectToThisServer'
|
||||
defaultMessage="Couldn't connect to this server"
|
||||
/>
|
||||
{header}
|
||||
</span>
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.havingTroubleConnecting'
|
||||
defaultMessage={'We\'re having trouble connecting to this {appName} server. We\'ll keep trying to establish a connection.'}
|
||||
values={{
|
||||
appName: props.appName,
|
||||
}}
|
||||
/>
|
||||
<br/>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.refreshThenVerify'
|
||||
defaultMessage="If refreshing this page (Ctrl+R or Command+R) doesn't help, please check the following:"
|
||||
/>
|
||||
{subHeader}
|
||||
</span>
|
||||
<ul className='ErrorView-bullets'>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.troubleshooting.computerIsConnected'
|
||||
defaultMessage='Ensure your computer is connected to the internet.'
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.troubleshooting.urlIsCorrect.appNameIsCorrect'
|
||||
defaultMessage='Verify that the URL <link>{url}</link> is correct.'
|
||||
values={{
|
||||
appName: props.appName,
|
||||
url: props.url,
|
||||
link: (msg: React.ReactNode) => (
|
||||
<a
|
||||
onClick={props.handleLink}
|
||||
href='#'
|
||||
>
|
||||
{msg}
|
||||
</a>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</li>
|
||||
{bullets}
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.troubleshooting.webContentsView.canReachFromBrowserWindow'
|
||||
defaultMessage='Try opening <link>{url}</link> in a browser window.'
|
||||
values={{
|
||||
url: props.url,
|
||||
url,
|
||||
link: (msg: React.ReactNode) => (
|
||||
<a
|
||||
onClick={props.handleLink}
|
||||
onClick={handleLink}
|
||||
href='#'
|
||||
>
|
||||
{msg}
|
||||
@@ -88,13 +63,10 @@ export default function ErrorView(props: Props) {
|
||||
</li>
|
||||
</ul>
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.contactAdmin'
|
||||
defaultMessage='If the issue persists, please contact your admin'
|
||||
/>
|
||||
{contactAdmin}
|
||||
</span>
|
||||
<span className='ErrorView-techInfo'>
|
||||
{props.errorInfo}
|
||||
{errorInfo}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
80
src/renderer/components/IncompatibleErrorView.tsx
Normal file
80
src/renderer/components/IncompatibleErrorView.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
import ErrorView from './ErrorView';
|
||||
|
||||
type Props = {
|
||||
darkMode: boolean;
|
||||
appName?: string;
|
||||
url?: string;
|
||||
handleLink: () => void;
|
||||
handleUpgradeLink: () => void;
|
||||
};
|
||||
|
||||
export default function IncompatibleErrorView({darkMode, appName, url, handleLink, handleUpgradeLink}: Props) {
|
||||
const header = (
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.incompatibleServerVersion'
|
||||
defaultMessage='Incompatible server version'
|
||||
/>
|
||||
);
|
||||
|
||||
const subHeader = (
|
||||
<>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.serverVersionIsIncompatible'
|
||||
defaultMessage={'The {appName} Server you are accessing is incompatible with this version of the {appName} Desktop App. To connect to this server, please try the following:'}
|
||||
values={{
|
||||
appName,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
const bullets = (
|
||||
<>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.troubleshooting.downgradeApp'
|
||||
defaultMessage='<link>Downgrade your {appName} Desktop App</link> to version v5.10 or earlier.'
|
||||
values={{
|
||||
appName,
|
||||
link: (msg: React.ReactNode) => (
|
||||
<a
|
||||
href='#'
|
||||
onClick={handleUpgradeLink}
|
||||
>
|
||||
{msg}
|
||||
</a>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
|
||||
const contactAdmin = (
|
||||
<FormattedMessage
|
||||
id='renderer.components.errorView.contactAdminUpgrade'
|
||||
defaultMessage='If the issue persists, contact your {appName} Administrator or IT department to upgrade this {appName} Server.'
|
||||
values={{
|
||||
appName,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<ErrorView
|
||||
darkMode={darkMode}
|
||||
header={header}
|
||||
subHeader={subHeader}
|
||||
bullets={bullets}
|
||||
contactAdmin={contactAdmin}
|
||||
handleLink={handleLink}
|
||||
url={url}
|
||||
/>
|
||||
);
|
||||
}
|
@@ -11,9 +11,10 @@ import {injectIntl} from 'react-intl';
|
||||
import type {UniqueView, UniqueServer} from 'types/config';
|
||||
import type {DownloadedItems} from 'types/downloads';
|
||||
|
||||
import ConnectionErrorView from './ConnectionErrorView';
|
||||
import DeveloperModeIndicator from './DeveloperModeIndicator';
|
||||
import DownloadsDropdownButton from './DownloadsDropdown/DownloadsDropdownButton';
|
||||
import ErrorView from './ErrorView';
|
||||
import IncompatibleErrorView from './IncompatibleErrorView';
|
||||
import ServerDropdownButton from './ServerDropdownButton';
|
||||
import TabBar from './TabBar';
|
||||
|
||||
@@ -28,6 +29,7 @@ enum Status {
|
||||
RETRY = -1,
|
||||
FAILED = 0,
|
||||
NOSERVERS = -2,
|
||||
INCOMPATIBLE = -3,
|
||||
}
|
||||
|
||||
type Props = {
|
||||
@@ -61,7 +63,7 @@ type TabViewStatus = {
|
||||
status: Status;
|
||||
extra?: {
|
||||
url: string;
|
||||
error: string;
|
||||
error?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -186,6 +188,17 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
this.updateTabStatus(viewId, statusValue);
|
||||
});
|
||||
|
||||
window.desktop.onLoadIncompatibleServer((viewId, loadUrl) => {
|
||||
console.error(`${viewId}: tried to load incompatible server`);
|
||||
const statusValue = {
|
||||
status: Status.INCOMPATIBLE,
|
||||
extra: {
|
||||
url: loadUrl,
|
||||
},
|
||||
};
|
||||
this.updateTabStatus(viewId, statusValue);
|
||||
});
|
||||
|
||||
// can't switch tabs sequentially for some reason...
|
||||
window.desktop.onSetActiveView(this.setActiveView);
|
||||
|
||||
@@ -507,7 +520,7 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
switch (tabStatus.status) {
|
||||
case Status.FAILED:
|
||||
component = (
|
||||
<ErrorView
|
||||
<ConnectionErrorView
|
||||
darkMode={this.props.darkMode}
|
||||
errorInfo={tabStatus.extra?.error}
|
||||
url={tabStatus.extra ? tabStatus.extra.url : ''}
|
||||
@@ -515,6 +528,16 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
handleLink={this.openServerExternally}
|
||||
/>);
|
||||
break;
|
||||
case Status.INCOMPATIBLE:
|
||||
component = (
|
||||
<IncompatibleErrorView
|
||||
darkMode={this.props.darkMode}
|
||||
url={tabStatus.extra ? tabStatus.extra.url : ''}
|
||||
appName={this.props.appName}
|
||||
handleLink={this.openServerExternally}
|
||||
handleUpgradeLink={() => window.desktop.openServerUpgradeLink()}
|
||||
/>);
|
||||
break;
|
||||
case Status.LOADING:
|
||||
case Status.RETRY:
|
||||
case Status.DONE:
|
||||
|
@@ -107,6 +107,7 @@ export type BuildConfig = {
|
||||
defaultServers?: Server[];
|
||||
helpLink: string;
|
||||
academyLink: string;
|
||||
upgradeLink: string;
|
||||
enableServerManagement: boolean;
|
||||
enableAutoUpdater: boolean;
|
||||
managedResources: string[];
|
||||
|
@@ -38,6 +38,7 @@ declare global {
|
||||
doubleClickOnWindow: (windowName?: string) => void;
|
||||
focusCurrentView: () => void;
|
||||
openServerExternally: () => void;
|
||||
openServerUpgradeLink: () => void;
|
||||
closeDownloadsDropdown: () => void;
|
||||
closeDownloadsDropdownMenu: () => void;
|
||||
openDownloadsDropdown: () => void;
|
||||
@@ -72,6 +73,7 @@ declare global {
|
||||
onLoadRetry: (listener: (viewId: string, retry: Date, err: string, loadUrl: string) => void) => void;
|
||||
onLoadSuccess: (listener: (viewId: string) => void) => void;
|
||||
onLoadFailed: (listener: (viewId: string, err: string, loadUrl: string) => void) => void;
|
||||
onLoadIncompatibleServer: (listener: (viewId: string, loadUrl: string) => void) => void;
|
||||
onSetActiveView: (listener: (serverId: string, viewId: string) => void) => void;
|
||||
onMaximizeChange: (listener: (maximize: boolean) => void) => void;
|
||||
onEnterFullScreen: (listener: () => void) => void;
|
||||
|
Reference in New Issue
Block a user