This removes all AngularJS code Angular version 1 is unmaintained and largely obsolete since years. Additionally, I'd rather re-use the conventions and libraries from Converse instead of having different ones in converse-desktop. This means we're losing some functionality, such as the app settings and the about modal. This is unfortunate, but ideally (non-Electron) app settings should be implemented in Converse itself and not in this repo.pull/12/head
parent
cc3dae61ad
commit
1a62af799b
@ -0,0 +1,22 @@
|
||||
module.exports = {
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 13,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"globals": {
|
||||
"__dirname": true,
|
||||
"converse": true,
|
||||
"exports": true,
|
||||
"module": true,
|
||||
"process": true,
|
||||
"require": true,
|
||||
},
|
||||
"rules": {
|
||||
"prefer-const": "error",
|
||||
}
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
BIN ?= ./node_modules/.bin/
|
||||
ESLINT ?= ./node_modules/.bin/eslint
|
||||
|
||||
node_modules: package.json package-lock.json
|
||||
npm i
|
||||
|
||||
build: node_modules
|
||||
$(BIN)/electron-rebuild
|
||||
|
||||
serve: build
|
||||
npm start
|
||||
|
||||
.PHONY: eslint
|
||||
eslint: node_modules
|
||||
$(ESLINT) *.js
|
||||
$(ESLINT) app/**/*.js
|
@ -1,10 +0,0 @@
|
||||
let angApp = require(__dirname+'/../init')
|
||||
|
||||
angApp.controller('AboutController', function($scope, AppStateService, AppInfo) {
|
||||
|
||||
$scope.appInfo = AppInfo
|
||||
|
||||
$scope.closeAbout = () => {
|
||||
AppStateService.set(AppStateService.APP_STATE_DEFAULT)
|
||||
}
|
||||
})
|
@ -1,47 +0,0 @@
|
||||
let angApp = require(__dirname+'/../init')
|
||||
|
||||
angApp.controller('DefaultController', function($scope, $timeout, $http, AppInfo) {
|
||||
|
||||
$scope.appInfo = AppInfo
|
||||
|
||||
let getUpdateInfo = () => {
|
||||
$http({
|
||||
url: $scope.appInfo.APP_RELEASES_CHECK_URL,
|
||||
method: 'GET'
|
||||
}).then((response) => {
|
||||
let releaseTag = response.data[0].tag_name
|
||||
let releaseVersion = parseInt(releaseTag.replace(/v|\./g, ''))
|
||||
let appVersion = parseInt($scope.appInfo.APP_VERSION.replace(/v|\./g, ''))
|
||||
if (appVersion < releaseVersion ) {
|
||||
$scope.checkingForUpdate = 'updateAvailable'
|
||||
}
|
||||
else {
|
||||
$scope.checkingForUpdate = 'latest'
|
||||
}
|
||||
}).catch((error) => {
|
||||
$scope.checkingForUpdate = 'checkErr'
|
||||
})
|
||||
}
|
||||
|
||||
let checkForUpdate = (timeout = 5000) => {
|
||||
$scope.checkingForUpdate = 'inProgress'
|
||||
$timeout(() => {
|
||||
getUpdateInfo()
|
||||
}, timeout)
|
||||
}
|
||||
|
||||
let checkForUpdateDelayed = (timeout = 5000) => {
|
||||
$timeout(() => {
|
||||
checkForUpdate()
|
||||
}, timeout)
|
||||
}
|
||||
|
||||
checkForUpdateDelayed()
|
||||
|
||||
$scope.checkRetry = ($event) => {
|
||||
$event.preventDefault()
|
||||
checkForUpdate()
|
||||
}
|
||||
|
||||
|
||||
})
|
@ -1,7 +0,0 @@
|
||||
let angApp = require(__dirname+'/../init')
|
||||
|
||||
angApp.controller('FooterController', function($scope, AppInfo) {
|
||||
|
||||
$scope.appInfo = AppInfo
|
||||
|
||||
})
|
@ -1,21 +0,0 @@
|
||||
let angApp = require(__dirname+'/../init')
|
||||
|
||||
angApp.controller('LoginController', function($scope, DesktopService, CredentialsService) {
|
||||
|
||||
$scope.help = {}
|
||||
|
||||
$scope.showHelp = (item) => {
|
||||
$scope.help[item] = typeof $scope.help[item] === 'undefined' ? true : !$scope.help[item];
|
||||
}
|
||||
|
||||
$scope.addAccountAndLoginAction = () => {
|
||||
CredentialsService.addCredentials($scope.credentials.connectionManager,
|
||||
$scope.credentials.login,
|
||||
$scope.credentials.password
|
||||
)
|
||||
DesktopService.getCredentialsAndLogin()
|
||||
$scope.accountForm.$setPristine()
|
||||
$scope.accountForm.$setUntouched()
|
||||
$scope.credentials = {}
|
||||
}
|
||||
})
|
@ -1,40 +0,0 @@
|
||||
let angApp = require(__dirname+'/../init')
|
||||
|
||||
angApp.controller('SettingsController', function ($scope, $rootScope, AppStateService, SettingsService) {
|
||||
|
||||
let formInitialized = false
|
||||
$scope.settingsChanged = false
|
||||
$scope.settingsSaved = false
|
||||
|
||||
const settingsSetPristine = () => {
|
||||
$scope.settingsChanged = false
|
||||
formInitialized = false
|
||||
}
|
||||
|
||||
$scope.closeSettings = () => {
|
||||
$scope.settings = SettingsService.loadAll()
|
||||
settingsSetPristine()
|
||||
AppStateService.set(AppStateService.APP_STATE_DEFAULT)
|
||||
}
|
||||
|
||||
$scope.saveSettings = () => {
|
||||
$scope.settingsSaved = true
|
||||
SettingsService.saveAll($scope.settings)
|
||||
settingsSetPristine()
|
||||
}
|
||||
|
||||
$scope.restartApp = () => {
|
||||
$rootScope.$broadcast('app:restart')
|
||||
}
|
||||
|
||||
$scope.settings = SettingsService.loadAll()
|
||||
|
||||
$scope.$watch("settings", () => {
|
||||
if (!formInitialized) {
|
||||
formInitialized = true
|
||||
} else {
|
||||
$scope.settingsChanged = true
|
||||
}
|
||||
}, true)
|
||||
|
||||
})
|
@ -0,0 +1,24 @@
|
||||
const { addCredentials } = require('../credentials.js');
|
||||
const { getCredentials, removeCredentials } = require('../credentials.js');
|
||||
|
||||
converse.plugins.add('converse-desktop-credentials', {
|
||||
|
||||
initialize () {
|
||||
const { _converse } = this;
|
||||
const { api } = _converse;
|
||||
|
||||
api.listen.on('afterResourceBinding', () => {
|
||||
if (_converse.connection.pass) {
|
||||
addCredentials(
|
||||
converse.connectionManager,
|
||||
_converse.bare_jid,
|
||||
_converse.connection.pass
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
api.listen.on('logout', () => {
|
||||
getCredentials().then((result) => removeCredentials(result.login))
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,49 @@
|
||||
/* global require, module */
|
||||
|
||||
const settings = require('electron-settings');
|
||||
const keytar = require('keytar')
|
||||
|
||||
function addCredentials (connectionManager, login, password) {
|
||||
const xmppService = login.split('@').pop()
|
||||
settings.setSync('connectionManager', connectionManager)
|
||||
settings.setSync('login', login)
|
||||
keytar.setPassword(xmppService, login, password)
|
||||
}
|
||||
|
||||
function getCredentials () {
|
||||
const credentials = {}
|
||||
credentials.login = settings.getSync('login')
|
||||
return new Promise((resolve) => {
|
||||
if (credentials.login) {
|
||||
credentials.connectionManager = settings.getSync('connectionManager')
|
||||
credentials.xmppService = credentials.login.split('@').pop()
|
||||
let password = keytar.getPassword(credentials.xmppService, credentials.login)
|
||||
password.then((result) => {
|
||||
credentials.password = result
|
||||
resolve(credentials)
|
||||
})
|
||||
} else {
|
||||
resolve({});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeCredentials (login) {
|
||||
const xmppService = login.split('@').pop()
|
||||
const passwordDelete = keytar.deletePassword(xmppService, login)
|
||||
return new Promise((resolve, reject) => {
|
||||
passwordDelete.then(() => {
|
||||
settings.unsetSync('login')
|
||||
settings.unsetSync('connectionManager')
|
||||
resolve()
|
||||
}, (error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addCredentials,
|
||||
getCredentials,
|
||||
removeCredentials
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
const angular = require('angular')
|
||||
let angApp = angular.module('app', [])
|
||||
|
||||
angApp.constant('AppInfo', {
|
||||
APP_NAME: 'Converse Desktop',
|
||||
APP_VERSION: 'v0.1.0',
|
||||
APP_HOME: 'https://github.com/conversejs/converse-desktop',
|
||||
APP_RELEASES_CHECK_URL: 'https://api.github.com/repos/conversejs/converse-desktop/releases',
|
||||
APP_RELEASES_URL: 'https://github.com/conversejs/converse-desktop/releases',
|
||||
CONVERSE_VERSION: 'v7.0.4',
|
||||
ELECTRON_VERSION: '11.2.3'
|
||||
});
|
||||
|
||||
module.exports = angApp
|
@ -1,22 +0,0 @@
|
||||
let angApp = require(__dirname + '/../init')
|
||||
|
||||
angApp.factory('AppStateService', [ '$rootScope', ($rootScope) => {
|
||||
|
||||
let stateService = {}
|
||||
|
||||
stateService.APP_STATE_LOGIN = 'login'
|
||||
stateService.APP_STATE_DEFAULT = 'default'
|
||||
stateService.APP_STATE_SETTINGS = 'settings'
|
||||
stateService.APP_STATE_ABOUT = 'about'
|
||||
|
||||
stateService.set = (state) => {
|
||||
stateService.previousState = typeof stateService.state !== 'undefined' ?
|
||||
stateService.state : stateService.APP_STATE_DEFAULT
|
||||
stateService.state = state
|
||||
$rootScope.$broadcast('app:state:changed', stateService.state)
|
||||
}
|
||||
|
||||
stateService.set(stateService.APP_STATE_DEFAULT)
|
||||
|
||||
return stateService
|
||||
}])
|
@ -1,54 +0,0 @@
|
||||
let angApp = require(__dirname+'/../init')
|
||||
|
||||
angApp.factory('CredentialsService', () => {
|
||||
|
||||
const keytar = require('keytar')
|
||||
const settings = require('electron-settings')
|
||||
|
||||
let credentialsService = {}
|
||||
|
||||
credentialsService.getCredentials = () => {
|
||||
let credentials = {}
|
||||
credentials.login = settings.getSync('login')
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
if (credentials.login) {
|
||||
credentials.connectionManager = settings.getSync('connectionManager')
|
||||
credentials.xmppService = credentials.login.split('@').pop()
|
||||
let password = keytar.getPassword(credentials.xmppService, credentials.login)
|
||||
password.then((result) => {
|
||||
credentials.password = result
|
||||
resolve(credentials)
|
||||
})
|
||||
}
|
||||
else {
|
||||
reject(Error('No login stored'))
|
||||
}
|
||||
})
|
||||
return promise
|
||||
}
|
||||
|
||||
credentialsService.addCredentials = (connectionManager, login, password) => {
|
||||
let xmppService = login.split('@').pop()
|
||||
settings.setSync('connectionManager', connectionManager)
|
||||
settings.setSync('login', login)
|
||||
keytar.setPassword(xmppService, login, password)
|
||||
}
|
||||
|
||||
credentialsService.removeCredentials = (login) => {
|
||||
let xmppService = login.split('@').pop()
|
||||
passwordDelete = keytar.deletePassword(xmppService, login)
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
passwordDelete.then((result) => {
|
||||
settings.unsetSync('login')
|
||||
settings.unsetSync('connectionManager')
|
||||
resolve()
|
||||
}, (error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
return promise
|
||||
}
|
||||
|
||||
return credentialsService
|
||||
})
|
||||
|
@ -1,96 +0,0 @@
|
||||
let angApp = require(__dirname + '/../init')
|
||||
|
||||
const desktopPlugin = require(__dirname +'/../../libs/converse.js/converse-desktop/desktop-plugin')
|
||||
|
||||
angApp.factory('DesktopService', (
|
||||
$window, $timeout, CredentialsService, SystemService, AppStateService,
|
||||
SettingsService, XmppHelperService
|
||||
) => {
|
||||
|
||||
let desktopService = {}
|
||||
|
||||
desktopService._notifyMessage = () => {
|
||||
SystemService.playAudio()
|
||||
SystemService.showEnvelope()
|
||||
}
|
||||
|
||||
desktopService._hideNotifyMessage = () => {
|
||||
SystemService.hideEnvelope()
|
||||
}
|
||||
|
||||
desktopService.logout = () => {
|
||||
let credentials = CredentialsService.getCredentials()
|
||||
credentials.then((result) => {
|
||||
let remove = CredentialsService.removeCredentials(result.login)
|
||||
console.log('Remove credentials on logout')
|
||||
remove.then(() => {
|
||||
AppStateService.set(AppStateService.APP_STATE_LOGIN)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
desktopService.initConverse = (connectionManager, login, password) => {
|
||||
AppStateService.set(AppStateService.APP_STATE_DEFAULT) // Always set to default state before init
|
||||
desktopPlugin.register(login)
|
||||
let lang = navigator.language
|
||||
let allowBookmarks = SettingsService.get('allowBookmarks')
|
||||
let omemoDefault = SettingsService.get('omemoDefault')
|
||||
let xmppResource = XmppHelperService.getResourceFromJid(login)
|
||||
if (!xmppResource) {
|
||||
xmppResource = '.' + (Math.random().toString(36)+'00000000000000000').slice(2, 7) // Generate 5 char unique str
|
||||
login = login + '/converseDesktop'+xmppResource
|
||||
}
|
||||
let conversejsParams = {
|
||||
assets_path: './node_modules/converse.js/dist/',
|
||||
allow_bookmarks: allowBookmarks,
|
||||
auto_login: true,
|
||||
auto_reconnect: true,
|
||||
// debug: true,
|
||||
i18n: lang,
|
||||
jid: login,
|
||||
omemo_default: omemoDefault,
|
||||
password: password,
|
||||
play_sounds: false,
|
||||
priority: 50,
|
||||
view_mode: 'embedded',
|
||||
whitelisted_plugins: ['converseDesktop'],
|
||||
}
|
||||
if (connectionManager.startsWith('ws')) {
|
||||
conversejsParams.websocket_url = connectionManager
|
||||
} else {
|
||||
conversejsParams.bosh_service_url = connectionManager
|
||||
}
|
||||
$timeout(() => {
|
||||
converse.initialize(conversejsParams)
|
||||
}, 50)
|
||||
}
|
||||
|
||||
desktopService.getCredentialsAndLogin = () => {
|
||||
let credentials = CredentialsService.getCredentials()
|
||||
credentials.then((result) => {
|
||||
desktopService.initConverse(result.connectionManager, result.login, result.password)
|
||||
}, (error) => {
|
||||
AppStateService.set(AppStateService.APP_STATE_LOGIN)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
desktopService.chatToOpen = null
|
||||
|
||||
$window.document.addEventListener('conversejs-logout', function (e) {
|
||||
desktopService.logout()
|
||||
})
|
||||
|
||||
$window.document.addEventListener('conversejs-unread', function (e) {
|
||||
let sender = e.detail
|
||||
desktopService.chatToOpen = sender
|
||||
desktopService._notifyMessage()
|
||||
})
|
||||
|
||||
$window.document.addEventListener('conversejs-no-unread', function (e) {
|
||||
desktopService._hideNotifyMessage()
|
||||
})
|
||||
|
||||
return desktopService
|
||||
|
||||
})
|
@ -1,109 +0,0 @@
|
||||
let angApp = require(__dirname+'/../init')
|
||||
|
||||
angApp.factory('SettingsService', () => {
|
||||
|
||||
let settingsService = {}
|
||||
|
||||
const electronSettings = require('electron-settings')
|
||||
|
||||
const settings = {
|
||||
converseDesktop: {
|
||||
runMinimized: {
|
||||
default: false,
|
||||
title: 'Run minimized',
|
||||
hint: 'Default: false. Whether run Converse Desktop minimized to tray or not.'
|
||||
},
|
||||
minimizeOnClose: {
|
||||
default: false,
|
||||
title: 'Minimize on close',
|
||||
hint: 'Default: false. Minimize or close Converse Desktop window.'
|
||||
},
|
||||
preserveWindowSize: {
|
||||
default: true,
|
||||
title: 'Preserve window size',
|
||||
hint: 'Default: true, 800x600 otherwise.'
|
||||
},
|
||||
preserveWindowPosition: {
|
||||
default: true,
|
||||
title: 'Preserve window position',
|
||||
hint: 'Default: true, screen center otherwise.'
|
||||
}
|
||||
},
|
||||
conversejs: {
|
||||
allowBookmarks: {
|
||||
default: false,
|
||||
title: 'Allow server bookmarks',
|
||||
hint: 'Default: false. Enables/disables chatroom bookmarks functionality.'
|
||||
},
|
||||
omemoDefault: {
|
||||
default: false,
|
||||
title: 'Use OMEMO encryption by default',
|
||||
hint: 'Default: false. Use OMEMO encryption by default when the chat supports it.'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const iterateSettings = (callback, settingsObj) => {
|
||||
if(typeof settingsObj === "undefined") {
|
||||
settingsObj = settings
|
||||
}
|
||||
angular.forEach(settingsObj, (value, key) => {
|
||||
let settingsList = settingsObj[key]
|
||||
angular.forEach(settingsList, (value, key) => {
|
||||
let itemDefault = settingsList[key]['default']
|
||||
callback(key, itemDefault, settingsList)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Callback
|
||||
// TODO: replace with promise?
|
||||
const saveDefault = (key, value) => {
|
||||
if (!electronSettings.hasSync(key)) {
|
||||
electronSettings.setSync(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// Callback
|
||||
const save = (key, defaultValue, settingsList) => {
|
||||
let value = settingsList[key]['value']
|
||||
electronSettings.setSync(key, value)
|
||||
}
|
||||
|
||||
// Callback
|
||||
const loadAll = (key, defaultValue, settingsList) => {
|
||||
if (!electronSettings.hasSync(key)) {
|
||||
settingsList[key]['value'] = defaultValue
|
||||
}
|
||||
settingsList[key]['value'] = electronSettings.getSync(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* SettingsService
|
||||
*/
|
||||
settingsService.initDefaults = () => {
|
||||
iterateSettings(saveDefault)
|
||||
// Logout for versions with BOSH only
|
||||
if (electronSettings.hasSync('bosh')) {
|
||||
electronSettings.unsetSync('bosh')
|
||||
electronSettings.unsetSync('login')
|
||||
}
|
||||
}
|
||||
|
||||
settingsService.get = (key) => {
|
||||
return electronSettings.getSync(key)
|
||||
}
|
||||
|
||||
settingsService.loadAll = () => {
|
||||
let currentSettings = angular.copy(settings)
|
||||
iterateSettings(loadAll, currentSettings)
|
||||
return currentSettings
|
||||
}
|
||||
|
||||
settingsService.saveAll = (currentSettings) => {
|
||||
iterateSettings(save, currentSettings)
|
||||
}
|
||||
|
||||
return settingsService
|
||||
})
|
||||
|
@ -1,28 +0,0 @@
|
||||
let angApp = require(__dirname + '/../init')
|
||||
|
||||
angApp.factory('SystemService', () => {
|
||||
|
||||
const remote = require('electron').remote
|
||||
|
||||
let systemService = {}
|
||||
|
||||
systemService.playAudio = () => {
|
||||
var audio = new Audio(__dirname + '/../../resources/sounds/graceful.ogg')
|
||||
audio.play()
|
||||
}
|
||||
|
||||
systemService.showEnvelope = () => {
|
||||
remote.require('./main').trayService.showEnvelope()
|
||||
}
|
||||
|
||||
systemService.hideEnvelope = () => {
|
||||
remote.require('./main').trayService.hideEnvelope()
|
||||
}
|
||||
|
||||
systemService.reloadWindow = () => {
|
||||
remote.getCurrentWindow().reload()
|
||||
}
|
||||
|
||||
return systemService
|
||||
|
||||
})
|
@ -1,25 +0,0 @@
|
||||
let angApp = require(__dirname + '/../init')
|
||||
|
||||
angApp.factory('XmppHelperService', [() => {
|
||||
|
||||
let xmppHelperService = {}
|
||||
|
||||
/**
|
||||
* Use function copy from Strophe js lib because converse.js Strophe library
|
||||
* is under private _api and unavailable before converse.js is initialized.
|
||||
* This function is used _before_ converse.js is initialized.
|
||||
*
|
||||
* Get the resource portion of a JID String.
|
||||
* @param {string} jid A JID.
|
||||
* @return {string | null} A String containing the resource.
|
||||
*/
|
||||
xmppHelperService.getResourceFromJid = (jid) => {
|
||||
if (!jid) { return null }
|
||||
const s = jid.split("/")
|
||||
if (s.length < 2) { return null }
|
||||
s.splice(0, 1)
|
||||
return s.join('/')
|
||||
}
|
||||
|
||||
return xmppHelperService
|
||||
}])
|
@ -1,35 +0,0 @@
|
||||
<div class="page-about" ng-controller="AboutController">
|
||||
<div class="about-card">
|
||||
<div class="about-card__content">
|
||||
<div class="about-card__logo">
|
||||
<img src="./resources/images/logo.png" srcset="./resources/images/logo@2x.png 2x" alt=""
|
||||
class="chimeverse-branding__img" />
|
||||
</div>
|
||||
<div class="about-card__description">
|
||||
<h3 class="about__title">About {{appInfo.APP_NAME}} {{appInfo.APP_VERSION}}</h3>
|
||||
<div class="about__description">Jabber/XMPP client based on Converse.js and Electron</div>
|
||||
<div> </div>
|
||||
<div class="about__converse-version">
|
||||
Version of <a href="https://conversejs.org/" target="_blank">converse.js</a> is {{appInfo.CONVERSE_VERSION}}
|
||||
</div>
|
||||
<div class="about__electron-version">
|
||||
Version of <a href="https://www.electronjs.org/" target="_blank">electron</a> is {{appInfo.ELECTRON_VERSION}}
|
||||
</div>
|
||||
<div> </div>
|
||||
<div class="about__thanks">
|
||||
Thanks to
|
||||
<a href="https://github.com/nick-denry/Chimeverse/graphs/contributors" target="_blank">all contributors</a>
|
||||
</div>
|
||||
<div> </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="about__action">
|
||||
<button class="about__close-button" ng-click="closeAbout()">OK</button>
|
||||
</div>
|
||||
<div> </div>
|
||||
<div class="about__copyright">Copyright © 2019-2020 Nick Denry</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-include src="'./app/views/shared/_footer.html'"></ng-include>
|
@ -1,24 +0,0 @@
|
||||
<div class="page-default" ng-controller="DefaultController">
|
||||
<div class="chimeverse-branding noselect">
|
||||
<img src="./resources/images/logo.png" srcset="./resources/images/logo@2x.png 2x" alt=""
|
||||
class="chimeverse-branding__img" />
|
||||
<h3 class="chimeverse-branding__header">{{appInfo.APP_NAME}}</h3>
|
||||
<div class="chimeverse-branding__version">
|
||||
<span>{{appInfo.APP_VERSION}} </span>
|
||||
<span class="chimeverse-branding__update">
|
||||
<span class="update__checking" ng-show="checkingForUpdate == 'inProgress'">checking for update...</span>
|
||||
<span class="update__error" ng-show="checkingForUpdate == 'checkErr'">
|
||||
>_< check for update failed <a href="#" ng-click="checkRetry($event)">retry</a>
|
||||
</span>
|
||||
<span class="update__latest" ng-show="checkingForUpdate == 'latest'">latest version</span>
|
||||
<a class="update__available" href="{{appInfo.APP_RELEASES_URL}}" target="_blank"
|
||||
ng-show="checkingForUpdate == 'updateAvailable'">
|
||||
Update available
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conversejs-adoption">
|
||||
<div id="conversejs"></div>
|
||||
</div>
|
||||
</div>
|
@ -1,43 +0,0 @@
|
||||
<div class="login-form">
|
||||
<h3 class="login-form__title">Welcome to Converse Desktop</h3>
|
||||
<div class="login-form__description">Jabber/XMPP client based on Converse.js and Electron</div>
|
||||
<div class="login-form__card">
|
||||
<form name="accountForm" ng-controller="LoginController">
|
||||
<div class="login-form__wrapper">
|
||||
<div class="login-form__input-group">
|
||||
<span class="group-prepend oi" data-glyph="link-intact"></span>
|
||||
<input ng-model="credentials.connectionManager" class="login-form__input login-form__input--with-append" type="text" placeholder="Connection manager url" required>
|
||||
<span class="group-append--backgrounded oi" data-glyph="info" ng-click="showHelp('connectionManager')"></span>
|
||||
</div>
|
||||
<div class="login-form__input-help" ng-show="help.connectionManager == true"">
|
||||
<div>
|
||||
Should be a
|
||||
<a href="https://m.conversejs.org/docs/html/setup.html#bosh-section" target="_blank">BOSH service</a>
|
||||
or a
|
||||
<a href="https://m.conversejs.org/docs/html/setup.html#websocket-section" target="_blank">Websocket</a>
|
||||
URL
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-form__wrapper">
|
||||
<div class="login-form__input-group">
|
||||
<span class="group-prepend oi" data-glyph="person"></span>
|
||||
<input ng-model="credentials.login" class="login-form__input" type="text" placeholder="jid@jabber.org" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-form__wrapper">
|
||||
<div class="login-form__input-group">
|
||||
<span class="group-prepend oi" data-glyph="lock-locked"></span>
|
||||
<input ng-model="credentials.password" class="login-form__input" type="password" placeholder="Password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-form__wrapper">
|
||||
<button class="login-form__button" ng-click="addAccountAndLoginAction()" ng-disabled="accountForm.$invalid" disabled>Add account</button>
|
||||
</div>
|
||||
<div class="login-form__credentials-message">
|
||||
Credentials stored via <a href="https://atom.github.io/node-keytar/" target="_blank">Keychain</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<ng-include src="'./app/views/shared/_footer.html'"></ng-include>
|
@ -1,28 +0,0 @@
|
||||
<div class="settings-page" ng-controller="SettingsController">
|
||||
<form name="settignsForm">
|
||||
<h3 class="settings-page__title">Chimeverse settings</h3>
|
||||
<div class="form-item" ng-repeat="(key, item) in settings.converseDesktop">
|
||||
<label>
|
||||
<input type="checkbox" name="{{key}}" ng-model="item.value" /> {{item.title}}
|
||||
</label>
|
||||
<div class="form-item__hint">{{item.hint}}</div>
|
||||
</div>
|
||||
<h3 class="settings-page__title">Converse.js settings</h3>
|
||||
<div class="form-item" ng-repeat="(key, item) in settings.conversejs">
|
||||
<label>
|
||||
<input type="checkbox" name="{{key}}" ng-model="item.value" /> {{item.title}}
|
||||
</label>
|
||||
<div class="form-item__hint">{{item.hint}}</div>
|
||||
</div>
|
||||
<div class="form-item" ng-show="settingsSaved">
|
||||
<a href="#" ng-click="restartApp()" class="form-item__restart-app">
|
||||
Click here to restart the app and apply your changes
|
||||
</a>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="form-item__save-button" ng-class="{'active': settingsChanged == true}" ng-click="saveSettings()">Save</button>
|
||||
<button class="form-item__cancel-button" ng-click="closeSettings()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<ng-include src="'./app/views/shared/_footer.html'"></ng-include>
|
@ -1,4 +0,0 @@
|
||||
<div class="page__footer" ng-controller="FooterController">
|
||||
<span class="footer__version">{{appInfo.APP_NAME}} {{appInfo.APP_VERSION}}.</span>
|
||||
<a class="github-button" href="{{appInfo.APP_HOME}}" data-icon="octicon-star" aria-label="Star nick-denry/Chimeverse on GitHub">Star</a>
|
||||
</div>
|
@ -1,67 +0,0 @@
|
||||
let desktopPlugin = {}
|
||||
|
||||
desktopPlugin.register = (login) => {
|
||||
converse.plugins.add('converseDesktop', {
|
||||
initialize: (event) => {
|
||||
let _converse = event.properties._converse
|
||||
let Strophe = converse.env.Strophe
|
||||
|
||||
/**
|
||||
* Check if message stanza has some body payload
|
||||
* @param {*} stanzaNodes
|
||||
*/
|
||||
let isBodyMessage = (stanzaNodes) => {
|
||||
let result = false
|
||||
Object.keys(stanzaNodes).some((key) => {
|
||||
if (stanzaNodes[key].nodeName == 'body') {
|
||||
result = true
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
_converse.api.waitUntil('rosterContactsFetched'),
|
||||
_converse.api.waitUntil('chatBoxesFetched')
|
||||
]).then(() => {
|
||||
_converse.api.listen.on('logout', () => {
|
||||
let event = new CustomEvent('conversejs-logout')
|
||||
document.dispatchEvent(event)
|
||||
})
|
||||
_converse.api.listen.on('message', (data) => {
|
||||
// Display notifications only for "payloaded" messages
|
||||
if (isBodyMessage(data.stanza.childNodes)) {
|
||||
let sender = data.stanza.attributes.from.nodeValue
|
||||
let senderJid = Strophe.getBareJidFromJid(sender)
|
||||
let loginJid = Strophe.getBareJidFromJid(login)
|
||||
if (senderJid != loginJid) {
|
||||
console.log(senderJid)
|
||||
let event = new CustomEvent('conversejs-unread', {detail: senderJid})
|
||||
document.dispatchEvent(event)
|
||||
}
|
||||
}
|
||||
})
|
||||
_converse.api.listen.on('chatBoxFocused', () => {
|
||||
let event = new CustomEvent('conversejs-no-unread')
|
||||
document.dispatchEvent(event)
|
||||
//chimeverseService._hideNotifyMessage()
|
||||
})
|
||||
window.document.addEventListener('converse-force-logout', function (e) {
|
||||
console.log('Get converse-force-logout event')
|
||||
console.log('Logout form plugin')
|
||||
_converse.api.user.logout()
|
||||
//chimeverseService.logout()
|
||||
})
|
||||
window.document.addEventListener('conversejs-open-chat', function (e) {
|
||||
let chatToOpen = e.detail
|
||||
console.log('Get open-unread-chat event: '+chatToOpen)
|
||||
if (chatToOpen !== null) {
|
||||
_converse.api.chats.open(chatToOpen)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = desktopPlugin
|
@ -1,64 +0,0 @@
|
||||
// This file is required by the index.html file and will
|
||||
// be executed in the renderer process for that window.
|
||||
// All of the Node.js APIs are available in this process.
|
||||
|
||||
var angApp = require('./app/init')
|
||||
|
||||
require('./app/services/credentials-service')
|
||||
require('./app/services/settings-service')
|
||||
require('./app/services/system-service')
|
||||
require('./app/services/app-state-service')
|
||||
require('./app/services/xmpp-helper-service')
|
||||
require('./app/services/desktop-service')
|
||||
require('./app/controllers/settings-controller')
|
||||
require('./app/controllers/login-controller')
|
||||
require('./app/controllers/default-controller')
|
||||
require('./app/controllers/about-controller')
|
||||
require('./app/controllers/footer-controller')
|
||||
|
||||
angApp.controller('AppController', function ($scope, $timeout, DesktopService, SettingsService, AppStateService) {
|
||||
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
// Menu force logout event
|
||||
ipcRenderer.on('force-logout-event', () => {
|
||||
DesktopService.logout()
|
||||
let event = new CustomEvent("converse-force-logout") // Dispatch to the plugin
|
||||
document.dispatchEvent(event)
|
||||
})
|
||||
|
||||
// Menu settings event
|
||||
ipcRenderer.on('preferences-event', () => {
|
||||
AppStateService.set(AppStateService.APP_STATE_SETTINGS)
|
||||
})
|
||||
|
||||
// Menu about event
|
||||
ipcRenderer.on('about-page-event', () => {
|
||||
AppStateService.set(AppStateService.APP_STATE_ABOUT)
|
||||
})
|
||||
|
||||
// Menu about event
|
||||
ipcRenderer.on('open-unread-chat', () => {
|
||||
let event = new CustomEvent('conversejs-open-chat', {detail: DesktopService.chatToOpen})
|
||||
document.dispatchEvent(event)
|
||||
})
|
||||
|
||||
AppStateService.set(AppStateService.APP_STATE_DEFAULT)
|
||||
|
||||
$scope.$on('app:state:changed', (event, data) => {
|
||||
// @see https://docs.angularjs.org/error/$rootScope/inprog
|
||||
$timeout(() => {
|
||||
$scope.state = data
|
||||
console.log('Switch to the "' + $scope.state +'" state')
|
||||
}, 0)
|
||||
})
|
||||
|
||||
$scope.$on('app:restart', (event, data) => {
|
||||
ipcRenderer.send('app-restart')
|
||||
})
|
||||
|
||||
SettingsService.initDefaults()
|
||||
|
||||
DesktopService.getCredentialsAndLogin()
|
||||
|
||||
})
|
@ -1,39 +0,0 @@
|
||||
.page-about {
|
||||
color: #777;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
top: 47%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.about-card {
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 30px;
|
||||
min-width: 400px;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.about-card__content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.about__action {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.about__close-button {
|
||||
border: 0px solid #ddd;
|
||||
background: rgb(5,93,228);
|
||||
background: linear-gradient(0deg, rgba(5,93,228,1) 0%, rgba(76,145,255,1) 100%);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 18px;
|
||||
outline: none;
|
||||
padding: 10px 30px;
|
||||
}
|
||||
|
||||
.about__copyright {
|
||||
text-align: center;
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
.login-form {
|
||||
color: #777;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
top: 47%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.login-form__title {
|
||||
font-size: 28px;
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
margin: 0px 0px 15px 0px;
|
||||
}
|
||||
|
||||
.login-form__description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-form__card {
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 30px;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.login-form__wrapper {
|
||||
margin-bottom: 15px;;
|
||||
}
|
||||
|
||||
.login-form__input-group {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 0px;
|
||||
padding: 0px 0px 0px 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login-form__input-group:active,
|
||||
.login-form__input-group:focus,
|
||||
.login-form__input-group:hover {
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
|
||||
.login-form__input-group .group-prepend {
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 12px;
|
||||
}
|
||||
|
||||
.login-form__input-group .group-append--backgrounded {
|
||||
background: #f2f2f2;
|
||||
cursor: pointer;
|
||||
padding: 12px;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0 px;
|
||||
}
|
||||
|
||||
.login-form__input {
|
||||
border: 0px;
|
||||
color: #222;
|
||||
font-size: 18px;
|
||||
outline: none;
|
||||
padding: 10px;
|
||||
width: 290px;
|
||||
}
|
||||
|
||||
.login-form__input::placeholder { /* Most modern browsers support this now. */
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.login-form__input--with-append {
|
||||
width: 260px;
|
||||
}
|
||||
|
||||
.login-form__input-help {
|
||||
font-size: 13px;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.login-form__button {
|
||||
border: 1px solid #ddd;
|
||||
background: rgb(5,93,228);
|
||||
background: linear-gradient(0deg, rgba(5,93,228,1) 0%, rgba(76,145,255,1) 100%);
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||