Compare commits
135 Commits
v0.0.1-alp
...
v0.5.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
531973194c | ||
|
|
4d1face275 | ||
|
|
ca7503f1f0 | ||
|
|
9c163b4166 | ||
|
|
742afb1c09 | ||
|
|
edf34efd86 | ||
|
|
72ebed95da | ||
|
|
975a6ab8bf | ||
|
|
3352301b67 | ||
|
|
358260f766 | ||
|
|
b58052ce34 | ||
|
|
de9ad8082b | ||
|
|
d6bf84c821 | ||
|
|
d5cba4096d | ||
|
|
afa12cc266 | ||
|
|
42ede5e54b | ||
|
|
1549db5ce0 | ||
|
|
a0de440c2e | ||
|
|
7e54eb89c2 | ||
|
|
f8e77dfa72 | ||
|
|
db6d1f300a | ||
|
|
eac2b92cb6 | ||
|
|
a349e0e4e0 | ||
|
|
58f35569c8 | ||
|
|
4a9f51aa1b | ||
|
|
5bb05906b5 | ||
|
|
f80095d953 | ||
|
|
181803755a | ||
|
|
ef30cd9624 | ||
|
|
7c82f41e87 | ||
|
|
61dfcfc3b1 | ||
|
|
e3deb93730 | ||
|
|
d6a3e5fe1b | ||
|
|
dc15edf0cd | ||
|
|
e5a60cc077 | ||
|
|
4d5c57fa0b | ||
|
|
98bd4fd9b9 | ||
|
|
8b808ff9b2 | ||
|
|
4a2a495738 | ||
|
|
309816e40a | ||
|
|
79a31000df | ||
|
|
8410769fdd | ||
|
|
fd25ac0cc4 | ||
|
|
87797cf81e | ||
|
|
4638810127 | ||
|
|
e0c2d9f6c7 | ||
|
|
2c34eb8ff8 | ||
|
|
630bafca42 | ||
|
|
9b13547336 | ||
|
|
07d64fa8c0 | ||
|
|
d4cb4b1572 | ||
|
|
de1a24c726 | ||
|
|
e18d30a3a9 | ||
|
|
d9b6109607 | ||
|
|
6593417189 | ||
|
|
779c0bcf5d | ||
|
|
39ab6aff62 | ||
|
|
b037d1ca1f | ||
|
|
92d2ba7ee9 | ||
|
|
557e05db7c | ||
|
|
c0df294dec | ||
|
|
34700969ae | ||
|
|
1a36230cac | ||
|
|
1b9c3afdd4 | ||
|
|
b33e36b415 | ||
|
|
7ee9bf833e | ||
|
|
978128ae3e | ||
|
|
ca754d5eb9 | ||
|
|
be41b4069c | ||
|
|
a7cf1ddbb0 | ||
|
|
f098ae8250 | ||
|
|
84ae25ed06 | ||
|
|
5e5270e5ed | ||
|
|
157ffb7f34 | ||
|
|
70e4a11fe6 | ||
|
|
f142b5bb92 | ||
|
|
f9c9f59d09 | ||
|
|
22ea0dd9f7 | ||
|
|
1a63839f6d | ||
|
|
8ca092c403 | ||
|
|
474e9f0194 | ||
|
|
9f70068184 | ||
|
|
04f6e9e6e5 | ||
|
|
c05885baac | ||
|
|
9908ef51eb | ||
|
|
a4471f35ee | ||
|
|
b9c4910dd4 | ||
|
|
5c95e35839 | ||
|
|
e068d8e96f | ||
|
|
dda491938e | ||
|
|
71637d8e92 | ||
|
|
7cbdd9cae8 | ||
|
|
b59cd3cf23 | ||
|
|
88d50fa6a6 | ||
|
|
ef94998d21 | ||
|
|
2306514507 | ||
|
|
f7e3ed8a0c | ||
|
|
88036f864f | ||
|
|
82c6782c0d | ||
|
|
a72bccadf9 | ||
|
|
e55928183f | ||
|
|
ef5a44dec2 | ||
|
|
042afdf94f | ||
|
|
e09102456f | ||
|
|
4119f1238d | ||
|
|
c9b2ec0bac | ||
|
|
54bc001d46 | ||
|
|
e20194fc72 | ||
|
|
c1ef006e40 | ||
|
|
2523f8c5d0 | ||
|
|
30f44d2791 | ||
|
|
3c7369189f | ||
|
|
c8bbcf2248 | ||
|
|
62963ae563 | ||
|
|
2d43ce08ad | ||
|
|
2c5459233d | ||
|
|
56bf6fe097 | ||
|
|
89bc8401db | ||
|
|
39f3df5b8f | ||
|
|
5cc3bf0dc8 | ||
|
|
c594979d9b | ||
|
|
e12ad6e1d5 | ||
|
|
d62b87ec0c | ||
|
|
14c130d102 | ||
|
|
c4449570a9 | ||
|
|
011d368fd5 | ||
|
|
0d0518fcf5 | ||
|
|
f1a5bfcabf | ||
|
|
05d483b44c | ||
|
|
34a62e2d10 | ||
|
|
99e444aec0 | ||
|
|
56940dacf4 | ||
|
|
6e6ace049a | ||
|
|
5e40043e3e | ||
|
|
55b45420bd |
3
.gitignore
vendored
@@ -1,7 +1,8 @@
|
|||||||
node_modules
|
node_modules
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
domain.json
|
domain.json
|
||||||
|
dist
|
||||||
|
config.gypi
|
||||||
|
|
||||||
// osx garbage
|
// osx garbage
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
|||||||
23
.travis.yml
@@ -1,3 +1,24 @@
|
|||||||
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
|
|
||||||
|
os:
|
||||||
|
- osx
|
||||||
|
- linux
|
||||||
|
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- 'node'
|
- '6'
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- npm install -g gulp
|
||||||
|
- npm install
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- node_modules
|
||||||
|
- app/node_modules
|
||||||
|
- $HOME/.electron
|
||||||
|
- $HOME/.cache
|
||||||
|
|
||||||
|
script:
|
||||||
|
- npm run travis
|
||||||
|
|||||||
53
README.md
@@ -1,4 +1,7 @@
|
|||||||
# Zulip Desktop Client
|
# Zulip Desktop Client
|
||||||
|
[](https://travis-ci.org/zulip/zulip-electron)
|
||||||
|
[](https://ci.appveyor.com/project/akashnimare/zulip-electron/branch/master)
|
||||||
|
[](https://github.com/sindresorhus/xo)
|
||||||
|
|
||||||
This is an experimental replacement for the [Zulip Desktop
|
This is an experimental replacement for the [Zulip Desktop
|
||||||
app](https://github.com/zulip/zulip-desktop) implemented in
|
app](https://github.com/zulip/zulip-desktop) implemented in
|
||||||
@@ -8,6 +11,15 @@ The goal is to achieve feature-compatibility with the old desktop app
|
|||||||
and then start adding cool features like easy support for
|
and then start adding cool features like easy support for
|
||||||
multi-account, auto-updates etc.
|
multi-account, auto-updates etc.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
* node >= v6.3.1
|
||||||
|
* npm >= 3.10.3
|
||||||
|
* If you're on Debian or Ubuntu, you'll also need to install
|
||||||
|
`nodejs-legacy`:
|
||||||
|
```sh
|
||||||
|
$ sudo apt-get install nodejs-legacy
|
||||||
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Clone the source locally:
|
Clone the source locally:
|
||||||
@@ -16,14 +28,6 @@ Clone the source locally:
|
|||||||
$ git clone https://github.com/zulip/zulip-electron
|
$ git clone https://github.com/zulip/zulip-electron
|
||||||
$ cd zulip-electron
|
$ cd zulip-electron
|
||||||
```
|
```
|
||||||
If you're on Debian or Ubuntu, you'll also need to install
|
|
||||||
`nodejs-legacy`:
|
|
||||||
|
|
||||||
Use your package manager to install `npm`.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ sudo apt-get install npm nodejs-legacy
|
|
||||||
```
|
|
||||||
|
|
||||||
Install project dependencies:
|
Install project dependencies:
|
||||||
|
|
||||||
@@ -41,19 +45,32 @@ Start and watch changes
|
|||||||
```sh
|
```sh
|
||||||
$ npm run dev
|
$ npm run dev
|
||||||
```
|
```
|
||||||
|
# Making a release
|
||||||
|
|
||||||
|
To package app into an installer use command:
|
||||||
|
```
|
||||||
|
npm run dist
|
||||||
|
```
|
||||||
|
It will start the packaging process for operating system you are running this command on. Ready for distribution file (e.g. dmg, windows installer, deb package) will be outputted to `dist` directory.
|
||||||
|
|
||||||
|
You can create Windows installer only when running on Windows, the same is true for Linux and OSX. So to generate all three installers you need all three operating systems.
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- [x] Native Notifications
|
- [x] Native Notifications
|
||||||
- [x] Spell Checker
|
- [x] SpellChecker
|
||||||
- [x] Keyboard Shortcuts
|
- [x] OSX/Win/Linux installer
|
||||||
- Default shortcuts - <kbd>cmdOrctrl + k </kbd>
|
- [x] Automatic Updates (macOS/Windows)
|
||||||
- Change Zulip Server: <kbd>cmdOrctrl + ,</kbd>
|
- [x] Keyboard shortcuts
|
||||||
- Back: <kbd>cmdOrctrl + [</kbd>
|
|
||||||
- Forward: <kbd>cmdOrctrl + ]</kbd>
|
Description | Keys
|
||||||
- [ ] OSX/Win/Linux installer
|
-----------------------| -----------------------
|
||||||
- [ ] Launch on OS startup
|
Default shortcuts | <kbd>Cmd/Ctrl</kbd> <kbd>k</kbd>
|
||||||
- [ ] Automatic Updates
|
Change Zulip Server | <kbd>Cmd/Ctrl</kbd> <kbd>,</kbd>
|
||||||
|
Back | <kbd>Cmd/Ctrl</kbd> <kbd>[</kbd>
|
||||||
|
Forward | <kbd>Cmd/Ctrl</kbd> <kbd>]</kbd>
|
||||||
|
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
|
|||||||
BIN
app/.DS_Store
vendored
50
app/main/autoupdater.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
'use strict';
|
||||||
|
const os = require('os');
|
||||||
|
const {app, autoUpdater, dialog} = require('electron');
|
||||||
|
|
||||||
|
const version = app.getVersion();
|
||||||
|
const platform = os.platform() + '_' + os.arch(); // usually returns darwin_64
|
||||||
|
|
||||||
|
const updaterFeedURL = 'http://zulipdesktop.herokuapp.com/update/' + platform + '/' + version;
|
||||||
|
|
||||||
|
function appUpdater() {
|
||||||
|
autoUpdater.setFeedURL(updaterFeedURL);
|
||||||
|
|
||||||
|
// Log whats happening
|
||||||
|
// TODO send autoUpdater events to renderer so that we could
|
||||||
|
// it could console log in developer tools
|
||||||
|
autoUpdater.on('error', err => console.log(err));
|
||||||
|
autoUpdater.on('checking-for-update', () => console.log('checking-for-update'));
|
||||||
|
autoUpdater.on('update-available', () => console.log('update-available'));
|
||||||
|
autoUpdater.on('update-not-available', () => console.log('update-not-available'));
|
||||||
|
|
||||||
|
// Ask the user if update is available
|
||||||
|
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
|
||||||
|
let message = app.getName() + ' ' + releaseName + ' is now available. It will be installed the next time you restart the application.';
|
||||||
|
if (releaseNotes) {
|
||||||
|
const splitNotes = releaseNotes.split(/[^\r]\n/);
|
||||||
|
message += '\n\nRelease notes:\n';
|
||||||
|
splitNotes.forEach(notes => {
|
||||||
|
message += notes + '\n\n';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Ask user to update the app
|
||||||
|
dialog.showMessageBox({
|
||||||
|
type: 'question',
|
||||||
|
buttons: ['Install and Relaunch', 'Later'],
|
||||||
|
defaultId: 0,
|
||||||
|
message: 'A new version of ' + app.getName() + ' has been downloaded',
|
||||||
|
detail: message
|
||||||
|
}, response => {
|
||||||
|
if (response === 0) {
|
||||||
|
setTimeout(() => autoUpdater.quitAndInstall(), 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// init for updates
|
||||||
|
autoUpdater.checkForUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports = module.exports = {
|
||||||
|
appUpdater
|
||||||
|
};
|
||||||
@@ -1,12 +1,19 @@
|
|||||||
/* global app */
|
const {app} = require('electron').remote;
|
||||||
// eslint-disable-next-line no-unused-vars
|
const ipcRenderer = require('electron').ipcRenderer;
|
||||||
function addDomain() {
|
const JsonDB = require('node-json-db');
|
||||||
const request = require('request');
|
const request = require('request');
|
||||||
const ipcRenderer = require('electron').ipcRenderer;
|
|
||||||
const JsonDB = require('node-json-db');
|
|
||||||
|
|
||||||
const db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
const db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
||||||
|
const data = db.getData('/');
|
||||||
|
|
||||||
|
console.log(data.domain);
|
||||||
|
|
||||||
|
// if (data.domain && window.location.href.indexOf(data.domain) === -1) {
|
||||||
|
// window.location.href = data.domain
|
||||||
|
// }
|
||||||
|
// require('electron-connect').client.create();
|
||||||
|
|
||||||
|
window.addDomain = function () {
|
||||||
document.getElementById('main').innerHTML = 'checking...';
|
document.getElementById('main').innerHTML = 'checking...';
|
||||||
|
|
||||||
let newDomain = document.getElementById('url').value;
|
let newDomain = document.getElementById('url').value;
|
||||||
@@ -20,11 +27,10 @@ function addDomain() {
|
|||||||
document.getElementById('main').innerHTML = 'Connect';
|
document.getElementById('main').innerHTML = 'Connect';
|
||||||
db.push('/domain', domain);
|
db.push('/domain', domain);
|
||||||
ipcRenderer.send('new-domain', domain);
|
ipcRenderer.send('new-domain', domain);
|
||||||
// window.location.href = domain;
|
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('main').innerHTML = 'Connect';
|
document.getElementById('main').innerHTML = 'Connect';
|
||||||
document.getElementById('server-status').innerHTML = 'Not a vaild Zulip Server.';
|
document.getElementById('server-status').innerHTML = 'Not a vaild Zulip Server.';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
@@ -1,36 +1,58 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
const electron = require('electron');
|
const electron = require('electron');
|
||||||
const {app} = require('electron');
|
const {app} = require('electron');
|
||||||
const electronLocalshortcut = require('electron-localshortcut');
|
|
||||||
const ipc = require('electron').ipcMain;
|
const ipc = require('electron').ipcMain;
|
||||||
|
const electronLocalshortcut = require('electron-localshortcut');
|
||||||
const Configstore = require('configstore');
|
const Configstore = require('configstore');
|
||||||
const JsonDB = require('node-json-db');
|
const JsonDB = require('node-json-db');
|
||||||
const SpellChecker = require('simple-spellchecker');
|
const isDev = require('electron-is-dev');
|
||||||
const tray = require('./tray');
|
const tray = require('./tray');
|
||||||
const appMenu = require('./menu');
|
const appMenu = require('./menu');
|
||||||
const link = require('./link-helper');
|
const {linkIsInternal, skipImages} = require('./link-helper');
|
||||||
|
const {appUpdater} = require('./autoupdater');
|
||||||
const {linkIsInternal} = link;
|
|
||||||
|
|
||||||
const db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
const db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
||||||
const data = db.getData('/');
|
const data = db.getData('/');
|
||||||
|
|
||||||
|
// Handling squirrel.windows events on windows
|
||||||
|
if (require('electron-squirrel-startup')) {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
|
||||||
// adds debug features like hotkeys for triggering dev tools and reload
|
// adds debug features like hotkeys for triggering dev tools and reload
|
||||||
require('electron-debug')();
|
require('electron-debug')();
|
||||||
require('electron-context-menu')();
|
|
||||||
|
|
||||||
const conf = new Configstore('Zulip-Desktop');
|
const conf = new Configstore('Zulip-Desktop');
|
||||||
|
|
||||||
// spellchecker enabled
|
|
||||||
let myDictionary = null;
|
|
||||||
|
|
||||||
// prevent window being garbage collected
|
// prevent window being garbage collected
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
let targetLink;
|
let targetLink;
|
||||||
|
|
||||||
// Load this url in main window
|
// Load this url in main window
|
||||||
const targetUrl = 'file://' + path.join(__dirname, '../renderer', 'index.html');
|
const staticURL = 'file://' + path.join(__dirname, '../renderer', 'index.html');
|
||||||
|
|
||||||
|
const targetURL = function () {
|
||||||
|
if (data.domain === undefined) {
|
||||||
|
return staticURL;
|
||||||
|
}
|
||||||
|
return data.domain;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isAlreadyRunning = app.makeSingleInstance(() => {
|
||||||
|
if (mainWindow) {
|
||||||
|
if (mainWindow.isMinimized()) {
|
||||||
|
mainWindow.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
mainWindow.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isAlreadyRunning) {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
|
||||||
function checkWindowURL() {
|
function checkWindowURL() {
|
||||||
if (data.domain !== undefined) {
|
if (data.domain !== undefined) {
|
||||||
@@ -39,9 +61,11 @@ function checkWindowURL() {
|
|||||||
return targetLink;
|
return targetLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP_ICON = path.join(__dirname, '../resources', 'Icon');
|
function isWindowsOrmacOS() {
|
||||||
|
return process.platform === 'darwin' || process.platform === 'win32';
|
||||||
|
}
|
||||||
|
|
||||||
const spellDict = path.join(__dirname, '../../node_modules/simple-spellchecker/dict');
|
const APP_ICON = path.join(__dirname, '../resources', 'Icon');
|
||||||
|
|
||||||
const iconPath = () => {
|
const iconPath = () => {
|
||||||
return APP_ICON + (process.platform === 'win32' ? '.ico' : '.png');
|
return APP_ICON + (process.platform === 'win32' ? '.ico' : '.png');
|
||||||
@@ -77,12 +101,13 @@ function createMainWindow() {
|
|||||||
minHeight: 400,
|
minHeight: 400,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: path.join(__dirname, 'preload.js'),
|
preload: path.join(__dirname, 'preload.js'),
|
||||||
nodeIntegration: true,
|
plugins: true,
|
||||||
plugins: true
|
allowDisplayingInsecureContent: true,
|
||||||
|
nodeIntegration: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
win.loadURL(targetUrl);
|
win.loadURL(targetURL());
|
||||||
win.on('closed', onClosed);
|
win.on('closed', onClosed);
|
||||||
win.setTitle('Zulip');
|
win.setTitle('Zulip');
|
||||||
|
|
||||||
@@ -134,6 +159,8 @@ function createMainWindow() {
|
|||||||
app.commandLine.appendSwitch('ignore-certificate-errors', 'true');
|
app.commandLine.appendSwitch('ignore-certificate-errors', 'true');
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
|
// unregister all the shortcuts so that they don't interfare with other apps
|
||||||
|
electronLocalshortcut.unregisterAll(mainWindow);
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
app.quit();
|
app.quit();
|
||||||
}
|
}
|
||||||
@@ -152,20 +179,6 @@ app.on('ready', () => {
|
|||||||
|
|
||||||
const page = mainWindow.webContents;
|
const page = mainWindow.webContents;
|
||||||
|
|
||||||
// Add spellcheck dictionary
|
|
||||||
SpellChecker.getDictionary('en-US', spellDict, (err, result) => {
|
|
||||||
if (!err) {
|
|
||||||
myDictionary = result;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Define function for consult the dictionary.
|
|
||||||
ipc.on('checkspell', (event, word) => {
|
|
||||||
if (myDictionary !== null && word !== null) {
|
|
||||||
event.returnValue = myDictionary.spellCheck(word);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO - use global shortcut instead
|
// TODO - use global shortcut instead
|
||||||
electronLocalshortcut.register(mainWindow, 'CommandOrControl+R', () => {
|
electronLocalshortcut.register(mainWindow, 'CommandOrControl+R', () => {
|
||||||
mainWindow.reload();
|
mainWindow.reload();
|
||||||
@@ -183,33 +196,44 @@ app.on('ready', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// electronLocalshortcut.register(mainWindow, 'CommandOrControl+=', () => {
|
page.on('dom-ready', () => {
|
||||||
// page.send('zoomIn');
|
page.insertCSS(fs.readFileSync(path.join(__dirname, 'preload.css'), 'utf8'));
|
||||||
// });
|
mainWindow.show();
|
||||||
|
});
|
||||||
// electronLocalshortcut.register(mainWindow, 'CommandOrControl+-', () => {
|
|
||||||
// page.send('zoomOut');
|
|
||||||
// });
|
|
||||||
|
|
||||||
// electronLocalshortcut.register(mainWindow, 'CommandOrControl+0', () => {
|
|
||||||
// page.send('zoomActualSize');
|
|
||||||
// });
|
|
||||||
|
|
||||||
page.on('new-window', (event, url) => {
|
page.on('new-window', (event, url) => {
|
||||||
if (mainWindow.useDefaultWindowBehaviour) {
|
if (linkIsInternal(checkWindowURL(), url) && url.match(skipImages) === null) {
|
||||||
mainWindow.useDefaultWindowBehaviour = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (linkIsInternal(checkWindowURL(), url)) {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return mainWindow.loadURL(url);
|
return mainWindow.loadURL(url);
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
electron.shell.openExternal(url);
|
electron.shell.openExternal(url);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
page.once('did-frame-finish-load', () => {
|
||||||
|
const checkOS = isWindowsOrmacOS();
|
||||||
|
if (checkOS && !isDev) {
|
||||||
|
// Initate auto-updates on macOs and windows
|
||||||
|
appUpdater();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.on('will-quit', () => {
|
||||||
|
// unregister all the shortcuts so that they don't interfare with other apps
|
||||||
|
electronLocalshortcut.unregisterAll(mainWindow);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipc.on('new-domain', (e, domain) => {
|
ipc.on('new-domain', (e, domain) => {
|
||||||
mainWindow.loadURL(domain);
|
// mainWindow.loadURL(domain);
|
||||||
|
if (!mainWindow) {
|
||||||
|
mainWindow = createMainWindow();
|
||||||
|
mainWindow.loadURL(domain);
|
||||||
|
} else if (mainWindow.isMinimized()) {
|
||||||
|
mainWindow.loadURL(domain);
|
||||||
|
mainWindow.show();
|
||||||
|
} else {
|
||||||
|
mainWindow.loadURL(domain);
|
||||||
|
}
|
||||||
targetLink = domain;
|
targetLink = domain;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ const wurl = require('wurl');
|
|||||||
|
|
||||||
// Check link if it's internal/external
|
// Check link if it's internal/external
|
||||||
function linkIsInternal(currentUrl, newUrl) {
|
function linkIsInternal(currentUrl, newUrl) {
|
||||||
const currentDomain = wurl('domain', currentUrl);
|
const currentDomain = wurl('hostname', currentUrl);
|
||||||
const newDomain = wurl('domain', newUrl);
|
const newDomain = wurl('hostname', newUrl);
|
||||||
return currentDomain === newDomain;
|
return currentDomain === newDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We'll be needing this to open images in default browser
|
||||||
|
const skipImages = '.jpg|.gif|.png|.jpeg|.JPG|.PNG';
|
||||||
|
|
||||||
exports = module.exports = {
|
exports = module.exports = {
|
||||||
linkIsInternal
|
linkIsInternal, skipImages
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ function sendAction(action) {
|
|||||||
const viewSubmenu = [
|
const viewSubmenu = [
|
||||||
{
|
{
|
||||||
label: 'Reload',
|
label: 'Reload',
|
||||||
accelerator: 'CmdOrCtrl+R',
|
|
||||||
click(item, focusedWindow) {
|
click(item, focusedWindow) {
|
||||||
if (focusedWindow) {
|
if (focusedWindow) {
|
||||||
focusedWindow.reload();
|
focusedWindow.reload();
|
||||||
@@ -119,10 +118,8 @@ const darwinTpl = [
|
|||||||
{
|
{
|
||||||
label: 'Change Zulip Server',
|
label: 'Change Zulip Server',
|
||||||
accelerator: 'Cmd+,',
|
accelerator: 'Cmd+,',
|
||||||
click(item, focusedWindow) {
|
click() {
|
||||||
if (focusedWindow) {
|
addDomain();
|
||||||
addDomain();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -247,10 +244,8 @@ const otherTpl = [
|
|||||||
{
|
{
|
||||||
label: 'Change Zulip Server',
|
label: 'Change Zulip Server',
|
||||||
accelerator: 'Ctrl+,',
|
accelerator: 'Ctrl+,',
|
||||||
click(item, focusedWindow) {
|
click() {
|
||||||
if (focusedWindow) {
|
addDomain();
|
||||||
addDomain();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
1
app/main/preload.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/* We'll be overriding default styling so that app look more native * /
|
||||||
@@ -1,18 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const ipcRenderer = require('electron').ipcRenderer;
|
const ipcRenderer = require('electron').ipcRenderer;
|
||||||
const webFrame = require('electron').webFrame;
|
const {webFrame} = require('electron');
|
||||||
|
const {spellChecker} = require('./spellchecker');
|
||||||
|
|
||||||
// Implement spellcheck using electron api
|
require('./domain');
|
||||||
|
|
||||||
webFrame.setSpellCheckProvider('en-US', false, {
|
|
||||||
spellCheck: text => {
|
|
||||||
const res = ipcRenderer.sendSync('checkspell', text);
|
|
||||||
return res === null ? true : res;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle zooming functionality
|
|
||||||
|
|
||||||
|
// handle zooming functionality
|
||||||
const zoomIn = () => {
|
const zoomIn = () => {
|
||||||
webFrame.setZoomFactor(webFrame.getZoomFactor() + 0.1);
|
webFrame.setZoomFactor(webFrame.getZoomFactor() + 0.1);
|
||||||
};
|
};
|
||||||
@@ -25,7 +18,7 @@ const zoomActualSize = () => {
|
|||||||
webFrame.setZoomFactor(1);
|
webFrame.setZoomFactor(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get zooming actions from main process
|
// get zooming actions from main process
|
||||||
ipcRenderer.on('zoomIn', () => {
|
ipcRenderer.on('zoomIn', () => {
|
||||||
zoomIn();
|
zoomIn();
|
||||||
});
|
});
|
||||||
@@ -53,3 +46,9 @@ ipcRenderer.on('shortcut', () => {
|
|||||||
const nodes = document.querySelectorAll('.dropdown-menu li:nth-child(4) a');
|
const nodes = document.querySelectorAll('.dropdown-menu li:nth-child(4) a');
|
||||||
nodes[nodes.length - 1].click();
|
nodes[nodes.length - 1].click();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// To prevent failing this script on linux we need to load it after the document loaded
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// init spellchecker
|
||||||
|
spellChecker();
|
||||||
|
});
|
||||||
|
|||||||
27
app/main/spellchecker.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
|
||||||
|
|
||||||
|
function spellChecker() {
|
||||||
|
// Implement spellcheck using electron api
|
||||||
|
window.spellCheckHandler = new SpellCheckHandler();
|
||||||
|
window.spellCheckHandler.attachToInput();
|
||||||
|
|
||||||
|
// Start off as US English
|
||||||
|
window.spellCheckHandler.switchLanguage('en-US');
|
||||||
|
|
||||||
|
const contextMenuBuilder = new ContextMenuBuilder(window.spellCheckHandler);
|
||||||
|
const contextMenuListener = new ContextMenuListener(info => {
|
||||||
|
contextMenuBuilder.showPopupMenu(info);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clean up events after you navigate away from this page;
|
||||||
|
// otherwise, you may experience errors
|
||||||
|
window.addEventListener('beforeunload', () => {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
spellCheckHandler.unsubscribe();
|
||||||
|
contextMenuListener.unsubscribe();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports = module.exports = {
|
||||||
|
spellChecker
|
||||||
|
};
|
||||||
@@ -6,21 +6,16 @@ const {addDomain, about} = require('./windowmanager');
|
|||||||
|
|
||||||
let tray = null;
|
let tray = null;
|
||||||
|
|
||||||
const APP_ICON = path.join(__dirname, '../resources', 'Icon');
|
const APP_ICON = path.join(__dirname, '../resources/tray', 'tray');
|
||||||
|
|
||||||
const iconPath = () => {
|
const iconPath = () => {
|
||||||
return APP_ICON + (process.platform === 'win32' ? '.ico' : '.png');
|
if (process.platform === 'linux') {
|
||||||
|
return APP_ICON + 'linux.png';
|
||||||
|
}
|
||||||
|
return APP_ICON + (process.platform === 'win32' ? 'win.ico' : 'osx.png');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.create = () => {
|
exports.create = () => {
|
||||||
// Noone is using this feature. so let's hide it for now.
|
|
||||||
// const toggleWin = () => {
|
|
||||||
// if (win.isVisible()) {
|
|
||||||
// win.hide();
|
|
||||||
// } else {
|
|
||||||
// win.show();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
const contextMenu = electron.Menu.buildFromTemplate([
|
const contextMenu = electron.Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
label: 'About',
|
label: 'About',
|
||||||
@@ -33,10 +28,8 @@ exports.create = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Change Zulip server',
|
label: 'Change Zulip server',
|
||||||
click(item, focusedWindow) {
|
click() {
|
||||||
if (focusedWindow) {
|
addDomain();
|
||||||
addDomain();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
41
app/package.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "zulip",
|
||||||
|
"productName": "Zulip",
|
||||||
|
"version": "0.5.4",
|
||||||
|
"description": "Zulip Desktop App",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"email":"<svnitakash@gmail.com>",
|
||||||
|
"copyright": "©2016 Kandra Labs, Inc.",
|
||||||
|
"author": {
|
||||||
|
"name": "Akash Nimare",
|
||||||
|
"email": "svnitakash@gmail.com"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/zulip/zulip-electron.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/zulip/zulip-electron/issues"
|
||||||
|
},
|
||||||
|
"main": "main/index.js",
|
||||||
|
"keywords": [
|
||||||
|
"Zulip",
|
||||||
|
"Group Chat app",
|
||||||
|
"electron-app",
|
||||||
|
"electron",
|
||||||
|
"Desktop app",
|
||||||
|
"InstantMessaging"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"electron-is-dev": "0.1.2",
|
||||||
|
"electron-squirrel-startup": "1.0.0",
|
||||||
|
"configstore": "2.1.0",
|
||||||
|
"dialogs": "1.1.14",
|
||||||
|
"electron-debug": "1.1.0",
|
||||||
|
"electron-localshortcut": "0.6.1",
|
||||||
|
"node-json-db": "0.7.3",
|
||||||
|
"request": "2.79.0",
|
||||||
|
"electron-spellchecker": "0.7.0",
|
||||||
|
"wurl": "2.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,13 +7,17 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="about">
|
<div class="about">
|
||||||
<center><img src="../resources/zulip.png"></center>
|
<center><img src="../resources/zulip.png"></center>
|
||||||
<center><p class="detail"> Version : 0.0.1 </p>
|
<center><p class="detail" id="version"> Version : ?.?.? </p>
|
||||||
<center><p class="detail"> License : Apache </p>
|
<center><p class="detail"> License : Apache </p>
|
||||||
<center><p class="detail"> Maintainer : Zulip </p>
|
<center><p class="detail"> Maintainer : Zulip </p>
|
||||||
<p class="left"><a class="bug" onclick="linkInBrowser()" href="#">Found bug?</a></p>
|
<p class="left"><a class="bug" onclick="linkInBrowser()" href="#">Found bug?</a></p>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
const app = require('electron').remote.app;
|
||||||
|
const version_tag = document.getElementById('version');
|
||||||
|
version_tag.innerHTML = ' Version : ' + app.getVersion() + ' ';
|
||||||
|
|
||||||
function linkInBrowser(event) {
|
function linkInBrowser(event) {
|
||||||
|
|
||||||
const shell = require('electron').shell;
|
const shell = require('electron').shell;
|
||||||
@@ -24,4 +28,4 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -6,17 +6,6 @@
|
|||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<title>Login - Zulip</title>
|
<title>Login - Zulip</title>
|
||||||
<link rel="stylesheet" href="css/main.css" type="text/css" media="screen">
|
<link rel="stylesheet" href="css/main.css" type="text/css" media="screen">
|
||||||
<script type="text/javascript">
|
|
||||||
const JsonDB = require('node-json-db');
|
|
||||||
const {app} = require('electron').remote;
|
|
||||||
const db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
|
||||||
const data = db.getData('/');
|
|
||||||
|
|
||||||
if (data.domain) {
|
|
||||||
window.location.href = data.domain;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script>require('electron-connect').client.create()</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="container-layout">
|
<body class="container-layout">
|
||||||
<div class="section-main">
|
<div class="section-main">
|
||||||
@@ -34,7 +23,7 @@
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<div class="control-group control-required">
|
<div class="control-group control-required">
|
||||||
<div class="control-field">
|
<div class="control-field">
|
||||||
<input type="text" id="url" autofocus="autofocus" spellcheck="false" placeholder="zulip.tabbott.net">
|
<input type="text" id="url" autofocus="autofocus" spellcheck="false" placeholder="chat.zulip.org">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
@@ -49,6 +38,5 @@
|
|||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<script src="js/main.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
const {remote} = require('electron');
|
const {remote} = require('electron');
|
||||||
|
|
||||||
const prefWindow = remote.getCurrentWindow();
|
const prefWindow = remote.getCurrentWindow();
|
||||||
@@ -15,8 +16,10 @@ document.addEventListener('keydown', event => {
|
|||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
function addDomain() {
|
function addDomain() {
|
||||||
const request = require('request');
|
const request = require('request');
|
||||||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
const ipcRenderer = require('electron').ipcRenderer;
|
const ipcRenderer = require('electron').ipcRenderer;
|
||||||
const JsonDB = require('node-json-db');
|
const JsonDB = require('node-json-db');
|
||||||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
const {app} = require('electron').remote;
|
const {app} = require('electron').remote;
|
||||||
|
|
||||||
const db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
const db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
||||||
@@ -39,7 +42,7 @@ function addDomain() {
|
|||||||
} else {
|
} else {
|
||||||
document.getElementById('pic').style.display = 'none';
|
document.getElementById('pic').style.display = 'none';
|
||||||
document.getElementById('main').innerHTML = 'Switch';
|
document.getElementById('main').innerHTML = 'Switch';
|
||||||
document.getElementById('urladded').innerHTML = 'Not a vaild Zulip server.';
|
document.getElementById('urladded').innerHTML = 'Not a vaild Zulip Server.';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<div class="close" id="close-button">Close</div>
|
<div class="close" id="close-button">Close</div>
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<form onsubmit="addDomain(); return false">
|
<form onsubmit="addDomain(); return false">
|
||||||
<input id="url" type="text" placeholder="zulip.example.com">
|
<input id="url" type="text" placeholder="chat.zulip.org">
|
||||||
<button type="submit" id="main" value="Submit" onclick="addDomain();">
|
<button type="submit" id="main" value="Submit" onclick="addDomain();">
|
||||||
Switch</button>
|
Switch</button>
|
||||||
<img id="pic" src="img/loader.gif" />
|
<img id="pic" src="img/loader.gif" />
|
||||||
@@ -19,4 +19,4 @@
|
|||||||
</div>
|
</div>
|
||||||
<script src="js/pref.js"></script>
|
<script src="js/pref.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
BIN
app/resources/.DS_Store
vendored
|
Before Width: | Height: | Size: 333 B After Width: | Height: | Size: 2.6 KiB |
BIN
app/resources/tray/traylinux.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
app/resources/tray/trayosx.png
Normal file
|
After Width: | Height: | Size: 737 B |
BIN
app/resources/tray/traywin.ico
Normal file
|
After Width: | Height: | Size: 361 KiB |
23
appveyor.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
version: build{build}
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- x64
|
||||||
|
os: Previous Visual Studio 2015
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- node_modules
|
||||||
|
|
||||||
|
install:
|
||||||
|
- ps: Install-Product node 6 x64
|
||||||
|
- git reset --hard HEAD
|
||||||
|
- npm install npm -g
|
||||||
|
- node --version
|
||||||
|
- npm --version
|
||||||
|
- python --version
|
||||||
|
- npm install
|
||||||
|
- npm install -g gulp
|
||||||
|
|
||||||
|
build: off
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- npm run test
|
||||||
BIN
build/appdmg.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
build/icon.icns
Normal file
BIN
build/icon.ico
Normal file
|
After Width: | Height: | Size: 361 KiB |
BIN
build/icon.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
3
build/icons/1024x1024.png
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1b92ae5c6e5fb0e5b7fcdb46fe102fa0ca7f4d150016cf1a461c0e86921bc731
|
||||||
|
size 163336
|
||||||
BIN
build/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
build/icons/16x16.png
Normal file
|
After Width: | Height: | Size: 737 B |
BIN
build/icons/24x24.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
build/icons/256x256.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
build/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
build/icons/48x48.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
build/icons/512x512.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
build/icons/64x64.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
build/icons/96x96.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
build/zulip.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
@@ -1,5 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
|
const mocha = require('gulp-mocha');
|
||||||
const electron = require('electron-connect').server.create({
|
const electron = require('electron-connect').server.create({
|
||||||
verbose: true
|
verbose: true
|
||||||
});
|
});
|
||||||
@@ -27,4 +28,9 @@ gulp.task('reload:renderer', done => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('default', ['dev']);
|
// Test app using mocha+spectron
|
||||||
|
gulp.task('test', () => {
|
||||||
|
return gulp.src('tests/index.js').pipe(mocha());
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('default', ['dev', 'test']);
|
||||||
|
|||||||
110
package.json
@@ -1,9 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "Zulip-Desktop",
|
"name": "zulip",
|
||||||
"productName": "Zulip",
|
"productName": "Zulip",
|
||||||
"version": "0.3.1",
|
"version": "0.5.4",
|
||||||
"description": "Zulip Desktop App",
|
"description": "Zulip Desktop App",
|
||||||
"license": "MIT",
|
"license": "Apache-2.0",
|
||||||
|
"email":"<svnitakash@gmail.com>",
|
||||||
|
"copyright": "©2016 Kandra Labs, Inc.",
|
||||||
|
"author": {
|
||||||
|
"name": "Akash Nimare",
|
||||||
|
"email": "svnitakash@gmail.com"
|
||||||
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/zulip/zulip-electron.git"
|
"url": "https://github.com/zulip/zulip-electron.git"
|
||||||
@@ -11,38 +17,77 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/zulip/zulip-electron/issues"
|
"url": "https://github.com/zulip/zulip-electron/issues"
|
||||||
},
|
},
|
||||||
"main": "app/main/index.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "xo",
|
"start": "electron ./app/main",
|
||||||
"start": "electron .",
|
"postinstall": "install-app-deps",
|
||||||
|
"test": "gulp test && xo",
|
||||||
"dev": "gulp dev",
|
"dev": "gulp dev",
|
||||||
"build:osx": "electron-packager . --out=dist --app-version=$npm_package_version --prune --asar --icon=app/resources/Icon.icns --overwrite --platform=darwin --arch=x64",
|
"pack": "build --dir",
|
||||||
"build": "electron-packager . --out=dist --app-version=$npm_package_version --prune --asar --overwrite --all"
|
"dist": "build",
|
||||||
|
"travis": "cd ./scripts && ./travis-build-test.sh"
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"appId": "org.zulip.zulip-electron",
|
||||||
|
"asar": "true",
|
||||||
|
"files": [
|
||||||
|
"**/*",
|
||||||
|
"!node_modules/@paulcbetts/cld/deps/cld${/*}"
|
||||||
|
],
|
||||||
|
"copyright": "©2016 Kandra Labs, Inc.",
|
||||||
|
"mac": {
|
||||||
|
"category": "public.app-category.productivity"
|
||||||
|
},
|
||||||
|
"linux" : {
|
||||||
|
"synopsis": "Zulip Desktop App",
|
||||||
|
"category": "",
|
||||||
|
"packageCategory": "GNOME;GTK;Network;InstantMessaging",
|
||||||
|
"description": "Zulip Desktop Client for Linux",
|
||||||
|
"target" : ["deb", "AppImage"],
|
||||||
|
"version" : "0.5.4",
|
||||||
|
"title" : "Zulip",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"maintainer": "Akash Nimare <svnitakash@gmail.com>"
|
||||||
|
},
|
||||||
|
"dmg": {
|
||||||
|
"background": "build/appdmg.png",
|
||||||
|
"icon": "build/icon.icns",
|
||||||
|
"iconSize": 128,
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"x": 380,
|
||||||
|
"y": 240,
|
||||||
|
"type": "link",
|
||||||
|
"path": "/Applications"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 122,
|
||||||
|
"y": 240,
|
||||||
|
"type": "file"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"win": {
|
||||||
|
"target": "squirrel",
|
||||||
|
"icon": "build/icon.ico"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Zulip",
|
"Zulip",
|
||||||
"Group Chat app",
|
"Group Chat app",
|
||||||
"electron-app",
|
"electron-app",
|
||||||
"electron"
|
"electron",
|
||||||
|
"Desktop app",
|
||||||
|
"InstantMessaging"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
|
||||||
"configstore": "^2.0.0",
|
|
||||||
"dialogs": "1.1.14",
|
|
||||||
"electron-context-menu": "0.4.0",
|
|
||||||
"electron-debug": "^1.0.0",
|
|
||||||
"electron-dl": "^0.2.0",
|
|
||||||
"electron-localshortcut": "^0.6.1",
|
|
||||||
"node-json-db": "^0.7.2",
|
|
||||||
"request": "^2.74.0",
|
|
||||||
"simple-spellchecker": "^0.9.0",
|
|
||||||
"wurl": "^2.1.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"assert": "^1.4.1",
|
||||||
"devtron": "^1.1.0",
|
"devtron": "^1.1.0",
|
||||||
"electron": "1.3.3",
|
"electron-builder": "10.15.1",
|
||||||
|
"electron": "1.4.7",
|
||||||
"electron-connect": "^0.4.6",
|
"electron-connect": "^0.4.6",
|
||||||
"electron-packager": "^7.0.0",
|
|
||||||
"gulp": "^3.9.1",
|
"gulp": "^3.9.1",
|
||||||
|
"gulp-mocha": "^3.0.1",
|
||||||
|
"spectron": "^3.3.0",
|
||||||
"xo": "*"
|
"xo": "*"
|
||||||
},
|
},
|
||||||
"xo": {
|
"xo": {
|
||||||
@@ -55,13 +100,20 @@
|
|||||||
"warn",
|
"warn",
|
||||||
350
|
350
|
||||||
],
|
],
|
||||||
"no-warning-comments": 0
|
"no-warning-comments": 0,
|
||||||
|
"no-else-return": 0,
|
||||||
|
"import/no-unresolved": 0,
|
||||||
|
"import/no-extraneous-dependencies":0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"ignore": [
|
||||||
|
"tests/*.js"
|
||||||
|
],
|
||||||
"envs": [
|
"envs": [
|
||||||
"node",
|
"node",
|
||||||
"browser"
|
"browser",
|
||||||
|
"mocha"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
9
scripts/travis-build-test.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||||
|
export DISPLAY=:99.0
|
||||||
|
sh -e /etc/init.d/xvfb start
|
||||||
|
sleep 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
npm run test
|
||||||
27
tests/index.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
const assert = require('assert')
|
||||||
|
const Application = require('spectron').Application
|
||||||
|
|
||||||
|
describe('application launch', function () {
|
||||||
|
this.timeout(15000)
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
this.app = new Application({
|
||||||
|
path: require('electron'),
|
||||||
|
args: [__dirname + '/../app/main/index.js']
|
||||||
|
})
|
||||||
|
return this.app.start()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
if (this.app && this.app.isRunning()) {
|
||||||
|
return this.app.stop()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows an initial window', function () {
|
||||||
|
return this.app.client.getWindowCount().then(function (count) {
|
||||||
|
assert.equal(count, 1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
109
zulip-electron-launcher.sh
Executable file
@@ -0,0 +1,109 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Zulip Beta Client Launcher
|
||||||
|
|
||||||
|
# This script ensures that you have the latest version of the specified branch
|
||||||
|
# (defaults to master if none specified) and then updates or installs all your
|
||||||
|
# required npm modules.
|
||||||
|
|
||||||
|
# I recommend symlinking this script into your PATH.
|
||||||
|
|
||||||
|
# {{{ showUsage()
|
||||||
|
|
||||||
|
showUsage()
|
||||||
|
{
|
||||||
|
echo "Usage: $0 <branch_name>"
|
||||||
|
echo "Example: $0 dev"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
# {{{ envSetup()
|
||||||
|
|
||||||
|
envSetup()
|
||||||
|
{
|
||||||
|
defaultBranch="master"
|
||||||
|
startingDir=`pwd`
|
||||||
|
requirePop=0
|
||||||
|
|
||||||
|
# Check command line arguments
|
||||||
|
if [ "$#" -gt "1" ]
|
||||||
|
then
|
||||||
|
showUsage
|
||||||
|
elif [ "$#" -eq "1" ]
|
||||||
|
then
|
||||||
|
myBranch=$1
|
||||||
|
else
|
||||||
|
myBranch=$defaultBranch
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set workingDir
|
||||||
|
if [ -L $0 ]
|
||||||
|
then
|
||||||
|
realPath=`ls -l $0 | cut -d '>' -f 2`
|
||||||
|
workingDir=`dirname $realPath`
|
||||||
|
else
|
||||||
|
workingDir="."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set name of upstreamRemote
|
||||||
|
cd $workingDir
|
||||||
|
git remote -v | grep "github\.com.zulip.zulip-electron.git (fetch)" > /dev/null 2>&1
|
||||||
|
if [ $? -eq 0 ]
|
||||||
|
then
|
||||||
|
upstreamRemote=`git remote -v | grep "github\.com.zulip.zulip-electron.git (fetch)" | awk '{ print $1 }'`
|
||||||
|
else
|
||||||
|
upstreamRemote="origin"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
# {{{ gitCheckout()
|
||||||
|
|
||||||
|
gitCheckout()
|
||||||
|
{
|
||||||
|
git fetch $upstreamRemote
|
||||||
|
git checkout $myBranch
|
||||||
|
git rebase $upstreamRemote/master
|
||||||
|
if [ $? -gt 0 ]
|
||||||
|
then
|
||||||
|
echo "Stashing uncommitted changes and doing a new git pull"
|
||||||
|
git stash && requirePop=1
|
||||||
|
git rebase $upstreamRemote/master
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
# {{{ npmInstallStart()
|
||||||
|
|
||||||
|
npmInstallStart()
|
||||||
|
{
|
||||||
|
npm install
|
||||||
|
npm start &
|
||||||
|
}
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
# {{{ cleanUp()
|
||||||
|
|
||||||
|
cleanUp()
|
||||||
|
{
|
||||||
|
# Switch back to branch we started on
|
||||||
|
git checkout -
|
||||||
|
|
||||||
|
# Pop if we stashed
|
||||||
|
if [ $requirePop -eq 1 ]
|
||||||
|
then
|
||||||
|
echo "Popping out uncommitted changes"
|
||||||
|
git stash pop
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Return the whatever dir we started in
|
||||||
|
cd $startingDir
|
||||||
|
}
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
envSetup $*
|
||||||
|
gitCheckout
|
||||||
|
npmInstallStart
|
||||||
|
cleanUp
|
||||||