diff --git a/config/Symphony.config b/config/Symphony.config
index 85664e36..e2f612de 100644
--- a/config/Symphony.config
+++ b/config/Symphony.config
@@ -5,6 +5,7 @@
"isAutoUpdateEnabled": true,
"autoUpdateCheckInterval": "30",
"enableBrowserLogin": false,
+ "browserLoginAutoConnect": false,
"overrideUserAgent": false,
"minimizeOnClose" : "ENABLED",
"launchOnStartup" : "ENABLED",
diff --git a/installer/mac/postinstall.sh b/installer/mac/postinstall.sh
index 72cae78e..33c88015 100755
--- a/installer/mac/postinstall.sh
+++ b/installer/mac/postinstall.sh
@@ -18,6 +18,7 @@ always_on_top=$(sed -n '5p' ${settingsFilePath});
bring_to_front=$(sed -n '6p' ${settingsFilePath});
dev_tools_enabled=$(sed -n '7p' ${settingsFilePath});
enable_browser_login=$(sed -n '8p' ${settingsFilePath});
+browser_login_autoconnect=$(sed -n '9p' ${settingsFilePath});
## If any of the above values turn out to be empty, set default values ##
if [ "$pod_url" = "" ]; then pod_url="https://my.symphony.com"; fi
@@ -28,6 +29,8 @@ if [ "$always_on_top" = "" ] || [ "$always_on_top" = 'false' ]; then always_on_t
if [ "$bring_to_front" = "" ] || [ "$bring_to_front" = 'false' ]; then bring_to_front='DISABLED'; else bring_to_front='ENABLED'; fi
if [ "$dev_tools_enabled" = "" ]; then dev_tools_enabled=true; fi
if [ "$enable_browser_login" = "" ]; then enable_browser_login=false; fi
+if [ "$browser_login_autoconnect" = "" ]; then browser_login_autoconnect=false; fi
+
pod_url_escaped=$(sed 's#[&/\]#\\g' <<<"$pod_url")
context_origin_url_escaped=$(sed 's#[&/\]#\\g' <<<"$context_origin_url")
@@ -40,6 +43,7 @@ sed -i "" -E "s#\"launchOnStartup\" ?: ?\"([Ee][Nn][Aa][Bb][Ll][Ee][Dd]|[Dd][Ii]
sed -i "" -E "s#\"bringToFront\" ?: ?\"([Ee][Nn][Aa][Bb][Ll][Ee][Dd]|[Dd][Ii][Ss][Aa][Bb][Ll][Ee][Dd])\"#\"bringToFront\":\ \"$bring_to_front\"#g" "${newPath}"
sed -i "" -E "s#\"devToolsEnabled\" ?: ?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])#\"devToolsEnabled\":\ $dev_tools_enabled#g" "${newPath}"
sed -i "" -E "s#\"enableBrowserLogin\" ?: ?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])#\"enableBrowserLogin\":\ $enable_browser_login#g" "${newPath}"
+sed -i "" -E "s#\"browserLoginAutoConnect\" ?: ?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])#\"browserLoginAutoConnect\":\ $browser_login_autoconnect#g" "${newPath}"
## Get Symphony Permissions from the temp file ##
media=$(sed -n '1p' ${permissionsFilePath});
diff --git a/installer/win/WixSharpInstaller/Symphony.cs b/installer/win/WixSharpInstaller/Symphony.cs
index 021e4d64..d653d68a 100644
--- a/installer/win/WixSharpInstaller/Symphony.cs
+++ b/installer/win/WixSharpInstaller/Symphony.cs
@@ -159,6 +159,7 @@ class Script
new PublicProperty("USER_DATA_PATH", ""),
new PublicProperty("OVERRIDE_USER_AGENT", "false"),
new PublicProperty("ENABLE_BROWSER_LOGIN", "false"),
+ new PublicProperty("BROWSER_LOGIN_AUTOCONNECT", "false"),
new PublicProperty("CHROME_FLAGS", ""),
new Property("MSIINSTALLPERUSER", "1"),
new Property("PROGRAMSFOLDER", System.Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%"))
@@ -187,7 +188,7 @@ class Script
new ElevatedManagedAction(CustomActions.UpdateConfig, Return.check, When.After, Step.InstallFiles, Condition.NOT_BeingRemoved )
{
// The UpdateConfig action needs the built-in property INSTALLDIR as well as most of the custom properties
- UsesProperties = "INSTALLDIR,POD_URL,CONTEXT_ORIGIN_URL,MINIMIZE_ON_CLOSE,ALWAYS_ON_TOP,AUTO_START,BRING_TO_FRONT,MEDIA,LOCATION,NOTIFICATIONS,MIDI_SYSEX,POINTER_LOCK,FULL_SCREEN,OPEN_EXTERNAL,CUSTOM_TITLE_BAR,DEV_TOOLS_ENABLED,AUTO_LAUNCH_PATH,USER_DATA_PATH,OVERRIDE_USER_AGENT,CHROME_FLAGS,ENABLE_BROWSER_LOGIN"
+ UsesProperties = "INSTALLDIR,POD_URL,CONTEXT_ORIGIN_URL,MINIMIZE_ON_CLOSE,ALWAYS_ON_TOP,AUTO_START,BRING_TO_FRONT,MEDIA,LOCATION,NOTIFICATIONS,MIDI_SYSEX,POINTER_LOCK,FULL_SCREEN,OPEN_EXTERNAL,CUSTOM_TITLE_BAR,DEV_TOOLS_ENABLED,AUTO_LAUNCH_PATH,USER_DATA_PATH,OVERRIDE_USER_AGENT,CHROME_FLAGS,ENABLE_BROWSER_LOGIN,BROWSER_LOGIN_AUTOCONNECT"
},
// CleanRegistry
@@ -362,6 +363,7 @@ public class CustomActions
data = ReplaceBooleanProperty(data, "devToolsEnabled", session.Property("DEV_TOOLS_ENABLED"));
data = ReplaceBooleanProperty(data, "overrideUserAgent", session.Property("OVERRIDE_USER_AGENT"));
data = ReplaceBooleanProperty(data, "enableBrowserLogin", session.Property("ENABLE_BROWSER_LOGIN"));
+ data = ReplaceBooleanProperty(data, "browserLoginAutoConnect", session.Property("BROWSER_LOGIN_AUTOCONNECT"));
// Write the contents back to the file
System.IO.File.WriteAllText(filename, data);
}
diff --git a/installer/win/install_instructions_win.md b/installer/win/install_instructions_win.md
index c2f75f2d..b1841789 100644
--- a/installer/win/install_instructions_win.md
+++ b/installer/win/install_instructions_win.md
@@ -535,15 +535,15 @@ Expected values:
Expected values:
* "true"
- SDA will authenticate the user by relying on third-party browser
+ SDA will authenticate the user by relying on default browser
* "false"
SDA will authenticate the user in SDA
-#### Example, install with user-agent override
+#### Example, install with browser login enabled
msiexec /i Symphony.msi ENABLE_BROWSER_LOGIN="true"
-#### Example, install without user-agent override
+#### Example, install without browser login enabled
msiexec /i Symphony.msi ENABLE_BROWSER_LOGIN="false"
@@ -554,3 +554,25 @@ or
-------------------------------------------------------------------
+### BROWSER_LOGIN_AUTOCONNECT
+
+Acts in combination with ENABLE_BROWSER_LOGIN, if ENABLE_BROWSER_LOGIN is set to true.
+
+Expected values:
+
+* "true"
+ SDA will automatically authenticate the user by relying on default browser
+* "false"
+ User will need to click on Login button to start browser login flow.
+
+#### Example, install with browser login autoconnect enabled
+
+ msiexec /i Symphony.msi BROWSER_LOGIN_AUTOCONNECT="true"
+
+#### Example, install with browser login autoconnect disabled
+
+ msiexec /i Symphony.msi BROWSER_LOGIN_AUTOCONNECT="false"
+
+or
+
+ msiexec /i Symphony.msi
diff --git a/spec/__snapshots__/welcome.spec.ts.snap b/spec/__snapshots__/welcome.spec.ts.snap
index 91f5d8ad..98ac3111 100644
--- a/spec/__snapshots__/welcome.spec.ts.snap
+++ b/spec/__snapshots__/welcome.spec.ts.snap
@@ -99,35 +99,60 @@ exports[`welcome should render correctly 1`] = `
1,000 institutions.
-
-
-
- Log in with your pod URL
-
+
+
+ Log in with your pod URL
+
+
+
+
+ Pod URL
+
+
+
+
+ Find your pod URL in your invitation email.
+
-
+
{
message: '',
urlValid: true,
isPodConfigured: false,
- isSeamlessLoginEnabled: true,
+ isBrowserLoginEnabled: false,
+ browserLoginAutoConnect: false,
};
const onLabelEvent = 'on';
const removeListenerLabelEvent = 'removeListener';
@@ -26,17 +27,6 @@ describe('welcome', () => {
expect(spy).toBeCalledWith(welcomeLabel, expect.any(Function));
});
- it('should remove listener `welcome` when component is unmounted', () => {
- const spyMount = jest.spyOn(ipcRenderer, onLabelEvent);
- const spyUnmount = jest.spyOn(ipcRenderer, removeListenerLabelEvent);
-
- const wrapper = shallow(React.createElement(Welcome));
- expect(spyMount).toBeCalledWith(welcomeLabel, expect.any(Function));
-
- wrapper.unmount();
- expect(spyUnmount).toBeCalledWith(welcomeLabel, expect.any(Function));
- });
-
it('should call `updateState` when component is mounted', () => {
const spy = jest.spyOn(Welcome.prototype, 'setState');
shallow(React.createElement(Welcome));
@@ -113,11 +103,24 @@ describe('welcome', () => {
message: '',
urlValid: true,
isPodConfigured: true,
- isSeamlessLoginEnabled: true,
+ isBrowserLoginEnabled: false,
+ browserLoginAutoConnect: false,
+ isLoading: false,
};
const wrapper = shallow(React.createElement(Welcome));
ipcRenderer.send('welcome', welcomeMock);
const podUrlBox = `input.Welcome-main-container-podurl-box`;
expect(wrapper.find(podUrlBox).getElements()).toEqual([]);
});
+
+ it('should remove listener `welcome` when component is unmounted', () => {
+ const spyMount = jest.spyOn(ipcRenderer, onLabelEvent);
+ const spyUnmount = jest.spyOn(ipcRenderer, removeListenerLabelEvent);
+
+ const wrapper = shallow(React.createElement(Welcome));
+ expect(spyMount).toBeCalledWith(welcomeLabel, expect.any(Function));
+
+ wrapper.unmount();
+ expect(spyUnmount).toBeCalledWith(welcomeLabel, expect.any(Function));
+ });
});
diff --git a/src/app/app-menu.ts b/src/app/app-menu.ts
index b8f1bfcd..db4d7298 100644
--- a/src/app/app-menu.ts
+++ b/src/app/app-menu.ts
@@ -517,6 +517,7 @@ export class AppMenu {
enabled:
!bringToFrontCC || bringToFrontCC === CloudConfigDataTypes.NOT_SET,
},
+ this.buildSeparator(),
{
type: 'checkbox',
label: i18n.t('Browser login')(),
diff --git a/src/app/auto-update-handler.ts b/src/app/auto-update-handler.ts
index 173850d0..6c69be4f 100644
--- a/src/app/auto-update-handler.ts
+++ b/src/app/auto-update-handler.ts
@@ -95,6 +95,9 @@ export class AutoUpdate {
data: info,
});
}
+ if (isMac) {
+ config.backupGlobalConfig();
+ }
});
this.autoUpdater.on('error', (error) => {
diff --git a/src/app/config-handler.ts b/src/app/config-handler.ts
index b27ccfb0..ea06fa46 100644
--- a/src/app/config-handler.ts
+++ b/src/app/config-handler.ts
@@ -58,7 +58,8 @@ export interface IConfig {
installVariant?: string;
bootCount?: number;
startedAfterAutoUpdate?: boolean;
- enableBrowserLogin: boolean;
+ enableBrowserLogin?: boolean;
+ browserLoginAutoConnect?: boolean;
}
export interface IGlobalConfig {
diff --git a/src/app/main-api-handler.ts b/src/app/main-api-handler.ts
index f951741c..dfdecd8c 100644
--- a/src/app/main-api-handler.ts
+++ b/src/app/main-api-handler.ts
@@ -69,7 +69,7 @@ const broadcastMessage = (method, data) => {
mainEvents.publish(apiCmds.onSwiftSearchMessage, [method, data]);
};
-const getSeamlessLoginUrl = (pod: string) =>
+const getBrowserLoginUrl = (pod: string) =>
`${pod}/login/sso/initsso?RelayState=${pod}/client-bff/device-login/index.html?callbackScheme=symphony&action=login`;
const AUTH_STATUS_PATH = '/login/checkauth?type=user';
/**
@@ -384,9 +384,14 @@ ipcMain.on(
mainWebContents.focus();
}
break;
- case apiCmds.seamlessLogin:
+ case apiCmds.browserLogin:
+ await config.updateUserConfig({
+ browserLoginAutoConnect: arg.browserLoginAutoConnect,
+ });
if (!arg.isPodConfigured) {
- await config.updateUserConfig({ url: arg.newPodUrl });
+ await config.updateUserConfig({
+ url: arg.newPodUrl,
+ });
}
const urlFromCmd = getCommandLineArgs(process.argv, '--url=', false);
const { url: userConfigURL } = config.getUserConfigFields(['url']);
@@ -398,7 +403,7 @@ ipcMain.on(
: globalConfigURL;
const { subdomain, domain, tld } = whitelistHandler.parseDomain(podUrl);
const formattedPodUrl = `https://${subdomain}.${domain}${tld}`;
- const loginUrl = getSeamlessLoginUrl(formattedPodUrl);
+ const loginUrl = getBrowserLoginUrl(formattedPodUrl);
logger.info(
'main-api-handler:',
'check if sso is enabled for the pod',
@@ -408,19 +413,19 @@ ipcMain.on(
const authResponse = (await response.json()) as IAuthResponse;
logger.info('main-api-handler:', 'check auth response', authResponse);
if (
- arg.isSeamlessLoginEnabled &&
+ arg.isBrowserLoginEnabled &&
authResponse.authenticationType === 'sso'
) {
logger.info(
'main-api-handler:',
- 'seamless login is enabled - logging in',
+ 'browser login is enabled - logging in',
loginUrl,
);
await shell.openExternal(loginUrl);
} else {
logger.info(
'main-api-handler:',
- 'seamless login is not enabled - loading main window with',
+ 'browser login is not enabled - loading main window with',
formattedPodUrl,
);
const mainWebContents = windowHandler.getMainWebContents();
diff --git a/src/app/protocol-handler.ts b/src/app/protocol-handler.ts
index 82909668..d52010c5 100644
--- a/src/app/protocol-handler.ts
+++ b/src/app/protocol-handler.ts
@@ -63,7 +63,7 @@ class ProtocolHandler {
);
// Handle protocol for Seamless login
if (url?.includes('skey') && url?.includes('anticsrf')) {
- await this.handleSeamlessLogin(url);
+ await this.handleBrowserLogin(url);
return;
}
@@ -112,11 +112,12 @@ class ProtocolHandler {
/**
* Sets session cookies and navigates to the pod url
*/
- public async handleSeamlessLogin(protocolUri: string): Promise {
+ public async handleBrowserLogin(protocolUri: string): Promise {
const globalConfig = config.getGlobalConfigFields(['url']);
const userConfig = config.getUserConfigFields(['url']);
- const url = userConfig.url ? userConfig.url : globalConfig.url;
- const { subdomain, tld, domain } = whitelistHandler.parseDomain(url);
+ const redirectURL = userConfig.url ? userConfig.url : globalConfig.url;
+ const { subdomain, tld, domain } =
+ whitelistHandler.parseDomain(redirectURL);
const cookieDomain = `.${subdomain}.${domain}${tld}`;
if (protocolUri) {
const urlParams = new URLSearchParams(new URL(protocolUri).search);
@@ -124,7 +125,7 @@ class ProtocolHandler {
const anticsrfValue = urlParams.get('anticsrf');
if (skeyValue && anticsrfValue) {
const skeyCookie: CookiesSetDetails = {
- url,
+ url: redirectURL,
name: 'skey',
value: skeyValue,
secure: true,
@@ -133,7 +134,7 @@ class ProtocolHandler {
domain: cookieDomain,
};
const csrfCookie: CookiesSetDetails = {
- url,
+ url: redirectURL,
name: 'anti-csrf-cookie',
value: anticsrfValue,
secure: true,
@@ -152,10 +153,13 @@ class ProtocolHandler {
}
}
const mainWebContents = windowHandler.getMainWebContents();
- if (mainWebContents && !mainWebContents?.isDestroyed() && url) {
- logger.info('protocol-handler: redirecting main webContents ', url);
- windowHandler.setMainWindowOrigin(url);
- mainWebContents?.loadURL(url);
+ if (mainWebContents && !mainWebContents?.isDestroyed() && redirectURL) {
+ logger.info(
+ 'protocol-handler: redirecting main webContents ',
+ redirectURL,
+ );
+ windowHandler.setMainWindowOrigin(redirectURL);
+ mainWebContents?.loadURL(redirectURL);
}
}
}
diff --git a/src/app/stores/presence-status-store.ts b/src/app/stores/presence-status-store.ts
index d180ac18..bd81d2f9 100644
--- a/src/app/stores/presence-status-store.ts
+++ b/src/app/stores/presence-status-store.ts
@@ -14,7 +14,7 @@ import { isMac, isWindowsOS } from '../../common/env';
export class PresenceStatus {
private presenceStatus: IStatusBadge = {
statusCategory: EPresenceStatusCategory.NO_PRESENCE,
- statusGroup: EPresenceStatusGroup.OFFLINE,
+ statusGroup: EPresenceStatusGroup.HIDE_PRESENCE,
count: 0,
};
private tray: ITray = {
diff --git a/src/app/window-handler.ts b/src/app/window-handler.ts
index 7b4f138b..695d1f8f 100644
--- a/src/app/window-handler.ts
+++ b/src/app/window-handler.ts
@@ -222,6 +222,7 @@ export class WindowHandler {
'clientSwitch',
'enableRendererLogs',
'enableBrowserLogin',
+ 'browserLoginAutoConnect',
]);
logger.info(
`window-handler: main windows initialized with following config data`,
@@ -252,7 +253,7 @@ export class WindowHandler {
this.isPodConfigured = !config.isFirstTimeLaunch();
this.didShowWelcomeScreen = false;
this.shouldShowWelcomeScreen =
- config.isFirstTimeLaunch() || this.config.enableBrowserLogin;
+ config.isFirstTimeLaunch() || !!this.config.enableBrowserLogin;
this.windowOpts = {
...this.getWindowOpts(
@@ -566,7 +567,8 @@ export class WindowHandler {
message: '',
urlValid: !!userConfigUrl,
isPodConfigured: this.isPodConfigured && !!userConfigUrl,
- isSeamlessLoginEnabled: this.config.enableBrowserLogin,
+ isBrowserLoginEnabled: this.config.enableBrowserLogin,
+ browserLoginAutoConnect: this.config.browserLoginAutoConnect,
});
this.didShowWelcomeScreen = true;
this.mainWebContents.focus();
@@ -860,11 +862,6 @@ export class WindowHandler {
return;
}
logger.info(`finished loading welcome screen.`);
- const ssoValue = !!(
- this.userConfig.url &&
- this.userConfig.url.indexOf('/login/sso/initsso') > -1
- );
-
this.welcomeScreenWindow.webContents.send('page-load-welcome', {
locale: i18n.getLocale(),
resource: i18n.loadedResources,
@@ -882,7 +879,6 @@ export class WindowHandler {
url: userConfigUrl || this.startUrl,
message: '',
urlValid: !!userConfigUrl,
- sso: ssoValue,
});
this.appMenu = new AppMenu();
this.addWindow(opts.winKey, this.welcomeScreenWindow);
diff --git a/src/common/api-interface.ts b/src/common/api-interface.ts
index 64b1658e..bb7cf9b9 100644
--- a/src/common/api-interface.ts
+++ b/src/common/api-interface.ts
@@ -72,7 +72,7 @@ export enum apiCmds {
updateAndRestart = 'update-and-restart',
downloadUpdate = 'download-update',
checkForUpdates = 'check-for-updates',
- seamlessLogin = 'seamless-login',
+ browserLogin = 'browser-login',
updateMyPresence = 'update-my-presence',
getMyPresence = 'get-my-presence',
updateSymphonyTray = 'update-system-tray',
@@ -125,7 +125,8 @@ export interface IApiArgs {
newPodUrl: string;
startUrl: string;
isPodConfigured: boolean;
- isSeamlessLoginEnabled: boolean;
+ isBrowserLoginEnabled: boolean;
+ browserLoginAutoConnect: boolean;
swiftSearchData: any;
types: string[];
thumbnailSize: Size;
diff --git a/src/locale/en-US.json b/src/locale/en-US.json
index 39833546..3d8e4e10 100644
--- a/src/locale/en-US.json
+++ b/src/locale/en-US.json
@@ -223,6 +223,7 @@
"Find your pod URL in your invitation email.": "Find your pod URL in your invitation email.",
"Welcome to the largest global community in financial services with over": "Welcome to the largest global community in financial services with over",
" half a million users": " half a million users",
+ " and more than": " and more than",
" 1,000 institutions.": " 1,000 institutions.",
"Log in with your pod URL": "Log in with your pod URL",
"You’ll momentarily be redirected to your web browser.": "You’ll momentarily be redirected to your web browser.",
@@ -231,7 +232,9 @@
"Pod URL": "Pod URL",
"SSO": "SSO",
"Symphony Logo": "Symphony",
- "WelcomeText": "Welcome"
+ "WelcomeText": "Welcome",
+ "Automatically redirect to your web browser on launch": "Automatically redirect to your web browser on launch",
+ "Retry": "Retry"
},
"Window": "Window",
"Would you like to restart and apply these new settings now?": "Would you like to restart and apply these new settings now?",
diff --git a/src/locale/en.json b/src/locale/en.json
index 7c587b41..000a9d09 100644
--- a/src/locale/en.json
+++ b/src/locale/en.json
@@ -223,6 +223,7 @@
"Find your pod URL in your invitation email.": "Find your pod URL in your invitation email.",
"Welcome to the largest global community in financial services with over": "Welcome to the largest global community in financial services with over",
" half a million users": " half a million users",
+ " and more than": " and more than",
" 1,000 institutions.": " 1,000 institutions.",
"Log in with your pod URL": "Log in with your pod URL",
"You’ll momentarily be redirected to your web browser.": "You’ll momentarily be redirected to your web browser.",
@@ -231,7 +232,9 @@
"Pod URL": "Pod URL",
"SSO": "SSO",
"Symphony Logo": "Symphony",
- "WelcomeText": "Welcome"
+ "WelcomeText": "Welcome",
+ "Automatically redirect to your web browser on launch": "Automatically redirect to your web browser on launch",
+ "Retry": "Retry"
},
"Window": "Window",
"Would you like to restart and apply these new settings now?": "Would you like to restart and apply these new settings now?",
diff --git a/src/locale/fr-FR.json b/src/locale/fr-FR.json
index 87230376..520f46b3 100644
--- a/src/locale/fr-FR.json
+++ b/src/locale/fr-FR.json
@@ -223,6 +223,7 @@
"Find your pod URL in your invitation email.": "L'URL de votre instance Symphony est indiquée dans l'email d'invitation.",
"Welcome to the largest global community in financial services with over": "Bienvenue dans la communauté des services financiers la plus large au monde avec plus d'",
" half a million users": " un demi million d'usagers",
+ " and more than": " et plus de",
" 1,000 institutions.": " 1000 institutions.",
"Log in with your pod URL": "Connectez-vous avec l'URL de votre instance",
"You’ll momentarily be redirected to your web browser.": "Vous allez être redirigé(e) brièvement vers votre navigateur internet.",
diff --git a/src/locale/fr.json b/src/locale/fr.json
index 5783c7fe..af588bd0 100644
--- a/src/locale/fr.json
+++ b/src/locale/fr.json
@@ -223,6 +223,7 @@
"Find your pod URL in your invitation email.": "Find your pod URL in your invitation email.",
"Welcome to the largest global community in financial services with over": "Welcome to the largest global community in financial services with over",
" half a million users": " half a million users",
+ " and more than": " et plus de",
" 1,000 institutions.": " 1,000 institutions.",
"Log in with your pod URL": "Log in with your pod URL",
"You’ll momentarily be redirected to your web browser.": "You’ll momentarily be redirected to your web browser.",
diff --git a/src/locale/ja-JP.json b/src/locale/ja-JP.json
index 0c0d7097..5fd5553f 100644
--- a/src/locale/ja-JP.json
+++ b/src/locale/ja-JP.json
@@ -223,6 +223,7 @@
"Find your pod URL in your invitation email.": "招待メールでpod URLをご確認ください。",
"Welcome to the largest global community in financial services with over": "Welcome to the largest global community in financial services with over",
" half a million users": " half a million users",
+ " and more than": " and more than",
" 1,000 institutions.": " 1,000 institutions.",
"Log in with your pod URL": "Pod URLからログインください",
"You’ll momentarily be redirected to your web browser.": "まもなくウェブブラウザーにリダイレクトさせていただきます。",
diff --git a/src/locale/ja.json b/src/locale/ja.json
index 0fcb6129..7bdb27f4 100644
--- a/src/locale/ja.json
+++ b/src/locale/ja.json
@@ -223,6 +223,7 @@
"Find your pod URL in your invitation email.": "招待メールでpod URLをご確認ください。",
"Welcome to the largest global community in financial services with over": "Welcome to the largest global community in financial services with over",
" half a million users": " half a million users",
+ " and more than": " and more than",
" 1,000 institutions.": " 1,000 institutions.",
"Log in with your pod URL": "Pod URLからログインください",
"You’ll momentarily be redirected to your web browser.": "まもなくウェブブラウザーにリダイレクトさせていただきます。",
diff --git a/src/renderer/components/welcome.tsx b/src/renderer/components/welcome.tsx
index b97056c5..17474676 100644
--- a/src/renderer/components/welcome.tsx
+++ b/src/renderer/components/welcome.tsx
@@ -8,19 +8,23 @@ interface IState {
message: string;
urlValid: boolean;
isPodConfigured: boolean;
- isSeamlessLoginEnabled: boolean;
+ isBrowserLoginEnabled: boolean;
+ browserLoginAutoConnect: boolean;
isLoading: boolean;
}
const WELCOME_NAMESPACE = 'Welcome';
const DEFAULT_MESSAGE = 'Find your pod URL in your invitation email.';
const DEFAULT_POD_URL = 'https://[POD].symphony.com';
+const BROWSER_LOGIN_AUTO_REDIRECT_TIMEOUT = 2000;
export default class Welcome extends React.Component<{}, IState> {
private readonly eventHandlers = {
onLogin: () => this.login(),
};
+ private browserLoginTimeoutId: NodeJS.Timeout | undefined;
+
constructor(props) {
super(props);
this.state = {
@@ -28,7 +32,8 @@ export default class Welcome extends React.Component<{}, IState> {
message: '',
urlValid: false,
isPodConfigured: false,
- isSeamlessLoginEnabled: true,
+ isBrowserLoginEnabled: true,
+ browserLoginAutoConnect: false,
isLoading: false,
};
this.updateState = this.updateState.bind(this);
@@ -38,33 +43,44 @@ export default class Welcome extends React.Component<{}, IState> {
* Render the component
*/
public render(): JSX.Element {
- const { url, message, isPodConfigured } = this.state;
+ const { url, message, isPodConfigured, isLoading, isBrowserLoginEnabled } =
+ this.state;
return (
{this.getWelcomeImage()}
-
-
- {i18n.t(
- 'Welcome to the largest global community in financial services with over',
- WELCOME_NAMESPACE,
- )()}
-
-
- {i18n.t(' half a million users', WELCOME_NAMESPACE)()}
-
- {i18n.t(' and more than', WELCOME_NAMESPACE)()}
-
- {i18n.t(' 1,000 institutions.', WELCOME_NAMESPACE)()}
-
-
+ {isPodConfigured && (
+
+
+ {i18n.t('Welcome back!', WELCOME_NAMESPACE)()}
+
+
+ {i18n.t('Please login to continue', WELCOME_NAMESPACE)()}
+
+
+ )}
{!isPodConfigured && (
-
+
+
+
+ {i18n.t(
+ 'Welcome to the largest global community in financial services with over',
+ WELCOME_NAMESPACE,
+ )()}
+
+
+ {i18n.t(' half a million users', WELCOME_NAMESPACE)()}
+
+ {i18n.t(' and more than', WELCOME_NAMESPACE)()}
+
+ {i18n.t(' 1,000 institutions.', WELCOME_NAMESPACE)()}
+
+
-
+
)}
{this.renderLoginButton()}
-
-
- {i18n.t(
- 'You’ll momentarily be redirected to your web browser.',
- WELCOME_NAMESPACE,
- )()}
-
-
+ {isBrowserLoginEnabled && (
+
+
+ {i18n.t(
+ 'You’ll momentarily be redirected to your web browser.',
+ WELCOME_NAMESPACE,
+ )()}
+
+ {isLoading && (
+
+ {i18n.t('Retry', WELCOME_NAMESPACE)()}
+
+ )}
+
+ )}
);
@@ -110,7 +137,18 @@ export default class Welcome extends React.Component<{}, IState> {
* Perform actions on component being mounted
*/
public componentDidMount(): void {
- ipcRenderer.on('welcome', this.updateState);
+ ipcRenderer.on('welcome', (_event, data) => {
+ if (
+ data.isPodConfigured &&
+ data.browserLoginAutoConnect &&
+ data.isBrowserLoginEnabled
+ ) {
+ this.browserLoginTimeoutId = setTimeout(() => {
+ this.login();
+ }, BROWSER_LOGIN_AUTO_REDIRECT_TIMEOUT);
+ }
+ this.updateState(_event, data);
+ });
}
/**
@@ -125,12 +163,18 @@ export default class Welcome extends React.Component<{}, IState> {
*/
public login(): void {
this.setState({ isLoading: true });
- const { url, isPodConfigured, isSeamlessLoginEnabled } = this.state;
+ const {
+ url,
+ isPodConfigured,
+ isBrowserLoginEnabled,
+ browserLoginAutoConnect,
+ } = this.state;
ipcRenderer.send(apiName.symphonyApi, {
- cmd: apiCmds.seamlessLogin,
+ cmd: apiCmds.browserLogin,
newPodUrl: url,
isPodConfigured,
- isSeamlessLoginEnabled,
+ isBrowserLoginEnabled,
+ browserLoginAutoConnect,
});
}
@@ -159,13 +203,73 @@ export default class Welcome extends React.Component<{}, IState> {
});
}
+ /**
+ * Update pod url from the text box
+ * @param event
+ */
+ public updateBrowserLoginAutoConnect(event) {
+ const { urlValid } = this.state;
+ const browserLoginAutoConnect = event.target.checked;
+ if (!browserLoginAutoConnect) {
+ if (this.browserLoginTimeoutId) {
+ clearTimeout(this.browserLoginTimeoutId);
+ }
+ this.setState({
+ browserLoginAutoConnect,
+ });
+ }
+
+ if (urlValid && browserLoginAutoConnect) {
+ this.setState({
+ browserLoginAutoConnect,
+ isLoading: true,
+ });
+ const { url, isPodConfigured, isBrowserLoginEnabled } = this.state;
+ ipcRenderer.send(apiName.symphonyApi, {
+ cmd: apiCmds.browserLogin,
+ newPodUrl: url,
+ isPodConfigured,
+ isBrowserLoginEnabled,
+ browserLoginAutoConnect,
+ });
+ }
+ }
+
/**
* Renders login button content
*/
private renderLoginButton() {
- const { isLoading, isPodConfigured, urlValid } = this.state;
- if (!isLoading) {
- return (
+ const {
+ isLoading,
+ isPodConfigured,
+ urlValid,
+ isBrowserLoginEnabled,
+ browserLoginAutoConnect,
+ } = this.state;
+ return (
+
+ {isBrowserLoginEnabled && (
+
+
+
+
+
+
+
+ {i18n.t(
+ 'Automatically redirect to your web browser on launch',
+ WELCOME_NAMESPACE,
+ )()}
+
+
+
+ )}
+
{
onClick={this.eventHandlers.onLogin}
style={isPodConfigured ? { marginTop: '40px' } : {}}
>
- {i18n.t('log in', WELCOME_NAMESPACE)()}
+ {isLoading && (
+
+ )}
+ {!isLoading && i18n.t('log in', WELCOME_NAMESPACE)()}
- );
- }
- return (
-
+
);
}
diff --git a/src/renderer/styles/theme.less b/src/renderer/styles/theme.less
index e95d7b28..05b11a93 100644
--- a/src/renderer/styles/theme.less
+++ b/src/renderer/styles/theme.less
@@ -7,11 +7,13 @@
// Color palette
@electricity-ui-05: #e9f2f9;
-@electricity-ui-50: #0277d6;
-@electricity-ui-40: #2996fd;
+@electricity-ui-20: #aad4f8;
@electricity-ui-30: #6eb9fd;
+@electricity-ui-40: #2996fd;
+@electricity-ui-50: #0277d6;
@electricity-ui-60: #27588e;
+@graphite-10: #e3e5e7;
@graphite-20: #cdcfd4;
@graphite-05: #f1f1f3;
@graphite-80: #27292c;
diff --git a/src/renderer/styles/welcome.less b/src/renderer/styles/welcome.less
index b6bed5c2..f1cc6852 100644
--- a/src/renderer/styles/welcome.less
+++ b/src/renderer/styles/welcome.less
@@ -220,10 +220,10 @@ body {
text-decoration: none;
line-height: 12px;
background-color: @electricity-ui-50;
- color: #ffffff;
+ color: @text-color-primary;
cursor: pointer;
text-transform: uppercase;
- margin: 24px 0 4px 0;
+ margin: 16px 0 4px 0;
&:focus {
box-shadow: 0 0 10px rgba(61, 162, 253, 1);
@@ -236,16 +236,61 @@ body {
}
&-redirect-info-text-container {
- margin-top: 32px;
+ margin-top: 40px;
+ margin-bottom: 16px;
span {
font-weight: 400;
- font-size: 12px;
+ font-size: 14px;
line-height: 16px;
text-align: center;
color: @graphite-30;
}
}
+
+ &-retry-button {
+ box-shadow: none;
+ border: none;
+ cursor: pointer;
+ padding: 0;
+ margin: 0 8px;
+ font-size: 14px;
+ text-align: center;
+ display: inline-block;
+ text-decoration: none;
+ background-color: transparent;
+ color: @electricity-ui-30;
+ }
+
+ &-auto-connect-wrapper {
+ display: flex;
+ margin-top: 18px;
+
+ .auto-connect-labels {
+ display: flex;
+ flex-direction: column;
+ .auto-connect-label {
+ font-size: 14px;
+ color: @graphite-10;
+ margin-bottom: 8px;
+ font-weight: 300;
+ }
+ .auto-connect-help-label {
+ font-size: 12px;
+ color: @graphite-30;
+ }
+ }
+ }
+ &-welcome-back {
+ font-size: 14px;
+ color: @graphite-05;
+ margin-top: 40px;
+ }
+ &-login-label {
+ font-size: 18px;
+ color: @graphite-05;
+ margin-top: 13px;
+ }
}
@keyframes fade-in-logo {
@@ -313,15 +358,14 @@ body {
.splash-screen--spinner-container {
opacity: 0;
animation: fade-in-spinner 1s ease-in 0s forwards;
- margin-top: 2rem;
text-align: center;
}
.splash-screen--spinner {
display: inline-block;
line-height: 1;
- color: #0277d6;
- width: 40px;
- height: 40px;
+ color: @electricity-ui-50;
+ width: 20px;
+ height: 20px;
animation: progress-circular-rotate 1.4s linear infinite;
}
.splash-screen--spinner-circle {
@@ -330,3 +374,80 @@ body {
stroke-dashoffset: 0px;
stroke: currentColor;
}
+
+.switch {
+ margin: auto;
+ margin-right: 8px;
+ position: relative;
+ display: inline-block;
+ width: 43px;
+ height: 8px;
+}
+
+/* Hide default HTML checkbox */
+.switch input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+/* The slider */
+.slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ -webkit-transition: 0.4s;
+ transition: 0.4s;
+ background-color: @graphite-60;
+}
+
+.slider:before {
+ position: absolute;
+ content: '';
+ height: 14px;
+ width: 14px;
+ bottom: -5px;
+ -webkit-transition: 0.4s;
+ transition: 0.4s;
+ background-color: @graphite-80;
+ border: 2px solid @electricity-ui-40;
+ &:disabled {
+ background-color: #090a0b;
+ }
+}
+
+input:checked + .slider:before {
+ -webkit-transform: translateX(20px);
+ -ms-transform: translateX(20px);
+ transform: translateX(20px);
+ background-color: @electricity-ui-40;
+}
+
+input:not(:checked) + .slider {
+ &:hover {
+ &::before {
+ border-color: @electricity-ui-30;
+ }
+ }
+}
+
+input:checked + .slider {
+ &:hover {
+ &::before {
+ background-color: @electricity-ui-30;
+ border-color: @electricity-ui-30;
+ }
+ }
+}
+
+/* Rounded sliders */
+.slider.round {
+ border-radius: 34px;
+}
+
+.slider.round:before {
+ border-radius: 50%;
+}