[MM-22555] Auto-fill server URLs when deep linking into the Desktop App and the server isn't configured (#3200)
* Allow deep linking to non-configured servers by auto filling the modal * Fall back to base URL if URL with path name does not work * Allow deep linking directly into a new server with a permalink * Support welcome screen/no server case * Some cleanup
This commit is contained in:
@@ -128,8 +128,6 @@
|
|||||||
"main.tray.tray.expired": "Session Expired: Please sign in to continue receiving notifications.",
|
"main.tray.tray.expired": "Session Expired: Please sign in to continue receiving notifications.",
|
||||||
"main.tray.tray.mention": "You have been mentioned",
|
"main.tray.tray.mention": "You have been mentioned",
|
||||||
"main.tray.tray.unread": "You have unread channels",
|
"main.tray.tray.unread": "You have unread channels",
|
||||||
"main.views.viewManager.handleDeepLink.error.body": "There is no configured server in the app that matches the requested url: {url}",
|
|
||||||
"main.views.viewManager.handleDeepLink.error.title": "No matching server",
|
|
||||||
"main.windows.mainWindow.closeApp.dialog.checkboxLabel": "Don't ask again",
|
"main.windows.mainWindow.closeApp.dialog.checkboxLabel": "Don't ask again",
|
||||||
"main.windows.mainWindow.closeApp.dialog.detail": "You will no longer receive notifications for messages. If you want to leave {appName} running in the system tray, you can enable this in Settings.",
|
"main.windows.mainWindow.closeApp.dialog.detail": "You will no longer receive notifications for messages. If you want to leave {appName} running in the system tray, you can enable this in Settings.",
|
||||||
"main.windows.mainWindow.closeApp.dialog.message": "Are you sure you want to quit?",
|
"main.windows.mainWindow.closeApp.dialog.message": "Are you sure you want to quit?",
|
||||||
|
@@ -209,7 +209,7 @@ describe('app/serverViewState', () => {
|
|||||||
serverViewState.showNewServerModal();
|
serverViewState.showNewServerModal();
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
expect(ServerManager.addServer).toHaveBeenCalledWith(data);
|
expect(ServerManager.addServer).toHaveBeenCalledWith(data, undefined);
|
||||||
expect(serversCopy).toContainEqual(expect.objectContaining({
|
expect(serversCopy).toContainEqual(expect.objectContaining({
|
||||||
id: 'server-1',
|
id: 'server-1',
|
||||||
name: 'new-server',
|
name: 'new-server',
|
||||||
|
@@ -44,7 +44,7 @@ export class ServerViewState {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
ipcMain.on(SWITCH_SERVER, (event, serverId) => this.switchServer(serverId));
|
ipcMain.on(SWITCH_SERVER, (event, serverId) => this.switchServer(serverId));
|
||||||
ipcMain.on(SHOW_NEW_SERVER_MODAL, this.showNewServerModal);
|
ipcMain.on(SHOW_NEW_SERVER_MODAL, this.handleShowNewServerModal);
|
||||||
ipcMain.on(SHOW_EDIT_SERVER_MODAL, this.showEditServerModal);
|
ipcMain.on(SHOW_EDIT_SERVER_MODAL, this.showEditServerModal);
|
||||||
ipcMain.on(SHOW_REMOVE_SERVER_MODAL, this.showRemoveServerModal);
|
ipcMain.on(SHOW_REMOVE_SERVER_MODAL, this.showRemoveServerModal);
|
||||||
ipcMain.handle(VALIDATE_SERVER_URL, this.handleServerURLValidation);
|
ipcMain.handle(VALIDATE_SERVER_URL, this.handleServerURLValidation);
|
||||||
@@ -123,25 +123,32 @@ export class ServerViewState {
|
|||||||
* Server Modals
|
* Server Modals
|
||||||
*/
|
*/
|
||||||
|
|
||||||
showNewServerModal = () => {
|
showNewServerModal = (prefillURL?: string) => {
|
||||||
log.debug('showNewServerModal');
|
log.debug('showNewServerModal', {prefillURL});
|
||||||
|
|
||||||
const mainWindow = MainWindow.get();
|
const mainWindow = MainWindow.get();
|
||||||
if (!mainWindow) {
|
if (!mainWindow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalPromise = ModalManager.addModal<null, Server>(
|
const modalPromise = ModalManager.addModal<{prefillURL?: string}, Server>(
|
||||||
'newServer',
|
'newServer',
|
||||||
'mattermost-desktop://renderer/newServer.html',
|
'mattermost-desktop://renderer/newServer.html',
|
||||||
getLocalPreload('internalAPI.js'),
|
getLocalPreload('internalAPI.js'),
|
||||||
null,
|
{prefillURL},
|
||||||
mainWindow,
|
mainWindow,
|
||||||
!ServerManager.hasServers(),
|
!ServerManager.hasServers(),
|
||||||
);
|
);
|
||||||
|
|
||||||
modalPromise.then((data) => {
|
modalPromise.then((data) => {
|
||||||
const newServer = ServerManager.addServer(data);
|
let initialLoadURL;
|
||||||
|
if (prefillURL) {
|
||||||
|
const parsedServerURL = parseURL(data.url);
|
||||||
|
if (parsedServerURL) {
|
||||||
|
initialLoadURL = parseURL(`${parsedServerURL.origin}${prefillURL.substring(prefillURL.indexOf('/'))}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const newServer = ServerManager.addServer(data, initialLoadURL);
|
||||||
this.switchServer(newServer.id, true);
|
this.switchServer(newServer.id, true);
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
// e is undefined for user cancellation
|
// e is undefined for user cancellation
|
||||||
@@ -151,6 +158,8 @@ export class ServerViewState {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private handleShowNewServerModal = () => this.showNewServerModal();
|
||||||
|
|
||||||
private showEditServerModal = (e: IpcMainEvent, id: string) => {
|
private showEditServerModal = (e: IpcMainEvent, id: string) => {
|
||||||
log.debug('showEditServerModal', id);
|
log.debug('showEditServerModal', id);
|
||||||
|
|
||||||
@@ -281,6 +290,11 @@ export class ServerViewState {
|
|||||||
// If the original URL was invalid, don't replace that as they probably have a typo somewhere
|
// If the original URL was invalid, don't replace that as they probably have a typo somewhere
|
||||||
// Also strip the trailing slash if it's there so that the user can keep typing
|
// Also strip the trailing slash if it's there so that the user can keep typing
|
||||||
if (!remoteInfo) {
|
if (!remoteInfo) {
|
||||||
|
// If the URL provided has a path, try to validate the server with parts of the path removed, until we reach the root and then return a failure
|
||||||
|
if (parsedURL.pathname !== '/') {
|
||||||
|
return this.handleServerURLValidation(e, parsedURL.toString().substring(0, parsedURL.toString().lastIndexOf('/')), currentId);
|
||||||
|
}
|
||||||
|
|
||||||
return {status: URLValidationStatus.NotMattermost, validatedURL: parsedURL.toString().replace(/\/$/, '')};
|
return {status: URLValidationStatus.NotMattermost, validatedURL: parsedURL.toString().replace(/\/$/, '')};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,14 +12,16 @@ export class MattermostServer {
|
|||||||
name: string;
|
name: string;
|
||||||
url!: URL;
|
url!: URL;
|
||||||
isPredefined: boolean;
|
isPredefined: boolean;
|
||||||
|
initialLoadURL?: URL;
|
||||||
|
|
||||||
constructor(server: Server, isPredefined: boolean) {
|
constructor(server: Server, isPredefined: boolean, initialLoadURL?: URL) {
|
||||||
this.id = uuid();
|
this.id = uuid();
|
||||||
|
|
||||||
this.name = server.name;
|
this.name = server.name;
|
||||||
this.updateURL(server.url);
|
this.updateURL(server.url);
|
||||||
|
|
||||||
this.isPredefined = isPredefined;
|
this.isPredefined = isPredefined;
|
||||||
|
this.initialLoadURL = initialLoadURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateURL = (url: string) => {
|
updateURL = (url: string) => {
|
||||||
|
@@ -156,8 +156,8 @@ export class ServerManager extends EventEmitter {
|
|||||||
this.persistServers();
|
this.persistServers();
|
||||||
};
|
};
|
||||||
|
|
||||||
addServer = (server: Server) => {
|
addServer = (server: Server, initialLoadURL?: URL) => {
|
||||||
const newServer = new MattermostServer(server, false);
|
const newServer = new MattermostServer(server, false, initialLoadURL);
|
||||||
|
|
||||||
if (this.servers.has(newServer.id)) {
|
if (this.servers.has(newServer.id)) {
|
||||||
throw new Error('ID Collision detected. Cannot add server.');
|
throw new Error('ID Collision detected. Cannot add server.');
|
||||||
|
@@ -63,7 +63,7 @@ describe('main/app/intercom', () => {
|
|||||||
ModalManager.addModal.mockReturnValue(promise);
|
ModalManager.addModal.mockReturnValue(promise);
|
||||||
|
|
||||||
handleWelcomeScreenModal();
|
handleWelcomeScreenModal();
|
||||||
expect(ModalManager.addModal).toHaveBeenCalledWith('welcomeScreen', 'mattermost-desktop://renderer/welcomeScreen.html', '/some/preload.js', null, {}, true);
|
expect(ModalManager.addModal).toHaveBeenCalledWith('welcomeScreen', 'mattermost-desktop://renderer/welcomeScreen.html', '/some/preload.js', {prefillURL: undefined}, {}, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@ import ServerViewState from 'app/serverViewState';
|
|||||||
import {Logger} from 'common/log';
|
import {Logger} from 'common/log';
|
||||||
import ServerManager from 'common/servers/serverManager';
|
import ServerManager from 'common/servers/serverManager';
|
||||||
import {ping} from 'common/utils/requests';
|
import {ping} from 'common/utils/requests';
|
||||||
|
import {parseURL} from 'common/utils/url';
|
||||||
import NotificationManager from 'main/notifications';
|
import NotificationManager from 'main/notifications';
|
||||||
import {getLocalPreload} from 'main/utils';
|
import {getLocalPreload} from 'main/utils';
|
||||||
import ModalManager from 'main/views/modalManager';
|
import ModalManager from 'main/views/modalManager';
|
||||||
@@ -85,7 +86,7 @@ export function handleMainWindowIsShown() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleWelcomeScreenModal() {
|
export function handleWelcomeScreenModal(prefillURL?: string) {
|
||||||
log.debug('handleWelcomeScreenModal');
|
log.debug('handleWelcomeScreenModal');
|
||||||
|
|
||||||
const html = 'mattermost-desktop://renderer/welcomeScreen.html';
|
const html = 'mattermost-desktop://renderer/welcomeScreen.html';
|
||||||
@@ -96,10 +97,17 @@ export function handleWelcomeScreenModal() {
|
|||||||
if (!mainWindow) {
|
if (!mainWindow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const modalPromise = ModalManager.addModal<null, UniqueServer>('welcomeScreen', html, preload, null, mainWindow, !ServerManager.hasServers());
|
const modalPromise = ModalManager.addModal<{prefillURL?: string}, UniqueServer>('welcomeScreen', html, preload, {prefillURL}, mainWindow, !ServerManager.hasServers());
|
||||||
if (modalPromise) {
|
if (modalPromise) {
|
||||||
modalPromise.then((data) => {
|
modalPromise.then((data) => {
|
||||||
const newServer = ServerManager.addServer(data);
|
let initialLoadURL;
|
||||||
|
if (prefillURL) {
|
||||||
|
const parsedServerURL = parseURL(data.url);
|
||||||
|
if (parsedServerURL) {
|
||||||
|
initialLoadURL = parseURL(`${parsedServerURL.origin}${prefillURL.substring(prefillURL.indexOf('/'))}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const newServer = ServerManager.addServer(data, initialLoadURL);
|
||||||
ServerViewState.switchServer(newServer.id, true);
|
ServerViewState.switchServer(newServer.id, true);
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
// e is undefined for user cancellation
|
// e is undefined for user cancellation
|
||||||
|
@@ -65,6 +65,18 @@ export class ModalManager {
|
|||||||
return this.modalPromises.get(key) as Promise<T2>;
|
return this.modalPromises.get(key) as Promise<T2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
removeModal = (key: string) => {
|
||||||
|
const modalView = this.modalQueue.find((modal) => modal.key === key);
|
||||||
|
if (!modalView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modalView.hide();
|
||||||
|
modalView.resolve(null);
|
||||||
|
this.modalPromises.delete(key);
|
||||||
|
this.filterActive();
|
||||||
|
};
|
||||||
|
|
||||||
findModalByCaller = (event: IpcMainInvokeEvent) => {
|
findModalByCaller = (event: IpcMainInvokeEvent) => {
|
||||||
if (this.modalQueue.length) {
|
if (this.modalQueue.length) {
|
||||||
const requestModal = this.modalQueue.find((modal) => {
|
const requestModal = this.modalQueue.find((modal) => {
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import {dialog} from 'electron';
|
|
||||||
|
|
||||||
import ServerViewState from 'app/serverViewState';
|
import ServerViewState from 'app/serverViewState';
|
||||||
import {BROWSER_HISTORY_PUSH, LOAD_SUCCESS, SET_ACTIVE_VIEW} from 'common/communication';
|
import {BROWSER_HISTORY_PUSH, LOAD_SUCCESS, SET_ACTIVE_VIEW} from 'common/communication';
|
||||||
import ServerManager from 'common/servers/serverManager';
|
import ServerManager from 'common/servers/serverManager';
|
||||||
@@ -20,9 +18,6 @@ jest.mock('electron', () => ({
|
|||||||
getAppPath: () => '/path/to/app',
|
getAppPath: () => '/path/to/app',
|
||||||
getPath: jest.fn(() => '/valid/downloads/path'),
|
getPath: jest.fn(() => '/valid/downloads/path'),
|
||||||
},
|
},
|
||||||
dialog: {
|
|
||||||
showErrorBox: jest.fn(),
|
|
||||||
},
|
|
||||||
ipcMain: {
|
ipcMain: {
|
||||||
emit: jest.fn(),
|
emit: jest.fn(),
|
||||||
on: jest.fn(),
|
on: jest.fn(),
|
||||||
@@ -33,6 +28,7 @@ jest.mock('app/serverViewState', () => ({
|
|||||||
getCurrentServer: jest.fn(),
|
getCurrentServer: jest.fn(),
|
||||||
updateCurrentView: jest.fn(),
|
updateCurrentView: jest.fn(),
|
||||||
init: jest.fn(),
|
init: jest.fn(),
|
||||||
|
showNewServerModal: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('common/views/View', () => ({
|
jest.mock('common/views/View', () => ({
|
||||||
getViewName: jest.fn((a, b) => `${a}-${b}`),
|
getViewName: jest.fn((a, b) => `${a}-${b}`),
|
||||||
@@ -62,6 +58,10 @@ jest.mock('main/app/utils', () => ({
|
|||||||
flushCookiesStore: jest.fn(),
|
flushCookiesStore: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.mock('main/app/intercom', () => ({
|
||||||
|
handleWelcomeScreenModal: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
jest.mock('main/i18nManager', () => ({
|
jest.mock('main/i18nManager', () => ({
|
||||||
localizeMessage: jest.fn(),
|
localizeMessage: jest.fn(),
|
||||||
}));
|
}));
|
||||||
@@ -116,8 +116,9 @@ jest.mock('./MattermostWebContentsView', () => ({
|
|||||||
MattermostWebContentsView: jest.fn(),
|
MattermostWebContentsView: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('./modalManager', () => ({
|
jest.mock('main/views/modalManager', () => ({
|
||||||
showModal: jest.fn(),
|
showModal: jest.fn(),
|
||||||
|
removeModal: jest.fn(),
|
||||||
isModalDisplayed: jest.fn(),
|
isModalDisplayed: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('./webContentEvents', () => ({}));
|
jest.mock('./webContentEvents', () => ({}));
|
||||||
@@ -321,6 +322,7 @@ describe('main/views/viewManager', () => {
|
|||||||
isOpen: true,
|
isOpen: true,
|
||||||
url: new URL('http://server1.com/view'),
|
url: new URL('http://server1.com/view'),
|
||||||
},
|
},
|
||||||
|
undefined,
|
||||||
);
|
);
|
||||||
makeSpy.mockRestore();
|
makeSpy.mockRestore();
|
||||||
});
|
});
|
||||||
@@ -692,11 +694,12 @@ describe('main/views/viewManager', () => {
|
|||||||
expect(view.load).not.toHaveBeenCalled();
|
expect(view.load).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw dialog when cannot find the view', () => {
|
it('should open new server modal when using a server that does not exist', () => {
|
||||||
|
ServerManager.hasServers.mockReturnValue(true);
|
||||||
const view = {...baseView};
|
const view = {...baseView};
|
||||||
viewManager.handleDeepLink('mattermost://server-1.com/deep/link?thing=yes');
|
viewManager.handleDeepLink('mattermost://server-2.com/deep/link?thing=yes');
|
||||||
expect(view.load).not.toHaveBeenCalled();
|
expect(view.load).not.toHaveBeenCalled();
|
||||||
expect(dialog.showErrorBox).toHaveBeenCalled();
|
expect(ServerViewState.showNewServerModal).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reopen closed view if called upon', () => {
|
it('should reopen closed view if called upon', () => {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import type {IpcMainEvent, IpcMainInvokeEvent} from 'electron';
|
import type {IpcMainEvent, IpcMainInvokeEvent} from 'electron';
|
||||||
import {WebContentsView, dialog, ipcMain} from 'electron';
|
import {WebContentsView, ipcMain} from 'electron';
|
||||||
import isDev from 'electron-is-dev';
|
import isDev from 'electron-is-dev';
|
||||||
|
|
||||||
import ServerViewState from 'app/serverViewState';
|
import ServerViewState from 'app/serverViewState';
|
||||||
@@ -41,18 +41,18 @@ import {getFormattedPathName, parseURL} from 'common/utils/url';
|
|||||||
import Utils from 'common/utils/util';
|
import Utils from 'common/utils/util';
|
||||||
import type {MattermostView} from 'common/views/View';
|
import type {MattermostView} from 'common/views/View';
|
||||||
import {TAB_MESSAGING} 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} from 'main/app/utils';
|
||||||
import DeveloperMode from 'main/developerMode';
|
import DeveloperMode from 'main/developerMode';
|
||||||
import {localizeMessage} from 'main/i18nManager';
|
|
||||||
import performanceMonitor from 'main/performanceMonitor';
|
import performanceMonitor from 'main/performanceMonitor';
|
||||||
import PermissionsManager from 'main/permissionsManager';
|
import PermissionsManager from 'main/permissionsManager';
|
||||||
|
import ModalManager from 'main/views/modalManager';
|
||||||
import MainWindow from 'main/windows/mainWindow';
|
import MainWindow from 'main/windows/mainWindow';
|
||||||
|
|
||||||
import type {DeveloperSettings} from 'types/settings';
|
import type {DeveloperSettings} from 'types/settings';
|
||||||
|
|
||||||
import LoadingScreen from './loadingScreen';
|
import LoadingScreen from './loadingScreen';
|
||||||
import {MattermostWebContentsView} from './MattermostWebContentsView';
|
import {MattermostWebContentsView} from './MattermostWebContentsView';
|
||||||
import modalManager from './modalManager';
|
|
||||||
|
|
||||||
import {getLocalPreload, getAdjustedWindowBoundaries} from '../utils';
|
import {getLocalPreload, getAdjustedWindowBoundaries} from '../utils';
|
||||||
|
|
||||||
@@ -158,14 +158,14 @@ export class ViewManager {
|
|||||||
} else {
|
} else {
|
||||||
this.getViewLogger(viewId).warn(`Couldn't find a view with name: ${viewId}`);
|
this.getViewLogger(viewId).warn(`Couldn't find a view with name: ${viewId}`);
|
||||||
}
|
}
|
||||||
modalManager.showModal();
|
ModalManager.showModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
focusCurrentView = () => {
|
focusCurrentView = () => {
|
||||||
log.debug('focusCurrentView');
|
log.debug('focusCurrentView');
|
||||||
|
|
||||||
if (modalManager.isModalDisplayed()) {
|
if (ModalManager.isModalDisplayed()) {
|
||||||
modalManager.focusCurrentModal();
|
ModalManager.focusCurrentModal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,11 +227,11 @@ export class ViewManager {
|
|||||||
webContentsView.once(LOAD_FAILED, this.deeplinkFailed);
|
webContentsView.once(LOAD_FAILED, this.deeplinkFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (ServerManager.hasServers()) {
|
||||||
|
ServerViewState.showNewServerModal(`${parsedURL.host}${getFormattedPathName(parsedURL.pathname)}${parsedURL.search}`);
|
||||||
} else {
|
} else {
|
||||||
dialog.showErrorBox(
|
ModalManager.removeModal('welcomeScreen');
|
||||||
localizeMessage('main.views.viewManager.handleDeepLink.error.title', 'No matching server'),
|
handleWelcomeScreenModal(`${parsedURL.host}${getFormattedPathName(parsedURL.pathname)}${parsedURL.search}`);
|
||||||
localizeMessage('main.views.viewManager.handleDeepLink.error.body', 'There is no configured server in the app that matches the requested url: {url}', {url: parsedURL.toString()}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -439,7 +439,7 @@ export class ViewManager {
|
|||||||
} else if (recycle) {
|
} else if (recycle) {
|
||||||
views.set(view.id, recycle);
|
views.set(view.id, recycle);
|
||||||
} else {
|
} else {
|
||||||
views.set(view.id, this.makeView(srv, view));
|
views.set(view.id, this.makeView(srv, view, srv.initialLoadURL?.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@ import 'renderer/css/components/LoadingScreen.css';
|
|||||||
|
|
||||||
type ConfigureServerProps = {
|
type ConfigureServerProps = {
|
||||||
server?: UniqueServer;
|
server?: UniqueServer;
|
||||||
|
prefillURL?: string;
|
||||||
mobileView?: boolean;
|
mobileView?: boolean;
|
||||||
darkMode?: boolean;
|
darkMode?: boolean;
|
||||||
messageTitle?: string;
|
messageTitle?: string;
|
||||||
@@ -33,6 +34,7 @@ type ConfigureServerProps = {
|
|||||||
|
|
||||||
function ConfigureServer({
|
function ConfigureServer({
|
||||||
server,
|
server,
|
||||||
|
prefillURL,
|
||||||
mobileView,
|
mobileView,
|
||||||
darkMode,
|
darkMode,
|
||||||
messageTitle,
|
messageTitle,
|
||||||
@@ -53,8 +55,8 @@ function ConfigureServer({
|
|||||||
|
|
||||||
const mounted = useRef(false);
|
const mounted = useRef(false);
|
||||||
const [transition, setTransition] = useState<'inFromRight' | 'outToLeft'>();
|
const [transition, setTransition] = useState<'inFromRight' | 'outToLeft'>();
|
||||||
const [name, setName] = useState(prevName || '');
|
const [name, setName] = useState(prevName ?? '');
|
||||||
const [url, setUrl] = useState(prevURL || '');
|
const [url, setUrl] = useState(prevURL ?? prefillURL ?? '');
|
||||||
const [nameError, setNameError] = useState('');
|
const [nameError, setNameError] = useState('');
|
||||||
const [urlError, setURLError] = useState<{type: STATUS; value: string}>();
|
const [urlError, setURLError] = useState<{type: STATUS; value: string}>();
|
||||||
const [showContent, setShowContent] = useState(false);
|
const [showContent, setShowContent] = useState(false);
|
||||||
@@ -71,6 +73,11 @@ function ConfigureServer({
|
|||||||
setTransition('inFromRight');
|
setTransition('inFromRight');
|
||||||
setShowContent(true);
|
setShowContent(true);
|
||||||
mounted.current = true;
|
mounted.current = true;
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
fetchValidationResult(url);
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
mounted.current = false;
|
mounted.current = false;
|
||||||
};
|
};
|
||||||
|
@@ -27,6 +27,7 @@ type Props = {
|
|||||||
currentOrder?: number;
|
currentOrder?: number;
|
||||||
setInputRef?: (inputRef: HTMLInputElement) => void;
|
setInputRef?: (inputRef: HTMLInputElement) => void;
|
||||||
intl: IntlShape;
|
intl: IntlShape;
|
||||||
|
prefillURL?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
@@ -77,6 +78,13 @@ class NewServerModal extends React.PureComponent<Props, State> {
|
|||||||
this.mounted = false;
|
this.mounted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps: Readonly<Props>): void {
|
||||||
|
if (this.props.prefillURL && this.props.prefillURL !== prevProps.prefillURL) {
|
||||||
|
this.setState({serverUrl: this.props.prefillURL});
|
||||||
|
this.validateServerURL(this.props.prefillURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
initializeOnShow = async () => {
|
initializeOnShow = async () => {
|
||||||
const cameraDisabled = window.process.platform === 'win32' && await window.desktop.getMediaAccessStatus('camera') !== 'granted';
|
const cameraDisabled = window.process.platform === 'win32' && await window.desktop.getMediaAccessStatus('camera') !== 'granted';
|
||||||
const microphoneDisabled = window.process.platform === 'win32' && await window.desktop.getMediaAccessStatus('microphone') !== 'granted';
|
const microphoneDisabled = window.process.platform === 'win32' && await window.desktop.getMediaAccessStatus('microphone') !== 'granted';
|
||||||
|
@@ -25,12 +25,18 @@ const onSave = (data: UniqueServer) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const NewServerModalWrapper: React.FC = () => {
|
const NewServerModalWrapper: React.FC = () => {
|
||||||
|
const [data, setData] = useState<{prefillURL?: string}>();
|
||||||
const [unremoveable, setUnremovable] = useState<boolean>();
|
const [unremoveable, setUnremovable] = useState<boolean>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.desktop.modals.isModalUncloseable().then((uncloseable) => {
|
window.desktop.modals.isModalUncloseable().then((uncloseable) => {
|
||||||
setUnremovable(uncloseable);
|
setUnremovable(uncloseable);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.desktop.modals.getModalInfo<{prefillURL?: string}>().
|
||||||
|
then((data) => {
|
||||||
|
setData(data);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -39,6 +45,7 @@ const NewServerModalWrapper: React.FC = () => {
|
|||||||
onClose={unremoveable ? undefined : onClose}
|
onClose={unremoveable ? undefined : onClose}
|
||||||
onSave={onSave}
|
onSave={onSave}
|
||||||
editMode={false}
|
editMode={false}
|
||||||
|
prefillURL={data?.prefillURL}
|
||||||
show={true}
|
show={true}
|
||||||
/>
|
/>
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
|
@@ -20,6 +20,7 @@ const onConnect = (data: UniqueServer) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const WelcomeScreenModalWrapper = () => {
|
const WelcomeScreenModalWrapper = () => {
|
||||||
|
const [data, setData] = useState<{prefillURL?: string}>();
|
||||||
const [darkMode, setDarkMode] = useState(false);
|
const [darkMode, setDarkMode] = useState(false);
|
||||||
const [getStarted, setGetStarted] = useState(false);
|
const [getStarted, setGetStarted] = useState(false);
|
||||||
const [mobileView, setMobileView] = useState(false);
|
const [mobileView, setMobileView] = useState(false);
|
||||||
@@ -37,6 +38,14 @@ const WelcomeScreenModalWrapper = () => {
|
|||||||
setDarkMode(result);
|
setDarkMode(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.desktop.modals.getModalInfo<{prefillURL?: string}>().
|
||||||
|
then((data) => {
|
||||||
|
setData(data);
|
||||||
|
if (data.prefillURL) {
|
||||||
|
setGetStarted(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
handleWindowResize();
|
handleWindowResize();
|
||||||
window.addEventListener('resize', handleWindowResize);
|
window.addEventListener('resize', handleWindowResize);
|
||||||
|
|
||||||
@@ -56,6 +65,7 @@ const WelcomeScreenModalWrapper = () => {
|
|||||||
mobileView={mobileView}
|
mobileView={mobileView}
|
||||||
darkMode={darkMode}
|
darkMode={darkMode}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
|
prefillURL={data?.prefillURL}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<WelcomeScreen
|
<WelcomeScreen
|
||||||
|
Reference in New Issue
Block a user