mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-10-24 08:33:36 +00:00
Compare commits
43 Commits
| 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 |
12
.travis.yml
12
.travis.yml
@@ -1,12 +1,13 @@
|
||||
language: node_js
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
os:
|
||||
- osx
|
||||
- linux
|
||||
sudo: required
|
||||
|
||||
language: node_js
|
||||
node_js:
|
||||
- 'node'
|
||||
- '6'
|
||||
|
||||
before_install:
|
||||
- npm install -g gulp
|
||||
@@ -14,7 +15,10 @@ before_install:
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- node_modules
|
||||
- app/node_modules
|
||||
- $HOME/.electron
|
||||
- $HOME/.cache
|
||||
|
||||
script:
|
||||
- npm run travis
|
||||
|
||||
22
README.md
22
README.md
@@ -11,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
|
||||
* If you're on Debian or Ubuntu, you'll also need to install
|
||||
`nodejs-legacy`:
|
||||
```sh
|
||||
$ sudo apt-get install nodejs-legacy
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Clone the source locally:
|
||||
@@ -19,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:
|
||||
|
||||
@@ -59,6 +60,8 @@ You can create Windows installer only when running on Windows, the same is true
|
||||
|
||||
- [x] Native Notifications
|
||||
- [x] SpellChecker
|
||||
- [x] OSX/Win/Linux installer
|
||||
- [x] Automatic Updates (macOS/Windows)
|
||||
- [x] Keyboard shortcuts
|
||||
|
||||
Description | Keys
|
||||
@@ -68,9 +71,6 @@ Change Zulip Server | <kbd>Cmd/Ctrl</kbd> <kbd>,</kbd>
|
||||
Back | <kbd>Cmd/Ctrl</kbd> <kbd>[</kbd>
|
||||
Forward | <kbd>Cmd/Ctrl</kbd> <kbd>]</kbd>
|
||||
|
||||
- [x] OSX/Win/Linux installer
|
||||
- [ ] Launch on OS startup
|
||||
- [ ] Automatic Updates
|
||||
|
||||
## Contribute
|
||||
|
||||
|
||||
50
app/main/autoupdater.js
Normal file
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,7 +1,7 @@
|
||||
const JsonDB = require('node-json-db');
|
||||
const {app} = require('electron').remote;
|
||||
const request = require('request');
|
||||
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 data = db.getData('/');
|
||||
|
||||
@@ -3,23 +3,29 @@ 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 isDev = require('electron-is-dev');
|
||||
const tray = require('./tray');
|
||||
const appMenu = require('./menu');
|
||||
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
|
||||
if (require('electron-squirrel-startup')) {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// adds debug features like hotkeys for triggering dev tools and reload
|
||||
require('electron-debug')();
|
||||
|
||||
const conf = new Configstore('Zulip-Desktop');
|
||||
|
||||
|
||||
// prevent window being garbage collected
|
||||
let mainWindow;
|
||||
let targetLink;
|
||||
@@ -30,9 +36,8 @@ const staticURL = 'file://' + path.join(__dirname, '../renderer', 'index.html');
|
||||
const targetURL = function () {
|
||||
if (data.domain === undefined) {
|
||||
return staticURL;
|
||||
} else {
|
||||
return data.domain;
|
||||
}
|
||||
return data.domain;
|
||||
};
|
||||
|
||||
const isAlreadyRunning = app.makeSingleInstance(() => {
|
||||
@@ -56,6 +61,10 @@ function checkWindowURL() {
|
||||
return targetLink;
|
||||
}
|
||||
|
||||
function isWindowsOrmacOS() {
|
||||
return process.platform === 'darwin' || process.platform === 'win32';
|
||||
}
|
||||
|
||||
const APP_ICON = path.join(__dirname, '../resources', 'Icon');
|
||||
|
||||
const iconPath = () => {
|
||||
@@ -150,6 +159,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();
|
||||
}
|
||||
@@ -198,6 +209,19 @@ app.on('ready', () => {
|
||||
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) => {
|
||||
|
||||
@@ -22,7 +22,6 @@ function sendAction(action) {
|
||||
const viewSubmenu = [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.reload();
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
'use strict';
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
const {webFrame} = require('electron');
|
||||
const {spellChecker} = require('./spellchecker');
|
||||
|
||||
// Handle zooming functionality
|
||||
require('./domain');
|
||||
|
||||
// handle zooming functionality
|
||||
const zoomIn = () => {
|
||||
webFrame.setZoomFactor(webFrame.getZoomFactor() + 0.1);
|
||||
};
|
||||
@@ -15,7 +18,7 @@ const zoomActualSize = () => {
|
||||
webFrame.setZoomFactor(1);
|
||||
};
|
||||
|
||||
// Get zooming actions from main process
|
||||
// get zooming actions from main process
|
||||
ipcRenderer.on('zoomIn', () => {
|
||||
zoomIn();
|
||||
});
|
||||
@@ -44,9 +47,8 @@ ipcRenderer.on('shortcut', () => {
|
||||
nodes[nodes.length - 1].click();
|
||||
});
|
||||
|
||||
require('./domain');
|
||||
|
||||
// To prevent failing this script on linux we need to load it after the document loaded
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
require('./spellchecker');
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// init spellchecker
|
||||
spellChecker();
|
||||
});
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
|
||||
|
||||
// Implement spellcheck using electron api
|
||||
function spellChecker() {
|
||||
// Implement spellcheck using electron api
|
||||
window.spellCheckHandler = new SpellCheckHandler();
|
||||
window.spellCheckHandler.attachToInput();
|
||||
|
||||
window.spellCheckHandler = new SpellCheckHandler();
|
||||
window.spellCheckHandler.attachToInput();
|
||||
// Start off as US English
|
||||
window.spellCheckHandler.switchLanguage('en-US');
|
||||
|
||||
// Start off as US English
|
||||
window.spellCheckHandler.switchLanguage('en-US');
|
||||
const contextMenuBuilder = new ContextMenuBuilder(window.spellCheckHandler);
|
||||
const contextMenuListener = new ContextMenuListener(info => {
|
||||
contextMenuBuilder.showPopupMenu(info);
|
||||
});
|
||||
|
||||
let contextMenuBuilder = new ContextMenuBuilder(window.spellCheckHandler);
|
||||
let 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,10 +6,13 @@ 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 = () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "zulip",
|
||||
"productName": "Zulip",
|
||||
"version": "0.5.1",
|
||||
"version": "0.5.4",
|
||||
"description": "Zulip Desktop App",
|
||||
"license": "Apache-2.0",
|
||||
"email":"<svnitakash@gmail.com>",
|
||||
@@ -27,15 +27,15 @@
|
||||
"InstantMessaging"
|
||||
],
|
||||
"dependencies": {
|
||||
"configstore": "^2.0.0",
|
||||
"electron-is-dev": "0.1.2",
|
||||
"electron-squirrel-startup": "1.0.0",
|
||||
"configstore": "2.1.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",
|
||||
"electron-spellchecker": "^0.5.12",
|
||||
"wurl": "^2.1.0"
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,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">
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 333 B After Width: | Height: | Size: 2.6 KiB |
BIN
app/resources/tray/traylinux.png
Normal file
BIN
app/resources/tray/traylinux.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
BIN
app/resources/tray/trayosx.png
Normal file
BIN
app/resources/tray/trayosx.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 737 B |
BIN
app/resources/tray/traywin.ico
Normal file
BIN
app/resources/tray/traywin.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 361 KiB |
16
package.json
16
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "zulip",
|
||||
"productName": "Zulip",
|
||||
"version": "0.5.1",
|
||||
"version": "0.5.4",
|
||||
"description": "Zulip Desktop App",
|
||||
"license": "Apache-2.0",
|
||||
"email":"<svnitakash@gmail.com>",
|
||||
@@ -40,10 +40,10 @@
|
||||
"linux" : {
|
||||
"synopsis": "Zulip Desktop App",
|
||||
"category": "",
|
||||
"packageCategory": "",
|
||||
"packageCategory": "GNOME;GTK;Network;InstantMessaging",
|
||||
"description": "Zulip Desktop Client for Linux",
|
||||
"target" : ["deb", "AppImage"],
|
||||
"version" : "0.5.1",
|
||||
"version" : "0.5.4",
|
||||
"title" : "Zulip",
|
||||
"license": "Apache-2.0",
|
||||
"maintainer": "Akash Nimare <svnitakash@gmail.com>"
|
||||
@@ -67,7 +67,7 @@
|
||||
]
|
||||
},
|
||||
"win": {
|
||||
"target": "nsis",
|
||||
"target": "squirrel",
|
||||
"icon": "build/icon.ico"
|
||||
}
|
||||
},
|
||||
@@ -82,7 +82,7 @@
|
||||
"devDependencies": {
|
||||
"assert": "^1.4.1",
|
||||
"devtron": "^1.1.0",
|
||||
"electron-builder": "*",
|
||||
"electron-builder": "10.15.1",
|
||||
"electron": "1.4.7",
|
||||
"electron-connect": "^0.4.6",
|
||||
"gulp": "^3.9.1",
|
||||
@@ -101,7 +101,9 @@
|
||||
350
|
||||
],
|
||||
"no-warning-comments": 0,
|
||||
"no-else-return": 0
|
||||
"no-else-return": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"import/no-extraneous-dependencies":0
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -114,4 +116,4 @@
|
||||
"mocha"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ const assert = require('assert')
|
||||
const Application = require('spectron').Application
|
||||
|
||||
describe('application launch', function () {
|
||||
this.timeout(10000)
|
||||
this.timeout(15000)
|
||||
|
||||
beforeEach(function () {
|
||||
this.app = new Application({
|
||||
|
||||
@@ -74,11 +74,11 @@ gitCheckout()
|
||||
}
|
||||
|
||||
# }}}
|
||||
# {{{ npmUpgradeStart()
|
||||
# {{{ npmInstallStart()
|
||||
|
||||
npmUpgradeStart()
|
||||
npmInstallStart()
|
||||
{
|
||||
npm upgrade
|
||||
npm install
|
||||
npm start &
|
||||
}
|
||||
|
||||
@@ -105,5 +105,5 @@ cleanUp()
|
||||
|
||||
envSetup $*
|
||||
gitCheckout
|
||||
npmUpgradeStart
|
||||
cleanUp
|
||||
npmInstallStart
|
||||
cleanUp
|
||||
Reference in New Issue
Block a user