Protocol handler for deep linking in desktop app
This commit is contained in:
@@ -20,6 +20,12 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"protocols": [
|
||||||
|
{
|
||||||
|
"name": "Mattermost",
|
||||||
|
"schemes": ["mattermost"]
|
||||||
|
}
|
||||||
|
],
|
||||||
"deb": {
|
"deb": {
|
||||||
"synopsis": "Mattermost"
|
"synopsis": "Mattermost"
|
||||||
},
|
},
|
||||||
|
@@ -254,8 +254,7 @@ const MainPage = createReactClass({
|
|||||||
withTab={this.props.teams.length > 1}
|
withTab={this.props.teams.length > 1}
|
||||||
useSpellChecker={this.props.useSpellChecker}
|
useSpellChecker={this.props.useSpellChecker}
|
||||||
onSelectSpellCheckerLocale={this.props.onSelectSpellCheckerLocale}
|
onSelectSpellCheckerLocale={this.props.onSelectSpellCheckerLocale}
|
||||||
src={team.url}
|
team={team}
|
||||||
name={team.name}
|
|
||||||
onTargetURLChange={self.handleTargetURLChange}
|
onTargetURLChange={self.handleTargetURLChange}
|
||||||
onUnreadCountChange={handleUnreadCountChange}
|
onUnreadCountChange={handleUnreadCountChange}
|
||||||
onNotificationClick={handleNotificationClick}
|
onNotificationClick={handleNotificationClick}
|
||||||
|
@@ -15,11 +15,10 @@ const preloadJS = `file://${remote.app.getAppPath()}/browser/webview/mattermost_
|
|||||||
|
|
||||||
const MattermostView = createReactClass({
|
const MattermostView = createReactClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
name: PropTypes.string,
|
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
onTargetURLChange: PropTypes.func,
|
onTargetURLChange: PropTypes.func,
|
||||||
onUnreadCountChange: PropTypes.func,
|
onUnreadCountChange: PropTypes.func,
|
||||||
src: PropTypes.string,
|
team: PropTypes.object,
|
||||||
active: PropTypes.bool,
|
active: PropTypes.bool,
|
||||||
withTab: PropTypes.bool,
|
withTab: PropTypes.bool,
|
||||||
useSpellChecker: PropTypes.bool,
|
useSpellChecker: PropTypes.bool,
|
||||||
@@ -44,8 +43,18 @@ const MattermostView = createReactClass({
|
|||||||
var self = this;
|
var self = this;
|
||||||
var webview = findDOMNode(this.refs.webview);
|
var webview = findDOMNode(this.refs.webview);
|
||||||
|
|
||||||
|
ipcRenderer.on('protocol-deeplink', (event, lastUrl) => {
|
||||||
|
webview.executeJavaScript(
|
||||||
|
'history.pushState(null, null, "/' +
|
||||||
|
lastUrl.replace(lastUrl.match(/(?:[^/]*\/){3}/), '') + '");'
|
||||||
|
);
|
||||||
|
webview.executeJavaScript(
|
||||||
|
'dispatchEvent(new PopStateEvent("popstate", null));'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
webview.addEventListener('did-fail-load', (e) => {
|
webview.addEventListener('did-fail-load', (e) => {
|
||||||
console.log(self.props.name, 'webview did-fail-load', e);
|
console.log(self.props.team.name, 'webview did-fail-load', e);
|
||||||
if (e.errorCode === -3) { // An operation was aborted (due to user action).
|
if (e.errorCode === -3) { // An operation was aborted (due to user action).
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -139,7 +148,7 @@ const MattermostView = createReactClass({
|
|||||||
});
|
});
|
||||||
|
|
||||||
webview.addEventListener('console-message', (e) => {
|
webview.addEventListener('console-message', (e) => {
|
||||||
const message = `[${this.props.name}] ${e.message}`;
|
const message = `[${this.props.team.name}] ${e.message}`;
|
||||||
switch (e.level) {
|
switch (e.level) {
|
||||||
case 0:
|
case 0:
|
||||||
console.log(message);
|
console.log(message);
|
||||||
@@ -223,6 +232,10 @@ const MattermostView = createReactClass({
|
|||||||
if (!this.props.active) {
|
if (!this.props.active) {
|
||||||
classNames.push('mattermostView-hidden');
|
classNames.push('mattermostView-hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deeplinkingUrl = remote.getCurrentWindow().deeplinkingUrl;
|
||||||
|
const lastUrl = (deeplinkingUrl === null ? this.props.team.url : deeplinkingUrl);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{ errorView }
|
{ errorView }
|
||||||
@@ -230,7 +243,7 @@ const MattermostView = createReactClass({
|
|||||||
id={this.props.id}
|
id={this.props.id}
|
||||||
className={classNames.join(' ')}
|
className={classNames.join(' ')}
|
||||||
preload={preloadJS}
|
preload={preloadJS}
|
||||||
src={this.props.src}
|
src={lastUrl}
|
||||||
ref='webview'
|
ref='webview'
|
||||||
/>
|
/>
|
||||||
</div>);
|
</div>);
|
||||||
|
28
src/main.js
28
src/main.js
@@ -44,6 +44,7 @@ const assetsDir = path.resolve(app.getAppPath(), 'assets');
|
|||||||
// be closed automatically when the JavaScript object is garbage collected.
|
// be closed automatically when the JavaScript object is garbage collected.
|
||||||
var mainWindow = null;
|
var mainWindow = null;
|
||||||
let spellChecker = null;
|
let spellChecker = null;
|
||||||
|
let deeplinkingUrl = null;
|
||||||
|
|
||||||
var argv = require('yargs').parse(process.argv.slice(1));
|
var argv = require('yargs').parse(process.argv.slice(1));
|
||||||
|
|
||||||
@@ -148,7 +149,14 @@ const trayImages = (() => {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
// If there is already an instance, activate the window in the existing instace and quit this one
|
// If there is already an instance, activate the window in the existing instace and quit this one
|
||||||
if (app.makeSingleInstance((/*commandLine, workingDirectory*/) => {
|
if (app.makeSingleInstance((commandLine/*, workingDirectory*/) => {
|
||||||
|
// Protocol handler for win32
|
||||||
|
// argv: An array of the second instance’s (command line / deep linked) arguments
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
// Keep only command line / deep linked arguments
|
||||||
|
deeplinkingUrl = commandLine.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
// Someone tried to run a second instance, we should focus our window.
|
// Someone tried to run a second instance, we should focus our window.
|
||||||
if (mainWindow) {
|
if (mainWindow) {
|
||||||
if (mainWindow.isMinimized()) {
|
if (mainWindow.isMinimized()) {
|
||||||
@@ -319,6 +327,15 @@ ipcMain.on('download-url', (event, URL) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.setAsDefaultProtocolClient('Mattermost');
|
||||||
|
|
||||||
|
// Protocol handler for osx
|
||||||
|
app.on('open-url', function(event, url) {
|
||||||
|
event.preventDefault();
|
||||||
|
deeplinkingUrl = url.replace('Mattermost', 'https');
|
||||||
|
mainWindow.webContents.send('protocol-deeplink', deeplinkingUrl);
|
||||||
|
});
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
// This method will be called when Electron has finished
|
||||||
// initialization and is ready to create browser windows.
|
// initialization and is ready to create browser windows.
|
||||||
app.on('ready', () => {
|
app.on('ready', () => {
|
||||||
@@ -331,9 +348,16 @@ app.on('ready', () => {
|
|||||||
catch((err) => console.log('An error occurred: ', err));
|
catch((err) => console.log('An error occurred: ', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Protocol handler for win32
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
// Keep only command line / deep linked arguments
|
||||||
|
deeplinkingUrl = process.argv.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
mainWindow = createMainWindow(config, {
|
mainWindow = createMainWindow(config, {
|
||||||
hideOnStartup,
|
hideOnStartup,
|
||||||
linuxAppIcon: path.join(assetsDir, 'appicon.png')
|
linuxAppIcon: path.join(assetsDir, 'appicon.png'),
|
||||||
|
deeplinkingUrl
|
||||||
});
|
});
|
||||||
mainWindow.on('closed', () => {
|
mainWindow.on('closed', () => {
|
||||||
// Dereference the window object, usually you would store windows
|
// Dereference the window object, usually you would store windows
|
||||||
|
@@ -42,6 +42,7 @@ function createMainWindow(config, options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mainWindow = new BrowserWindow(windowOptions);
|
const mainWindow = new BrowserWindow(windowOptions);
|
||||||
|
mainWindow.deeplinkingUrl = options.deeplinkingUrl;
|
||||||
|
|
||||||
const indexURL = global.isDev ? 'http://localhost:8080/browser/index.html' : `file://${app.getAppPath()}/browser/index.html`;
|
const indexURL = global.isDev ? 'http://localhost:8080/browser/index.html' : `file://${app.getAppPath()}/browser/index.html`;
|
||||||
mainWindow.loadURL(indexURL);
|
mainWindow.loadURL(indexURL);
|
||||||
|
Reference in New Issue
Block a user