mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-11-10 17:05:47 +00:00
Compare commits
7 Commits
sentry
...
test-travi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68dd63d472 | ||
|
|
d2f53a0b71 | ||
|
|
fba0330512 | ||
|
|
4ff914cf34 | ||
|
|
4831bea447 | ||
|
|
01849bf601 | ||
|
|
349294f536 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -7,13 +7,6 @@ node_modules/
|
|||||||
# Compiled binary build directory
|
# Compiled binary build directory
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
#snap generated files
|
|
||||||
snap/parts
|
|
||||||
snap/prime
|
|
||||||
snap/snap
|
|
||||||
snap/stage
|
|
||||||
snap/*.snap
|
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
30
.travis.yml
30
.travis.yml
@@ -2,8 +2,10 @@ sudo: required
|
|||||||
dist: trusty
|
dist: trusty
|
||||||
|
|
||||||
os:
|
os:
|
||||||
- osx
|
- osx
|
||||||
- linux
|
- linux
|
||||||
|
|
||||||
|
osx_image: xcode9.0
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -12,6 +14,19 @@ addons:
|
|||||||
- libxext-dev
|
- libxext-dev
|
||||||
- libxtst-dev
|
- libxtst-dev
|
||||||
- libxkbfile-dev
|
- libxkbfile-dev
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- $(ls ./dist/*.AppImage | tr "\n" ":")
|
||||||
|
- $(ls ./dist/*.deb | tr "\n" ":")
|
||||||
|
- $(ls ./dist/*.dmg | tr "\n" ":")
|
||||||
|
- $(ls ./dist/*.zip | tr "\n" ":")
|
||||||
|
- $(ls ./dist/*.dmg.blockmap | tr "\n" ":")
|
||||||
|
- $(ls ./dist/github/*.json | tr "\n" ":")
|
||||||
|
- $(ls ./dist/github/*.yml | tr "\n" ":")
|
||||||
|
- $(ls ./dist/*.yml | tr "\n" ":")
|
||||||
|
- $(ls ./dist/mac/*.yml | tr "\n" ":")
|
||||||
|
- $(ls ./dist/linux/*.yml | tr "\n" ":")
|
||||||
|
debug: true
|
||||||
|
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
@@ -26,9 +41,18 @@ cache:
|
|||||||
directories:
|
directories:
|
||||||
- node_modules
|
- node_modules
|
||||||
- app/node_modules
|
- app/node_modules
|
||||||
|
- ~/.cache
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- npm run travis
|
- npm run travis
|
||||||
|
- chmod +x ./scripts/install-release-dependencies.sh
|
||||||
|
- ./scripts/install-release-dependencies.sh
|
||||||
|
- npm run dist
|
||||||
|
- node ./scripts/prepare-artifacts.js
|
||||||
|
# log out /dist files might be useful to know
|
||||||
|
# what files are uploaded
|
||||||
|
- ls dist
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
webhooks:
|
webhooks:
|
||||||
urls:
|
urls:
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ const iconPath = () => {
|
|||||||
function createMainWindow() {
|
function createMainWindow() {
|
||||||
// Load the previous state with fallback to defaults
|
// Load the previous state with fallback to defaults
|
||||||
const mainWindowState = windowStateKeeper({
|
const mainWindowState = windowStateKeeper({
|
||||||
defaultWidth: 1100,
|
defaultWidth: 1000,
|
||||||
defaultHeight: 720
|
defaultHeight: 600
|
||||||
});
|
});
|
||||||
|
|
||||||
// Let's keep the window position global so that we can access it in other process
|
// Let's keep the window position global so that we can access it in other process
|
||||||
@@ -71,6 +71,7 @@ function createMainWindow() {
|
|||||||
minHeight: 400,
|
minHeight: 400,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
plugins: true,
|
plugins: true,
|
||||||
|
allowDisplayingInsecureContent: true,
|
||||||
nodeIntegration: true
|
nodeIntegration: true
|
||||||
},
|
},
|
||||||
show: false
|
show: false
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
const os = require('os');
|
const os = require('os');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const { app, shell, BrowserWindow, Menu, dialog } = require('electron');
|
const { app, shell, BrowserWindow, Menu } = require('electron');
|
||||||
|
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ class AppMenu {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
label: 'Toggle Sidebar',
|
label: 'Toggle Sidebar',
|
||||||
accelerator: 'CommandOrControl+Shift+S',
|
accelerator: 'CommandOrControl+S',
|
||||||
click(item, focusedWindow) {
|
click(item, focusedWindow) {
|
||||||
if (focusedWindow) {
|
if (focusedWindow) {
|
||||||
const newValue = !ConfigUtil.getConfigItem('showSidebar');
|
const newValue = !ConfigUtil.getConfigItem('showSidebar');
|
||||||
@@ -388,19 +388,9 @@ class AppMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static resetAppSettings() {
|
static resetAppSettings() {
|
||||||
const resetAppSettingsMessage = 'By proceeding you will be removing all connected organizations and preferences from Zulip.';
|
|
||||||
|
|
||||||
// We save App's settings/configurations in following files
|
// We save App's settings/configurations in following files
|
||||||
const settingFiles = ['window-state.json', 'domain.json', 'settings.json'];
|
const settingFiles = ['window-state.json', 'domain.json', 'settings.json'];
|
||||||
|
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'warning',
|
|
||||||
buttons: ['YES', 'NO'],
|
|
||||||
defaultId: 0,
|
|
||||||
message: 'Are you sure?',
|
|
||||||
detail: resetAppSettingsMessage
|
|
||||||
}, response => {
|
|
||||||
if (response === 0) {
|
|
||||||
settingFiles.forEach(settingFileName => {
|
settingFiles.forEach(settingFileName => {
|
||||||
const getSettingFilesPath = path.join(app.getPath('appData'), appName, settingFileName);
|
const getSettingFilesPath = path.join(app.getPath('appData'), appName, settingFileName);
|
||||||
fs.access(getSettingFilesPath, error => {
|
fs.access(getSettingFilesPath, error => {
|
||||||
@@ -414,8 +404,6 @@ class AppMenu {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setMenu(props) {
|
setMenu(props) {
|
||||||
const tpl = process.platform === 'darwin' ? this.getDarwinTpl(props) : this.getOtherTpl(props);
|
const tpl = process.platform === 'darwin' ? this.getDarwinTpl(props) : this.getOtherTpl(props);
|
||||||
|
|||||||
1380
app/package-lock.json
generated
Normal file
1380
app/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "zulip",
|
"name": "zulip",
|
||||||
"productName": "Zulip",
|
"productName": "Zulip",
|
||||||
"version": "1.9.0",
|
"version": "1.8.2",
|
||||||
"description": "Zulip Desktop App",
|
"description": "Zulip Desktop App",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"copyright": "Kandra Labs, Inc.",
|
"copyright": "Kandra Labs, Inc.",
|
||||||
@@ -30,13 +30,12 @@
|
|||||||
"electron-is-dev": "0.3.0",
|
"electron-is-dev": "0.3.0",
|
||||||
"electron-log": "2.2.7",
|
"electron-log": "2.2.7",
|
||||||
"electron-spellchecker": "1.1.2",
|
"electron-spellchecker": "1.1.2",
|
||||||
"electron-updater": "2.21.4",
|
"electron-updater": "2.21.0",
|
||||||
"electron-window-state": "4.1.1",
|
"electron-window-state": "4.1.1",
|
||||||
"is-online": "7.0.0",
|
"is-online": "7.0.0",
|
||||||
"node-json-db": "0.7.3",
|
"node-json-db": "0.7.3",
|
||||||
"request": "2.81.0",
|
"request": "2.81.0",
|
||||||
"semver": "5.4.1",
|
"semver": "5.4.1",
|
||||||
"@sentry/electron": "0.5.0",
|
|
||||||
"wurl": "2.5.0"
|
"wurl": "2.5.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
|||||||
@@ -1,23 +1,19 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="stylesheet" href="css/about.css">
|
<link rel="stylesheet" href="css/about.css">
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body>
|
|
||||||
<div class="about">
|
<div class="about">
|
||||||
<img class="logo" src="../resources/zulip.png" />
|
<img class="logo" src="../resources/zulip.png" />
|
||||||
<p class="detail" id="version">v?.?.?</p>
|
<p class="detail" id="version">v?.?.?</p>
|
||||||
<div class="maintenance-info">
|
<div class="maintenance-info">
|
||||||
<p class="detail maintainer">
|
<p class="detail maintainer">
|
||||||
Maintained by
|
Maintained by <a onclick="linkInBrowser('website')">Zulip</a>
|
||||||
<a onclick="linkInBrowser('website')">Zulip</a>
|
|
||||||
</p>
|
</p>
|
||||||
<p class="detail license">
|
<p class="detail license">
|
||||||
Available under the
|
Available under the <a onclick="linkInBrowser('license')">Apache 2.0 License</a>
|
||||||
<a onclick="linkInBrowser('license')">Apache 2.0 License</a>
|
|
||||||
</p>
|
</p>
|
||||||
<a class="bug" onclick="linkInBrowser('bug')" href="#">Found bug?</a>
|
<a class="bug" onclick="linkInBrowser('bug')" href="#">Found bug?</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,6 +41,5 @@
|
|||||||
shell.openExternal(url);
|
shell.openExternal(url);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script>require('./js/shared/preventdrag.js')</script>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -121,14 +121,11 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.action-button.active {
|
.action-button.active {
|
||||||
/* background-color: rgba(255, 255, 255, 0.25); */
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
background-color: #efefef;
|
|
||||||
opacity: 0.9;
|
|
||||||
padding-right: 14px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-button.active i {
|
.action-button.active i {
|
||||||
color: #1c262b;
|
color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab:first-child {
|
.tab:first-child {
|
||||||
@@ -262,11 +259,6 @@ webview {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
webview.download-webview {
|
|
||||||
z-index: -1;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
webview.onload {
|
webview.onload {
|
||||||
transition: opacity 1s cubic-bezier(0.95, 0.05, 0.795, 0.035);
|
transition: opacity 1s cubic-bezier(0.95, 0.05, 0.795, 0.035);
|
||||||
}
|
}
|
||||||
@@ -292,7 +284,7 @@ webview.focus {
|
|||||||
#setting-tooltip {
|
#setting-tooltip {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
background: #222c31;
|
background: #222c31;
|
||||||
margin-left: 48px;
|
margin-left: 45px;
|
||||||
padding: 6px 8px;
|
padding: 6px 8px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
@@ -364,8 +356,6 @@ webview.focus {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-grow: 1;
|
|
||||||
flex-basis: 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ td:nth-child(odd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav.active {
|
.nav.active {
|
||||||
color: #4ebfac;
|
color: #464e5a;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -123,19 +123,12 @@ td:nth-child(odd) {
|
|||||||
.nav.active::before {
|
.nav.active::before {
|
||||||
background: #464e5a;
|
background: #464e5a;
|
||||||
width: 3px;
|
width: 3px;
|
||||||
height: 18px;
|
height: 16px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -8px;
|
left: -8px;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* We don't want to show this in nav item since we have the + button for adding an Organization */
|
|
||||||
|
|
||||||
#nav-AddServer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings-header {
|
#settings-header {
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
color: #222c31;
|
color: #222c31;
|
||||||
@@ -151,12 +144,12 @@ td:nth-child(odd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#new-server-container {
|
#new-server-container {
|
||||||
padding-left: 42px;
|
opacity: 1;
|
||||||
padding-top: 25px;
|
transition: opacity 0.3s;
|
||||||
margin-right: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
padding: 4px 0 6px 0;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #222c31;
|
color: #222c31;
|
||||||
}
|
}
|
||||||
@@ -168,16 +161,6 @@ td:nth-child(odd) {
|
|||||||
padding: 4px 0 6px 0;
|
padding: 4px 0 6px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-server-info-row {
|
|
||||||
display: flex;
|
|
||||||
margin: 8px 0 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-server-info-right {
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-title {
|
.sub-title {
|
||||||
padding: 4px 0 6px 0;
|
padding: 4px 0 6px 0;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -188,40 +171,20 @@ img.server-info-icon {
|
|||||||
width: 36px;
|
width: 36px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
cursor: pointer;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.server-info-left {
|
.server-info-left {
|
||||||
margin: 4px 20px 0 0;
|
margin: 10px 20px 0 0;
|
||||||
min-width: 40%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.server-info-right {
|
.server-info-right {
|
||||||
margin-top: 4px;
|
|
||||||
width: 55%;
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
justify-content: space-between;
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.server-info-row {
|
.server-info-row {
|
||||||
display: inline-block;
|
display: flex;
|
||||||
margin: 5px 0 0 0;
|
margin: 8px 0 0 0;
|
||||||
}
|
|
||||||
|
|
||||||
.server-info-left .server-info-row {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: inherit;
|
|
||||||
vertical-align: -2px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.server-url {
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.server-info-alias {
|
.server-info-alias {
|
||||||
@@ -229,10 +192,6 @@ img.server-info-icon {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.server-url-info {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.setting-input-key {
|
.setting-input-key {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
height: 27px;
|
height: 27px;
|
||||||
@@ -246,16 +205,18 @@ img.server-info-icon {
|
|||||||
.setting-input-value {
|
.setting-input-value {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
height: 22px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 13px;
|
padding: 7px;
|
||||||
border: #ededed 2px solid;
|
border: #ededed 2px solid;
|
||||||
outline-width: 0;
|
outline-width: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
max-width: 450px;
|
max-width: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-input-value:focus {
|
.setting-input-value:focus {
|
||||||
border: #4EBFAC 2px solid;
|
border: #7cb980 2px solid;
|
||||||
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-block {
|
.setting-block {
|
||||||
@@ -311,6 +272,7 @@ img.server-info-icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.settings-card:hover {
|
.settings-card:hover {
|
||||||
|
border-left: 8px solid #bcbcbc;
|
||||||
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 0px 0px rgba(0, 0, 0, 0.12);
|
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 0px 0px rgba(0, 0, 0, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,15 +282,11 @@ img.server-info-icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.red {
|
.red {
|
||||||
color: #ef5350;
|
color: #ffffff;
|
||||||
padding: 8px;
|
background: #ef5350;
|
||||||
border: rgba(239, 83, 80, 0.5) solid 1px;
|
padding: 3px;
|
||||||
}
|
padding-right: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
.red:hover {
|
|
||||||
color: #e63431;
|
|
||||||
border: rgba(239, 83, 80, 0.7) solid 1px;
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.blue {
|
.blue {
|
||||||
@@ -358,8 +316,8 @@ img.server-info-icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i.open-tab-button {
|
i.open-tab-button {
|
||||||
padding-left: 2px;
|
padding: 0 5px;
|
||||||
font-size: 19px;
|
font-size: 18px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,10 +370,17 @@ i.open-tab-button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#open-create-org-link {
|
#open-create-org-link {
|
||||||
|
color: #666;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#open-create-org-link:hover {
|
||||||
|
color: #005580;
|
||||||
|
;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.toggle {
|
.toggle {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-left: -9999px;
|
margin-left: -9999px;
|
||||||
@@ -470,94 +435,6 @@ input.toggle-round:checked+label:after {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Add new server modal */
|
|
||||||
|
|
||||||
.add-server-modal {
|
|
||||||
display: block;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1;
|
|
||||||
padding-top: 15vh;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
/* background: rgba(61, 64, 67, 15); */
|
|
||||||
background: linear-gradient(35deg, #003b52, #45b59b);
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Modal Content */
|
|
||||||
|
|
||||||
.modal-container {
|
|
||||||
background-color: #f4f7f8;
|
|
||||||
margin: auto;
|
|
||||||
padding: 57px;
|
|
||||||
border: #dae1e3 1px solid;
|
|
||||||
width: 550px;
|
|
||||||
height: 370px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-server-modal .page-title {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 1.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
margin-top: 30px;
|
|
||||||
color: #7d878a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider hr {
|
|
||||||
margin-left: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
width: 44%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.server-center {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
align-items: center;
|
|
||||||
padding-top: 13px;
|
|
||||||
margin-left: -5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.server-center button {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
margin: auto;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
color: #fff;
|
|
||||||
background: #4EBFAC;
|
|
||||||
border-color: none;
|
|
||||||
border: none;
|
|
||||||
width: 98%;
|
|
||||||
height: 46px;
|
|
||||||
border-radius: 3px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.server-center button:hover {
|
|
||||||
background: #329588;
|
|
||||||
}
|
|
||||||
|
|
||||||
.server-center button:focus {
|
|
||||||
background: #329588;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* responsive grid */
|
/* responsive grid */
|
||||||
|
|
||||||
@media (max-width: 650px) {
|
@media (max-width: 650px) {
|
||||||
@@ -571,53 +448,3 @@ input.toggle-round:checked+label:after {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
|
||||||
.modal-container {
|
|
||||||
width: 60vw;
|
|
||||||
padding: 40px;
|
|
||||||
min-width: 300px;
|
|
||||||
}
|
|
||||||
.server-center button {
|
|
||||||
margin-right: -12px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.divider {
|
|
||||||
margin-right: -8px;
|
|
||||||
}
|
|
||||||
.divider hr {
|
|
||||||
margin-left: 6px;
|
|
||||||
margin-right: 6px;
|
|
||||||
width: 43%;
|
|
||||||
}
|
|
||||||
#new-server-container {
|
|
||||||
padding-left: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
.divider {
|
|
||||||
margin-left: 4%;
|
|
||||||
}
|
|
||||||
.divider hr {
|
|
||||||
margin-left: 2px;
|
|
||||||
margin-right: 2px;
|
|
||||||
width: 40%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
.settings-card {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.server-info-right {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
const { shell } = require('electron').remote;
|
|
||||||
const LinkUtil = require('../utils/link-util');
|
|
||||||
const DomainUtil = require('../utils/domain-util');
|
|
||||||
const hiddenWebView = require('../components/hidden-webview');
|
|
||||||
|
|
||||||
function handleExternalLink(event) {
|
|
||||||
const { url } = event;
|
|
||||||
const domainPrefix = DomainUtil.getDomain(this.props.index).url;
|
|
||||||
|
|
||||||
// Whitelist URLs which are allowed to be opened in the app
|
|
||||||
const {
|
|
||||||
isInternalUrl: isWhiteListURL,
|
|
||||||
isUploadsUrl: isUploadsURL
|
|
||||||
} = LinkUtil.isInternal(domainPrefix, url);
|
|
||||||
|
|
||||||
if (isWhiteListURL) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// only open the pdf, mp3, mp4 etc.. in hidden webview since opening the
|
|
||||||
// image in webview will do nothing and will not save it
|
|
||||||
// whereas the pdf will be saved to user desktop once openened in
|
|
||||||
// in the hidden webview and will not trigger webview reload
|
|
||||||
if (!LinkUtil.isImage(url) && isUploadsURL) {
|
|
||||||
hiddenWebView.loadURL(url);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// open internal urls inside the current webview.
|
|
||||||
this.$el.loadURL(url);
|
|
||||||
} else {
|
|
||||||
event.preventDefault();
|
|
||||||
shell.openExternal(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = handleExternalLink;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
// this hidden webview will be used to open pdf url and
|
|
||||||
// save it to user's computer without triggering a reload
|
|
||||||
// when navigating to pdf url to download it.
|
|
||||||
const hiddenWebView = document.createElement('webview');
|
|
||||||
hiddenWebView.classList.add('download-webview');
|
|
||||||
hiddenWebView.src = 'about:blank';
|
|
||||||
document.querySelector('#webviews-container').appendChild(hiddenWebView);
|
|
||||||
|
|
||||||
module.exports = hiddenWebView;
|
|
||||||
@@ -3,12 +3,13 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const DomainUtil = require(__dirname + '/../utils/domain-util.js');
|
||||||
const ConfigUtil = require(__dirname + '/../utils/config-util.js');
|
const ConfigUtil = require(__dirname + '/../utils/config-util.js');
|
||||||
const SystemUtil = require(__dirname + '/../utils/system-util.js');
|
const SystemUtil = require(__dirname + '/../utils/system-util.js');
|
||||||
const { app, dialog } = require('electron').remote;
|
const LinkUtil = require(__dirname + '/../utils/link-util.js');
|
||||||
|
const { shell, app, dialog } = require('electron').remote;
|
||||||
|
|
||||||
const BaseComponent = require(__dirname + '/../components/base.js');
|
const BaseComponent = require(__dirname + '/../components/base.js');
|
||||||
const handleExternalLink = require(__dirname + '/../components/handle-external-link.js');
|
|
||||||
|
|
||||||
const shouldSilentWebview = ConfigUtil.getConfigItem('silent');
|
const shouldSilentWebview = ConfigUtil.getConfigItem('silent');
|
||||||
class WebView extends BaseComponent {
|
class WebView extends BaseComponent {
|
||||||
@@ -45,7 +46,16 @@ class WebView extends BaseComponent {
|
|||||||
|
|
||||||
registerListeners() {
|
registerListeners() {
|
||||||
this.$el.addEventListener('new-window', event => {
|
this.$el.addEventListener('new-window', event => {
|
||||||
handleExternalLink.call(this, event);
|
const { url } = event;
|
||||||
|
const domainPrefix = DomainUtil.getDomain(this.props.index).url;
|
||||||
|
|
||||||
|
if (LinkUtil.isInternal(domainPrefix, url) || url === (domainPrefix + '/')) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.$el.loadURL(url);
|
||||||
|
} else {
|
||||||
|
event.preventDefault();
|
||||||
|
shell.openExternal(url);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (shouldSilentWebview) {
|
if (shouldSilentWebview) {
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class ServerManagerView {
|
|||||||
// Remove focus from the settings icon at sidebar bottom
|
// Remove focus from the settings icon at sidebar bottom
|
||||||
this.$settingsButton.classList.remove('active');
|
this.$settingsButton.classList.remove('active');
|
||||||
} else {
|
} else {
|
||||||
this.openSettings('AddServer');
|
this.openSettings('Servers');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ class ServerManagerView {
|
|||||||
this.tabs[this.activeTabIndex].webview.reload();
|
this.tabs[this.activeTabIndex].webview.reload();
|
||||||
});
|
});
|
||||||
this.$addServerButton.addEventListener('click', () => {
|
this.$addServerButton.addEventListener('click', () => {
|
||||||
this.openSettings('AddServer');
|
this.openSettings('Servers');
|
||||||
});
|
});
|
||||||
this.$settingsButton.addEventListener('click', () => {
|
this.$settingsButton.addEventListener('click', () => {
|
||||||
this.openSettings('General');
|
this.openSettings('General');
|
||||||
@@ -268,10 +268,10 @@ class ServerManagerView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
activateLastTab(index) {
|
activateLastTab(index) {
|
||||||
// Open all the tabs in background, also activate the tab based on the index
|
// Open last active tab
|
||||||
this.activateTab(index);
|
|
||||||
// Save last active tab
|
|
||||||
ConfigUtil.setConfigItem('lastActiveTab', index);
|
ConfigUtil.setConfigItem('lastActiveTab', index);
|
||||||
|
// Open all the tabs in background
|
||||||
|
this.activateTab(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
activateTab(index, hideOldTab = true) {
|
activateTab(index, hideOldTab = true) {
|
||||||
@@ -311,7 +311,7 @@ class ServerManagerView {
|
|||||||
webContents.send('toggle-sidebar', state);
|
webContents.send('toggle-sidebar', state);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('toggle-silent', (event, state) => {
|
ipcRenderer.on('toogle-silent', (event, state) => {
|
||||||
const webviews = document.querySelectorAll('webview');
|
const webviews = document.querySelectorAll('webview');
|
||||||
webviews.forEach(webview => {
|
webviews.forEach(webview => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const BaseSection = require(__dirname + '/base-section.js');
|
|
||||||
const DomainUtil = require(__dirname + '/../../utils/domain-util.js');
|
|
||||||
const ServerInfoForm = require(__dirname + '/server-info-form.js');
|
|
||||||
|
|
||||||
class ConnectedOrgSection extends BaseSection {
|
|
||||||
constructor(props) {
|
|
||||||
super();
|
|
||||||
this.props = props;
|
|
||||||
}
|
|
||||||
|
|
||||||
template() {
|
|
||||||
return `
|
|
||||||
<div class="settings-pane" id="server-settings-pane">
|
|
||||||
<div class="page-title">Connected organizations</div>
|
|
||||||
<div class="title" id="existing-servers">All the connected orgnizations will appear here.</div>
|
|
||||||
<div id="server-info-container"></div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
|
||||||
this.initServers();
|
|
||||||
}
|
|
||||||
|
|
||||||
initServers() {
|
|
||||||
this.props.$root.innerHTML = '';
|
|
||||||
|
|
||||||
const servers = DomainUtil.getDomains();
|
|
||||||
this.props.$root.innerHTML = this.template();
|
|
||||||
this.$serverInfoContainer = document.getElementById('server-info-container');
|
|
||||||
this.$existingServers = document.getElementById('existing-servers');
|
|
||||||
|
|
||||||
const noServerText = 'All the connected orgnizations will appear here';
|
|
||||||
// Show noServerText if no servers are there otherwise hide it
|
|
||||||
this.$existingServers.innerHTML = servers.length === 0 ? noServerText : '';
|
|
||||||
|
|
||||||
for (let i = 0; i < servers.length; i++) {
|
|
||||||
new ServerInfoForm({
|
|
||||||
$root: this.$serverInfoContainer,
|
|
||||||
server: servers[i],
|
|
||||||
index: i,
|
|
||||||
onChange: this.reloadApp
|
|
||||||
}).init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ConnectedOrgSection;
|
|
||||||
37
app/renderer/js/pages/preference/create-new-org.js
Normal file
37
app/renderer/js/pages/preference/create-new-org.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const BaseComponent = require(__dirname + '/../../components/base.js');
|
||||||
|
const shell = require('electron').shell;
|
||||||
|
|
||||||
|
class CreateOrganziation extends BaseComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super();
|
||||||
|
this.props = props;
|
||||||
|
}
|
||||||
|
|
||||||
|
template() {
|
||||||
|
return `
|
||||||
|
<div class="setting-row">
|
||||||
|
<div class="setting-description">
|
||||||
|
<span id="open-create-org-link">Or create a new organization on zulipchat.com<i class="material-icons open-tab-button">open_in_new</i></span>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.props.$root.innerHTML = this.template();
|
||||||
|
this.openCreateNewOrgExternalLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
openCreateNewOrgExternalLink() {
|
||||||
|
const link = 'https://zulipchat.com/beta/';
|
||||||
|
const externalCreateNewOrgEl = document.getElementById('open-create-org-link');
|
||||||
|
externalCreateNewOrgEl.addEventListener('click', () => {
|
||||||
|
shell.openExternal(link);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = CreateOrganziation;
|
||||||
@@ -180,7 +180,7 @@ class GeneralSection extends BaseSection {
|
|||||||
const newValue = !ConfigUtil.getConfigItem('silent', true);
|
const newValue = !ConfigUtil.getConfigItem('silent', true);
|
||||||
ConfigUtil.setConfigItem('silent', newValue);
|
ConfigUtil.setConfigItem('silent', newValue);
|
||||||
this.updateSilentOption();
|
this.updateSilentOption();
|
||||||
currentBrowserWindow.send('toggle-silent', newValue);
|
currentBrowserWindow.send('toogle-silent', newValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class PreferenceNav extends BaseComponent {
|
|||||||
|
|
||||||
this.props = props;
|
this.props = props;
|
||||||
|
|
||||||
this.navItems = ['General', 'Network', 'AddServer', 'Organizations', 'Shortcuts'];
|
this.navItems = ['General', 'Network', 'Servers', 'Shortcuts'];
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
const BaseComponent = require(__dirname + '/../../components/base.js');
|
const BaseComponent = require(__dirname + '/../../components/base.js');
|
||||||
const DomainUtil = require(__dirname + '/../../utils/domain-util.js');
|
const DomainUtil = require(__dirname + '/../../utils/domain-util.js');
|
||||||
const shell = require('electron').shell;
|
|
||||||
|
|
||||||
class NewServerForm extends BaseComponent {
|
class NewServerForm extends BaseComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -12,24 +11,17 @@ class NewServerForm extends BaseComponent {
|
|||||||
|
|
||||||
template() {
|
template() {
|
||||||
return `
|
return `
|
||||||
<div class="server-input-container">
|
<div class="settings-card">
|
||||||
<div class="title">Organization URL</div>
|
<div class="server-info-right">
|
||||||
<div class="add-server-info-row">
|
<div class="title">URL of Zulip organization</div>
|
||||||
<input class="setting-input-value" autofocus placeholder="your-organization.zulipchat.com or zulip.your-organization.com"/>
|
<div class="server-info-row">
|
||||||
|
<input class="setting-input-value" autofocus placeholder="your-organization.zulipchat.com or chat.your-organization.com"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="server-center">
|
<div class="server-info-row">
|
||||||
<div class="server-save-action">
|
<div class="action blue server-save-action">
|
||||||
<button id="connect">Connect</button>
|
<i class="material-icons">add_box</i>
|
||||||
|
<span>Add</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="server-center">
|
|
||||||
<div class="divider">
|
|
||||||
<hr class="left"/>OR<hr class="right" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="server-center">
|
|
||||||
<div class="server-save-action">
|
|
||||||
<button id="open-create-org-link">Create a new organization</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,25 +43,17 @@ class NewServerForm extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
submitFormHandler() {
|
submitFormHandler() {
|
||||||
this.$saveServerButton.children[0].innerHTML = 'Connecting...';
|
this.$saveServerButton.children[1].innerHTML = 'Adding...';
|
||||||
DomainUtil.checkDomain(this.$newServerUrl.value).then(serverConf => {
|
DomainUtil.checkDomain(this.$newServerUrl.value).then(serverConf => {
|
||||||
DomainUtil.addDomain(serverConf).then(() => {
|
DomainUtil.addDomain(serverConf).then(() => {
|
||||||
this.props.onChange(this.props.index);
|
this.props.onChange(this.props.index);
|
||||||
});
|
});
|
||||||
}, errorMessage => {
|
}, errorMessage => {
|
||||||
this.$saveServerButton.children[0].innerHTML = 'Connect';
|
this.$saveServerButton.children[1].innerHTML = 'Add';
|
||||||
alert(errorMessage);
|
alert(errorMessage);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
openCreateNewOrgExternalLink() {
|
|
||||||
const link = 'https://zulipchat.com/new/';
|
|
||||||
const externalCreateNewOrgEl = document.getElementById('open-create-org-link');
|
|
||||||
externalCreateNewOrgEl.addEventListener('click', () => {
|
|
||||||
shell.openExternal(link);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
initActions() {
|
initActions() {
|
||||||
this.$saveServerButton.addEventListener('click', () => {
|
this.$saveServerButton.addEventListener('click', () => {
|
||||||
this.submitFormHandler();
|
this.submitFormHandler();
|
||||||
@@ -81,8 +65,6 @@ class NewServerForm extends BaseComponent {
|
|||||||
this.submitFormHandler();
|
this.submitFormHandler();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// open create new org link in default browser
|
|
||||||
this.openCreateNewOrgExternalLink();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ const Nav = require(__dirname + '/js/pages/preference/nav.js');
|
|||||||
const ServersSection = require(__dirname + '/js/pages/preference/servers-section.js');
|
const ServersSection = require(__dirname + '/js/pages/preference/servers-section.js');
|
||||||
const GeneralSection = require(__dirname + '/js/pages/preference/general-section.js');
|
const GeneralSection = require(__dirname + '/js/pages/preference/general-section.js');
|
||||||
const NetworkSection = require(__dirname + '/js/pages/preference/network-section.js');
|
const NetworkSection = require(__dirname + '/js/pages/preference/network-section.js');
|
||||||
const ConnectedOrgSection = require(__dirname + '/js/pages/preference/connected-org-section.js');
|
|
||||||
const ShortcutsSection = require(__dirname + '/js/pages/preference/shortcuts-section.js');
|
const ShortcutsSection = require(__dirname + '/js/pages/preference/shortcuts-section.js');
|
||||||
|
|
||||||
class PreferenceView extends BaseComponent {
|
class PreferenceView extends BaseComponent {
|
||||||
@@ -40,7 +39,7 @@ class PreferenceView extends BaseComponent {
|
|||||||
handleNavigation(navItem) {
|
handleNavigation(navItem) {
|
||||||
this.nav.select(navItem);
|
this.nav.select(navItem);
|
||||||
switch (navItem) {
|
switch (navItem) {
|
||||||
case 'AddServer': {
|
case 'Servers': {
|
||||||
this.section = new ServersSection({
|
this.section = new ServersSection({
|
||||||
$root: this.$settingsContainer
|
$root: this.$settingsContainer
|
||||||
});
|
});
|
||||||
@@ -52,12 +51,6 @@ class PreferenceView extends BaseComponent {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'Organizations': {
|
|
||||||
this.section = new ConnectedOrgSection({
|
|
||||||
$root: this.$settingsContainer
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'Network': {
|
case 'Network': {
|
||||||
this.section = new NetworkSection({
|
this.section = new NetworkSection({
|
||||||
$root: this.$settingsContainer
|
$root: this.$settingsContainer
|
||||||
|
|||||||
@@ -16,18 +16,19 @@ class ServerInfoForm extends BaseComponent {
|
|||||||
<div class="settings-card">
|
<div class="settings-card">
|
||||||
<div class="server-info-left">
|
<div class="server-info-left">
|
||||||
<img class="server-info-icon" src="${this.props.server.icon}"/>
|
<img class="server-info-icon" src="${this.props.server.icon}"/>
|
||||||
|
</div>
|
||||||
|
<div class="server-info-right">
|
||||||
<div class="server-info-row">
|
<div class="server-info-row">
|
||||||
<span class="server-info-alias">${this.props.server.alias}</span>
|
<span class="server-info-alias">${this.props.server.alias}</span>
|
||||||
<i class="material-icons open-tab-button">open_in_new</i>
|
<i class="material-icons open-tab-button">open_in_new</i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="server-info-row">
|
||||||
<div class="server-info-right">
|
<input class="setting-input-value" disabled value="${this.props.server.url}"/>
|
||||||
<div class="server-info-row server-url">
|
|
||||||
<span class="server-url-info" title="${this.props.server.url}">${this.props.server.url}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="server-info-row">
|
<div class="server-info-row">
|
||||||
<div class="action red server-delete-action">
|
<div class="action red server-delete-action">
|
||||||
<span>Disconnect</span>
|
<i class="material-icons">indeterminate_check_box</i>
|
||||||
|
<span>Delete</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -43,7 +44,6 @@ class ServerInfoForm extends BaseComponent {
|
|||||||
initForm() {
|
initForm() {
|
||||||
this.$serverInfoForm = this.generateNodeFromTemplate(this.template());
|
this.$serverInfoForm = this.generateNodeFromTemplate(this.template());
|
||||||
this.$serverInfoAlias = this.$serverInfoForm.getElementsByClassName('server-info-alias')[0];
|
this.$serverInfoAlias = this.$serverInfoForm.getElementsByClassName('server-info-alias')[0];
|
||||||
this.$serverIcon = this.$serverInfoForm.getElementsByClassName('server-info-icon')[0];
|
|
||||||
this.$deleteServerButton = this.$serverInfoForm.getElementsByClassName('server-delete-action')[0];
|
this.$deleteServerButton = this.$serverInfoForm.getElementsByClassName('server-delete-action')[0];
|
||||||
this.$openServerButton = this.$serverInfoForm.getElementsByClassName('open-tab-button')[0];
|
this.$openServerButton = this.$serverInfoForm.getElementsByClassName('open-tab-button')[0];
|
||||||
this.props.$root.appendChild(this.$serverInfoForm);
|
this.props.$root.appendChild(this.$serverInfoForm);
|
||||||
@@ -71,12 +71,7 @@ class ServerInfoForm extends BaseComponent {
|
|||||||
this.$serverInfoAlias.addEventListener('click', () => {
|
this.$serverInfoAlias.addEventListener('click', () => {
|
||||||
ipcRenderer.send('forward-message', 'switch-server-tab', this.props.index);
|
ipcRenderer.send('forward-message', 'switch-server-tab', this.props.index);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$serverIcon.addEventListener('click', () => {
|
|
||||||
ipcRenderer.send('forward-message', 'switch-server-tab', this.props.index);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ServerInfoForm;
|
module.exports = ServerInfoForm;
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const BaseSection = require(__dirname + '/base-section.js');
|
const BaseSection = require(__dirname + '/base-section.js');
|
||||||
|
const DomainUtil = require(__dirname + '/../../utils/domain-util.js');
|
||||||
|
const ServerInfoForm = require(__dirname + '/server-info-form.js');
|
||||||
const NewServerForm = require(__dirname + '/new-server-form.js');
|
const NewServerForm = require(__dirname + '/new-server-form.js');
|
||||||
|
const CreateOrganziation = require(__dirname + '/create-new-org.js');
|
||||||
|
|
||||||
class ServersSection extends BaseSection {
|
class ServersSection extends BaseSection {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -11,13 +14,12 @@ class ServersSection extends BaseSection {
|
|||||||
|
|
||||||
template() {
|
template() {
|
||||||
return `
|
return `
|
||||||
<div class="add-server-modal">
|
|
||||||
<div class="modal-container">
|
|
||||||
<div class="settings-pane" id="server-settings-pane">
|
<div class="settings-pane" id="server-settings-pane">
|
||||||
<div class="page-title">Add a Zulip organization</div>
|
<div class="page-title">Register or login to a Zulip organization to get started</div>
|
||||||
<div id="new-server-container"></div>
|
<div id="new-server-container"></div>
|
||||||
</div>
|
<div class="title" id="existing-servers"></div>
|
||||||
</div>
|
<div id="server-info-container"></div>
|
||||||
|
<div id="create-organization-container"></div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -29,10 +31,35 @@ class ServersSection extends BaseSection {
|
|||||||
initServers() {
|
initServers() {
|
||||||
this.props.$root.innerHTML = '';
|
this.props.$root.innerHTML = '';
|
||||||
|
|
||||||
|
const servers = DomainUtil.getDomains();
|
||||||
this.props.$root.innerHTML = this.template();
|
this.props.$root.innerHTML = this.template();
|
||||||
|
this.$serverInfoContainer = document.getElementById('server-info-container');
|
||||||
|
this.$existingServers = document.getElementById('existing-servers');
|
||||||
this.$newServerContainer = document.getElementById('new-server-container');
|
this.$newServerContainer = document.getElementById('new-server-container');
|
||||||
|
this.$newServerButton = document.getElementById('new-server-action');
|
||||||
|
|
||||||
|
this.$serverInfoContainer.innerHTML = servers.length ? '' : '';
|
||||||
|
// Show Existing servers if servers are there otherwise hide it
|
||||||
|
this.$existingServers.innerHTML = servers.length === 0 ? '' : 'Connected organizations';
|
||||||
this.initNewServerForm();
|
this.initNewServerForm();
|
||||||
|
|
||||||
|
this.$createOrganizationContainer = document.getElementById('create-organization-container');
|
||||||
|
this.initCreateNewOrganization();
|
||||||
|
|
||||||
|
for (let i = 0; i < servers.length; i++) {
|
||||||
|
new ServerInfoForm({
|
||||||
|
$root: this.$serverInfoContainer,
|
||||||
|
server: servers[i],
|
||||||
|
index: i,
|
||||||
|
onChange: this.reloadApp
|
||||||
|
}).init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initCreateNewOrganization() {
|
||||||
|
new CreateOrganziation({
|
||||||
|
$root: this.$createOrganizationContainer
|
||||||
|
}).init();
|
||||||
}
|
}
|
||||||
|
|
||||||
initNewServerForm() {
|
initNewServerForm() {
|
||||||
|
|||||||
@@ -78,6 +78,14 @@ class ShortcutsSection extends BaseSection {
|
|||||||
<td><kbd>${userOSKey}</kbd><kbd>A</kbd></td>
|
<td><kbd>${userOSKey}</kbd><kbd>A</kbd></td>
|
||||||
<td>Select All</td>
|
<td>Select All</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><kbd>${userOSKey}</kbd><kbd>F</kbd></td>
|
||||||
|
<td>Find</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><kbd>${userOSKey}</kbd><kbd>G</kbd></td>
|
||||||
|
<td>Find Next</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>Control</kbd><kbd>${userOSKey}</kbd><kbd>Space</kbd></td>
|
<td><kbd>Control</kbd><kbd>${userOSKey}</kbd><kbd>Space</kbd></td>
|
||||||
<td>Emoji & Symbols</td>
|
<td>Emoji & Symbols</td>
|
||||||
@@ -113,7 +121,7 @@ class ShortcutsSection extends BaseSection {
|
|||||||
<td>Actual Size</td>
|
<td>Actual Size</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd></td>
|
<td><kbd>${userOSKey}</kbd><kbd>S</kbd></td>
|
||||||
<td>Toggle Sidebar</td>
|
<td>Toggle Sidebar</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -248,7 +256,7 @@ class ShortcutsSection extends BaseSection {
|
|||||||
<td>Actual Size</td>
|
<td>Actual Size</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd></td>
|
<td><kbd>${userOSKey}</kbd> + <kbd>S</kbd></td>
|
||||||
<td>Toggle Sidebar</td>
|
<td>Toggle Sidebar</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -4,14 +4,10 @@ const { ipcRenderer } = require('electron');
|
|||||||
const SetupSpellChecker = require('./spellchecker');
|
const SetupSpellChecker = require('./spellchecker');
|
||||||
|
|
||||||
const ConfigUtil = require(__dirname + '/utils/config-util.js');
|
const ConfigUtil = require(__dirname + '/utils/config-util.js');
|
||||||
const LinkUtil = require(__dirname + '/utils/link-util.js');
|
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-unassigned-import
|
// eslint-disable-next-line import/no-unassigned-import
|
||||||
require('./notification');
|
require('./notification');
|
||||||
|
|
||||||
// Prevent drag and drop event in main process which prevents remote code executaion
|
|
||||||
require(__dirname + '/shared/preventdrag.js');
|
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
// Create the menu for the below
|
// Create the menu for the below
|
||||||
document.querySelector('.dropdown-toggle').click();
|
document.querySelector('.dropdown-toggle').click();
|
||||||
@@ -24,7 +20,7 @@ const shortcut = () => {
|
|||||||
// Create the menu for the below
|
// Create the menu for the below
|
||||||
const node = document.querySelector('a[data-overlay-trigger=keyboard-shortcuts]');
|
const node = document.querySelector('a[data-overlay-trigger=keyboard-shortcuts]');
|
||||||
// Additional check
|
// Additional check
|
||||||
if (node.text.trim().toLowerCase() === 'keyboard shortcuts (?)') {
|
if (node.text.trim().toLowerCase() === 'keyboard shortcuts') {
|
||||||
node.click();
|
node.click();
|
||||||
} else {
|
} else {
|
||||||
// Atleast click the dropdown
|
// Atleast click the dropdown
|
||||||
@@ -56,24 +52,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
ipcRenderer.send('forward-message', 'reload-viewer');
|
ipcRenderer.send('forward-message', 'reload-viewer');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open image attachment link in the lightbox instead of opening in the default browser
|
|
||||||
const { $, lightbox } = window;
|
|
||||||
|
|
||||||
$('#main_div').on('click', '.message_content p a', function (e) {
|
|
||||||
const url = $(this).attr('href');
|
|
||||||
|
|
||||||
if (LinkUtil.isImage(url)) {
|
|
||||||
const $img = $(this).parent().siblings('.message_inline_image').find('img');
|
|
||||||
|
|
||||||
// prevent the image link from opening in a new page.
|
|
||||||
e.preventDefault();
|
|
||||||
// prevent the message compose dialog from happening.
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
lightbox.open($img);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clean up spellchecker events after you navigate away from this page;
|
// Clean up spellchecker events after you navigate away from this page;
|
||||||
@@ -82,10 +60,3 @@ window.addEventListener('beforeunload', () => {
|
|||||||
SetupSpellChecker.unsubscribeSpellChecker();
|
SetupSpellChecker.unsubscribeSpellChecker();
|
||||||
});
|
});
|
||||||
|
|
||||||
// electron's globalShortcut can cause unexpected results
|
|
||||||
// so adding the reload shortcut in the old-school way
|
|
||||||
document.addEventListener('keydown', event => {
|
|
||||||
if (event.code === 'F5') {
|
|
||||||
ipcRenderer.send('forward-message', 'hard-reload');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
// This is a security fix. Following function prevents drag and drop event in the app
|
|
||||||
// so that attackers can't execute any remote code within the app
|
|
||||||
// It doesn't affect the compose box so that users can still
|
|
||||||
// use drag and drop event to share files etc
|
|
||||||
|
|
||||||
const preventDragAndDrop = () => {
|
|
||||||
const preventEvents = ['dragover', 'drop'];
|
|
||||||
preventEvents.forEach(dragEvents => {
|
|
||||||
document.addEventListener(dragEvents, event => {
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
preventDragAndDrop();
|
|
||||||
@@ -19,20 +19,7 @@ class LinkUtil {
|
|||||||
const currentDomain = wurl('hostname', currentUrl);
|
const currentDomain = wurl('hostname', currentUrl);
|
||||||
const newDomain = wurl('hostname', newUrl);
|
const newDomain = wurl('hostname', newUrl);
|
||||||
|
|
||||||
const sameDomainUrl = (currentDomain === newDomain || newUrl === currentUrl + '/');
|
return (currentDomain === newDomain) && newUrl.includes('/#narrow');
|
||||||
const isUploadsUrl = newUrl.includes(currentUrl + '/user_uploads/');
|
|
||||||
const isInternalUrl = newUrl.includes('/#narrow') || isUploadsUrl;
|
|
||||||
|
|
||||||
return {
|
|
||||||
isInternalUrl: sameDomainUrl && isInternalUrl,
|
|
||||||
isUploadsUrl
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
isImage(url) {
|
|
||||||
// test for images extension as well as urls like .png?s=100
|
|
||||||
const isImageUrl = /\.(bmp|gif|jpg|jpeg|png|webp)\?*.*$/i;
|
|
||||||
return isImageUrl.test(url);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,5 +44,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
<script>require('./js/shared/preventdrag.js')</script>
|
|
||||||
</html>
|
</html>
|
||||||
@@ -18,5 +18,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<script src="js/pages/network.js"></script>
|
<script src="js/pages/network.js"></script>
|
||||||
<script>require('./js/shared/preventdrag.js')</script>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -13,5 +13,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<script src="js/pages/preference/preference.js"></script>
|
<script src="js/pages/preference/preference.js"></script>
|
||||||
<script>require('./js/shared/preventdrag.js')</script>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ To build and run the app from source, you'll need the following:
|
|||||||
* [Python](https://www.python.org/downloads/release/python-2713/)
|
* [Python](https://www.python.org/downloads/release/python-2713/)
|
||||||
(v2.7.x recommended)
|
(v2.7.x recommended)
|
||||||
* A C++ compiler compatible with C++11
|
* A C++ compiler compatible with C++11
|
||||||
* Linux users also need [Snapcraft](https://snapcraft.io/)
|
|
||||||
* Development headers for the libXext, libXtst, and libxkbfile libraries
|
* Development headers for the libXext, libXtst, and libxkbfile libraries
|
||||||
|
|
||||||
### Debian/Ubuntu and friends
|
### Debian/Ubuntu and friends
|
||||||
@@ -26,7 +25,7 @@ manager (see [here][nodesource-install] for more on the first command):
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
|
$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
|
||||||
$ sudo apt install git nodejs python build-essential snapcraft libxext-dev libxtst-dev libxkbfile-dev libgconf-2-4
|
$ sudo apt install git nodejs python build-essential libxext-dev libxtst-dev libxkbfile-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
[nodesource-install]: https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions
|
[nodesource-install]: https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions
|
||||||
@@ -77,7 +76,7 @@ This command will produce distributable packages or installers for the
|
|||||||
operating system you're running on:
|
operating system you're running on:
|
||||||
* on Windows, a Windows installer file
|
* on Windows, a Windows installer file
|
||||||
* on macOS, a `.dmg` file
|
* on macOS, a `.dmg` file
|
||||||
* on Linux, a plain `.zip` file as well as a `.deb` file, `.snap` file and an
|
* on Linux, a plain `.zip` file as well as a `.deb` file and an
|
||||||
`AppImage` file.
|
`AppImage` file.
|
||||||
To generate all three types, you will need all three operating
|
To generate all three types, you will need all three operating
|
||||||
systems.
|
systems.
|
||||||
|
|||||||
9854
package-lock.json
generated
Normal file
9854
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "zulip",
|
"name": "zulip",
|
||||||
"productName": "Zulip",
|
"productName": "Zulip",
|
||||||
"version": "1.9.0",
|
"version": "1.8.2",
|
||||||
"main": "./app/main",
|
"main": "./app/main",
|
||||||
"description": "Zulip Desktop App",
|
"description": "Zulip Desktop App",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron app --disable-http-cache --no-electron-connect",
|
"start": "electron app --disable-http-cache --no-electron-connect",
|
||||||
"reinstall": "node ./tools/reinstall-node-modules.js",
|
"reinstall": "./tools/reinstall-node-modules",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"test": "xo",
|
"test": "xo",
|
||||||
"test-e2e": "gulp test-e2e",
|
"test-e2e": "gulp test-e2e",
|
||||||
@@ -55,8 +55,7 @@
|
|||||||
"target": [
|
"target": [
|
||||||
"deb",
|
"deb",
|
||||||
"zip",
|
"zip",
|
||||||
"AppImage",
|
"AppImage"
|
||||||
"snap"
|
|
||||||
],
|
],
|
||||||
"maintainer": "Akash Nimare <svnitakash@gmail.com>"
|
"maintainer": "Akash Nimare <svnitakash@gmail.com>"
|
||||||
},
|
},
|
||||||
@@ -65,9 +64,6 @@
|
|||||||
"afterInstall": "./scripts/debian-add-repo.sh",
|
"afterInstall": "./scripts/debian-add-repo.sh",
|
||||||
"afterRemove": "./scripts/debian-uninstaller.sh"
|
"afterRemove": "./scripts/debian-uninstaller.sh"
|
||||||
},
|
},
|
||||||
"snap": {
|
|
||||||
"synopsis": "Zulip Desktop App"
|
|
||||||
},
|
|
||||||
"dmg": {
|
"dmg": {
|
||||||
"background": "build/appdmg.png",
|
"background": "build/appdmg.png",
|
||||||
"icon": "build/icon.icns",
|
"icon": "build/icon.icns",
|
||||||
@@ -117,8 +113,8 @@
|
|||||||
"assert": "1.4.1",
|
"assert": "1.4.1",
|
||||||
"cp-file": "^5.0.0",
|
"cp-file": "^5.0.0",
|
||||||
"devtron": "1.4.0",
|
"devtron": "1.4.0",
|
||||||
"electron": "1.8.4",
|
"electron": "1.8.2",
|
||||||
"electron-builder": "20.8.1",
|
"electron-builder": "20.4.1",
|
||||||
"electron-connect": "0.6.2",
|
"electron-connect": "0.6.2",
|
||||||
"electron-debug": "1.4.0",
|
"electron-debug": "1.4.0",
|
||||||
"google-translate-api": "2.3.0",
|
"google-translate-api": "2.3.0",
|
||||||
@@ -127,7 +123,7 @@
|
|||||||
"is-ci": "^1.0.10",
|
"is-ci": "^1.0.10",
|
||||||
"nodemon": "^1.14.11",
|
"nodemon": "^1.14.11",
|
||||||
"pre-commit": "1.2.2",
|
"pre-commit": "1.2.2",
|
||||||
"spectron": "3.8.0",
|
"spectron": "3.7.2",
|
||||||
"tap-colorize": "^1.2.0",
|
"tap-colorize": "^1.2.0",
|
||||||
"tape": "^4.8.0",
|
"tape": "^4.8.0",
|
||||||
"xo": "0.18.2"
|
"xo": "0.18.2"
|
||||||
@@ -168,7 +164,8 @@
|
|||||||
],
|
],
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"tests/*.js",
|
"tests/*.js",
|
||||||
"tools/locale-helper/*.js"
|
"tools/locale-helper/*.js",
|
||||||
|
"scripts/*.js"
|
||||||
],
|
],
|
||||||
"envs": [
|
"envs": [
|
||||||
"node",
|
"node",
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
# This script runs when user install the debian package
|
# This script runs when user install the debian package
|
||||||
|
|
||||||
# Link to the binary
|
|
||||||
ln -sf '/opt/${productFilename}/${executable}' '/usr/local/bin/${executable}';
|
|
||||||
echo 'Successfully added /opt/${productFilename}/${executable} to /usr/local/bin/${executable}'
|
|
||||||
|
|
||||||
# Install apt repository source list if it does not exist
|
# Install apt repository source list if it does not exist
|
||||||
if ! grep ^ /etc/apt/sources.list /etc/apt/sources.list.d/* | grep zulip.list; then
|
if ! grep ^ /etc/apt/sources.list /etc/apt/sources.list.d/* | grep zulip.list; then
|
||||||
sudo apt-key adv --keyserver pool.sks-keyservers.net --recv 69AD12704E71A4803DCA3A682424BE5AE9BD10D9
|
sudo apt-key adv --keyserver pool.sks-keyservers.net --recv 69AD12704E71A4803DCA3A682424BE5AE9BD10D9
|
||||||
|
|||||||
@@ -29,7 +29,3 @@ appDirectory=/home/$getSudoUser/.config/Zulip/;
|
|||||||
if [ -d $appDirectory ]; then
|
if [ -d $appDirectory ]; then
|
||||||
sudo rm -rf $appDirectory;
|
sudo rm -rf $appDirectory;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Delete the link to the binary
|
|
||||||
echo 'Removing binary link'
|
|
||||||
sudo rm -f '/usr/local/bin/${executable}';
|
|
||||||
9
scripts/install-release-dependencies.sh
Normal file
9
scripts/install-release-dependencies.sh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||||
|
sudo apt-get install --no-install-recommends -y icnsutils
|
||||||
|
|
||||||
|
# to build 32 bit from a machine with 64 bit
|
||||||
|
sudo apt-get install --no-install-recommends -y gcc-multilib g++-multilib
|
||||||
|
fi
|
||||||
28
scripts/prepare-artifacts.js
Normal file
28
scripts/prepare-artifacts.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
if (!process.env.TRAVIS_OS_NAME === 'linux') {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// go to dist directory
|
||||||
|
process.chdir(path.resolve(__dirname, '../dist'));
|
||||||
|
|
||||||
|
const extensions = /\.deb|\.AppImage|\.zip/;
|
||||||
|
const files = fs.readdirSync(process.cwd()).filter(file => file.includes);
|
||||||
|
|
||||||
|
function changeFileName(file) {
|
||||||
|
file = file.replace(/^z/, 'Z');
|
||||||
|
file = file.replace(/_{2}/, '-');
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change file name to what we want
|
||||||
|
// eg zulip_1.8.2_amd64.deb -> Zulip-1.8.2-amd64.deb
|
||||||
|
// and change file name
|
||||||
|
files.map(file => {
|
||||||
|
const newFileName = changeFileName(file);
|
||||||
|
fs.renameSync(file, newFileName);
|
||||||
|
});
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
name: zulip
|
|
||||||
version: 1.8.2
|
|
||||||
summary: Zulip
|
|
||||||
description: Zulip Desktop Client for Linux
|
|
||||||
confinement: strict
|
|
||||||
grade: stable
|
|
||||||
icon: ../build/icon.png
|
|
||||||
apps:
|
|
||||||
zulip:
|
|
||||||
command: env TMPDIR=$XDG_RUNTIME_DIR desktop-launch $SNAP/zulip
|
|
||||||
plugs:
|
|
||||||
- desktop
|
|
||||||
- desktop-legacy
|
|
||||||
- home
|
|
||||||
- x11
|
|
||||||
- unity7
|
|
||||||
- browser-support
|
|
||||||
- network
|
|
||||||
- gsettings
|
|
||||||
- pulseaudio
|
|
||||||
- opengl
|
|
||||||
parts:
|
|
||||||
app:
|
|
||||||
plugin: dump
|
|
||||||
stage-packages:
|
|
||||||
- libasound2
|
|
||||||
- libgconf2-4
|
|
||||||
- libnotify4
|
|
||||||
- libnspr4
|
|
||||||
- libnss3
|
|
||||||
- libpcre3
|
|
||||||
- libpulse0
|
|
||||||
- libxss1
|
|
||||||
- libxtst6
|
|
||||||
source: ../dist/linux-unpacked
|
|
||||||
after:
|
|
||||||
- desktop-gtk2
|
|
||||||
@@ -7,7 +7,7 @@ test('app runs', function (t) {
|
|||||||
const app = setup.createApp()
|
const app = setup.createApp()
|
||||||
setup.waitForLoad(app, t)
|
setup.waitForLoad(app, t)
|
||||||
.then(() => app.client.windowByIndex(1)) // focus on webview
|
.then(() => app.client.windowByIndex(1)) // focus on webview
|
||||||
.then(() => app.client.waitForExist('//*[@id="connect"]')) // id of the connect button
|
.then(() => app.client.waitForExist('//*[@id="new-server-container"]/div/div/div[2]/input'))
|
||||||
.then(() => setup.endTest(app, t),
|
.then(() => setup.endTest(app, t),
|
||||||
(err) => setup.endTest(app, t, err || 'error'))
|
(err) => setup.endTest(app, t, err || 'error'))
|
||||||
})
|
})
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const test = require('tape')
|
|
||||||
const setup = require('./setup')
|
|
||||||
|
|
||||||
// Create new org link should open in the default browser [WIP]
|
|
||||||
|
|
||||||
test('new-org-link', function (t) {
|
|
||||||
t.timeoutAfter(50e3)
|
|
||||||
setup.resetTestDataDir()
|
|
||||||
const app = setup.createApp()
|
|
||||||
setup.waitForLoad(app, t)
|
|
||||||
.then(() => app.client.windowByIndex(1)) // focus on webview
|
|
||||||
.then(() => app.client.click('#open-create-org-link')) // Click on new org link button
|
|
||||||
.then(() => setup.wait(5000))
|
|
||||||
.then(() => setup.endTest(app, t),
|
|
||||||
(err) => setup.endTest(app, t, err || 'error'))
|
|
||||||
})
|
|
||||||
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
const {exec} = require('child_process');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const isWindows = process.platform === 'win32';
|
|
||||||
const command = path.join(__dirname, `reinstall-node-modules${isWindows ? '.cmd' : ''}`);
|
|
||||||
|
|
||||||
const proc = exec(command, error => {
|
|
||||||
if (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
proc.stdout.on('data', data => console.log(data.toString()));
|
|
||||||
proc.stderr.on('data', data => console.error(data.toString()));
|
|
||||||
proc.on('exit', code => {
|
|
||||||
process.exit(code);
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user