Compare commits
167 Commits
v0.0.1-alp
...
v0.5.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
297b307726 | ||
|
|
deed66973f | ||
|
|
03486e438d | ||
|
|
e113f59aad | ||
|
|
29ece4824a | ||
|
|
66c62c55e2 | ||
|
|
40852942d2 | ||
|
|
15c8591691 | ||
|
|
e21902a5e3 | ||
|
|
a5d42e8ccd | ||
|
|
0923df7250 | ||
|
|
37f5258210 | ||
|
|
19819f7d48 | ||
|
|
40f74cdac2 | ||
|
|
e4ba3b9721 | ||
|
|
9a221585b9 | ||
|
|
069a0ff306 | ||
|
|
3153fb91da | ||
|
|
92d4d27fa8 | ||
|
|
209fc4a65c | ||
|
|
5e9ecedecd | ||
|
|
613df32bf1 | ||
|
|
7606f37695 | ||
|
|
a2f758a46b | ||
|
|
2a477abe5f | ||
|
|
5f027820f4 | ||
|
|
9e75861546 | ||
|
|
4060596474 | ||
|
|
2e5888c8af | ||
|
|
03d1188e14 | ||
|
|
c91b0c209a | ||
|
|
531973194c | ||
|
|
4d1face275 | ||
|
|
ca7503f1f0 | ||
|
|
9c163b4166 | ||
|
|
742afb1c09 | ||
|
|
f9f70f001b | ||
|
|
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
|
||||
npm-debug.log
|
||||
domain.json
|
||||
|
||||
dist
|
||||
config.gypi
|
||||
|
||||
// osx garbage
|
||||
*.DS_Store
|
||||
|
||||
23
.travis.yml
@@ -1,3 +1,24 @@
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
os:
|
||||
- osx
|
||||
- linux
|
||||
|
||||
language: 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
|
||||
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
|
||||
multi-account, auto-updates etc.
|
||||
|
||||
## Prerequisites
|
||||
* node >= v6.3.1
|
||||
* npm >= 3.10.3
|
||||
* python (v2.7.x recommended)
|
||||
* If you're on Debian or Ubuntu, you'll need to install following packages:
|
||||
```sh
|
||||
$ sudo apt-get install nodejs-legacy build-essential libxext-dev libxtst-dev libxkbfile-dev
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Clone the source locally:
|
||||
@@ -16,14 +28,6 @@ Clone the source locally:
|
||||
$ git clone https://github.com/zulip/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:
|
||||
|
||||
@@ -41,19 +45,32 @@ Start and watch changes
|
||||
```sh
|
||||
$ 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
|
||||
|
||||
- [x] Native Notifications
|
||||
- [x] Spell Checker
|
||||
- [x] Keyboard Shortcuts
|
||||
- Default shortcuts - <kbd>cmdOrctrl + k </kbd>
|
||||
- Change Zulip Server: <kbd>cmdOrctrl + ,</kbd>
|
||||
- Back: <kbd>cmdOrctrl + [</kbd>
|
||||
- Forward: <kbd>cmdOrctrl + ]</kbd>
|
||||
- [ ] OSX/Win/Linux installer
|
||||
- [ ] Launch on OS startup
|
||||
- [ ] Automatic Updates
|
||||
- [x] SpellChecker
|
||||
- [x] OSX/Win/Linux installer
|
||||
- [x] Automatic Updates (macOS/Windows)
|
||||
- [x] Keyboard shortcuts
|
||||
|
||||
Description | Keys
|
||||
-----------------------| -----------------------
|
||||
Default shortcuts | <kbd>Cmd/Ctrl</kbd> <kbd>k</kbd>
|
||||
Change Zulip Server | <kbd>Cmd/Ctrl</kbd> <kbd>,</kbd>
|
||||
Back | <kbd>Cmd/Ctrl</kbd> <kbd>[</kbd>
|
||||
Forward | <kbd>Cmd/Ctrl</kbd> <kbd>]</kbd>
|
||||
|
||||
|
||||
## Contribute
|
||||
|
||||
|
||||
BIN
app/.DS_Store
vendored
56
app/main/autoupdater.js
Normal file
@@ -0,0 +1,56 @@
|
||||
'use strict';
|
||||
// const os = require('os');
|
||||
const {app, dialog} = require('electron');
|
||||
const {autoUpdater} = require('electron-updater');
|
||||
|
||||
// We don't need to call all of these since it's automatically handled by electron-updater
|
||||
// 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
|
||||
const log = require('electron-log');
|
||||
log.transports.file.level = 'info';
|
||||
autoUpdater.logger = log;
|
||||
// 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, info) => {
|
||||
// let message = app.getName() + ' ' + info.releaseName + ' is now available. It will be installed the next time you restart the application.';
|
||||
// if (info.releaseNotes) {
|
||||
// const splitNotes = info.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: 'It will be installed the next time you restart the application'
|
||||
}, response => {
|
||||
if (response === 0) {
|
||||
setTimeout(() => autoUpdater.quitAndInstall(), 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
// init for updates
|
||||
autoUpdater.checkForUpdates();
|
||||
}
|
||||
|
||||
exports = module.exports = {
|
||||
appUpdater
|
||||
};
|
||||
@@ -1,12 +1,19 @@
|
||||
/* global app */
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function addDomain() {
|
||||
const request = require('request');
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
const JsonDB = require('node-json-db');
|
||||
const {app} = require('electron').remote;
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
const JsonDB = require('node-json-db');
|
||||
const request = require('request');
|
||||
|
||||
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...';
|
||||
|
||||
let newDomain = document.getElementById('url').value;
|
||||
@@ -20,11 +27,10 @@ function addDomain() {
|
||||
document.getElementById('main').innerHTML = 'Connect';
|
||||
db.push('/domain', domain);
|
||||
ipcRenderer.send('new-domain', domain);
|
||||
// window.location.href = domain;
|
||||
} else {
|
||||
document.getElementById('main').innerHTML = 'Connect';
|
||||
document.getElementById('server-status').innerHTML = 'Not a vaild Zulip Server.';
|
||||
document.getElementById('server-status').innerHTML = 'Not a valid Zulip Server.';
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,36 +1,59 @@
|
||||
'use strict';
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const electron = require('electron');
|
||||
const {app} = require('electron');
|
||||
const electronLocalshortcut = require('electron-localshortcut');
|
||||
const ipc = require('electron').ipcMain;
|
||||
const electronLocalshortcut = require('electron-localshortcut');
|
||||
const Configstore = require('configstore');
|
||||
const JsonDB = require('node-json-db');
|
||||
const SpellChecker = require('simple-spellchecker');
|
||||
const isDev = require('electron-is-dev');
|
||||
const tray = require('./tray');
|
||||
const appMenu = require('./menu');
|
||||
const link = require('./link-helper');
|
||||
|
||||
const {linkIsInternal} = link;
|
||||
const {linkIsInternal, skipImages} = require('./link-helper');
|
||||
const {appUpdater} = require('./autoupdater');
|
||||
|
||||
const db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
||||
const data = db.getData('/');
|
||||
|
||||
/* Handling squirrel.windows events on windows
|
||||
Update - Not needed for NSIS
|
||||
if (require('electron-squirrel-startup')) {
|
||||
app.quit();
|
||||
} */
|
||||
|
||||
// adds debug features like hotkeys for triggering dev tools and reload
|
||||
require('electron-debug')();
|
||||
require('electron-context-menu')();
|
||||
|
||||
const conf = new Configstore('Zulip-Desktop');
|
||||
|
||||
// spellchecker enabled
|
||||
let myDictionary = null;
|
||||
|
||||
// prevent window being garbage collected
|
||||
let mainWindow;
|
||||
let targetLink;
|
||||
|
||||
// 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() {
|
||||
if (data.domain !== undefined) {
|
||||
@@ -39,9 +62,11 @@ function checkWindowURL() {
|
||||
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 = () => {
|
||||
return APP_ICON + (process.platform === 'win32' ? '.ico' : '.png');
|
||||
@@ -77,12 +102,13 @@ function createMainWindow() {
|
||||
minHeight: 400,
|
||||
webPreferences: {
|
||||
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.setTitle('Zulip');
|
||||
|
||||
@@ -134,6 +160,8 @@ function createMainWindow() {
|
||||
app.commandLine.appendSwitch('ignore-certificate-errors', 'true');
|
||||
|
||||
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') {
|
||||
app.quit();
|
||||
}
|
||||
@@ -152,20 +180,6 @@ app.on('ready', () => {
|
||||
|
||||
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
|
||||
electronLocalshortcut.register(mainWindow, 'CommandOrControl+R', () => {
|
||||
mainWindow.reload();
|
||||
@@ -183,33 +197,44 @@ app.on('ready', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// electronLocalshortcut.register(mainWindow, 'CommandOrControl+=', () => {
|
||||
// page.send('zoomIn');
|
||||
// });
|
||||
|
||||
// electronLocalshortcut.register(mainWindow, 'CommandOrControl+-', () => {
|
||||
// page.send('zoomOut');
|
||||
// });
|
||||
|
||||
// electronLocalshortcut.register(mainWindow, 'CommandOrControl+0', () => {
|
||||
// page.send('zoomActualSize');
|
||||
// });
|
||||
page.on('dom-ready', () => {
|
||||
page.insertCSS(fs.readFileSync(path.join(__dirname, 'preload.css'), 'utf8'));
|
||||
mainWindow.show();
|
||||
});
|
||||
|
||||
page.on('new-window', (event, url) => {
|
||||
if (mainWindow.useDefaultWindowBehaviour) {
|
||||
mainWindow.useDefaultWindowBehaviour = false;
|
||||
return;
|
||||
}
|
||||
if (linkIsInternal(checkWindowURL(), url)) {
|
||||
if (linkIsInternal(checkWindowURL(), url) && url.match(skipImages) === null) {
|
||||
event.preventDefault();
|
||||
return mainWindow.loadURL(url);
|
||||
}
|
||||
event.preventDefault();
|
||||
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) => {
|
||||
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;
|
||||
});
|
||||
|
||||
@@ -2,11 +2,14 @@ const wurl = require('wurl');
|
||||
|
||||
// Check link if it's internal/external
|
||||
function linkIsInternal(currentUrl, newUrl) {
|
||||
const currentDomain = wurl('domain', currentUrl);
|
||||
const newDomain = wurl('domain', newUrl);
|
||||
const currentDomain = wurl('hostname', currentUrl);
|
||||
const newDomain = wurl('hostname', newUrl);
|
||||
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 = {
|
||||
linkIsInternal
|
||||
linkIsInternal, skipImages
|
||||
};
|
||||
|
||||
69
app/main/macos-swipe-navigation.js
Normal file
@@ -0,0 +1,69 @@
|
||||
// Adopted from
|
||||
// https://github.com/wozaki/twitter-js-apps/blob/9bc00eafd575fd180dc7a450e1b1daf425e67b80/redux/src/main/renderer/registries/electron/swipeNavigatorImpl.js
|
||||
|
||||
'use strict'
|
||||
const {remote} = require('electron');
|
||||
|
||||
const THRESHOLD_DELTA_X = 70;
|
||||
const THRESHOLD_LIMIT_DELTA_Y = 50;
|
||||
const THRESHOLD_TIME = 50;
|
||||
|
||||
// TODO avoid module global state
|
||||
let tracking = false;
|
||||
let deltaX = 0;
|
||||
let deltaY = 0;
|
||||
let startTime = 0;
|
||||
let time = 0;
|
||||
|
||||
module.exports.register = function register() {
|
||||
remote.getCurrentWindow()
|
||||
.on('scroll-touch-begin', onScrollBegin)
|
||||
.on('scroll-touch-end', onScrollEnd)
|
||||
.on('swipe', onSwipe)
|
||||
|
||||
window.addEventListener('wheel', onMouseWheel, {passive: true});
|
||||
window.addEventListener('beforeunload', remove);
|
||||
}
|
||||
|
||||
const remove = module.exports.remove = function remove() {
|
||||
remote.getCurrentWindow()
|
||||
.removeListener('scroll-touch-begin', onScrollBegin)
|
||||
.removeListener('scroll-touch-end', onScrollEnd)
|
||||
.removeListener('swipe', onSwipe)
|
||||
|
||||
window.removeEventListener('mousewheel', onMouseWheel);
|
||||
window.removeEventListener('beforeunload', remove);
|
||||
}
|
||||
|
||||
function onSwipe(e, direction) {
|
||||
if (direction === 'left')
|
||||
remote.getCurrentWebContents().goBack()
|
||||
else if (direction === 'right')
|
||||
remote.getCurrentWebContents().goForward()
|
||||
}
|
||||
|
||||
function onMouseWheel(e) {
|
||||
if (tracking) {
|
||||
deltaX = deltaX + e.deltaX
|
||||
deltaY = deltaY + e.deltaY
|
||||
time = (new Date()).getTime() - startTime
|
||||
}
|
||||
}
|
||||
|
||||
function onScrollBegin() {
|
||||
tracking = true
|
||||
startTime = (new Date()).getTime()
|
||||
}
|
||||
|
||||
function onScrollEnd() {
|
||||
if (time > THRESHOLD_TIME && tracking && Math.abs(deltaY) < THRESHOLD_LIMIT_DELTA_Y)
|
||||
if (deltaX > THRESHOLD_DELTA_X)
|
||||
remote.getCurrentWebContents().goForward()
|
||||
else if (deltaX < -THRESHOLD_DELTA_X)
|
||||
remote.getCurrentWebContents().goBack()
|
||||
|
||||
tracking = false
|
||||
deltaX = 0
|
||||
deltaY = 0
|
||||
startTime = 0
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
const os = require('os');
|
||||
const electron = require('electron');
|
||||
|
||||
const {dialog} = require('electron');
|
||||
|
||||
const app = electron.app;
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
const shell = electron.shell;
|
||||
@@ -19,10 +21,17 @@ function sendAction(action) {
|
||||
win.webContents.send(action);
|
||||
}
|
||||
|
||||
function clearCache() {
|
||||
const win = BrowserWindow.getAllWindows()[0];
|
||||
const ses = win.webContents.session;
|
||||
ses.clearCache(() => {
|
||||
dialog.showMessageBox({type: 'info', buttons: [], message: 'Cache cleared!'});
|
||||
});
|
||||
}
|
||||
|
||||
const viewSubmenu = [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.reload();
|
||||
@@ -119,10 +128,8 @@ const darwinTpl = [
|
||||
{
|
||||
label: 'Change Zulip Server',
|
||||
accelerator: 'Cmd+,',
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
addDomain();
|
||||
}
|
||||
click() {
|
||||
addDomain();
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -137,8 +144,15 @@ const darwinTpl = [
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Clear Cache',
|
||||
click() {
|
||||
clearCache();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Log Out',
|
||||
accelerator: 'Cmd+L',
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
sendAction('log-out');
|
||||
@@ -247,10 +261,8 @@ const otherTpl = [
|
||||
{
|
||||
label: 'Change Zulip Server',
|
||||
accelerator: 'Ctrl+,',
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
addDomain();
|
||||
}
|
||||
click() {
|
||||
addDomain();
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -268,8 +280,15 @@ const otherTpl = [
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Clear Cache',
|
||||
click() {
|
||||
clearCache();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Log Out',
|
||||
accelerator: 'Ctrl+L',
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
sendAction('log-out');
|
||||
@@ -317,7 +336,6 @@ const otherTpl = [
|
||||
{
|
||||
role: 'selectall'
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
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,15 @@
|
||||
'use strict';
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
const webFrame = require('electron').webFrame;
|
||||
const {webFrame} = require('electron');
|
||||
const {spellChecker} = require('./spellchecker');
|
||||
|
||||
// Implement spellcheck using electron api
|
||||
// enable swipe back/forward navigation on macOS
|
||||
require('./macos-swipe-navigation.js').register();
|
||||
|
||||
webFrame.setSpellCheckProvider('en-US', false, {
|
||||
spellCheck: text => {
|
||||
const res = ipcRenderer.sendSync('checkspell', text);
|
||||
return res === null ? true : res;
|
||||
}
|
||||
});
|
||||
|
||||
// Handle zooming functionality
|
||||
// eslint-disable-next-line import/no-unassigned-import
|
||||
require('./domain');
|
||||
|
||||
// handle zooming functionality
|
||||
const zoomIn = () => {
|
||||
webFrame.setZoomFactor(webFrame.getZoomFactor() + 0.1);
|
||||
};
|
||||
@@ -25,7 +22,7 @@ const zoomActualSize = () => {
|
||||
webFrame.setZoomFactor(1);
|
||||
};
|
||||
|
||||
// Get zooming actions from main process
|
||||
// get zooming actions from main process
|
||||
ipcRenderer.on('zoomIn', () => {
|
||||
zoomIn();
|
||||
});
|
||||
@@ -53,3 +50,9 @@ ipcRenderer.on('shortcut', () => {
|
||||
const nodes = document.querySelectorAll('.dropdown-menu li:nth-child(4) a');
|
||||
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;
|
||||
|
||||
const APP_ICON = path.join(__dirname, '../resources', 'Icon');
|
||||
const APP_ICON = path.join(__dirname, '../resources/tray', 'tray');
|
||||
|
||||
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 = () => {
|
||||
// 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([
|
||||
{
|
||||
label: 'About',
|
||||
@@ -33,10 +28,8 @@ exports.create = () => {
|
||||
},
|
||||
{
|
||||
label: 'Change Zulip server',
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
addDomain();
|
||||
}
|
||||
click() {
|
||||
addDomain();
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
42
app/package.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "zulip",
|
||||
"productName": "Zulip",
|
||||
"version": "0.5.6",
|
||||
"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-updater": "1.4.1",
|
||||
"electron-log": "1.3.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": "1.0.0",
|
||||
"wurl": "2.1.0"
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,17 @@
|
||||
<body>
|
||||
<div class="about">
|
||||
<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"> Maintainer : Zulip </p>
|
||||
<p class="left"><a class="bug" onclick="linkInBrowser()" href="#">Found bug?</a></p>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
const app = require('electron').remote.app;
|
||||
const version_tag = document.getElementById('version');
|
||||
version_tag.innerHTML = ' Version : ' + app.getVersion() + ' ';
|
||||
|
||||
function linkInBrowser(event) {
|
||||
|
||||
const shell = require('electron').shell;
|
||||
@@ -24,4 +28,4 @@
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -6,17 +6,6 @@
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Login - Zulip</title>
|
||||
<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>
|
||||
<body class="container-layout">
|
||||
<div class="section-main">
|
||||
@@ -34,7 +23,7 @@
|
||||
<fieldset>
|
||||
<div class="control-group control-required">
|
||||
<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 class="control-group">
|
||||
@@ -49,6 +38,5 @@
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
<script src="js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
'use strict';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const {remote} = require('electron');
|
||||
|
||||
const prefWindow = remote.getCurrentWindow();
|
||||
@@ -15,8 +16,10 @@ document.addEventListener('keydown', event => {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function addDomain() {
|
||||
const request = require('request');
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
const JsonDB = require('node-json-db');
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const {app} = require('electron').remote;
|
||||
|
||||
const db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
||||
@@ -39,7 +42,7 @@ function addDomain() {
|
||||
} else {
|
||||
document.getElementById('pic').style.display = 'none';
|
||||
document.getElementById('main').innerHTML = 'Switch';
|
||||
document.getElementById('urladded').innerHTML = 'Not a vaild Zulip server.';
|
||||
document.getElementById('urladded').innerHTML = 'Not a valid Zulip Server.';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="close" id="close-button">Close</div>
|
||||
<div class="form">
|
||||
<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();">
|
||||
Switch</button>
|
||||
<img id="pic" src="img/loader.gif" />
|
||||
@@ -19,4 +19,4 @@
|
||||
</div>
|
||||
<script src="js/pref.js"></script>
|
||||
</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';
|
||||
const gulp = require('gulp');
|
||||
const mocha = require('gulp-mocha');
|
||||
const electron = require('electron-connect').server.create({
|
||||
verbose: true
|
||||
});
|
||||
@@ -27,4 +28,9 @@ gulp.task('reload:renderer', 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']);
|
||||
|
||||
116
package.json
@@ -1,9 +1,15 @@
|
||||
{
|
||||
"name": "Zulip-Desktop",
|
||||
"name": "zulip",
|
||||
"productName": "Zulip",
|
||||
"version": "0.3.1",
|
||||
"version": "0.5.6",
|
||||
"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": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/zulip/zulip-electron.git"
|
||||
@@ -11,38 +17,82 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/zulip/zulip-electron/issues"
|
||||
},
|
||||
"main": "app/main/index.js",
|
||||
"scripts": {
|
||||
"test": "xo",
|
||||
"start": "electron .",
|
||||
"start": "electron ./app/main",
|
||||
"postinstall": "install-app-deps",
|
||||
"test": "gulp test && xo",
|
||||
"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",
|
||||
"build": "electron-packager . --out=dist --app-version=$npm_package_version --prune --asar --overwrite --all"
|
||||
"pack": "build --dir",
|
||||
"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.6",
|
||||
"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": "nsis",
|
||||
"icon": "build/icon.ico",
|
||||
"iconUrl": "https://raw.githubusercontent.com/zulip/zulip-electron/master/build/icon.ico"
|
||||
},
|
||||
"nsis": {
|
||||
"perMachine": true,
|
||||
"oneClick": false
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"Zulip",
|
||||
"Group Chat app",
|
||||
"electron-app",
|
||||
"electron"
|
||||
"Zulip",
|
||||
"Group Chat app",
|
||||
"electron-app",
|
||||
"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": {
|
||||
"assert": "^1.4.1",
|
||||
"devtron": "^1.1.0",
|
||||
"electron": "1.3.3",
|
||||
"electron-builder": "13.0.0",
|
||||
"electron": "1.4.7",
|
||||
"electron-connect": "^0.4.6",
|
||||
"electron-packager": "^7.0.0",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-mocha": "^3.0.1",
|
||||
"spectron": "^3.3.0",
|
||||
"xo": "*"
|
||||
},
|
||||
"xo": {
|
||||
@@ -53,15 +103,23 @@
|
||||
"rules": {
|
||||
"max-lines": [
|
||||
"warn",
|
||||
350
|
||||
500
|
||||
],
|
||||
"no-warning-comments": 0
|
||||
"no-warning-comments": 0,
|
||||
"no-else-return": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"import/no-extraneous-dependencies":0
|
||||
}
|
||||
}
|
||||
],
|
||||
"ignore": [
|
||||
"tests/*.js",
|
||||
"app/main/macos-swipe-navigation.js"
|
||||
],
|
||||
"envs": [
|
||||
"node",
|
||||
"browser"
|
||||
"browser",
|
||||
"mocha"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
10
scripts/travis-build-test.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
export {no_proxy,NO_PROXY}="127.0.0.1,localhost"
|
||||
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
|
||||