diff --git a/src/common/communication.ts b/src/common/communication.ts index 164dcb0a..b167f1f1 100644 --- a/src/common/communication.ts +++ b/src/common/communication.ts @@ -118,3 +118,5 @@ export const UPDATE_URL_VIEW_WIDTH = 'update-url-view-width'; export const DISPATCH_GET_DESKTOP_SOURCES = 'dispatch-get-desktop-sources'; export const DESKTOP_SOURCES_RESULT = 'desktop-sources-result'; +export const RELOAD_CURRENT_VIEW = 'reload-current-view'; + diff --git a/src/main/views/MattermostView.test.js b/src/main/views/MattermostView.test.js index 7426a177..481c31db 100644 --- a/src/main/views/MattermostView.test.js +++ b/src/main/views/MattermostView.test.js @@ -105,12 +105,15 @@ describe('main/views/MattermostView', () => { describe('retry', () => { const window = {on: jest.fn()}; const mattermostView = new MattermostView(tabView, {}, window, {}); + const retryInBackgroundFn = jest.fn(); beforeEach(() => { + jest.useFakeTimers(); mattermostView.view.webContents.loadURL.mockImplementation(() => Promise.resolve()); mattermostView.loadSuccess = jest.fn(); mattermostView.loadRetry = jest.fn(); mattermostView.emit = jest.fn(); + mattermostView.retryInBackground = () => retryInBackgroundFn; }); it('should do nothing when webcontents are destroyed', () => { @@ -140,7 +143,7 @@ describe('main/views/MattermostView', () => { expect(mattermostView.loadRetry).toBeCalledWith('http://server-1.com', error); }); - it('should set to error status when max retries are reached', async () => { + it('should set to error status and retry in the background when max retries are reached', async () => { mattermostView.maxRetries = 0; const error = new Error('test'); const promise = Promise.reject(error); @@ -151,6 +154,8 @@ describe('main/views/MattermostView', () => { expect(mattermostView.loadRetry).not.toBeCalled(); expect(WindowManager.sendToRenderer).toBeCalledWith(LOAD_FAILED, mattermostView.tab.name, expect.any(String), expect.any(String)); expect(mattermostView.status).toBe(-1); + jest.runAllTimers(); + expect(retryInBackgroundFn).toBeCalled(); }); }); diff --git a/src/main/views/MattermostView.ts b/src/main/views/MattermostView.ts index 2d6e6acf..ce7317fc 100644 --- a/src/main/views/MattermostView.ts +++ b/src/main/views/MattermostView.ts @@ -175,13 +175,27 @@ export class MattermostView extends EventEmitter { } else { WindowManager.sendToRenderer(LOAD_FAILED, this.tab.name, err.toString(), loadURL.toString()); this.emit(LOAD_FAILED, this.tab.name, err.toString(), loadURL.toString()); - log.info(`[${Util.shorten(this.tab.name)}] Couldn't stablish a connection with ${loadURL}: ${err}.`); + log.info(`[${Util.shorten(this.tab.name)}] Couldn't stablish a connection with ${loadURL}: ${err}. Will continue to retry in the background.`); this.status = Status.ERROR; + this.retryLoad = setTimeout(this.retryInBackground(loadURL), RELOAD_INTERVAL); } }); }; } + retryInBackground = (loadURL: string) => { + return () => { + // window was closed while retrying + if (!this.view || !this.view.webContents) { + return; + } + const loading = this.view.webContents.loadURL(loadURL, {userAgent: composeUserAgent()}); + loading.then(this.loadSuccess(loadURL)).catch(() => { + this.retryLoad = setTimeout(this.retryInBackground(loadURL), RELOAD_INTERVAL); + }); + }; + } + loadRetry = (loadURL: string, err: Error) => { this.retryLoad = setTimeout(this.retry(loadURL), RELOAD_INTERVAL); WindowManager.sendToRenderer(LOAD_RETRY, this.tab.name, Date.now() + RELOAD_INTERVAL, err.toString(), loadURL.toString()); diff --git a/src/main/views/viewManager.ts b/src/main/views/viewManager.ts index e80cccfb..bbd998c4 100644 --- a/src/main/views/viewManager.ts +++ b/src/main/views/viewManager.ts @@ -98,7 +98,7 @@ export class ViewManager { view.load(url); view.on(UPDATE_TARGET_URL, this.showURLView); view.on(LOADSCREEN_END, this.finishLoading); - view.once(LOAD_FAILED, this.failLoading); + view.on(LOAD_FAILED, this.failLoading); } reloadViewIfNeeded = (viewName: string) => { diff --git a/src/main/windows/windowManager.ts b/src/main/windows/windowManager.ts index b15bfad8..abdd5d39 100644 --- a/src/main/windows/windowManager.ts +++ b/src/main/windows/windowManager.ts @@ -24,6 +24,7 @@ import { BROWSER_HISTORY_BUTTON, DISPATCH_GET_DESKTOP_SOURCES, DESKTOP_SOURCES_RESULT, + RELOAD_CURRENT_VIEW, } from 'common/communication'; import urlUtils from 'common/utils/url'; import {SECOND} from 'common/utils/constants'; @@ -68,6 +69,7 @@ export class WindowManager { ipcMain.handle(GET_VIEW_NAME, this.handleGetViewName); ipcMain.handle(GET_VIEW_WEBCONTENTS_ID, this.handleGetWebContentsId); ipcMain.on(DISPATCH_GET_DESKTOP_SOURCES, this.handleGetDesktopSources); + ipcMain.on(RELOAD_CURRENT_VIEW, this.handleReloadCurrentView); } handleUpdateConfig = () => { @@ -650,6 +652,15 @@ export class WindowManager { })); }); } + + handleReloadCurrentView = () => { + const view = this.viewManager?.getCurrentView(); + if (!view) { + return; + } + view?.reload(); + this.viewManager?.showByName(view?.name); + } } const windowManager = new WindowManager(); diff --git a/src/renderer/components/ErrorView.tsx b/src/renderer/components/ErrorView.tsx index a71a5a24..1671a247 100644 --- a/src/renderer/components/ErrorView.tsx +++ b/src/renderer/components/ErrorView.tsx @@ -13,6 +13,7 @@ type Props = { id?: string; active?: boolean; appName?: string; + handleLink: () => void; }; export default function ErrorView(props: Props) { @@ -42,27 +43,26 @@ export default function ErrorView(props: Props) { >

{`Cannot connect to ${props.appName}`}


-

{`We're having trouble connecting to ${props.appName}. If refreshing this page (Ctrl+R or Command+R) does not work please verify that:`}

-
+

+ {`We're having trouble connecting to ${props.appName}. We'll continue to try and establish a connection.`} +
+ {'If refreshing this page (Ctrl+R or Command+R) does not work please verify that:'} +