Use own state service

This commit is contained in:
Nick Denry 2020-05-09 18:07:42 +03:00
parent d15db0b97b
commit 2fb70a00bb
28 changed files with 370 additions and 273 deletions

View File

@ -0,0 +1,7 @@
let angApp = require(__dirname+'/../init')
angApp.controller('DefaultController', function($scope, ChimeVerseService) {
console.log('always-test')
});

View File

@ -0,0 +1,11 @@
let angApp = require(__dirname+'/../init')
angApp.controller('LoginController', function($scope, ChimeVerseService, SettingsServise) {
$scope.addAccountAndLoginAction = () => {
SettingsServise.addCredentials($scope.bosh,
$scope.login,
$scope.password
)
ChimeVerseService.initConverse($scope.bosh, $scope.login, $scope.password)
}
});

View File

@ -0,0 +1,6 @@
let angApp = require(__dirname+'/../init')
angApp.controller('SettingsController', function ($scope, ChimeVerseService) {
})

4
app/init.js Normal file
View File

@ -0,0 +1,4 @@
const angular = require('angular')
let angApp = angular.module('app', [])
module.exports = angApp

View File

@ -0,0 +1,19 @@
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.set = (state) => {
stateService.state = state
$rootScope.$broadcast('app:state:changed', stateService.state);
}
stateService.set(stateService.APP_STATE_DEFAULT)
return stateService
}])

View File

@ -0,0 +1,60 @@
let angApp = require(__dirname + '/../init')
angApp.factory('ChimeVerseService', ($window, SettingsServise, SystemService, AppStateService) => {
let chimeverseService = {}
chimeverseService._notifyMessage = () => {
SystemService.playAudio()
SystemService.showEnvelope()
}
chimeverseService._hideNotifyMessage = () => {
SystemService.hideEnvelope()
}
chimeverseService.logout = () => {
let credentials = SettingsServise.getCredentials()
credentials.then((result) => {
let remove = SettingsServise.removeCredentials(result.login)
console.log('Remove credential on logout')
remove.then(() => {
console.log('Switch to the login state')
AppStateService.set(AppStateService.APP_STATE_LOGIN)
})
})
}
chimeverseService.initConverse = (bosh, login, password) => {
AppStateService.set(AppStateService.APP_STATE_DEFAULT) // Always set to default state before init
let lang = navigator.language
converse.initialize({
allow_bookmarks: false,
bosh_service_url: bosh,
view_mode: 'embedded',
jid: login + '/chimeverse',
password: password,
auto_login: true,
whitelisted_plugins: ['chimeVerse'],
i18n: lang,
priority: 50,
// debug: true,
auto_reconnect: true
})
}
$window.document.addEventListener('conversejs-logout', function (e) {
chimeverseService.logout()
});
$window.document.addEventListener('conversejs-unread', function (e) {
chimeverseService._notifyMessage()
});
$window.document.addEventListener('conversejs-no-unread', function (e) {
chimeverseService._hideNotifyMessage()
});
return chimeverseService
})

View File

@ -0,0 +1,54 @@
let angApp = require(__dirname+'/../init')
angApp.factory('SettingsServise', () => {
const keytar = require('keytar')
const settings = require('electron-settings')
let settingsService = {}
settingsService.getCredentials = () => {
let credentials = {}
credentials.login = settings.get('login')
let promise = new Promise((resolve, reject) => {
if (credentials.login) {
credentials.bosh = settings.get('bosh')
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
}
settingsService.addCredentials = (bosh, login, password) => {
let xmppService = login.split('@').pop()
settings.set('bosh', bosh)
settings.set('login', login)
keytar.setPassword(xmppService, login, password)
}
settingsService.removeCredentials = (login) => {
let xmppService = login.split('@').pop()
passwordDelete = keytar.deletePassword(xmppService, login)
let promise = new Promise((resolve, reject) => {
passwordDelete.then((result) => {
settings.delete('login')
settings.delete('bosh')
resolve()
}, (error) => {
reject(error)
})
})
return promise
}
return settingsService
})

View File

@ -0,0 +1,28 @@
let angApp = require(__dirname + '/../init')
angApp.factory('SystemService', () => {
const remote = require('electron').remote
let systemService = {}
systemService.playAudio = () => {
var audio = new Audio(__dirname + '/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
})

View File

@ -0,0 +1,10 @@
<div class="page-default">
<div class="chimeverse-branding">
<img src="./resources/images/logo.png" srcset="./resources/images/logo@2x.png 2x" alt="" />
<h3 class="uk-heading-small uk-text-muted uk-margin-remove">Chimeverse</h3>
<div class="uk-text-small uk-text-muted">v0.1.52</div>
</div>
<div class="conversejs-adoption">
<div id="conversejs"></div>
</div>
</div>

View File

@ -1,11 +0,0 @@
.ng-cloak {
display: none !important;
}
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
user-select: none; /* Non-prefixed version, currently
supported by Chrome and Opera */
}

View File

@ -1,84 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Chimeverse</title>
<link rel="stylesheet" type="text/css" media="screen" href="node_modules/converse.js/css/converse.css">
<link rel="stylesheet" type="text/css" href="node_modules/uikit/dist/css/uikit.min.css">
<link rel="stylesheet" type="text/css" href="css/app.css">
</head>
<body ng-app="app">
<div class="main-window" ng-controller="AppController">
<!-- Account form -->
<div ng-show="showLoginForm" class="uk-section uk-section-muted uk-flex uk-flex-middle uk-animation-fade ng-cloak" uk-height-viewport>
<div class="uk-width-1-1">
<div class="uk-container">
<h3 class="uk-card-title uk-text-center">Welcome to Chimeverse</h3>
<div class="uk-text-center">Jabber/XMPP client based on Converse.js and Electron</div>
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid>
<div class="uk-width-1-1@m">
<div class="uk-margin uk-width-large uk-margin-auto uk-card uk-card-default uk-card-body uk-box-shadow-large">
<form name="accountForm">
<div class="uk-margin">
<div class="uk-inline uk-width-1-1">
<span class="uk-form-icon" uk-icon="icon: link"></span>
<input ng-model="bosh" class="uk-input uk-form-large" type="text" placeholder="Bosh service url" required>
</div>
</div>
<div class="uk-margin">
<div class="uk-inline uk-width-1-1">
<span class="uk-form-icon" uk-icon="icon: user"></span>
<input ng-model="login" class="uk-input uk-form-large" type="text" placeholder="jid@jabber.org" required>
</div>
</div>
<div class="uk-margin">
<div class="uk-inline uk-width-1-1">
<span class="uk-form-icon" uk-icon="icon: lock"></span>
<input ng-model="password" class="uk-input uk-form-large" type="password" placeholder="Password" required>
</div>
</div>
<div class="uk-margin">
<button class="uk-button uk-button-primary uk-button-large uk-width-1-1" ng-click="addAccountAction()" ng-disabled="accountForm.$invalid" disabled>Add account</button>
</div>
<div class="uk-text-small uk-text-center">
Credentials stored via Keychain
</div>
</form>
</div>
</div>
<head>
<meta charset="UTF-8">
<title>Chimeverse</title>
<link rel="stylesheet" type="text/css" media="screen" href="node_modules/converse.js/dist/converse.min.css">
<link rel="stylesheet" type="text/css" href="resources/css/app.css">
<link rel="stylesheet" type="text/css" href="resources/css/page-default.css">
</head>
<base href="./">
<body ng-app="app">
<div class="main-background"></div>
<div class="main-window" ng-controller="AppController" ng-cloak>
<div ng-show="state == 'default'">
<ng-include src="'./app/views/default/page.html'" onload="getCredentialsAndLogin()"></ng-include>
</div>
<div ng-show="state == 'login'" ng-controller="LoginController">
<form name="accountForm">
<div class="uk-margin">
<div class="uk-inline uk-width-1-1">
<span class="uk-form-icon" uk-icon="icon: link"></span>
<input ng-model="bosh" class="uk-input uk-form-large" type="text" placeholder="Bosh service url" required>
</div>
</div>
</div>
</div>
<!-- /Account form -->
<!-- Background and settings -->
<div ng-show="!showLoginForm" class="uk-position-center ng-cloak noselect">
<div class="uk-text-center">
<img src="images/logo.png" srcset="images/logo@2x.png 2x" alt="" />
<h3 class="uk-heading-small uk-text-muted uk-margin-remove">Chimeverse</h3>
<div class="uk-text-small uk-text-muted">v0.0.16</div>
<div class="uk-margin">
<div class="uk-inline uk-width-1-1">
<span class="uk-form-icon" uk-icon="icon: user"></span>
<input ng-model="login" class="uk-input uk-form-large" type="text" placeholder="jid@jabber.org" required>
</div>
</div>
<div class="uk-margin">
<div class="uk-inline uk-width-1-1">
<span class="uk-form-icon" uk-icon="icon: lock"></span>
<input ng-model="password" class="uk-input uk-form-large" type="password" placeholder="Password" required>
</div>
</div>
<div class="uk-margin">
<button class="uk-button uk-button-primary uk-button-large uk-width-1-1" ng-click="addAccountAndLoginAction()" ng-disabled="accountForm.$invalid" disabled>Add account</button>
</div>
<div class="uk-text-small uk-text-center">
Credentials stored via Keychain
</div>
</form>
</div>
<div ng-show="state == 'settings'">
settings
</div>
</div>
<script src="node_modules/uikit/dist/js/uikit.min.js"></script>
<script src="node_modules/uikit/dist/js/uikit-icons.min.js"></script>
<!--
<!--
@see comment https://github.com/signalapp/libsignal-protocol-javascript/issues/6#issuecomment-247208665
-->
<script>
window.nodeRequire = require
delete window.require
</script>
<script src="node_modules/converse.js/3rdparty/libsignal-protocol.js"></script>
<script>
window.require = window.nodeRequire
delete window.nodeRequire
</script>
<script>
// You can also require other files to run in this process
require('converse.js')
require('./renderer.js')
</script>
</body>
</html>
<script>
window.nodeRequire = require
delete window.require
</script>
<!-- Place libsignal at libs dir as it's no more distributed with converse.js -->
<script src="libs/converse.js/3rdparty/libsignal-protocol.js"></script>
<script>
window.require = window.nodeRequire
delete window.nodeRequire
</script>
<script>
// You can also require other files to run in this process
require('./node_modules/converse.js/dist/locales/' + navigator.language + '-LC_MESSAGES-converse-po.js')
require('./node_modules/converse.js/dist/locales/dayjs/' + navigator.language + '.js')
require('./node_modules/converse.js/dist/emojis.js')
require('./node_modules/converse.js/dist/converse.js')
require('./renderer.js')
</script>
</body>
</html>

View File

@ -0,0 +1,36 @@
let chimeversePlugin = {}
chimeversePlugin.register = () => {
converse.plugins.add('chimeVerse', {
initialize: (event) => {
let _converse = event.properties._converse
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) => {
let event = new CustomEvent("conversejs-unread")
document.dispatchEvent(event)
//chimeverseService._notifyMessage(data)
})
_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()
});
})
}
})
}
module.exports = chimeversePlugin

View File

@ -33,7 +33,7 @@ function createWindow () {
menuService.createMenu()
// Open the DevTools.
// mainWindow.webContents.openDevTools()
mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {

View File

@ -11,7 +11,7 @@ let trayService = {}
trayService.initTray = (window) => {
trayServiceWindow = window
let iconPath = __dirname + '/../images/icon.png'
let iconPath = __dirname + '/../resources/images/icon.png'
tray = new Tray(iconPath)
tray.setToolTip('Chimeverse')
@ -22,11 +22,11 @@ trayService.initTray = (window) => {
}
trayService.showEnvelope = () => {
tray.setImage(__dirname + '/../images/envelope.png')
tray.setImage(__dirname + '/../resources/images/envelope.png')
}
trayService.hideEnvelope = () => {
tray.setImage(__dirname + '/../images/icon.png')
tray.setImage(__dirname + '/../resources/images/icon.png')
}
module.exports = trayService

10
package-lock.json generated
View File

@ -66,11 +66,6 @@
"resolved": "https://registry.npmjs.org/angular/-/angular-1.7.9.tgz",
"integrity": "sha512-5se7ZpcOtu0MBFlzGv5dsM1quQDoDeUTwZrWjGtTNA7O88cD8TEk5IEKCTDa3uECV9XnvKREVUr7du1ACiWGFQ=="
},
"angular-route": {
"version": "1.7.9",
"resolved": "https://registry.npmjs.org/angular-route/-/angular-route-1.7.9.tgz",
"integrity": "sha512-vRoj5hzdQtWbODhWJqDzD1iNOEfCKshO6GFBuPVV7RHlPjzIc4R2dHCc7Qiv/8F3LDxJDohc6vSnTDMLHuaqeA=="
},
"ansi-align": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
@ -3453,11 +3448,6 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
"uikit": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/uikit/-/uikit-3.4.2.tgz",
"integrity": "sha512-z5NH1s8sTMHjVQ+Exr2IKgPn/bG9f5PSK4HcTZaBlw3mF6f5UgefWIA3xKVsOtOeJSOQ2T8lk++59syRF5NwOw=="
},
"unique-string": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",

View File

@ -26,11 +26,9 @@
},
"dependencies": {
"angular": "^1.7.9",
"angular-route": "^1.7.9",
"converse.js": "^6.0.0",
"electron-settings": "^3.2.0",
"keytar": "^4.13.0",
"n": "^6.5.1",
"uikit": "^3.4.2"
"n": "^6.5.1"
}
}

View File

@ -2,191 +2,46 @@
// be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process.
const angular = require('angular')
var angApp = require('./app/init')
var angApp = angular.module('app', [])
require('./app/services/settings-service')
require('./app/services/system-service')
require('./app/services/app-state-service')
require('./app/services/chimeverse-service')
require('./app/controllers/settings-controller')
require('./app/controllers/login-controller')
require('./app/controllers/default-controller')
const chimeversePlugin = require('./libs/converse.js/3rdparty/chimeverse-plugin')
chimeversePlugin.register()
angApp.controller('AppController', function ($scope, $timeout, ChimeVerseService, SettingsServise, AppStateService) {
angApp.factory('SettingsServise', () => {
const keytar = require('keytar')
const settings = require('electron-settings')
let settingsService = {}
settingsService.getCredentials = () => {
let credentials = {}
credentials.login = settings.get('login')
let promise = new Promise((resolve, reject) => {
if (credentials.login) {
credentials.bosh = settings.get('bosh')
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
}
settingsService.addCredentials = (bosh, login, password) => {
let xmppService = login.split('@').pop()
settings.set('bosh', bosh)
settings.set('login', login)
keytar.setPassword(xmppService, login, password)
}
settingsService.removeCredentials = (login) => {
let xmppService = login.split('@').pop()
passwordDelete = keytar.deletePassword(xmppService, login)
let promise = new Promise((resolve, reject) => {
passwordDelete.then((result) => {
settings.delete('login')
settings.delete('bosh')
resolve()
}, (error) => {
reject(error)
})
})
return promise
}
return settingsService
})
angApp.factory('SystemService', () => {
const remote = require('electron').remote
let systemService = {}
systemService.playAudio = () => {
var audio = new Audio(__dirname + '/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
})
angApp.factory('ChimeVerseService', (SettingsServise, SystemService) => {
let chimeverseService = {}
chimeverseService.settings = SettingsServise
chimeverseService.system = SystemService
chimeverseService._notifyMessage = (data) => {
if (data.message.attributes.sender === 'me') {
chimeverseService.system.hideEnvelope()
return ;
}
if (data.message.attributes.chat_state === 'active') {
chimeverseService.system.playAudio()
chimeverseService.system.showEnvelope()
}
}
chimeverseService.logout = () => {
let credentials = SettingsServise.getCredentials()
credentials.then((result) => {
let remove = chimeverseService.settings.removeCredentials(result.login)
remove.then(() => {
chimeverseService.system.reloadWindow()
})
})
}
chimeverseService.addChimeVersePluign = () => {
converse.plugins.add('chimeVerse', {
initialize: (event) => {
var _converse = event.properties._converse
Promise.all([
_converse.api.waitUntil('rosterContactsFetched'),
_converse.api.waitUntil('chatBoxesFetched')
]).then(() => {
_converse.api.listen.on('logout', () => {
chimeverseService.logout()
})
_converse.api.listen.on('messageAdded', (data) => {
chimeverseService._notifyMessage(data)
})
_converse.api.listen.on('chatBoxFocused', () => {
chimeverseService.system.hideEnvelope()
})
})
}
})
}
chimeverseService.initConverse = (bosh, login, password) => {
chimeverseService.addChimeVersePluign()
let lang = navigator.language
converse.initialize({
bosh_service_url: bosh,
view_mode: 'fullscreen',
jid: login + '/chimeverse',
password: password,
auto_login: true,
whitelisted_plugins: ['chimeVerse'],
i18n: lang,
priority: 50,
// debug: true,
auto_reconnect: true
})
}
return chimeverseService
})
angApp.controller('AppController', function ($scope, ChimeVerseService) {
//const { remote, ipcRenderer } = require('electron')
const { ipcRenderer } = require('electron')
$scope.showLoginForm = false
ipcRenderer.on('force-logout-event', () => {
ChimeVerseService.logout()
ipcRenderer.getCurrentWindow().reload()
let event = new CustomEvent("converse-force-logout") // Dispatch to the plugin
document.dispatchEvent(event)
//remote.getCurrentWindow().reload()
})
$scope.addAccountAction = () => {
ChimeVerseService.settings.addCredentials($scope.bosh, $scope.login, $scope.password)
$scope.showLoginForm = false
ChimeVerseService.initConverse($scope.bosh, $scope.login, $scope.password)
}
$scope.state = 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($scope.state)
}, 0)
});
$scope.getCredentialsAndLogin = () => {
let credentials = ChimeVerseService.settings.getCredentials()
let credentials = SettingsServise.getCredentials()
credentials.then((result) => {
ChimeVerseService.initConverse(result.bosh, result.login, result.password)
}, (error) => {
$scope.showLoginForm = true
$scope.$apply()
AppStateService.set(AppStateService.APP_STATE_LOGIN)
})
}
$scope.getCredentialsAndLogin()
})

33
resources/css/app.css Normal file
View File

@ -0,0 +1,33 @@
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
user-select: none; /* Non-prefixed version, currently
supported by Chrome and Opera */
}
body {
background: #f8f8f8;
}
.main-background {
background: #f8f8f8;
height: 100%;
left: 0px;
position: fixed;
top: 0px;
width: 100%;
z-index: -1;
}
.conversejs-adoption {
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,6 @@
.chimeverse-branding {
left: 50%;
position: absolute;
top: 50%;
width: 300px;
}

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB