Comparar commits
16 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| efb3dd025f | |||
| 457e175a41 | |||
| 757770b9f7 | |||
| 3dee2ef385 | |||
| e70b2481a8 | |||
| 9023a4c9c8 | |||
| c5ad776f8c | |||
| 2bb914cb9a | |||
| 9158727327 | |||
| e904bd8045 | |||
| 4fb2ea3ee3 | |||
| 78cb8426c3 | |||
| daa5d35d7a | |||
| daf6217a63 | |||
| 479ebb3a26 | |||
| 4961e7e8e7 |
+1
-1
@@ -18,7 +18,7 @@ linters:
|
||||
ImportantRule:
|
||||
enabled: false
|
||||
Indentation:
|
||||
width: 4
|
||||
width: 3
|
||||
LeadingZero:
|
||||
style: include_zero
|
||||
NameFormat:
|
||||
|
||||
@@ -9,3 +9,7 @@ before_install:
|
||||
|
||||
script:
|
||||
- ./node_modules/.bin/grunt pre-commit
|
||||
|
||||
branches:
|
||||
except:
|
||||
- refactoring
|
||||
|
||||
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## 3.1.1 - 2017-02-14
|
||||
### Fixed
|
||||
- fix path to dependencies
|
||||
|
||||
## 3.1.0 - 2017-02-14
|
||||
### Added
|
||||
- add application states
|
||||
|
||||
-394
@@ -1,394 +0,0 @@
|
||||
/* global module:false */
|
||||
module.exports = function(grunt) {
|
||||
|
||||
var dep = grunt.file.readJSON('dep.json');
|
||||
var dep_files = dep.map(function(el) {
|
||||
return el.file;
|
||||
});
|
||||
dep_files.push('<%= target %>/lib/translation.js');
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
app: grunt.file.readJSON('package.json'),
|
||||
meta: {
|
||||
banner: grunt.file.read('banner.js')
|
||||
},
|
||||
target: 'dev',
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc: '.jshintrc'
|
||||
},
|
||||
gruntfile: {
|
||||
src: 'Gruntfile.js'
|
||||
},
|
||||
files: ['src/jsxc.lib.*.js']
|
||||
},
|
||||
copy: {
|
||||
main: {
|
||||
files: [{
|
||||
expand: true,
|
||||
src: ['lib/emojione/assets/svg/*.svg',
|
||||
'lib/otr/build/**', 'lib/otr/lib/*.js',
|
||||
'lib/otr/vendor/*.js', 'lib/*.js', 'LICENSE',
|
||||
'img/**', 'sound/**'
|
||||
],
|
||||
dest: '<%= target %>/'
|
||||
}, {
|
||||
expand: true,
|
||||
cwd: 'lib/',
|
||||
src: ['*.css'],
|
||||
dest: '<%= target %>/css/'
|
||||
}, {
|
||||
expand: true,
|
||||
cwd: 'lib/magnific-popup/dist/',
|
||||
src: ['*.css'],
|
||||
dest: '<%= target %>/css/'
|
||||
}]
|
||||
}
|
||||
},
|
||||
clean: ['<%= target %>/'],
|
||||
usebanner: {
|
||||
dist: {
|
||||
options: {
|
||||
position: 'top',
|
||||
banner: '<%= meta.banner %>'
|
||||
},
|
||||
files: {
|
||||
src: ['<%= target %>/*.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
replace: {
|
||||
version: {
|
||||
src: ['<%= target %>/jsxc.js'],
|
||||
overwrite: true,
|
||||
replacements: [{
|
||||
from: '< $ app.version $ >',
|
||||
to: "<%= app.version %>"
|
||||
}]
|
||||
},
|
||||
libraries: {
|
||||
src: ['<%= target %>/jsxc.js'],
|
||||
overwrite: true,
|
||||
replacements: [{
|
||||
from: '<$ dep.libraries $>',
|
||||
to: function() {
|
||||
var i, d, libraries = '';
|
||||
|
||||
for (i = 0; i < dep.length; i++) {
|
||||
d = dep[i];
|
||||
if (typeof d.name === 'string') {
|
||||
libraries += '<a href="' + d.url + '">' + d.name + '</a> (' + d.license + '), ';
|
||||
}
|
||||
}
|
||||
|
||||
return libraries.replace(/, $/, '');
|
||||
}
|
||||
}]
|
||||
},
|
||||
locales: {
|
||||
src: ['<%= target %>/lib/translation.js'],
|
||||
overwrite: true,
|
||||
replacements: [{
|
||||
from: /^{/g,
|
||||
to: 'var I18next = {'
|
||||
}, {
|
||||
from: /}$/g,
|
||||
to: '};'
|
||||
}]
|
||||
},
|
||||
template: {
|
||||
src: ['tmp/template.js'],
|
||||
overwrite: true,
|
||||
replacements: [{
|
||||
from: 'var jsxc.gui.template = {};',
|
||||
to: ''
|
||||
}]
|
||||
},
|
||||
imageUrl: {
|
||||
src: ['<%= target %>/css/*.css'],
|
||||
overwrite: true,
|
||||
replacements: [{
|
||||
from: /image-url\(["'](.+)["']\)/g,
|
||||
to: 'url(\'../img/$1\')'
|
||||
}]
|
||||
},
|
||||
// IE 10 does not like comments starting with @
|
||||
todo: {
|
||||
src: ['build/jsxc.js'],
|
||||
overwrite: true,
|
||||
replacements: [{
|
||||
from: /\/\/@(.*)/g,
|
||||
to: '//$1'
|
||||
}]
|
||||
}
|
||||
},
|
||||
merge_data: {
|
||||
target: {
|
||||
src: ['locales/*.{json,y{,a}ml}'],
|
||||
dest: '<%= target %>/lib/translation.js'
|
||||
}
|
||||
},
|
||||
concat: {
|
||||
dep: {
|
||||
options: {
|
||||
banner: '/*!\n' +
|
||||
' * <%= app.name %> v<%= app.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
|
||||
' * \n' +
|
||||
' * This file concatenates all dependencies of <%= app.name %>.\n' +
|
||||
' * \n' +
|
||||
' */\n\n',
|
||||
process: function(src, filepath) {
|
||||
filepath = filepath.replace(/^[a-z]+\//i, '');
|
||||
|
||||
if (filepath.match(/crypto\.js$/)) {
|
||||
src += ';';
|
||||
}
|
||||
|
||||
var data = dep[dep_files.indexOf(filepath)];
|
||||
|
||||
if (data) {
|
||||
return '\n/*!\n * Source: ' + filepath + ', license: ' + data.license + ', url: ' + data.url + '\n */\n' + src;
|
||||
} else {
|
||||
return src;
|
||||
}
|
||||
}
|
||||
},
|
||||
src: dep_files,
|
||||
dest: '<%= target %>/lib/jsxc.dep.js'
|
||||
},
|
||||
jsxc: {
|
||||
options: {
|
||||
banner: '/*! This file is concatenated for the browser. */\n\n'
|
||||
},
|
||||
src: ['src/jsxc.intro.js', 'src/jsxc.lib.js', 'src/jsxc.lib.xmpp.js',
|
||||
'src/jsxc.lib.*.js', 'tmp/template.js', 'src/jsxc.outro.js'
|
||||
],
|
||||
dest: '<%= target %>/jsxc.js'
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
jsxc: {
|
||||
options: {
|
||||
mangle: false,
|
||||
sourceMap: true,
|
||||
preserveComments: 'some'
|
||||
},
|
||||
files: {
|
||||
'<%= target %>/lib/jsxc.dep.min.js': ['<%= target %>/lib/jsxc.dep.js'],
|
||||
'<%= target %>/jsxc.min.js': ['<%= target %>/jsxc.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
search: {
|
||||
bower: {
|
||||
files: {
|
||||
src: ['bower.json']
|
||||
},
|
||||
options: {
|
||||
searchString: "<%= app.version %>",
|
||||
logFormat: 'console',
|
||||
onComplete: function(m) {
|
||||
if (m.numMatches === 0) {
|
||||
grunt.fail.fatal('No entry in bower.json for current version found.');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
console: {
|
||||
files: {
|
||||
src: ['src/*.js']
|
||||
},
|
||||
options: {
|
||||
searchString: /console\.log\((?!'[<>]|msg)/g,
|
||||
logFormat: 'console',
|
||||
failOnMatch: true
|
||||
}
|
||||
},
|
||||
changelog: {
|
||||
files: {
|
||||
src: ['CHANGELOG.md']
|
||||
},
|
||||
options: {
|
||||
searchString: "<%= app.version %>",
|
||||
logFormat: 'console',
|
||||
onComplete: function(m) {
|
||||
if (m.numMatches === 0) {
|
||||
grunt.fail.fatal("No entry in CHANGELOG.md for current version found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
compress: {
|
||||
main: {
|
||||
options: {
|
||||
archive: "archives/jsxc-<%= app.version %>.zip"
|
||||
},
|
||||
files: [{
|
||||
src: ['**'],
|
||||
expand: true,
|
||||
dest: 'jsxc/',
|
||||
cwd: 'build/'
|
||||
}]
|
||||
}
|
||||
},
|
||||
dataUri: {
|
||||
dist: {
|
||||
src: '<%= target %>/css/*.css',
|
||||
dest: '<%= target %>/css/',
|
||||
options: {
|
||||
target: ['<%= target %>/img/*.*', '<%= target %>/img/**/*.*'],
|
||||
fixDirLevel: false,
|
||||
maxBytes: 2048
|
||||
}
|
||||
}
|
||||
},
|
||||
jsdoc: {
|
||||
dist: {
|
||||
src: ['src/jsxc.lib.*'],
|
||||
dest: 'doc'
|
||||
}
|
||||
},
|
||||
autoprefixer: {
|
||||
no_dest: {
|
||||
src: '<%= target %>/css/*.css'
|
||||
}
|
||||
},
|
||||
csslint: {
|
||||
strict: {
|
||||
options: {
|
||||
import: 2
|
||||
},
|
||||
src: ['<%= target %>/css/*.css']
|
||||
},
|
||||
},
|
||||
sass: {
|
||||
dist: {
|
||||
files: {
|
||||
'<%= target %>/css/jsxc.css': 'scss/jsxc.scss',
|
||||
'<%= target %>/css/jsxc.webrtc.css': 'scss/jsxc.webrtc.scss'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
locales: {
|
||||
files: ['locales/*'],
|
||||
tasks: ['merge_data', 'replace:locales', 'concat:dep']
|
||||
},
|
||||
css: {
|
||||
files: ['scss/*'],
|
||||
tasks: ['sass', 'autoprefixer', 'replace:imageUrl']
|
||||
},
|
||||
js: {
|
||||
files: ['src/jsxc.lib.*'],
|
||||
tasks: ['concat:jsxc']
|
||||
},
|
||||
template: {
|
||||
files: ['template/*.html'],
|
||||
tasks: ['htmlConvert', 'replace:template', 'concat:jsxc']
|
||||
}
|
||||
},
|
||||
jsbeautifier: {
|
||||
'default': {
|
||||
src: ['Gruntfile.js', 'src/jsxc.lib.*', 'template/*.html',
|
||||
'example/*.html', 'example/js/dev.js', 'example/js/example.js',
|
||||
'example/css/example.css'
|
||||
],
|
||||
options: {
|
||||
config: '.jsbeautifyrc'
|
||||
}
|
||||
},
|
||||
'pre-commit': {
|
||||
src: ['Gruntfile.js', 'src/jsxc.lib.*', 'template/*.html',
|
||||
'example/*.html', 'example/js/dev.js', 'example/js/example.js',
|
||||
'example/css/example.css'
|
||||
],
|
||||
options: {
|
||||
config: '.jsbeautifyrc',
|
||||
mode: 'VERIFY_ONLY'
|
||||
}
|
||||
}
|
||||
},
|
||||
prettysass: {
|
||||
options: {
|
||||
alphabetize: false,
|
||||
indent: 4
|
||||
},
|
||||
jsxc: {
|
||||
src: ['scss/*.scss']
|
||||
}
|
||||
},
|
||||
htmlConvert: {
|
||||
options: {
|
||||
target: 'js',
|
||||
rename: function(name) {
|
||||
return name.match(/([-_0-9a-z]+)\.html$/i)[1];
|
||||
},
|
||||
quoteChar: '\'',
|
||||
indentString: '',
|
||||
indentGlobal: ''
|
||||
},
|
||||
'jsxc.gui.template': {
|
||||
src: 'template/*.html',
|
||||
dest: 'tmp/template.js'
|
||||
}
|
||||
},
|
||||
scsslint: {
|
||||
files: ['scss/*.scss'],
|
||||
options: {
|
||||
config: '.scss-lint.yml'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// These plugins provide necessary tasks.
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-banner');
|
||||
grunt.loadNpmTasks('grunt-text-replace');
|
||||
grunt.loadNpmTasks('grunt-search');
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
grunt.loadNpmTasks('grunt-jsdoc');
|
||||
grunt.loadNpmTasks('grunt-data-uri');
|
||||
grunt.loadNpmTasks('grunt-merge-data');
|
||||
grunt.loadNpmTasks('grunt-contrib-csslint');
|
||||
grunt.loadNpmTasks('grunt-sass');
|
||||
grunt.loadNpmTasks('grunt-autoprefixer');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-jsbeautifier');
|
||||
grunt.loadNpmTasks('grunt-prettysass');
|
||||
grunt.loadNpmTasks('grunt-html-convert');
|
||||
grunt.loadNpmTasks('grunt-scss-lint');
|
||||
|
||||
//Default task
|
||||
grunt.registerTask('default', ['build', 'watch']);
|
||||
|
||||
grunt.registerTask('build', ['jshint', 'clean', 'sass', 'replace:imageUrl',
|
||||
'autoprefixer', 'copy', 'merge_data', 'replace:locales', 'htmlConvert',
|
||||
'replace:template', 'concat'
|
||||
]);
|
||||
|
||||
grunt.registerTask('build:prerelease', 'Build a new pre-release', function() {
|
||||
grunt.config.set('target', 'build');
|
||||
|
||||
grunt.task.run(['search:console', 'search:bower', 'build', 'usebanner',
|
||||
'replace:version', 'replace:libraries', 'replace:todo',
|
||||
'uglify', 'compress'
|
||||
]);
|
||||
});
|
||||
|
||||
grunt.registerTask('build:release', 'Build a new release', function() {
|
||||
grunt.config.set('target', 'build');
|
||||
|
||||
grunt.task.run(['search:changelog', 'build:prerelease', 'jsdoc']);
|
||||
});
|
||||
|
||||
// before commit
|
||||
grunt.registerTask('pre-commit', ['search:console', 'jsbeautifier:pre-commit', 'scsslint', 'jshint']);
|
||||
|
||||
grunt.registerTask('beautify', ['jsbeautifier', 'prettysass']);
|
||||
};
|
||||
+6
-1
@@ -1,4 +1,4 @@
|
||||
# JavaScript XMPP Client
|
||||
# JavaScript XMPP Client 4.0
|
||||
|
||||
[](https://travis-ci.org/jsxc/jsxc)
|
||||
[](https://dependencyci.com/github/jsxc/jsxc)
|
||||
@@ -8,3 +8,8 @@ Real-time chat app. This app requires an external XMPP server (openfire, ejabber
|
||||
You find a full list of features, supported protocols and browsers on [our homepage](http://www.jsxc.org).
|
||||
|
||||
If you are looking for install instructions or developer notes, please also checkout our [wiki](https://github.com/jsxc/jsxc/wiki/).
|
||||
|
||||
## Rewrite / Refactoring
|
||||
:warning: This branch is under heavy construction and definitely not ready for production.
|
||||
|
||||
This next big step for JSXC uses [Typescript](http://www.typescriptlang.org/index.html), [Webpack](https://webpack.github.io), [Handlebars](http://handlebarsjs.com), [Karma](http://karma-runner.github.io), [Mocha](https://mochajs.org), [Chai](http://chaijs.com) and [Sinon](http://sinonjs.org) to bring the best open XMPP chat experience to you. Currently we ship no packed version, so install all dependencies with `npm install` and execute `npm run dev` to test the current state. An example application is available at `example/ts.html`. To run all tests, enter `npm test`.
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"name": "jsxc",
|
||||
"version": "3.1.0",
|
||||
"homepage": "https://www.jsxc.org",
|
||||
"authors": [
|
||||
"sualko <klaus@jsxc.org>"
|
||||
],
|
||||
"description": "Real-time chat app",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"xmpp",
|
||||
"webrtc",
|
||||
"otr",
|
||||
"chat",
|
||||
"realtime"
|
||||
],
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"lib/",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"emojione": "~2.2.7",
|
||||
"favico.js": "^0.3.10",
|
||||
"strophe.bookmarks": "strophe/strophejs-plugin-bookmarks#f51c60629cb0ad278f92bfb8d8dbb8cb455d9c98",
|
||||
"strophe.js": "strophejs#a11ebefa3db1b6712d51d0d309b9f68f8e391d1b",
|
||||
"strophe.vcard": "strophe/strophejs-plugin-vcard#de3a0c97a2c520ed900ee15b04a0c16d5c663891",
|
||||
"strophe.x": "strophe/strophejs-plugin-dataforms",
|
||||
"strophe.chatstates": "strophe/strophejs-plugin-chatstates",
|
||||
"jquery-i18next": "^1.2.0",
|
||||
"i18next": "^5.0.0",
|
||||
"magnific-popup": "^1.1.0"
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* jsxc v3.1.0 - 2017-02-14
|
||||
* jsxc v3.1.1 - 2017-02-14
|
||||
*
|
||||
* Copyright (c) 2017 Klaus Herberth <klaus@jsxc.org> <br>
|
||||
* Released under the MIT license
|
||||
@@ -7,7 +7,7 @@
|
||||
* Please see http://www.jsxc.org/
|
||||
*
|
||||
* @author Klaus Herberth <klaus@jsxc.org>
|
||||
* @version 3.1.0
|
||||
* @version 3.1.1
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@ var jsxc = null, RTC = null, RTCPeerconnection = null;
|
||||
*/
|
||||
jsxc = {
|
||||
/** Version of jsxc */
|
||||
version: '3.1.0',
|
||||
version: '3.1.1',
|
||||
|
||||
/** True if i'm the master */
|
||||
master: false,
|
||||
|
||||
externo
+3
-3
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+1122
-1
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+7
@@ -0,0 +1,7 @@
|
||||
declare module '*.hbs' {
|
||||
// const content: any;
|
||||
// export default content;
|
||||
export default function template(options:any);
|
||||
}
|
||||
|
||||
declare function require(file:string):(context?:any, options?:any)=>string;
|
||||
-116
@@ -1,116 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "strophe.js",
|
||||
"file": "lib/strophe.js/strophe.js",
|
||||
"license": "multiple",
|
||||
"url": "http://strophe.im/strophejs/"
|
||||
},
|
||||
{
|
||||
"name": "strophe.js/muc",
|
||||
"file": "lib/strophe.muc.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins"
|
||||
},
|
||||
{
|
||||
"name": "strophe.js/disco",
|
||||
"file": "lib/strophe.disco.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins"
|
||||
},
|
||||
{
|
||||
"name": "strophe.js/caps",
|
||||
"file": "lib/strophe.caps.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins"
|
||||
},
|
||||
{
|
||||
"name": "strophe.js/vcard",
|
||||
"file": "lib/strophe.vcard/index.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins"
|
||||
},
|
||||
{
|
||||
"name": "strophe.js/bookmarks",
|
||||
"file": "lib/strophe.bookmarks/index.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins/tree/master/bookmarks"
|
||||
},
|
||||
{
|
||||
"name": "strophe.js/x",
|
||||
"file": "lib/strophe.x/index.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins/tree/master/dataforms"
|
||||
},
|
||||
{
|
||||
"name": "strophe.js/chatstates",
|
||||
"file": "lib/strophe.chatstates/index.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins/tree/master/chatstates"
|
||||
},
|
||||
{
|
||||
"name": "strophe.jinglejs",
|
||||
"file": "lib/strophe.jinglejs/strophe.jinglejs-bundle.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/sualko/strophe.jinglejs"
|
||||
},
|
||||
{
|
||||
"name": "Salsa20",
|
||||
"file": "lib/otr/build/dep/salsa20.js",
|
||||
"license": "AGPL3",
|
||||
"url": "https://github.com/neoatlantis/node-salsa20"
|
||||
},
|
||||
{
|
||||
"name": "bigint",
|
||||
"file": "lib/otr/build/dep/bigint.js",
|
||||
"license": "public domain",
|
||||
"url": "www.leemon.com"
|
||||
},
|
||||
{
|
||||
"name": "cryptojs",
|
||||
"file": "lib/otr/build/dep/crypto.js",
|
||||
"license": "code.google.com/p/crypto-js/wiki/license",
|
||||
"url": "code.google.com/p/crypto-js"
|
||||
},
|
||||
{
|
||||
"name": "eventemitter",
|
||||
"file": "lib/otr/build/dep/eventemitter.js",
|
||||
"license": "MIT",
|
||||
"url": "http://git.io/ee"
|
||||
},
|
||||
{
|
||||
"name": "otr.js",
|
||||
"file": "lib/otr/build/otr.js",
|
||||
"license": "MPL v2.0",
|
||||
"url": "https://arlolra.github.io/otr/"
|
||||
},
|
||||
{
|
||||
"name": "i18next",
|
||||
"file": "lib/i18next/i18next.min.js",
|
||||
"license": "MIT",
|
||||
"url": "http://i18next.com/"
|
||||
},
|
||||
{
|
||||
"name": "jquery-i18next",
|
||||
"file": "lib/jquery-i18next/jquery-i18next.min.js",
|
||||
"license": "MIT",
|
||||
"url": "http://i18next.com/"
|
||||
},
|
||||
{
|
||||
"name": "Magnific Popup",
|
||||
"file": "lib/magnific-popup/dist/jquery.magnific-popup.min.js",
|
||||
"license": "MIT",
|
||||
"url": "http://dimsemenov.com/plugins/magnific-popup/"
|
||||
},
|
||||
{
|
||||
"name": "favico.js",
|
||||
"file": "lib/favico.js/favico.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/ejci/favico.js"
|
||||
},
|
||||
{
|
||||
"name": "emoji one",
|
||||
"file": "lib/emojione/lib/js/emojione.js",
|
||||
"license": "CC-BY 4.0",
|
||||
"url": "http://emojione.com"
|
||||
}
|
||||
]
|
||||
+1
-1
@@ -458,7 +458,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -3620,7 +3620,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1020,7 +1020,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -658,7 +658,7 @@ otherwise only dialog with given name is closed.
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
+1
-1
@@ -4148,7 +4148,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -536,7 +536,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1707,7 +1707,7 @@ alphabetical of the name
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -3441,7 +3441,7 @@ and save. Check border cases and remove html.
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
+1
-1
@@ -5073,7 +5073,7 @@ normal signal
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -309,7 +309,7 @@ jsxc.Message.PLAIN = 'plain';
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -291,7 +291,7 @@ $(document).on('update.gui.jsxc', function(ev, bid) {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -3169,7 +3169,7 @@ jsxc.gui.template.get = function(name, bid, msg) {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1007,7 +1007,7 @@ jsxc = {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1720,7 +1720,7 @@ $(document).one('connected.jsxc', function() {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -195,7 +195,7 @@ jsxc.notice = {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -319,7 +319,7 @@ jsxc.notification = {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -349,7 +349,7 @@ jsxc.options = {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -574,7 +574,7 @@ jsxc.otr = {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -660,7 +660,7 @@ jsxc.storage = {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -102,7 +102,7 @@ jsxc.tab = {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1524,7 +1524,7 @@ $(document).ready(function() {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -387,7 +387,7 @@ jsxc.xmpp.bookmarks.showDialog = function(room) {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -290,7 +290,7 @@ $(document).on('attached.jsxc', jsxc.xmpp.chatState.init);
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -372,7 +372,7 @@ $(document).on('stateChange.jsxc', function(ev, state) {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1396,7 +1396,7 @@ jsxc.xmpp.carbons = {
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
+1
-1
@@ -2446,7 +2446,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1405,7 +1405,7 @@ messages.
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -2760,7 +2760,7 @@ modification is done to it.
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
+1
-1
@@ -2220,7 +2220,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -2332,7 +2332,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
+1
-1
@@ -434,7 +434,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -3444,7 +3444,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1022,7 +1022,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -504,7 +504,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1185,7 +1185,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1620,7 +1620,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -1316,7 +1316,7 @@
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 13:39:34 GMT+0100 (CET)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 14 2017 16:15:49 GMT+0100 (CET)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>JSXC example application</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
|
||||
|
||||
<link href="css/bootstrap.min.css" media="all" rel="stylesheet" type="text/css" />
|
||||
|
||||
<!-- require:dependencies -->
|
||||
<link href="../build/css/jquery-ui.min.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<link href="../css/bundle.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<!-- endrequire -->
|
||||
|
||||
<link href="../node_modules/simplebar/dist/simplebar.css" media="all" rel="stylesheet" type="text/css" />
|
||||
|
||||
<link href="css/example.css" media="all" rel="stylesheet" type="text/css" />
|
||||
|
||||
<style>
|
||||
#jsxc-role {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: #a1a1a1;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
}
|
||||
.jsxc-master #jsxc-role {
|
||||
background-color: green;
|
||||
}
|
||||
.jsxc-slave #jsxc-role {
|
||||
background-color: orange;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="jsxc-role"></div>
|
||||
|
||||
<form id="loginForm" style="margin-top: 100px; padding:15px;" class="form-inline">
|
||||
<div class="form-group">
|
||||
<input class="form-control" type="text" name="url" placeholder="Bosh url" value="/http-bind/" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input class="form-control" type="text" name="jid" placeholder="Jabber Id" value="" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input class="form-control" type="text" name="password" placeholder="Password" value="" />
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary">Login</button>
|
||||
</form>
|
||||
|
||||
<p style="padding:15px"><a class="btn btn-danger" href="javascript:jsxc.deleteAllData()">Delete all Data</a>
|
||||
<a class="btn btn-default" href="javascript:jsxc.enableDebugMode()">Enable Debug Mode</a>
|
||||
<a class="btn btn-default" href="javascript:jsxc.disableDebugMode()">Disable Debug Mode</a></p>
|
||||
|
||||
<!-- require:dependencies -->
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="js/jquery-ui.min.js"></script>
|
||||
<script src="../build/lib/jquery.slimscroll.js"></script>
|
||||
<script src="../build/lib/jquery.fullscreen.js"></script>
|
||||
<!-- <script src="../build/lib/jsxc.dep.js"></script> -->
|
||||
<!-- endrequire -->
|
||||
|
||||
<script src="../node_modules/simplebar/dist/simplebar.js"></script>
|
||||
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
|
||||
<!-- jsxc library -->
|
||||
<script src="../bundle.js"></script>
|
||||
|
||||
<script>
|
||||
$('#loginForm').submit(function(ev){
|
||||
ev.preventDefault();
|
||||
|
||||
var url = $(this).find('[name="url"]').val();
|
||||
var jid = $(this).find('[name="jid"]').val();
|
||||
var password = $(this).find('[name="password"]').val();
|
||||
|
||||
jsxc.start(url, jid, password);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 3.1749999 3.1750001"
|
||||
height="12"
|
||||
width="12"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="presence_online.svg">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1879"
|
||||
inkscape:window-height="1176"
|
||||
id="namedview5307"
|
||||
showgrid="false"
|
||||
inkscape:zoom="55.625733"
|
||||
inkscape:cx="3.7142348"
|
||||
inkscape:cy="6.3732363"
|
||||
inkscape:window-x="1241"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 1.4 KiB |
+100
@@ -0,0 +1,100 @@
|
||||
// jshint node:true
|
||||
|
||||
// var path = require('path');
|
||||
var webpackConfig = require('./webpack.config.js');
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: '',
|
||||
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: [ /*'karma-typescript',*/ 'mocha', 'chai'],
|
||||
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'./node_modules/jquery/dist/jquery.min.js',
|
||||
'./node_modules/strophe.js/strophe.js',
|
||||
'./node_modules/es6-promise/dist/es6-promise.js',
|
||||
'test/*.spec.ts',
|
||||
'test/**/*.spec.ts'
|
||||
],
|
||||
|
||||
|
||||
// list of files to exclude
|
||||
exclude: [],
|
||||
|
||||
// webpack configuration
|
||||
webpack: {
|
||||
devtool: 'eval-source-map',
|
||||
module: webpackConfig.module,
|
||||
resolve: webpackConfig.resolve,
|
||||
//externals: webpackConfig.externals,
|
||||
// target: 'node',
|
||||
node: {
|
||||
fs: 'empty'
|
||||
}
|
||||
},
|
||||
|
||||
webpackMiddleware: {
|
||||
quiet: false,
|
||||
stats: {
|
||||
colors: true
|
||||
}
|
||||
},
|
||||
|
||||
mime: {
|
||||
'text/x-typescript': ['ts', 'tsx']
|
||||
},
|
||||
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
'test/**/*.spec.ts': ['webpack' /*'karma-typescript'*/ ]
|
||||
},
|
||||
|
||||
karmaTypescriptConfig: {
|
||||
include: ['test/**/*.spec.ts']
|
||||
},
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: [ /*'progress', 'karma-typescript',*/ 'mocha'],
|
||||
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_DEBUG,
|
||||
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: true,
|
||||
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
browsers: ['Chrome'],
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
singleRun: false,
|
||||
|
||||
// Concurrency level
|
||||
// how many browser should be started simultaneous
|
||||
concurrency: Infinity
|
||||
});
|
||||
};
|
||||
+52
-23
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsxc",
|
||||
"version": "3.1.0",
|
||||
"version": "3.1.1",
|
||||
"description": "Real-time xmpp chat application with video calls, file transfer and encrypted communication",
|
||||
"homepage": "http://www.jsxc.org/",
|
||||
"bugs": "https://github.com/jsxc/jsxc/issues",
|
||||
@@ -10,30 +10,59 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/jsxc/jsxc"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "webpack --config webpack.config.js",
|
||||
"dev": "webpack --config webpack.config.js --watch",
|
||||
"test": "karma start"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.0.0",
|
||||
"@types/jquery": "^3.2.3",
|
||||
"@types/mocha": "^2.2.41",
|
||||
"@types/simplebar": "^2.4.0",
|
||||
"@types/sinon": "^2.3.1",
|
||||
"autoprefixer-core": "^6.0.1",
|
||||
"bower": "^1.8.0",
|
||||
"grunt": "^1.0.1",
|
||||
"grunt-autoprefixer": "^3.0.4",
|
||||
"grunt-banner": "~0.6.0",
|
||||
"grunt-contrib-clean": "~1.0.0",
|
||||
"grunt-contrib-compress": "^1.4.1",
|
||||
"grunt-contrib-concat": "^1.0.1",
|
||||
"grunt-contrib-copy": "~1.0.0",
|
||||
"grunt-contrib-csslint": "^2.0.0",
|
||||
"grunt-contrib-jshint": "~1.1.0",
|
||||
"grunt-contrib-uglify": "^2.0.0",
|
||||
"grunt-contrib-watch": "^1.0.0",
|
||||
"grunt-data-uri": "^0.3.0",
|
||||
"grunt-html-convert": "0.0.2",
|
||||
"grunt-jsbeautifier": "^0.2.13",
|
||||
"grunt-jsdoc": "^2.1.0",
|
||||
"grunt-merge-data": "^0.4.5",
|
||||
"grunt-prettysass": "^0.2.3",
|
||||
"grunt-sass": "2.0.0",
|
||||
"grunt-scss-lint": "^0.5.0",
|
||||
"grunt-search": "^0.1.8",
|
||||
"grunt-text-replace": "~0.4.0",
|
||||
"node-sass": "4.3.0"
|
||||
"chai": "^4.0.2",
|
||||
"css-loader": "^0.28.4",
|
||||
"es6-promise": "^4.1.0",
|
||||
"extract-text-webpack-plugin": "^2.1.2",
|
||||
"handlebars-loader": "^1.5.0",
|
||||
"handlebars-runtime": "^1.0.12",
|
||||
"i18next": "^8.4.2",
|
||||
"karma": "^1.7.0",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-chrome-launcher": "^2.1.1",
|
||||
"karma-firefox-launcher": "^1.0.1",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.3",
|
||||
"karma-phantomjs-launcher": "^1.0.4",
|
||||
"karma-sinon": "^1.0.5",
|
||||
"karma-spec-reporter": "0.0.31",
|
||||
"karma-typescript": "^3.0.4",
|
||||
"karma-webpack": "^2.0.3",
|
||||
"mocha": "^3.4.2",
|
||||
"node-sass": "^4.5.3",
|
||||
"precompile-handlebars": "^1.0.5",
|
||||
"resolve-url-loader": "^2.0.3",
|
||||
"sass-loader": "^6.0.6",
|
||||
"sinon": "^2.3.5",
|
||||
"strophe": "^1.2.4",
|
||||
"ts-loader": "^2.2.0",
|
||||
"ts-node": "^3.1.0",
|
||||
"typescript": "^2.3.4",
|
||||
"webpack": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/emojione": "^2.2.1",
|
||||
"@types/handlebars": "^4.0.33",
|
||||
"@types/strophe": "^1.2.28",
|
||||
"i18next": "^7.1.1",
|
||||
"jquery": "^3.2.1",
|
||||
"magnific-popup": "^1.1.0",
|
||||
"moment": "^2.18.1",
|
||||
"simplebar": "^2.4.3",
|
||||
"strophe.js": "^1.2.14",
|
||||
"tslib": "^1.7.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
@import "modules";
|
||||
|
||||
#jsxc_buddylist {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 204px;
|
||||
z-index: 85;
|
||||
|
||||
.jsxc_unreadMsg {
|
||||
.jsxc_name {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_oneway {
|
||||
.jsxc_avatar, .jsxc_caption {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_right {
|
||||
float: right;
|
||||
margin-right: 6px;
|
||||
|
||||
div {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
color: $white;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_more {
|
||||
margin-right: 6px;
|
||||
z-index: 10;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jsxc_options {
|
||||
height: 20px;
|
||||
float: left;
|
||||
border-radius: 2px;
|
||||
background-color: $roster_icon_bg;
|
||||
|
||||
> div {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
float: left;
|
||||
margin-right: 0 1px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
opacity: 0.6;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.jsxc_hideOffline {
|
||||
.jsxc_rosteritem[data-status='offline'] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
@import "../lib/magnific-popup/src/css/main";
|
||||
@import "../lib/emojione/assets/css/emojione";
|
||||
|
||||
// BEGIN: bootstrap
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/variables";
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/mixins";
|
||||
|
||||
// Spec and IE10+
|
||||
@keyframes progress-bar-stripes {
|
||||
from {
|
||||
background-position: 40px 0;
|
||||
}
|
||||
|
||||
to {
|
||||
background-position: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc_dialog {
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/progress-bars";
|
||||
}
|
||||
|
||||
#jsxc_dialog, #jsxc_webrtc {
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/utilities";
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/code";
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/grid";
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/alerts";
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/buttons";
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/button-groups";
|
||||
@import "../lib/bootstrap/assets/stylesheets/bootstrap/forms";
|
||||
|
||||
.progress {
|
||||
margin-bottom: 0;
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.mfp-close {
|
||||
font-size: 23px;
|
||||
}
|
||||
}
|
||||
|
||||
.mfp-bg {
|
||||
z-index: 9000;
|
||||
}
|
||||
|
||||
.mfp-wrap {
|
||||
z-index: 9010;
|
||||
}
|
||||
|
||||
.mfp-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// END: bootstrap
|
||||
@@ -1,530 +0,0 @@
|
||||
.jsxc_right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.jsxc_center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.jsxc_hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.jsxc_uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.jsxc_sep {
|
||||
border-top: 1px solid $separator;
|
||||
}
|
||||
|
||||
.jsxc_name {
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.jsxc_maxWidth {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.jsxc_meta {
|
||||
text-align: right;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#jsxc_dialog {
|
||||
padding: 20px;
|
||||
min-width: 320px;
|
||||
max-width: 100%;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
position: relative;
|
||||
background: #FFF;
|
||||
width: auto;
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1em;
|
||||
|
||||
input {
|
||||
margin-bottom: 5px;
|
||||
width: 60%;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type='submit'] {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-top: 1px solid #eee;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.jsxc_right {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
form {
|
||||
fieldset {
|
||||
margin-bottom: 30px;
|
||||
padding: 0 30px;
|
||||
border: 1px solid #d9d9d9;
|
||||
|
||||
h3 {
|
||||
font-size: 15px;
|
||||
color: #000;
|
||||
background-color: #f2f2f2;
|
||||
padding: 10px;
|
||||
margin: 0 -30px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
legend {
|
||||
border: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
input {
|
||||
outline: none;
|
||||
|
||||
&:invalid {
|
||||
border: 1px solid $dialog_input_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group button {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
input[readonly] {
|
||||
background-color: $dialog_input_readonly_bg;
|
||||
}
|
||||
|
||||
.jsxc_inputinfo {
|
||||
padding: 0;
|
||||
font-style: italic;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.jsxc_waiting {
|
||||
&:before {
|
||||
content: " ";
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
background-size: 100%;
|
||||
margin: 0 3px 0 0;
|
||||
background-image: image-url("loading.gif");
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_libraries, .jsxc_credits {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.jsxc_warning {
|
||||
display: block;
|
||||
background-color: #fbfe7a;
|
||||
padding: 3px 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
margin: 0 5px;
|
||||
background-color: $avatar_bg;
|
||||
border-radius: 50%;
|
||||
float: left;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 30px;
|
||||
color: $avatar_color;
|
||||
position: relative;
|
||||
font-family: $font_sans;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -6px;
|
||||
border: 2px solid $roster_bg;
|
||||
}
|
||||
}
|
||||
|
||||
ul.jsxc_vCard {
|
||||
min-width: 400px;
|
||||
|
||||
ul {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
li {
|
||||
cursor: default !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Spot which is attached to xmpp: uris
|
||||
.jsxc_spot {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
text-indent: -99999em;
|
||||
margin-top: 3px;
|
||||
margin-right: 5px;
|
||||
line-height: 100%;
|
||||
cursor: pointer;
|
||||
border: 1px solid $spot_border;
|
||||
background-color: $white;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&.jsxc_online, &.jsxc_chat, &.jsxc_away, &.jsxc_xa, &.jsxc_dnd, &.jsxc_offline {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_unread {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_unreadMsg {
|
||||
.jsxc_name {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.jsxc_unread {
|
||||
display: block;
|
||||
background-color: $unread_bg;
|
||||
border-radius: 11px;
|
||||
color: $unread_color;
|
||||
font-size: 80%;
|
||||
padding: 2px;
|
||||
line-height: 15px;
|
||||
float: right;
|
||||
margin-right: 3px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check if required
|
||||
.jsxc_list {
|
||||
.jsxc_inner {
|
||||
box-sizing: border-box;
|
||||
max-height: 0;
|
||||
transition: max-height 0.5s;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&.jsxc_opened {
|
||||
.jsxc_inner {
|
||||
max-height: 1000px;
|
||||
visibility: visible;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#cboxWrapper {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.jsxc_loading {
|
||||
margin: 0 auto;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 0;
|
||||
background-size: 32px 32px !important;
|
||||
background: image-url("loading.gif");
|
||||
}
|
||||
|
||||
// @TODO: check
|
||||
#jsxc_loginForm input[type='submit'] {
|
||||
height: 34px;
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
margin-bottom: 0;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
line-height: 1.428571429;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
user-select: none;
|
||||
color: $white;
|
||||
background-color: $loginForm_bg;
|
||||
border-color: $loginForm_border;
|
||||
}
|
||||
|
||||
.jsxc_oneway .jsxc_avatar {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
img.jsxc_vCard {
|
||||
float: right;
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
border: 5px solid $white;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsxc_alert {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
|
||||
&.jsxc_alert-warning {
|
||||
color: #8a6d3b;
|
||||
background-color: #fcf8e3;
|
||||
border-color: #faebcc;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_btn {
|
||||
width: auto;
|
||||
min-width: 25px;
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
margin: 0 2px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 1.42857143;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.5s;
|
||||
|
||||
&.jsxc_btn-default {
|
||||
border-color: #ccc;
|
||||
color: #555;
|
||||
background-color: rgba(240, 240, 240, 0.9);
|
||||
|
||||
&:hover {
|
||||
background-color: #d6d6d6;
|
||||
}
|
||||
}
|
||||
|
||||
&.jsxc_btn-primary {
|
||||
color: #fff;
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
|
||||
&:hover {
|
||||
background-color: #296496;
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled], &[disabled]:hover {
|
||||
opacity: 0.65;
|
||||
cursor: not-allowed;
|
||||
color: #fff;
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #FFF;
|
||||
color: #333;
|
||||
border-radius: 3px;
|
||||
z-index: 110;
|
||||
margin: 8px 2px 5px 10px;
|
||||
right: 0;
|
||||
filter: drop-shadow(0 0 5px rgba(150, 150, 150, 0.75));
|
||||
padding: 4px 12px;
|
||||
padding-left: 5px;
|
||||
|
||||
&:after {
|
||||
bottom: 100%;
|
||||
right: 6px;
|
||||
border: solid transparent;
|
||||
content: " ";
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border-color: rgba(238, 238, 238, 0);
|
||||
border-bottom-color: #fff;
|
||||
border-width: 10px;
|
||||
}
|
||||
|
||||
&.jsxc_open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
border: 0;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #000;
|
||||
opacity: 0.5;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.jsxc_disabled {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.5;
|
||||
|
||||
&:hover {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
span {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
display: inline-block;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
vertical-align: sub;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_editicon {
|
||||
background-image: image-url("edit_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_deleteicon {
|
||||
background-image: image-url("delete_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_chaticon {
|
||||
background-image: image-url("speech_balloon_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_videoicon {
|
||||
background-image: image-url("camera_icon_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_infoicon {
|
||||
background-image: image-url("info_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_settingsicon {
|
||||
background-image: image-url("gear_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_helpicon {
|
||||
background-image: image-url("help_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_contacticon {
|
||||
background-image: image-url("contact_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_groupcontacticon {
|
||||
background-image: image-url("groupcontact_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_bookmarkicon {
|
||||
background-image: image-url("bookmark_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_announcementicon {
|
||||
background-image: image-url("megaphone_icon_black.svg");
|
||||
}
|
||||
|
||||
.jsxc_more {
|
||||
float: right;
|
||||
width: 44px;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
background-image: image-url("more_black.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
opacity: 0.4;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: 25px;
|
||||
}
|
||||
}
|
||||
@@ -1,399 +0,0 @@
|
||||
#jsxc_roster {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 200px;
|
||||
overflow: visible;
|
||||
border-left: 1px solid #e1e1e1;
|
||||
display: none;
|
||||
|
||||
// border-left: 1px solid $roster_border_left;
|
||||
z-index: 80;
|
||||
margin-left: 10px;
|
||||
background-color: $roster_bg;
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.slimScrollDiv {
|
||||
margin-bottom: 30px;
|
||||
z-index: 40;
|
||||
}
|
||||
|
||||
.jsxc_wait {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 160px;
|
||||
padding: 20px;
|
||||
background-color: $white;
|
||||
z-index: 60;
|
||||
|
||||
img {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 5px;
|
||||
font-size: 1.13em;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
height: 35px;
|
||||
padding: 7px 6px 5px;
|
||||
font-size: 13px;
|
||||
width: 145px;
|
||||
border: 1px solid #ddd;
|
||||
box-sizing: border-box;
|
||||
background-image: none;
|
||||
background-color: $roster_input_bg;
|
||||
border-radius: 3px;
|
||||
box-shadow: inner 0 0 5px $roster_input_shadow;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
p {
|
||||
color: $roster_color;
|
||||
padding: 10px;
|
||||
|
||||
a {
|
||||
color: $roster_a;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_avatar {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_expand input {
|
||||
left: 51px;
|
||||
width: 137px;
|
||||
}
|
||||
|
||||
&.jsxc_noConnection {
|
||||
.slimScrollDiv {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> .jsxc_bottom {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.jsxc_state_hidden {
|
||||
display: block;
|
||||
right: -200px;
|
||||
transition: right 0.5s;
|
||||
|
||||
#jsxc_toggleRoster {
|
||||
&:before {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.jsxc_state_shown {
|
||||
display: block;
|
||||
right: 0;
|
||||
transition: right 0.5s;
|
||||
}
|
||||
|
||||
> .jsxc_bottom {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
line-height: 34px;
|
||||
background-color: $roster_bottom_bg;
|
||||
z-index: 50;
|
||||
padding-right: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: $roster_bottom_bg_hover;
|
||||
}
|
||||
|
||||
.jsxc_inner {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
border-top: 1px solid $roster_bottom_border_top;
|
||||
background-color: $roster_bottom_bg;
|
||||
|
||||
li:last-child {
|
||||
border-bottom: 1px solid $roster_bottom_border_top;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
height: 44px;
|
||||
background-color: $roster_bottom_bg;
|
||||
color: $roster_bottom_color;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
padding-left: 44px;
|
||||
line-height: 44px;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 15px center;
|
||||
background-size: 16px 16px;
|
||||
opacity: 0.8;
|
||||
|
||||
&.jsxc_disabled {
|
||||
color: $roster_bottom_disabled;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&:hover:not(.jsxc_disabled) {
|
||||
color: $roster_bottom_color_hover;
|
||||
background-color: $roster_bottom_bg_hover;
|
||||
}
|
||||
|
||||
&.jsxc_warning {
|
||||
background-color: $warning_bg;
|
||||
|
||||
&:hover {
|
||||
background-color: $warning_bg_hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div > span {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc_toggleRoster {
|
||||
width: 14px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: -14px !important;
|
||||
top: 0;
|
||||
z-index: 110;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: $roster_toggle_hover;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
border-style: solid;
|
||||
border-width: 6px 4px 6px 0;
|
||||
border-color: transparent $roster_bg;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_rosteritem {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 44px;
|
||||
border-bottom: 1px solid $roster_bottom_border_top;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
color: $roster_color;
|
||||
font-family: $font_sans;
|
||||
line-height: 44px;
|
||||
padding-left: 6px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:hover {
|
||||
background-color: $roster_bg_hover;
|
||||
}
|
||||
|
||||
&.jsxc_bookmarked {
|
||||
.jsxc_avatar:after {
|
||||
content: " ";
|
||||
width: 20%;
|
||||
height: 30%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 2px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-image: image-url("bookmark_red.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_caption {
|
||||
padding-right: 30px;
|
||||
height: 100%;
|
||||
line-height: 100%;
|
||||
|
||||
// padding-top: 4px;
|
||||
box-sizing: border-box;
|
||||
|
||||
* {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jsxc_name {
|
||||
height: 100%;
|
||||
line-height: 40px;
|
||||
|
||||
.jsxc_min & {
|
||||
height: 50%;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.jsxc_rosteritem & {
|
||||
height: 50%;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_lastmsg {
|
||||
font-size: 12px;
|
||||
display: none;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
.jsxc_min & {
|
||||
display: block;
|
||||
height: 50%;
|
||||
line-height: 17.5px;
|
||||
}
|
||||
|
||||
.jsxc_rosteritem & {
|
||||
display: block;
|
||||
height: 50%;
|
||||
line-height: 17.5px;
|
||||
}
|
||||
|
||||
.jsxc_text {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.jsxc_unread {
|
||||
line-height: 100%;
|
||||
font-size: 8px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
display: none;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
border-radius: 50%;
|
||||
background-color: orange;
|
||||
vertical-align: top;
|
||||
margin: 0;
|
||||
float: none;
|
||||
|
||||
.jsxc_unreadMsg & {
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_emoticon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc_avatar {
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
#jsxc_presence {
|
||||
cursor: pointer;
|
||||
padding-left: 2px;
|
||||
overflow: hidden;
|
||||
|
||||
> span {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
// Presence indicator
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 10px;
|
||||
margin-top: -8px;
|
||||
border: 2px solid whitesmoke;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc_menu {
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
text-align: center;
|
||||
|
||||
&:hover > span {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> span {
|
||||
opacity: 0.5;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: image-url("menu_black.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center 10px;
|
||||
background-size: 17px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc_notice {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
float: right;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
|
||||
span {
|
||||
background-color: $notice_bg;
|
||||
border-radius: 11px;
|
||||
color: $notice_color;
|
||||
font-size: 80%;
|
||||
padding: 2px;
|
||||
position: relative;
|
||||
animation: bounce 2s 1s infinite;
|
||||
}
|
||||
|
||||
> span:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
.jsxc_online, .jsxc_chat, .jsxc_away, .jsxc_xa, .jsxc_dnd {
|
||||
&:before {
|
||||
content: " ";
|
||||
display: block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 100%;
|
||||
line-height: 12px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
z-index: 99;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 100%;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_online:before {
|
||||
background-color: $state_online;
|
||||
}
|
||||
|
||||
.jsxc_chat:before {
|
||||
background-image: image-url("presence_chat.svg");
|
||||
background-color: $state_chat;
|
||||
}
|
||||
|
||||
.jsxc_away:before {
|
||||
background-image: image-url("presence_away.svg");
|
||||
background-color: $state_away;
|
||||
}
|
||||
|
||||
.jsxc_xa:before {
|
||||
background-image: image-url("presence_xa.svg");
|
||||
background-color: $state_xa;
|
||||
}
|
||||
|
||||
.jsxc_dnd:before {
|
||||
background-image: image-url("presence_dnd.svg");
|
||||
background-color: $state_dnd;
|
||||
}
|
||||
|
||||
.jsxc_hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_invalid {
|
||||
border: 2px solid $invalid_border !important;
|
||||
}
|
||||
@@ -1,706 +0,0 @@
|
||||
#jsxc_windowList {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 210px;
|
||||
left: 0;
|
||||
z-index: 50;
|
||||
transition: right 0.5s;
|
||||
|
||||
&.jsxc_roster_hidden {
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
clip: rect(-10000px, 10000px, 30px, 30px);
|
||||
}
|
||||
|
||||
> ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
height: 44px;
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
transition: right 0.5s;
|
||||
|
||||
> li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
height: 44px;
|
||||
width: 46px;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
white-space: normal;
|
||||
|
||||
&.jsxc_normal {
|
||||
transition: width 0.2s;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
&.jsxc_min {
|
||||
transition: width 0.2s;
|
||||
width: 46px !important;
|
||||
|
||||
// overwrite resizeable width
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: 200px !important;
|
||||
}
|
||||
|
||||
.jsxc_emoticons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_tools {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc_windowListSB {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> {
|
||||
div {
|
||||
box-sizing: border-box;
|
||||
width: 14px;
|
||||
height: 100%;
|
||||
background-color: $windowListSB_bg;
|
||||
color: $windowListSB_color;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
background-color: $windowListSB_bg_hover;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_disabled {
|
||||
background-color: $windowListSB_bg_disabled !important;
|
||||
color: $windowListSB_color_disabled;
|
||||
cursor: default !important;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_bar {
|
||||
background-color: $window_bar_bg;
|
||||
cursor: pointer;
|
||||
height: 44px;
|
||||
line-height: 26px;
|
||||
padding: 2px;
|
||||
color: $window_bar_color;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
.jsxc_normal & {
|
||||
color: $window_bar_color_hover;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_tools {
|
||||
&:hover {
|
||||
.jsxc_normal & {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_min & {
|
||||
background-color: $window_min_bar_bg;
|
||||
color: $window_min_bar_color;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_window {
|
||||
position: absolute;
|
||||
bottom: -284px;
|
||||
top: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: auto;
|
||||
background-color: $window_bg;
|
||||
z-index: 80;
|
||||
cursor: default;
|
||||
border: 1px solid $window_border;
|
||||
border-bottom: 0;
|
||||
|
||||
.jsxc_min & {
|
||||
transition: bottom 0.2s;
|
||||
}
|
||||
|
||||
.jsxc_normal & {
|
||||
transition: bottom 0.2s;
|
||||
}
|
||||
|
||||
.jsxc_showOverlay & {
|
||||
.jsxc_overlay {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_emoticons {
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:after {
|
||||
content: " ";
|
||||
background-image: image-url("smiley.svg");
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 30px 30px;
|
||||
opacity: 0.3;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.jsxc_inner {
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
ul {
|
||||
width: 210px;
|
||||
margin-bottom: 8px;
|
||||
background-color: $emoticon_selection_bg;
|
||||
border-radius: 3px;
|
||||
z-index: 200;
|
||||
list-style-type: none;
|
||||
padding: 3px;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
border-left: 8px solid transparent;
|
||||
border-right: 8px solid transparent;
|
||||
border-top: 8px solid $emoticon_selection_bg;
|
||||
display: block;
|
||||
width: 0;
|
||||
z-index: 1;
|
||||
left: 7px;
|
||||
top: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
div {
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
background-size: 30px 30px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
&:hover {
|
||||
background-color: $emoticon_selection_hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:after {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_fade {
|
||||
position: relative;
|
||||
|
||||
.jsxc_overlay {
|
||||
display: none;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
overflow-y: scroll;
|
||||
|
||||
> div {
|
||||
background-color: #fff;
|
||||
margin: 30px 10px;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
.jsxc_close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
|
||||
&:after {
|
||||
content: "×";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
font-size: 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
cursor: pointer;
|
||||
color: #000;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_body {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
li {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_avatar {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.jsxc_textarea {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.slimScrollDiv {
|
||||
margin: 0 0 6px;
|
||||
left: auto !important;
|
||||
top: auto !important;
|
||||
}
|
||||
|
||||
textarea {
|
||||
&.jsxc_textinput {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
margin: 0;
|
||||
padding: 14px 40px 12px;
|
||||
outline: none;
|
||||
border-radius: 0;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
display: block;
|
||||
resize: none;
|
||||
transition: height 0.5s;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: $window_placeholder;
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_tools {
|
||||
float: right;
|
||||
|
||||
> .jsxc_disabled {
|
||||
opacity: 0.3;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
> div {
|
||||
width: 25px;
|
||||
height: 40px;
|
||||
display: block;
|
||||
float: left;
|
||||
color: $tools_color;
|
||||
opacity: 0.4;
|
||||
font-family: $font_sans;
|
||||
line-height: 40px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
|
||||
&.jsxc_settings {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_close {
|
||||
font-size: 20px;
|
||||
|
||||
&:hover {
|
||||
color: $window_close_hover;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_more {
|
||||
background-image: image-url("more_white.svg");
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.ui-resizable-w {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.ui-resizable-nw {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
z-index: 95 !important;
|
||||
background-image: image-url("resize_gray.svg");
|
||||
}
|
||||
|
||||
.ui-resizable-n {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 15px;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_chatmessage {
|
||||
margin: 3px;
|
||||
padding: 4px;
|
||||
word-wrap: break-word;
|
||||
background-color: $chatmessage_bg;
|
||||
position: relative;
|
||||
outline: none;
|
||||
clear: both;
|
||||
|
||||
&.jsxc_error {
|
||||
opacity: 0.7;
|
||||
|
||||
&:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 3px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: yellow;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $chatmessage_a;
|
||||
text-decoration: underline;
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
|
||||
&[download]:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 5px;
|
||||
left: 0;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
background-image: url("../img/download_icon_black.svg");
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
|
||||
&[download]:hover {
|
||||
&:before {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.jsxc_avatar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_attachment {
|
||||
border-radius: 3px;
|
||||
background-color: #fff;
|
||||
padding: 3px;
|
||||
padding-left: 30px;
|
||||
min-height: 30px;
|
||||
margin-bottom: 5px;
|
||||
background-position: 3px center;
|
||||
background-size: 25px 25px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: image-url("filetypes/file.svg");
|
||||
|
||||
img {
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&.jsxc_image {
|
||||
line-height: 0;
|
||||
padding: 0;
|
||||
background-image: url("");
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&.jsxc_application {
|
||||
background-image: image-url("filetypes/application.svg");
|
||||
}
|
||||
|
||||
&.jsxc_application-pdf {
|
||||
background-image: image-url("filetypes/application-pdf.svg");
|
||||
}
|
||||
|
||||
&.jsxc_audio {
|
||||
background-image: image-url("filetypes/audio.svg");
|
||||
}
|
||||
|
||||
&.jsxc_video {
|
||||
background-image: image-url("filetypes/video.svg");
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.jsxc_text {
|
||||
background-image: image-url("filetypes/text.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_timestamp {
|
||||
font-size: 8px;
|
||||
color: $chatmessage_timestamp;
|
||||
line-height: 8px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.jsxc_encrypted {
|
||||
&.jsxc_received.jsxc_out .jsxc_timestamp {
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.jsxc_timestamp:after {
|
||||
content: " ";
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 8px;
|
||||
margin-left: 2px;
|
||||
background-image: image-url("padlock_close_grey.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_in {
|
||||
float: left;
|
||||
position: relative;
|
||||
max-width: 76%;
|
||||
margin-left: 10px;
|
||||
border-radius: 3px;
|
||||
background-color: $chatmessage_in_bg;
|
||||
|
||||
&:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
border-style: solid;
|
||||
border-width: 5px 6px 5px 0;
|
||||
border-color: transparent $chatmessage_in_bg;
|
||||
display: block;
|
||||
width: 0;
|
||||
z-index: 1;
|
||||
left: -6px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
.jsxc_timestamp {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_out {
|
||||
float: right;
|
||||
position: relative;
|
||||
max-width: 76%;
|
||||
margin-right: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 3px;
|
||||
background-color: $chatmessage_out_bg;
|
||||
|
||||
&:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
border-style: solid;
|
||||
border-width: 5px 0 5px 6px;
|
||||
border-color: transparent $chatmessage_out_bg;
|
||||
display: block;
|
||||
width: 0;
|
||||
z-index: 1;
|
||||
right: -6px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
&.jsxc_received {
|
||||
&:before {
|
||||
content: "✓";
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
right: 2px;
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
color: $chatmessage_received;
|
||||
}
|
||||
|
||||
.jsxc_timestamp {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_timestamp {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_sys {
|
||||
width: auto;
|
||||
max-width: none;
|
||||
padding-right: 4px;
|
||||
box-sizing: border-box;
|
||||
margin-right: 3px;
|
||||
border-radius: 3px;
|
||||
background-color: transparent;
|
||||
font-size: 0.8em;
|
||||
font-style: italic;
|
||||
|
||||
.jsxc_emoticon {
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&.jsxc_composing {
|
||||
text-align: center;
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
display: block;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
transition: opacity 0.6s;
|
||||
|
||||
&:before {
|
||||
content: " ";
|
||||
width: 1.5em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
background-size: 80%;
|
||||
background-repeat: no-repeat;
|
||||
margin: 0 3px 0 0;
|
||||
background-image: image-url("composing.png");
|
||||
}
|
||||
|
||||
&.jsxc_fadein {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.jsxc_settings {
|
||||
position: relative;
|
||||
|
||||
.jsxc_inner {
|
||||
left: auto;
|
||||
top: 100%;
|
||||
right: -6px;
|
||||
}
|
||||
}
|
||||
|
||||
div.jsxc_transfer {
|
||||
background-image: image-url("padlock_open_black.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: 14px 14px;
|
||||
opacity: 0.3;
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.jsxc_disabled {
|
||||
background-image: image-url("padlock_open_disabled_black.svg");
|
||||
cursor: default;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
&.jsxc_fin {
|
||||
opacity: 1;
|
||||
background-image: image-url("padlock_close_grey.svg");
|
||||
}
|
||||
|
||||
&.jsxc_enc {
|
||||
opacity: 1;
|
||||
background-image: image-url("padlock_close_orange.svg");
|
||||
|
||||
&.jsxc_trust {
|
||||
background-image: image-url("padlock_close_green.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
@import "colors";
|
||||
@import "dep";
|
||||
|
||||
//fonts
|
||||
$font_sans: Arial, sans-serif;
|
||||
$font_serif: serif;
|
||||
|
||||
@import "modules";
|
||||
@import "buddylist";
|
||||
@import "state";
|
||||
@import "emoticons";
|
||||
@import "roster";
|
||||
@import "window";
|
||||
@import "muc";
|
||||
|
||||
@import "_jsxc";
|
||||
@import "webrtc";
|
||||
@@ -0,0 +1,20 @@
|
||||
@import "modules/all";
|
||||
@import "vendor/all";
|
||||
|
||||
//fonts
|
||||
$font_sans: Arial, sans-serif;
|
||||
$font_serif: serif;
|
||||
|
||||
@import "partials/button";
|
||||
@import "partials/dialog";
|
||||
@import "partials/emoticons";
|
||||
@import "partials/icon";
|
||||
@import "partials/jsxc";
|
||||
@import "partials/menu";
|
||||
@import "partials/roster";
|
||||
@import "partials/webrtc";
|
||||
@import "partials/window-list";
|
||||
@import "partials/window";
|
||||
|
||||
@import "partials/jsxc";
|
||||
@import "partials/webrtc";
|
||||
@@ -0,0 +1,5 @@
|
||||
@import "animation";
|
||||
@import "colors";
|
||||
@import "muc";
|
||||
@import "webrtc";
|
||||
@import "presence";
|
||||
@@ -25,12 +25,23 @@ $dialog_input_invalid: $red;
|
||||
$dialog_input_readonly_bg: $gray90;
|
||||
$spot_bg: $white;
|
||||
$spot_border: $black;
|
||||
|
||||
$state_online: green;
|
||||
$state_chat: green;
|
||||
$state_away: $orange;
|
||||
$state_xa: $orange;
|
||||
$state_dnd: $red;
|
||||
$state_offline: $gray60;
|
||||
|
||||
$presenceColors: (
|
||||
online: green,
|
||||
chat: green,
|
||||
away: $orange,
|
||||
xa: $orange,
|
||||
dnd: $red,
|
||||
offline: $gray60
|
||||
);
|
||||
|
||||
$notice_bg: $orange;
|
||||
$notice_color: $black;
|
||||
$window_unread_cycle: $orange;
|
||||
@@ -0,0 +1,6 @@
|
||||
%muc-avatar-icon {
|
||||
text-indent: 999px;
|
||||
background-image: url("../img/group_white.svg");
|
||||
background-size: 70% 70% !important;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
$presences: online chat away xa dnd;
|
||||
|
||||
@mixin presenceIndicator($target) {
|
||||
|
||||
@each $presence in $presences {
|
||||
[data-presence="#{$presence}"] #{$target} {
|
||||
&:before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 100%;
|
||||
line-height: 12px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
z-index: 99;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 100%;
|
||||
box-sizing: content-box;
|
||||
background-image: url("../img/presence_#{$presence}.svg");
|
||||
background-color: map-get($presenceColors, $presence);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
%fullscreen {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9000;
|
||||
background-color: $fullscreen_bg;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
.jsxc-btn {
|
||||
width: auto;
|
||||
min-width: 25px;
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
margin: 0 2px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 1.42857143;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.5s;
|
||||
|
||||
&.jsxc-btn-default {
|
||||
border-color: #ccc;
|
||||
color: #555;
|
||||
background-color: rgba(240, 240, 240, 0.9);
|
||||
|
||||
&:hover {
|
||||
background-color: #d6d6d6;
|
||||
}
|
||||
}
|
||||
|
||||
&.jsxc-btn-primary {
|
||||
color: #fff;
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
|
||||
&:hover {
|
||||
background-color: #296496;
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled], &[disabled]:hover {
|
||||
opacity: 0.65;
|
||||
cursor: not-allowed;
|
||||
color: #fff;
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
.jsxc-dialog {
|
||||
padding: 20px;
|
||||
min-width: 320px;
|
||||
max-width: 100%;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
position: relative;
|
||||
background: #FFF;
|
||||
width: auto;
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1em;
|
||||
|
||||
input {
|
||||
margin-bottom: 5px;
|
||||
width: 60%;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type='submit'] {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-top: 1px solid #eee;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.jsxc-right {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
form {
|
||||
fieldset {
|
||||
margin-bottom: 30px;
|
||||
padding: 0 30px;
|
||||
border: 1px solid #d9d9d9;
|
||||
|
||||
h3 {
|
||||
font-size: 15px;
|
||||
color: #000;
|
||||
background-color: #f2f2f2;
|
||||
padding: 10px;
|
||||
margin: 0 -30px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
legend {
|
||||
border: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
input {
|
||||
outline: none;
|
||||
|
||||
&:invalid {
|
||||
border: 1px solid $dialog_input_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group button {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
input[readonly] {
|
||||
background-color: $dialog_input_readonly_bg;
|
||||
}
|
||||
|
||||
.jsxc-inputinfo {
|
||||
padding: 0;
|
||||
font-style: italic;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.jsxc-waiting {
|
||||
&:before {
|
||||
content: " ";
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
background-size: 100%;
|
||||
margin: 0 3px 0 0;
|
||||
background-image: url("../img/loading.gif");
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-libraries, .jsxc-credits {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.jsxc-warning {
|
||||
display: block;
|
||||
background-color: #fbfe7a;
|
||||
padding: 3px 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
.jsxc_emoticon {
|
||||
.jsxc-emoticon {
|
||||
display: inline-block;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
@@ -6,14 +6,14 @@
|
||||
border: 0;
|
||||
vertical-align: bottom;
|
||||
|
||||
&.jsxc_large {
|
||||
&.jsxc-large {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc_roster .jsxc_emoticon.jsxc_large {
|
||||
#jsxc-roster .jsxc-emoticon.jsxc-large {
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
$emoticons: angel, angry, smile, grin, sad, wink, tonguesmile, surpised, kiss, sunglassess, crysad, doubt, zip, thumbsup, thumbsdown, beer, devil, kissing, rose, music, love, tired, surprised;
|
||||
|
||||
@each $emoticon in $emoticons {
|
||||
.jsxc_#{$emoticon} {
|
||||
background: image-url("emotions/#{$emoticon}.png");
|
||||
.jsxc-#{$emoticon} {
|
||||
background: url("../img/emotions/#{$emoticon}.png");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
.jsxc-icon-edit {
|
||||
background-image: url("../img/edit_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-delete {
|
||||
background-image: url("../img/delete_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-chat {
|
||||
background-image: url("../img/speech_balloon_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-video {
|
||||
background-image: url("../img/camera_icon_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-info {
|
||||
background-image: url("../img/info_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-setting {
|
||||
background-image: url("../img/gear_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-help {
|
||||
background-image: url("../img/help_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-contact {
|
||||
background-image: url("../img/contact_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-groupcontact {
|
||||
background-image: url("../img/groupcontact_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-bookmark {
|
||||
background-image: url("../img/bookmark_black.svg");
|
||||
}
|
||||
|
||||
.jsxc-icon-announcement {
|
||||
background-image: url("../img/megaphone_icon_black.svg");
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
.jsxc-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.jsxc-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.jsxc-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc-clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.jsxc-uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.jsxc-separator {
|
||||
border-top: 1px solid $separator;
|
||||
}
|
||||
|
||||
.jsxc-name {
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.jsxc-max-width {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.jsxc-meta {
|
||||
text-align: right;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.jsxc-invalid {
|
||||
border: 2px solid $invalid_border !important;
|
||||
}
|
||||
|
||||
.jsxc-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
margin: 0 5px;
|
||||
background-color: $avatar_bg;
|
||||
border-radius: 50%;
|
||||
float: left;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 30px;
|
||||
color: $avatar_color;
|
||||
position: relative;
|
||||
font-family: $font_sans;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -6px;
|
||||
border: 2px solid $roster_bg;
|
||||
}
|
||||
}
|
||||
|
||||
ul.jsxc-vCard {
|
||||
min-width: 400px;
|
||||
|
||||
ul {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
li {
|
||||
cursor: default !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Spot which is attached to xmpp: uris
|
||||
.jsxc-spot {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
text-indent: -99999em;
|
||||
margin-top: 3px;
|
||||
margin-right: 5px;
|
||||
line-height: 100%;
|
||||
cursor: pointer;
|
||||
border: 1px solid $spot_border;
|
||||
background-color: $white;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&.jsxc-online, &.jsxc-chat, &.jsxc-away, &.jsxc-xa, &.jsxc-dnd, &.jsxc-offline {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-unread {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc-unreadMsg {
|
||||
.jsxc-name {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.jsxc-unread {
|
||||
display: block;
|
||||
background-color: $unread_bg;
|
||||
border-radius: 11px;
|
||||
color: $unread_color;
|
||||
font-size: 80%;
|
||||
padding: 2px;
|
||||
line-height: 15px;
|
||||
float: right;
|
||||
margin-right: 3px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-loading {
|
||||
margin: 0 auto;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 0;
|
||||
background-size: 32px 32px !important;
|
||||
background: url("../img/loading.gif");
|
||||
}
|
||||
|
||||
// @TODO: check
|
||||
#jsxc-login-form input[type='submit'] {
|
||||
height: 34px;
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
margin-bottom: 0;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
line-height: 1.428571429;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
user-select: none;
|
||||
color: $white;
|
||||
background-color: $loginForm_bg;
|
||||
border-color: $loginForm_border;
|
||||
}
|
||||
|
||||
.jsxc-oneway .jsxc-avatar {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
img.jsxc-vCard {
|
||||
float: right;
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
border: 5px solid $white;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsxc-alert {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
|
||||
&.jsxc-alert-warning {
|
||||
color: #8a6d3b;
|
||||
background-color: #fcf8e3;
|
||||
border-color: #faebcc;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-more {
|
||||
float: right;
|
||||
width: 44px;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
background-image: url("../img/more_black.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
opacity: 0.4;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: 25px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
.jsxc-menu {
|
||||
.jsxc-inner {
|
||||
box-sizing: border-box;
|
||||
max-height: 0;
|
||||
transition: max-height 0.5s;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&.jsxc-opened {
|
||||
.jsxc-inner {
|
||||
max-height: 1000px;
|
||||
visibility: visible;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
border: 0;
|
||||
cursor: auto;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-menu-dropdown {
|
||||
.jsxc-inner {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #FFF;
|
||||
color: #333;
|
||||
border-radius: 3px;
|
||||
z-index: 110;
|
||||
margin: 8px 2px 5px 10px;
|
||||
right: 0;
|
||||
filter: drop-shadow(0 0 5px rgba(150, 150, 150, 0.75));
|
||||
padding: 4px 12px 4px 5px;
|
||||
top: 100%;
|
||||
bottom: auto;
|
||||
overflow: visible;
|
||||
|
||||
&:after {
|
||||
bottom: 100%;
|
||||
right: 6px;
|
||||
border: solid transparent;
|
||||
content: " ";
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border-color: rgba(238, 238, 238, 0);
|
||||
border-bottom-color: #fff;
|
||||
border-width: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: #000;
|
||||
opacity: 0.5;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.jsxc-disabled {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.5;
|
||||
|
||||
&:hover {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
span {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
display: inline-block;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
vertical-align: sub;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,15 @@
|
||||
%muc-avatar-icon {
|
||||
text-indent: 999px;
|
||||
background-image: image-url("group_white.svg");
|
||||
background-size: 70% 70% !important;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.jsxc_windowItem {
|
||||
&.jsxc_groupchat.jsxc_normal {
|
||||
.jsxc_fade {
|
||||
.jsxc-window-item {
|
||||
&.jsxc-groupchat.jsxc-normal {
|
||||
.jsxc-fade {
|
||||
padding-top: 44px;
|
||||
}
|
||||
|
||||
.jsxc_fingerprints, .jsxc_verification, .jsxc_transfer, .jsxc_video, .jsxc_sendFile {
|
||||
.jsxc-fingerprints, .jsxc-verification, .jsxc-transfer, .jsxc-video, .jsxc-sendFile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_members {
|
||||
background-image: image-url("group_white.svg");
|
||||
.jsxc-members {
|
||||
background-image: url("../img/group_white.svg");
|
||||
background-size: 15px 15px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
@@ -26,10 +19,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_chatmessage.jsxc_in {
|
||||
.jsxc-chatmessage.jsxc-in {
|
||||
margin-left: 50px;
|
||||
|
||||
.jsxc_avatar {
|
||||
.jsxc-avatar {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
@@ -42,14 +35,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_bar {
|
||||
.jsxc_avatar {
|
||||
.jsxc-bar {
|
||||
.jsxc-avatar {
|
||||
@extend %muc-avatar-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_memberlist {
|
||||
.jsxc-memberlist {
|
||||
height: 44px;
|
||||
width: 100%;
|
||||
background-color: $window_bar_bg;
|
||||
@@ -79,18 +72,18 @@
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.jsxc_name {
|
||||
.jsxc-name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_avatar {
|
||||
.jsxc-avatar {
|
||||
margin-left: 2px;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.jsxc_expand {
|
||||
&.jsxc-expand {
|
||||
ul {
|
||||
white-space: normal;
|
||||
|
||||
@@ -100,7 +93,7 @@
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
|
||||
.jsxc_name {
|
||||
.jsxc-name {
|
||||
display: block;
|
||||
cursor: default;
|
||||
|
||||
@@ -109,7 +102,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_avatar {
|
||||
.jsxc-avatar {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
@@ -119,11 +112,11 @@
|
||||
}
|
||||
|
||||
li[data-type='groupchat'] {
|
||||
.jsxc_avatar {
|
||||
.jsxc-avatar {
|
||||
@extend %muc-avatar-icon;
|
||||
}
|
||||
|
||||
.jsxc_video {
|
||||
.jsxc-video {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,492 @@
|
||||
#jsxc-roster {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 200px;
|
||||
overflow: visible;
|
||||
border-left: 1px solid #e1e1e1;
|
||||
z-index: 80;
|
||||
margin-left: 10px;
|
||||
background-color: $roster_bg;
|
||||
transition: right 0.5s;
|
||||
|
||||
.jsxc-roster-hidden & {
|
||||
right: -200px;
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jsxc-avatar {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-wait {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 160px;
|
||||
padding: 20px;
|
||||
background-color: $white;
|
||||
z-index: 60;
|
||||
|
||||
img {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 5px;
|
||||
font-size: 1.13em;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
height: 35px;
|
||||
padding: 7px 6px 5px;
|
||||
font-size: 13px;
|
||||
width: 145px;
|
||||
border: 1px solid #ddd;
|
||||
box-sizing: border-box;
|
||||
background-image: none;
|
||||
background-color: $roster_input_bg;
|
||||
border-radius: 3px;
|
||||
box-shadow: inner 0 0 5px $roster_input_shadow;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
p {
|
||||
color: $roster_color;
|
||||
padding: 10px;
|
||||
|
||||
a {
|
||||
color: $roster_a;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-expand input {
|
||||
left: 51px;
|
||||
width: 137px;
|
||||
}
|
||||
|
||||
&.jsxc-state_hidden {
|
||||
display: block;
|
||||
right: -200px;
|
||||
transition: right 0.5s;
|
||||
}
|
||||
|
||||
&.jsxc-state_shown {
|
||||
display: block;
|
||||
right: 0;
|
||||
transition: right 0.5s;
|
||||
}
|
||||
|
||||
> .jsxc-bottom {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
line-height: 34px;
|
||||
background-color: $roster_bottom_bg;
|
||||
z-index: 50;
|
||||
padding-right: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: $roster_bottom_bg_hover;
|
||||
}
|
||||
|
||||
.jsxc-inner {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
border-top: 1px solid $roster_bottom_border_top;
|
||||
background-color: $roster_bottom_bg;
|
||||
|
||||
li:last-child {
|
||||
border-bottom: 1px solid $roster_bottom_border_top;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
height: 44px;
|
||||
background-color: $roster_bottom_bg;
|
||||
color: $roster_bottom_color;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
padding-left: 44px;
|
||||
line-height: 44px;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 15px center;
|
||||
background-size: 16px 16px;
|
||||
opacity: 0.8;
|
||||
|
||||
&.jsxc-disabled {
|
||||
color: $roster_bottom_disabled;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&:hover:not(.jsxc-disabled) {
|
||||
color: $roster_bottom_color_hover;
|
||||
background-color: $roster_bottom_bg_hover;
|
||||
}
|
||||
|
||||
&.jsxc-warning {
|
||||
background-color: $warning_bg;
|
||||
|
||||
&:hover {
|
||||
background-color: $warning_bg_hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div > span {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
padding: 15px;
|
||||
|
||||
button,
|
||||
input {
|
||||
width: 100%;
|
||||
margin: 0 0 5px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #dadada;
|
||||
border-color: #c1c1c1;
|
||||
transition: background-color 0.5s;
|
||||
|
||||
&:hover {
|
||||
background-color: #a2a2a2;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-roster-status {
|
||||
display: none;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&.jsxc-status-show {
|
||||
.jsxc-roster-status {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.jsxc-bottom, .jsxc-contact-list {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-roster-toggle {
|
||||
width: 14px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: -14px;
|
||||
top: 0;
|
||||
z-index: 110;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: $roster_toggle_hover;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-roster-item {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 44px;
|
||||
border-bottom: 1px solid $roster_bottom_border_top;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
color: $roster_color;
|
||||
font-family: $font_sans;
|
||||
line-height: 44px;
|
||||
padding-left: 6px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:hover {
|
||||
background-color: $roster_bg_hover;
|
||||
}
|
||||
|
||||
&.jsxc-bookmarked {
|
||||
.jsxc-avatar:after {
|
||||
content: " ";
|
||||
width: 20%;
|
||||
height: 30%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 2px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("../img/bookmark_red.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-caption {
|
||||
padding-right: 30px;
|
||||
height: 100%;
|
||||
line-height: 100%;
|
||||
// padding-top: 4px;
|
||||
box-sizing: border-box;
|
||||
|
||||
* {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jsxc-name {
|
||||
height: 100%;
|
||||
line-height: 40px;
|
||||
|
||||
.jsxc-min & {
|
||||
height: 50%;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.jsxc-rosteritem & {
|
||||
height: 50%;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-lastmsg {
|
||||
font-size: 12px;
|
||||
display: none;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
.jsxc-min & {
|
||||
display: block;
|
||||
height: 50%;
|
||||
line-height: 17.5px;
|
||||
}
|
||||
|
||||
.jsxc-rosteritem & {
|
||||
display: block;
|
||||
height: 50%;
|
||||
line-height: 17.5px;
|
||||
}
|
||||
|
||||
.jsxc-text {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.jsxc-unread {
|
||||
line-height: 100%;
|
||||
font-size: 8px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
display: none;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
border-radius: 50%;
|
||||
background-color: orange;
|
||||
vertical-align: top;
|
||||
margin: 0;
|
||||
float: none;
|
||||
|
||||
.jsxc-unreadMsg & {
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-emoticon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-menu-presence {
|
||||
cursor: pointer;
|
||||
padding-left: 2px;
|
||||
overflow: hidden;
|
||||
|
||||
> span {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
// Presence indicator
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 10px;
|
||||
margin-top: -8px;
|
||||
border: 2px solid whitesmoke;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-menu-main {
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
text-align: center;
|
||||
|
||||
&:hover > span {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> span {
|
||||
opacity: 0.5;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("../img/menu_black.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center 10px;
|
||||
background-size: 17px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc-notice {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
float: right;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
|
||||
span {
|
||||
background-color: $notice_bg;
|
||||
border-radius: 11px;
|
||||
color: $notice_color;
|
||||
font-size: 80%;
|
||||
padding: 2px;
|
||||
position: relative;
|
||||
animation: bounce 2s 1s infinite;
|
||||
}
|
||||
|
||||
> span:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-contact-list {
|
||||
@include presenceIndicator(".jsxc-avatar");
|
||||
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 204px;
|
||||
z-index: 85;
|
||||
|
||||
&.jsxc-hide-offline {
|
||||
.jsxc-roster-item[data-status='offline'] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-unreadMsg {
|
||||
.jsxc-name {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-oneway {
|
||||
.jsxc-avatar,
|
||||
.jsxc-caption {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-right {
|
||||
float: right;
|
||||
margin-right: 6px;
|
||||
|
||||
div {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
color: $white;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-menu {
|
||||
float: right;
|
||||
height: 100%;
|
||||
width: 42px;
|
||||
|
||||
> span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-image: url("../img/more_black.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
opacity: 0.6;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-inner {
|
||||
left: auto;
|
||||
right: 5px;
|
||||
padding: 4px;
|
||||
overflow: visible;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
line-height: 42px;
|
||||
width: 42px;
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,5 @@
|
||||
@import "colors";
|
||||
|
||||
%fullscreen {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9000;
|
||||
background-color: $fullscreen_bg;
|
||||
}
|
||||
|
||||
#jsxc_webrtc {
|
||||
#jsxc-webrtc {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
@@ -19,7 +8,7 @@
|
||||
z-index: 9999;
|
||||
background-color: black;
|
||||
|
||||
.jsxc_status {
|
||||
.jsxc-status {
|
||||
z-index: 9999;
|
||||
border-radius: 20px;
|
||||
display: none;
|
||||
@@ -37,7 +26,7 @@
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
li .jsxc_name {
|
||||
li .jsxc-name {
|
||||
cursor: auto;
|
||||
|
||||
&:hover {
|
||||
@@ -46,7 +35,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_establishing, .jsxc_ringing {
|
||||
.jsxc-establishing, .jsxc-ringing {
|
||||
&:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
@@ -62,14 +51,14 @@
|
||||
$establishingColor1: #a1a1a1;
|
||||
$establishingColor2: #f1f1f1;
|
||||
|
||||
.jsxc_establishing:before {
|
||||
.jsxc-establishing:before {
|
||||
content: " ";
|
||||
display: block;
|
||||
width: 40px;
|
||||
height: 10px;
|
||||
box-sizing: border-box;
|
||||
background-color: $establishingColor1;
|
||||
animation-name: jsxc_establishing;
|
||||
animation-name: jsxc-establishing;
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
position: absolute;
|
||||
@@ -80,7 +69,7 @@ $establishingColor2: #f1f1f1;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
@keyframes jsxc_establishing {
|
||||
@keyframes jsxc-establishing {
|
||||
0% {
|
||||
border-width: 0;
|
||||
background-color: $establishingColor1;
|
||||
@@ -105,7 +94,7 @@ $establishingColor2: #f1f1f1;
|
||||
$ringingColor1: #98d48f;
|
||||
$ringingColor2: #76ba6c;
|
||||
|
||||
.jsxc_ringing:before {
|
||||
.jsxc-ringing:before {
|
||||
content: " ";
|
||||
display: block;
|
||||
width: 20px;
|
||||
@@ -113,7 +102,7 @@ $ringingColor2: #76ba6c;
|
||||
box-sizing: border-box;
|
||||
background-color: $ringingColor1;
|
||||
border-radius: 50%;
|
||||
animation-name: jsxc_ringing;
|
||||
animation-name: jsxc-ringing;
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
position: absolute;
|
||||
@@ -124,7 +113,7 @@ $ringingColor2: #76ba6c;
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
@keyframes jsxc_ringing {
|
||||
@keyframes jsxc-ringing {
|
||||
0% {
|
||||
background-color: $ringingColor1;
|
||||
width: 20px;
|
||||
@@ -150,17 +139,17 @@ $ringingColor2: #76ba6c;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_bell:before {
|
||||
.jsxc-bell:before {
|
||||
content: " ";
|
||||
display: block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
box-sizing: border-box;
|
||||
background-image: image-url("bell.svg");
|
||||
background-image: url("../img/bell.svg");
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
animation-name: jsxc_ringing;
|
||||
animation-name: jsxc-ringing;
|
||||
animation-duration: 1.5s;
|
||||
animation-iteration-count: infinite;
|
||||
position: absolute;
|
||||
@@ -171,7 +160,7 @@ $ringingColor2: #76ba6c;
|
||||
margin-top: -40px;
|
||||
}
|
||||
|
||||
@keyframes jsxc_bell {
|
||||
@keyframes jsxc-bell {
|
||||
0% {
|
||||
margin-left: -50px;
|
||||
}
|
||||
@@ -205,7 +194,7 @@ $ringingColor2: #76ba6c;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_videoContainer {
|
||||
.jsxc-videoContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -213,7 +202,7 @@ $ringingColor2: #76ba6c;
|
||||
bottom: 0;
|
||||
background-color: $video_bg;
|
||||
|
||||
&.jsxc_minimized {
|
||||
&.jsxc-minimized {
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
@@ -223,7 +212,7 @@ $ringingColor2: #76ba6c;
|
||||
background-color: transparent;
|
||||
box-shadow: 0 0 10px #a1a1a1;
|
||||
|
||||
.jsxc_localvideo {
|
||||
.jsxc-localvideo {
|
||||
position: static;
|
||||
display: block;
|
||||
}
|
||||
@@ -233,30 +222,30 @@ $ringingColor2: #76ba6c;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo {
|
||||
.jsxc-noRemoteVideo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
right: 250px;
|
||||
|
||||
.jsxc_controlbar {
|
||||
.jsxc-controlbar {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.jsxc_controlbar {
|
||||
.jsxc-controlbar {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_remotevideo {
|
||||
.jsxc-remotevideo {
|
||||
@extend %fullscreen;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo {
|
||||
.jsxc-noRemoteVideo {
|
||||
@extend %fullscreen;
|
||||
|
||||
p {
|
||||
@@ -303,7 +292,7 @@ $ringingColor2: #76ba6c;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_localvideo {
|
||||
.jsxc-localvideo {
|
||||
width: 160px;
|
||||
height: 120px;
|
||||
position: absolute;
|
||||
@@ -320,7 +309,7 @@ div {
|
||||
height: 100%;
|
||||
background-color: $black;
|
||||
|
||||
&.jsxc_localvideo {
|
||||
&.jsxc-localvideo {
|
||||
border: 1px solid $white;
|
||||
}
|
||||
}
|
||||
@@ -330,23 +319,23 @@ div {
|
||||
height: 100%;
|
||||
background-color: $black;
|
||||
|
||||
&.jsxc_localvideo {
|
||||
&.jsxc-localvideo {
|
||||
border: 1px solid $white;
|
||||
}
|
||||
}
|
||||
|
||||
&.jsxc_video {
|
||||
background-image: image-url("camera_icon_white.svg");
|
||||
&.jsxc-video {
|
||||
background-image: url("../img/camera_icon_white.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: 15px 15px;
|
||||
opacity: 0.4;
|
||||
|
||||
&.jsxc_disabled {
|
||||
background-image: image-url("camera_disabled_icon_white.svg");
|
||||
&.jsxc-disabled {
|
||||
background-image: url("../img/camera_disabled_icon_white.svg");
|
||||
}
|
||||
|
||||
&:not(.jsxc_disabled) {
|
||||
&:not(.jsxc-disabled) {
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
@@ -354,7 +343,7 @@ div {
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_controlbar {
|
||||
.jsxc-controlbar {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 0;
|
||||
@@ -369,7 +358,7 @@ div {
|
||||
top: initial;
|
||||
}
|
||||
|
||||
&.jsxc_visible {
|
||||
&.jsxc-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -381,7 +370,7 @@ div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.jsxc_videoControl {
|
||||
.jsxc-videoControl {
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
margin: 0 5px;
|
||||
@@ -397,24 +386,24 @@ div {
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_hangUp {
|
||||
background-image: image-url("hang_up_red.svg");
|
||||
.jsxc-hangUp {
|
||||
background-image: url("../img/hang_up_red.svg");
|
||||
}
|
||||
|
||||
.jsxc_fullscreen {
|
||||
background-image: image-url("fullscreen_white.svg");
|
||||
.jsxc-fullscreen {
|
||||
background-image: url("../img/fullscreen_white.svg");
|
||||
}
|
||||
|
||||
.jsxc_showchat {
|
||||
.jsxc-showchat {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_multi > div {
|
||||
.jsxc-multi > div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_snapshotbar {
|
||||
.jsxc-snapshotbar {
|
||||
width: 100%;
|
||||
display: none;
|
||||
|
||||
@@ -423,7 +412,7 @@ div {
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_buttongroup {
|
||||
.jsxc-buttongroup {
|
||||
display: inline;
|
||||
|
||||
button {
|
||||
@@ -441,7 +430,7 @@ div {
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_chatarea {
|
||||
.jsxc-chatarea {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@@ -454,21 +443,21 @@ div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.jsxc_settings {
|
||||
.jsxc-settings {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.jsxc_close {
|
||||
.jsxc-close {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.jsxc_video {
|
||||
.jsxc-video {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.jsxc_bar {}
|
||||
.jsxc-bar {}
|
||||
|
||||
.jsxc_window {
|
||||
.jsxc-window {
|
||||
bottom: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
@@ -481,10 +470,10 @@ div {
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc_fullscreen.jsxc_localvideo {
|
||||
.jsxc-fullscreen.jsxc-localvideo {
|
||||
border: 1px solid $white;
|
||||
}
|
||||
|
||||
.jsxc_videoSuitable .jsxc_name {
|
||||
.jsxc-videoSuitable .jsxc-name {
|
||||
font-style: italic;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
#jsxc-window-list {
|
||||
@include presenceIndicator(".jsxc-window-bar .jsxc-avatar");
|
||||
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 210px;
|
||||
left: 0;
|
||||
z-index: 50;
|
||||
transition: right 0.5s;
|
||||
|
||||
.jsxc-roster-hidden & {
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
clip: rect(-10000px, 10000px, 30px, 30px);
|
||||
}
|
||||
|
||||
> ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
height: 44px;
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
transition: right 0.5s;
|
||||
|
||||
> li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
height: 44px;
|
||||
width: 46px;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
white-space: normal;
|
||||
|
||||
&.jsxc-normal {
|
||||
transition: width 0.2s;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
&.jsxc-minimized {
|
||||
transition: width 0.2s;
|
||||
width: 46px !important;
|
||||
// overwrite resizeable width
|
||||
@media (min-width: 768px) {
|
||||
width: 200px !important;
|
||||
}
|
||||
|
||||
.jsxc-emoticons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc-tools {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc-window-list-handler {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> {
|
||||
div {
|
||||
box-sizing: border-box;
|
||||
width: 14px;
|
||||
height: 100%;
|
||||
background-color: $windowListSB_bg;
|
||||
color: $windowListSB_color;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
background-color: $windowListSB_bg_hover;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-disabled {
|
||||
background-color: $windowListSB_bg_disabled !important;
|
||||
color: $windowListSB_color_disabled;
|
||||
cursor: default !important;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,657 @@
|
||||
.jsxc-window {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
top: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: auto;
|
||||
background-color: $window_bg;
|
||||
z-index: 80;
|
||||
cursor: default;
|
||||
border: 1px solid $window_border;
|
||||
border-bottom: 0;
|
||||
|
||||
.jsxc-showOverlay & {
|
||||
.jsxc-overlay {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-avatar {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.jsxc-message-area {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 2px;
|
||||
bottom: 44px;
|
||||
left: 0;
|
||||
overflow: auto;
|
||||
padding: 3px;
|
||||
z-index: 10;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-button {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #d1d1d1;
|
||||
border: 0;
|
||||
border-right: 3px solid transparent;
|
||||
border-radius: 1px;
|
||||
|
||||
&:hover {
|
||||
background: #c1c1c1;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: #b1b1b1;
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
border: 0 none #fff;
|
||||
border-radius: 50px;
|
||||
|
||||
&:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-corner {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
// .slimScrollDiv {
|
||||
// margin: 0 0 6px;
|
||||
// left: auto !important;
|
||||
// top: auto !important;
|
||||
// }
|
||||
textarea {
|
||||
&.jsxc-message-input {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
margin: 0;
|
||||
padding: 14px 40px 12px;
|
||||
outline: none;
|
||||
border-radius: 0;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
display: block;
|
||||
resize: none;
|
||||
transition: height 0.2s;
|
||||
font-size: 13px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: $window_placeholder;
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-tools {
|
||||
float: right;
|
||||
|
||||
> .jsxc-disabled {
|
||||
opacity: 0.3;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
> div {
|
||||
width: 25px;
|
||||
height: 40px;
|
||||
display: block;
|
||||
float: left;
|
||||
color: $tools_color;
|
||||
opacity: 0.4;
|
||||
font-family: $font_sans;
|
||||
line-height: 40px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
|
||||
&.jsxc-menu {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-close {
|
||||
font-size: 20px;
|
||||
|
||||
&:hover {
|
||||
color: $window_close_hover;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-more {
|
||||
background-image: url("../img/more_white.svg");
|
||||
opacity: 0.4;
|
||||
}
|
||||
// .ui-resizable-w {
|
||||
// left: 0;
|
||||
// }
|
||||
//
|
||||
// .ui-resizable-nw {
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// width: 15px;
|
||||
// height: 15px;
|
||||
// z-index: 95 !important;
|
||||
// background-image: url("../img/resize_gray.svg");
|
||||
// }
|
||||
//
|
||||
// .ui-resizable-n {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// right: 0;
|
||||
// height: 15px;
|
||||
// z-index: 100;
|
||||
// }
|
||||
}
|
||||
|
||||
.jsxc-window-bar {
|
||||
background-color: $window_bar_bg;
|
||||
cursor: pointer;
|
||||
height: 44px;
|
||||
line-height: 26px;
|
||||
padding: 2px;
|
||||
color: $window_bar_color;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
&:hover {
|
||||
.jsxc-normal & {
|
||||
color: $window_bar_color_hover;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-tools {
|
||||
&:hover {
|
||||
.jsxc-normal & {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-minimized & {
|
||||
background-color: $window_min_bar_bg;
|
||||
color: $window_min_bar_color;
|
||||
}
|
||||
|
||||
.jsxc-highlight & {
|
||||
background-color: orange;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-window-fade {
|
||||
position: relative;
|
||||
height: 320px;
|
||||
transition: height 0.2s;
|
||||
overflow: hidden;
|
||||
|
||||
.jsxc-normal & {}
|
||||
|
||||
.jsxc-minimized & {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.jsxc-overlay {
|
||||
display: none;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
overflow-y: scroll;
|
||||
|
||||
> div {
|
||||
background-color: #fff;
|
||||
margin: 30px 10px;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
.jsxc-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
|
||||
&:after {
|
||||
content: "×";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
font-size: 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
cursor: pointer;
|
||||
color: #000;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-body {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
li {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-menu-emoticons {
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
cursor: pointer;
|
||||
z-index: 30;
|
||||
|
||||
&:after {
|
||||
content: " ";
|
||||
background-image: url("../img/smiley.svg");
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 30px 30px;
|
||||
opacity: 0.3;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.jsxc-inner {
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
ul {
|
||||
width: 217px;
|
||||
margin-bottom: 8px;
|
||||
background-color: $emoticon_selection_bg;
|
||||
border-radius: 3px;
|
||||
z-index: 200;
|
||||
list-style-type: none;
|
||||
padding: 3px;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
border-left: 8px solid transparent;
|
||||
border-right: 8px solid transparent;
|
||||
border-top: 8px solid $emoticon_selection_bg;
|
||||
display: block;
|
||||
width: 0;
|
||||
z-index: 1;
|
||||
left: 7px;
|
||||
top: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
&:hover {
|
||||
background-color: $emoticon_selection_hover;
|
||||
}
|
||||
|
||||
.jsxc-emoticon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:after {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-chatmessage {
|
||||
margin: 3px;
|
||||
padding: 4px;
|
||||
word-wrap: break-word;
|
||||
background-color: $chatmessage_bg;
|
||||
position: relative;
|
||||
outline: none;
|
||||
clear: both;
|
||||
|
||||
&.jsxc-error {
|
||||
opacity: 0.7;
|
||||
|
||||
&:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 3px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: yellow;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $chatmessage_a;
|
||||
text-decoration: underline;
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
|
||||
&[download]:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 5px;
|
||||
left: 0;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
background-image: url("../img/download_icon_black.svg");
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
|
||||
&[download]:hover {
|
||||
&:before {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.jsxc-avatar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc-attachment {
|
||||
border-radius: 3px;
|
||||
background-color: #fff;
|
||||
padding: 3px 3px 3px 30px;
|
||||
min-height: 30px;
|
||||
margin-bottom: 5px;
|
||||
background-position: 3px center;
|
||||
background-size: 25px 25px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("../img/filetypes/file.svg");
|
||||
|
||||
img {
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&.jsxc-image {
|
||||
line-height: 0;
|
||||
padding: 0;
|
||||
background-image: url("");
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&.jsxc-application {
|
||||
background-image: url("../img/filetypes/application.svg");
|
||||
}
|
||||
|
||||
&.jsxc-application-pdf {
|
||||
background-image: url("../img/filetypes/application-pdf.svg");
|
||||
}
|
||||
|
||||
&.jsxc-audio {
|
||||
background-image: url("../img/filetypes/audio.svg");
|
||||
}
|
||||
|
||||
&.jsxc-video {
|
||||
background-image: url("../img/filetypes/video.svg");
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.jsxc-text {
|
||||
background-image: url("../img/filetypes/text.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-timestamp {
|
||||
font-size: 8px;
|
||||
color: $chatmessage_timestamp;
|
||||
line-height: 8px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.jsxc-encrypted {
|
||||
&.jsxc-received.jsxc-out .jsxc-timestamp {
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.jsxc-timestamp:after {
|
||||
content: " ";
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 8px;
|
||||
margin-left: 2px;
|
||||
background-image: url("../img/padlock_close_grey.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-in {
|
||||
float: left;
|
||||
position: relative;
|
||||
max-width: 76%;
|
||||
margin-left: 10px;
|
||||
border-radius: 3px;
|
||||
background-color: $chatmessage_in_bg;
|
||||
|
||||
&:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
border-style: solid;
|
||||
border-width: 5px 6px 5px 0;
|
||||
border-color: transparent $chatmessage_in_bg;
|
||||
display: block;
|
||||
width: 0;
|
||||
z-index: 1;
|
||||
left: -6px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
.jsxc-timestamp {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-out {
|
||||
float: right;
|
||||
position: relative;
|
||||
max-width: 76%;
|
||||
margin-right: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 3px;
|
||||
background-color: $chatmessage_out_bg;
|
||||
|
||||
&:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
border-style: solid;
|
||||
border-width: 5px 0 5px 6px;
|
||||
border-color: transparent $chatmessage_out_bg;
|
||||
display: block;
|
||||
width: 0;
|
||||
z-index: 1;
|
||||
right: -6px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
&.jsxc-received {
|
||||
&:before {
|
||||
content: "✓";
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
right: 2px;
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
color: $chatmessage_received;
|
||||
}
|
||||
|
||||
.jsxc-timestamp {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-timestamp {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-sys {
|
||||
width: auto;
|
||||
max-width: none;
|
||||
padding-right: 4px;
|
||||
box-sizing: border-box;
|
||||
margin-right: 3px;
|
||||
border-radius: 3px;
|
||||
background-color: transparent;
|
||||
font-size: 0.8em;
|
||||
font-style: italic;
|
||||
|
||||
.jsxc-emoticon {
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&.jsxc-composing {
|
||||
text-align: center;
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
display: block;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
transition: opacity 0.6s;
|
||||
|
||||
&:before {
|
||||
content: " ";
|
||||
width: 1.5em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
background-size: 80%;
|
||||
background-repeat: no-repeat;
|
||||
margin: 0 3px 0 0;
|
||||
background-image: url("../img/composing.png");
|
||||
}
|
||||
|
||||
&.jsxc-fadein {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jsxc-menu-settings {
|
||||
position: relative;
|
||||
|
||||
.jsxc-inner {
|
||||
left: auto;
|
||||
top: 100%;
|
||||
right: -6px;
|
||||
}
|
||||
}
|
||||
|
||||
div.jsxc-transfer {
|
||||
background-image: url("../img/padlock_open_black.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: 14px 14px;
|
||||
opacity: 0.3;
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
cursor: pointer;
|
||||
z-index: 20;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.jsxc-disabled {
|
||||
background-image: url("../img/padlock_open_disabled_black.svg");
|
||||
cursor: default;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
&.jsxc-fin {
|
||||
opacity: 1;
|
||||
background-image: url("../img/padlock_close_grey.svg");
|
||||
}
|
||||
|
||||
&.jsxc-enc {
|
||||
opacity: 1;
|
||||
background-image: url("../img/padlock_close_orange.svg");
|
||||
|
||||
&.jsxc-trust {
|
||||
background-image: url("../img/padlock_close_green.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
externo
+61
@@ -0,0 +1,61 @@
|
||||
@import "../../lib/magnific-popup/src/css/main";
|
||||
@import "../../lib/emojione/assets/css/emojione";
|
||||
|
||||
// BEGIN: bootstrap
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/variables";
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/mixins";
|
||||
|
||||
// Spec and IE10+
|
||||
@keyframes progress-bar-stripes {
|
||||
from {
|
||||
background-position: 40px 0;
|
||||
}
|
||||
|
||||
to {
|
||||
background-position: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
#jsxc-dialog {
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/progress-bars";
|
||||
}
|
||||
|
||||
#jsxc-dialog, #jsxc-webrtc {
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/utilities";
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/code";
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/grid";
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/alerts";
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/buttons";
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/button-groups";
|
||||
@import "../../lib/bootstrap/assets/stylesheets/bootstrap/forms";
|
||||
|
||||
.progress {
|
||||
margin-bottom: 0;
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.mfp-close {
|
||||
font-size: 23px;
|
||||
}
|
||||
}
|
||||
|
||||
.mfp-bg {
|
||||
z-index: 9000;
|
||||
}
|
||||
|
||||
.mfp-wrap {
|
||||
z-index: 9010;
|
||||
}
|
||||
|
||||
.mfp-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// END: bootstrap
|
||||
|
||||
#cboxWrapper {
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
import Storage from './Storage'
|
||||
import {IConnection} from './connection/ConnectionInterface'
|
||||
import * as Connector from './connection/xmpp/connector'
|
||||
import XMPPConnection from './connection/xmpp/Connection'
|
||||
import StorageConnection from './connection/storage/Connection'
|
||||
import JID from './JID'
|
||||
import Contact from './Contact'
|
||||
import ContactData from './ContactData'
|
||||
import Roster from './ui/Roster'
|
||||
import ChatWindow from './ui/ChatWindow'
|
||||
import ChatWindowList from './ui/ChatWindowList'
|
||||
import SortedPersistentMap from './SortedPersistentMap'
|
||||
import PersistentMap from './PersistentMap'
|
||||
import Log from './util/Log'
|
||||
import {Presence} from './connection/AbstractConnection'
|
||||
import Client from './Client'
|
||||
import {Notice, NoticeData, TYPE as NOTICETYPE} from './Notice'
|
||||
|
||||
interface IConnectionParameters {
|
||||
url:string,
|
||||
jid: string,
|
||||
sid?:string,
|
||||
rid?:string,
|
||||
timestamp?:number,
|
||||
inactivity?:number
|
||||
};
|
||||
|
||||
export default class Account {
|
||||
private storage:Storage;
|
||||
|
||||
private uid:string;
|
||||
|
||||
private connection:IConnection;
|
||||
|
||||
private connectionArguments;
|
||||
|
||||
private connectionParameters:IConnectionParameters;
|
||||
|
||||
private contacts = {};
|
||||
|
||||
private windows:SortedPersistentMap;
|
||||
|
||||
private notices:SortedPersistentMap;
|
||||
|
||||
private contact:Contact;
|
||||
|
||||
constructor(boshUrl: string, jid: string, sid: string, rid:string);
|
||||
constructor(boshUrl: string, jid: string, password: string);
|
||||
constructor(uid:string);
|
||||
constructor() {
|
||||
if (arguments.length === 1) {
|
||||
this.uid = arguments[0];
|
||||
} else if (arguments.length === 3 || arguments.length === 4) {
|
||||
this.uid = (new JID(arguments[1])).bare;
|
||||
this.connectionArguments = arguments;
|
||||
}
|
||||
|
||||
this.connection = new StorageConnection(this);
|
||||
|
||||
this.contact = new Contact(this, new ContactData({
|
||||
jid: new JID(this.uid),
|
||||
name: this.uid
|
||||
}));
|
||||
Roster.get().setRosterAvatar(this.contact);
|
||||
|
||||
this.restoreContacts();
|
||||
this.initNotices();
|
||||
this.initWindows();
|
||||
|
||||
this.getStorage().registerHook('contact:', (contactData) => {
|
||||
let contact = new Contact(this, contactData.jid);
|
||||
|
||||
if (typeof this.contacts[contact.getId()] === 'undefined') { console.log('add', contactData.jid)
|
||||
this.contacts[contact.getId()] = contact;
|
||||
|
||||
Roster.get().add(contact);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public connect() {
|
||||
let self = this;
|
||||
|
||||
if (!this.connectionArguments) {
|
||||
this.reloadConnectionData();
|
||||
}
|
||||
|
||||
if (self.connectionParameters && self.connectionParameters.inactivity && (new Date()).getTime() - self.connectionParameters.timestamp > self.connectionParameters.inactivity) {
|
||||
Log.warn('Credentials expired')
|
||||
|
||||
this.closeAllChatWindows();
|
||||
|
||||
return Promise.reject('Credentials expired');
|
||||
}
|
||||
|
||||
return Connector.login.apply(this, this.connectionArguments).then(this.successfulConnected);
|
||||
}
|
||||
|
||||
public getContact(jid:JID):Contact {
|
||||
return this.contacts[jid.bare];
|
||||
}
|
||||
|
||||
public addContact(data:ContactData):Contact {
|
||||
let contact = new Contact(this, data);
|
||||
contact.save();
|
||||
|
||||
this.contacts[contact.getId()] = contact;
|
||||
|
||||
this.save();
|
||||
|
||||
return contact;
|
||||
}
|
||||
|
||||
public removeContact(contact:Contact) {
|
||||
let id = contact.getId();
|
||||
|
||||
if (this.contacts[id]) {
|
||||
delete this.contacts[id];
|
||||
|
||||
Roster.get().remove(contact);
|
||||
|
||||
//@REVIEW contact.getChatWindow would be nice
|
||||
let chatWindow = this.windows.get(id);
|
||||
|
||||
if (chatWindow) {
|
||||
this.closeChatWindow(chatWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public removeAllContacts() {
|
||||
for(let id in this.contacts) {
|
||||
let contact = this.contacts[id];
|
||||
|
||||
delete this.contacts[id];
|
||||
|
||||
Roster.get().remove(contact);
|
||||
}
|
||||
}
|
||||
|
||||
public openChatWindow(contact:Contact) {
|
||||
let chatWindow = new ChatWindow(this, contact);
|
||||
|
||||
chatWindow = ChatWindowList.get().add(chatWindow);
|
||||
|
||||
this.windows.push(chatWindow);
|
||||
|
||||
this.save();
|
||||
|
||||
return chatWindow;
|
||||
}
|
||||
|
||||
public closeChatWindow(chatWindow:ChatWindow) {
|
||||
// let id = chatWindow.getContact().getId();
|
||||
console.log('chatWindow', chatWindow)
|
||||
ChatWindowList.get().remove(chatWindow);
|
||||
|
||||
this.windows.remove(chatWindow);
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
public closeAllChatWindows() {
|
||||
this.windows.empty((id, chatWindow) => {
|
||||
ChatWindowList.get().remove(chatWindow);
|
||||
});
|
||||
}
|
||||
|
||||
public addNotice(noticeData:NoticeData) {
|
||||
let notice = new Notice(this.getStorage(), noticeData);
|
||||
|
||||
if (this.notices.get(notice.getId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Roster.get().addNotice(this, notice);
|
||||
|
||||
this.notices.push(notice);
|
||||
}
|
||||
|
||||
public removeNotice(notice:Notice) { console.log('removeNotice', notice);
|
||||
//Roster.get().removeNotice(this, notice);
|
||||
|
||||
this.notices.remove(notice);
|
||||
}
|
||||
|
||||
public getStorage() {
|
||||
if(!this.storage) {
|
||||
this.storage = new Storage(this.uid);
|
||||
}
|
||||
|
||||
return this.storage;
|
||||
}
|
||||
|
||||
public getConnection():IConnection {
|
||||
return this.connection;
|
||||
}
|
||||
|
||||
public getUid() {
|
||||
return this.uid;
|
||||
}
|
||||
|
||||
public getJID():JID {
|
||||
let storedAccountData = this.getStorage().getItem('account') || {};
|
||||
let jidString = (storedAccountData.connectionParameters) ? storedAccountData.connectionParameters.jid : this.getUid();
|
||||
|
||||
//@REVIEW maybe promise?
|
||||
return new JID(jidString);
|
||||
}
|
||||
|
||||
public remove() {
|
||||
this.removeAllContacts();
|
||||
this.closeAllChatWindows();
|
||||
|
||||
Client.removeAccount(this);
|
||||
}
|
||||
|
||||
private successfulConnected = (data) => {
|
||||
let connection = data.connection;
|
||||
let status = data.status;
|
||||
|
||||
this.connectionParameters = $.extend(this.connectionParameters, {
|
||||
url: connection.service,
|
||||
jid: connection.jid,
|
||||
sid: connection._proto.sid,
|
||||
rid: connection._proto.rid,
|
||||
timestamp: (new Date()).getTime()
|
||||
});
|
||||
|
||||
if (connection._proto.inactivity) {
|
||||
this.connectionParameters.inactivity = connection._proto.inactivity * 1000;
|
||||
}
|
||||
|
||||
this.save();
|
||||
|
||||
connection.connect_callback = (status) => {
|
||||
if (status === Strophe.Status.DISCONNECTED) {
|
||||
this.connectionDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
connection.nextValidRid = (rid) => {
|
||||
this.connectionParameters.timestamp = (new Date()).getTime();
|
||||
this.connectionParameters.rid = rid;
|
||||
this.save();
|
||||
};
|
||||
|
||||
this.connection = new XMPPConnection(this, connection);
|
||||
|
||||
if (status === Strophe.Status.CONNECTED) {
|
||||
Roster.get().setPresence(Presence.online);
|
||||
Roster.get().refreshOwnPresenceIndicator();
|
||||
|
||||
this.connection.getRoster().then(() => {
|
||||
this.connection.sendPresence();
|
||||
});
|
||||
} else {
|
||||
this.connection.sendPresence();
|
||||
}
|
||||
}
|
||||
|
||||
private connectionDisconnected() {
|
||||
console.log('disconnected');
|
||||
|
||||
this.remove();
|
||||
}
|
||||
|
||||
private save() {
|
||||
this.getStorage().setItem('account', {
|
||||
connectionParameters: this.connectionParameters,
|
||||
contacts: Object.keys(this.contacts),
|
||||
// windows: Object.keys(this.windows)
|
||||
});
|
||||
}
|
||||
|
||||
private reloadConnectionData() {
|
||||
let storedAccountData = this.getStorage().getItem('account') || {};
|
||||
console.log('storedAccountData', storedAccountData)
|
||||
this.connectionParameters = storedAccountData.connectionParameters;
|
||||
|
||||
let p = this.connectionParameters;
|
||||
this.connectionArguments = [p.url, (new JID(p.jid)).full, p.sid, p.rid];
|
||||
}
|
||||
|
||||
private restoreContacts() {
|
||||
let storedAccountData = this.getStorage().getItem('account');
|
||||
|
||||
storedAccountData.contacts.forEach((id) => {
|
||||
this.contacts[id] = new Contact(this, id);
|
||||
|
||||
Roster.get().add(this.contacts[id]);
|
||||
});
|
||||
}
|
||||
|
||||
private initWindows() {
|
||||
this.windows = new SortedPersistentMap(this.getStorage(), 'windows');
|
||||
|
||||
this.windows.setRemoveHook((id, chatWindow) => {
|
||||
console.log('remove hook', id, chatWindow);
|
||||
if (chatWindow) {
|
||||
ChatWindowList.get().remove(chatWindow);
|
||||
}
|
||||
});
|
||||
|
||||
this.windows.setPushHook((id) => {
|
||||
let chatWindow = new ChatWindow(this, this.contacts[id]);
|
||||
this.windows[id] = chatWindow;
|
||||
|
||||
ChatWindowList.get().add(chatWindow);
|
||||
|
||||
return chatWindow;
|
||||
});
|
||||
|
||||
this.windows.init();
|
||||
}
|
||||
|
||||
private initNotices() {
|
||||
this.notices = new SortedPersistentMap(this.getStorage(), 'notices');
|
||||
|
||||
this.notices.setRemoveHook((id) => {
|
||||
Roster.get().removeNotice(this, id);
|
||||
});
|
||||
|
||||
this.notices.setPushHook((id) => {
|
||||
let notice = new Notice(this.getStorage(), id);
|
||||
|
||||
Roster.get().addNotice(this, notice);
|
||||
|
||||
return notice;
|
||||
});
|
||||
|
||||
this.notices.init();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import Options from './Options';
|
||||
import Log from './util/Log';
|
||||
|
||||
export default class Attachment {
|
||||
private mimeType:string;
|
||||
|
||||
private data:any;
|
||||
|
||||
private thumbnailData:any;
|
||||
|
||||
private size:number;
|
||||
|
||||
private persistent:boolean;
|
||||
|
||||
private name:string;
|
||||
|
||||
constructor(name:string, mimeType:string, data:any);
|
||||
constructor(id:string);
|
||||
constructor() {
|
||||
// @TODO
|
||||
}
|
||||
|
||||
public save():boolean {
|
||||
if (this.isImage() && this.data && !this.thumbnailData) {
|
||||
this.generateThumbnail();
|
||||
}
|
||||
|
||||
if (this.size > Options.get('maxStorableSize')) {
|
||||
Log.debug('Attachment to large to store');
|
||||
|
||||
this.persistent = false;
|
||||
|
||||
return false;
|
||||
|
||||
//@TODO delete data and store thumbnailData
|
||||
}
|
||||
|
||||
//@TODO save to storage
|
||||
return true;
|
||||
}
|
||||
|
||||
public getSize():number {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public getMimeType():string {
|
||||
return this.mimeType;
|
||||
}
|
||||
|
||||
public getThumbnailData() {
|
||||
return this.thumbnailData;
|
||||
}
|
||||
|
||||
public getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public isPersistent():boolean {
|
||||
return this.persistent;
|
||||
}
|
||||
|
||||
public isImage():boolean {
|
||||
return /^image\//i.test(this.mimeType);
|
||||
}
|
||||
|
||||
public hasThumbnailData():boolean {
|
||||
return !!this.thumbnailData;
|
||||
}
|
||||
|
||||
public hasData():boolean {
|
||||
return !!this.data;
|
||||
}
|
||||
|
||||
public clearData() {
|
||||
this.data = null;
|
||||
}
|
||||
|
||||
private generateThumbnail():void {
|
||||
if(typeof Image === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
var sHeight, sWidth, sx, sy;
|
||||
var dHeight = 100,
|
||||
dWidth = 100;
|
||||
var canvas = <HTMLCanvasElement> $("<canvas>").get(0);
|
||||
|
||||
canvas.width = dWidth;
|
||||
canvas.height = dHeight;
|
||||
|
||||
var ctx = canvas.getContext("2d");
|
||||
var img = new Image();
|
||||
|
||||
img.src = this.data;
|
||||
|
||||
if (img.height > img.width) {
|
||||
sHeight = img.width;
|
||||
sWidth = img.width;
|
||||
sx = 0;
|
||||
sy = (img.height - img.width) / 2;
|
||||
} else {
|
||||
sHeight = img.height;
|
||||
sWidth = img.height;
|
||||
sx = (img.width - img.height) / 2;
|
||||
sy = 0;
|
||||
}
|
||||
|
||||
ctx.drawImage(img, sx, sy, sWidth, sHeight, 0, 0, dWidth, dHeight);
|
||||
|
||||
this.thumbnailData = canvas.toDataURL();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
export let NOTIFICATION_DEFAULT = 'default';
|
||||
export let NOTIFICATION_GRANTED = 'granted';
|
||||
export let NOTIFICATION_DENIED = 'denied';
|
||||
export let STATUS = ['offline', 'dnd', 'xa', 'away', 'chat', 'online'];
|
||||
export let SOUNDS = {
|
||||
MSG: 'incomingMessage.wav',
|
||||
CALL: 'Rotary-Phone6.mp3',
|
||||
NOTICE: 'Ping1.mp3'
|
||||
};
|
||||
export let REGEX = {
|
||||
JID: new RegExp('\\b[^"&\'\\/:<>@\\s]+@[\\w-_.]+\\b', 'ig'),
|
||||
URL: new RegExp(/(https?:\/\/|www\.)[^\s<>'"]+/gi)
|
||||
};
|
||||
export let NS = {
|
||||
CARBONS: 'urn:xmpp:carbons:2',
|
||||
FORWARD: 'urn:xmpp:forward:0'
|
||||
};
|
||||
export let HIDDEN = 'hidden';
|
||||
export let SHOWN = 'shown';
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
import Account from './Account'
|
||||
import Message from './Message'
|
||||
import {PluginInterface} from './PluginInterface'
|
||||
import Storage from './Storage';
|
||||
import * as UI from './ui/web'
|
||||
import JID from './JID'
|
||||
import Roster from './ui/Roster'
|
||||
import ChatWindowList from './ui/ChatWindowList'
|
||||
import RoleAllocator from './RoleAllocator'
|
||||
|
||||
export default class Client implements ClientInterface {
|
||||
private static storage;
|
||||
|
||||
private static accounts = {};
|
||||
|
||||
public static init() {
|
||||
let roleAllocator = RoleAllocator.get();
|
||||
let accountIds = Client.getStorage().getItem('accounts') || [];
|
||||
|
||||
accountIds.forEach(function(id) {
|
||||
Client.accounts[id] = new Account(id);
|
||||
|
||||
roleAllocator.waitUntilMaster().then(function(){
|
||||
return Client.accounts[id].connect();
|
||||
}).then(function(){
|
||||
|
||||
}).catch(function(msg){
|
||||
Client.accounts[id].remove();
|
||||
|
||||
console.warn(msg)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static addConnectionPlugin(plugin:PluginInterface) {
|
||||
|
||||
}
|
||||
|
||||
public static addPreSendMessageHook(hook:(Message, Builder)=>void, position?:number) {
|
||||
|
||||
}
|
||||
|
||||
public static hasFocus() {
|
||||
|
||||
}
|
||||
|
||||
public static isExtraSmallDevice():boolean {
|
||||
return $(window).width() < 500;
|
||||
}
|
||||
|
||||
public static isDebugMode():boolean {
|
||||
return Client.getStorage().getItem('debug') === true;
|
||||
}
|
||||
|
||||
public static getStorage() {
|
||||
if (!Client.storage) {
|
||||
Client.storage = new Storage();
|
||||
}
|
||||
|
||||
return Client.storage;
|
||||
}
|
||||
|
||||
public static getAccout(jid:JID):Account;
|
||||
public static getAccout(uid?:string):Account;
|
||||
public static getAccout() {
|
||||
let uid;
|
||||
|
||||
if (arguments[0] instanceof JID) {
|
||||
uid = arguments[0].bare;
|
||||
} else if (arguments[0]) {
|
||||
uid = arguments[0];
|
||||
} else {
|
||||
uid = Object.keys(Client.accounts)[0];
|
||||
}
|
||||
|
||||
return Client.accounts[uid];
|
||||
}
|
||||
|
||||
public static createAccount(boshUrl: string, jid: string, sid: string, rid:string);
|
||||
public static createAccount(boshUrl: string, jid: string, password: string);
|
||||
public static createAccount() {
|
||||
let account;
|
||||
|
||||
if (arguments.length === 4) {
|
||||
account = new Account(arguments[0], arguments[1], arguments[2], arguments[3]);
|
||||
} else if (arguments.length === 3) {
|
||||
account = new Account(arguments[0], arguments[1], arguments[2]);
|
||||
} else {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
||||
return account.connect().then(function(){
|
||||
Client.addAccount(account);
|
||||
});
|
||||
}
|
||||
|
||||
public static removeAccount(account:Account) {
|
||||
delete Client.accounts[account.getUid()];
|
||||
|
||||
Client.save();
|
||||
|
||||
if (Object.keys(Client.accounts).length === 0) {
|
||||
Roster.get().setNoConnection();
|
||||
}
|
||||
}
|
||||
|
||||
private static addAccount(account:Account) {
|
||||
Client.accounts[account.getUid()] = account;
|
||||
|
||||
Client.save()
|
||||
}
|
||||
|
||||
private static save() {
|
||||
Client.getStorage().setItem('accounts', Object.keys(this.accounts));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import {JIDInterface} from './JIDInterface'
|
||||
import {PluginInterface} from './PluginInterface'
|
||||
|
||||
export interface ClientInterface {
|
||||
init();
|
||||
|
||||
addConnectionPlugin(plugin:PluginInterface);
|
||||
|
||||
addPreSendMessageHook(hook:(Message, Builder)=>void, position?:number);
|
||||
|
||||
hasFocus();
|
||||
|
||||
isExtraSmallDevice():boolean;
|
||||
|
||||
isDebugMode():boolean;
|
||||
|
||||
getStorage();
|
||||
|
||||
getAccout(jid:JIDInterface):Account;
|
||||
getAccout(uid?:string):Account;
|
||||
|
||||
createAccount(boshUrl: string, jid: string, sid: string, rid:string);
|
||||
createAccount(boshUrl: string, jid: string, password: string);
|
||||
|
||||
removeAccount(account:Account);
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
import Storage from './Storage'
|
||||
import JID from './JID'
|
||||
import Message from './Message'
|
||||
import Notification from './Notification'
|
||||
import Translation from './util/Translation'
|
||||
import Account from './Account'
|
||||
import ContactData from './ContactData'
|
||||
import PersistentMap from './PersistentMap'
|
||||
import IdentifiableInterface from './IdentifiableInterface'
|
||||
import Log from './util/Log'
|
||||
import {Presence} from './connection/AbstractConnection'
|
||||
|
||||
export default class Contact implements IdentifiableInterface {
|
||||
private storage: Storage;
|
||||
|
||||
private readonly account:Account;
|
||||
|
||||
// @REVIEW Data to own object/type?
|
||||
private data:PersistentMap;
|
||||
|
||||
private jid:JID;
|
||||
|
||||
constructor(account:Account, data: ContactData);
|
||||
constructor(account:Account, id:string);
|
||||
constructor() {
|
||||
this.account = arguments[0];
|
||||
this.storage = this.account.getStorage();
|
||||
|
||||
if (typeof arguments[1] === 'string') {
|
||||
let id = arguments[1]; console.log('id', id)
|
||||
this.data = new PersistentMap(this.storage, 'contact', id);
|
||||
this.jid = new JID(this.data.get('jid'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let data = arguments[1] || {};
|
||||
|
||||
if (!data.jid) {
|
||||
throw 'Jid missing';
|
||||
} else if (typeof data.jid === 'string') {
|
||||
this.jid = new JID(data.jid);
|
||||
} else {
|
||||
this.jid = data.jid;
|
||||
data.jid = this.jid.full;
|
||||
}
|
||||
|
||||
this.data = new PersistentMap(this.storage, 'contact', this.jid.bare);
|
||||
|
||||
data.rnd = Math.random() // force storage event
|
||||
this.data.set(data);
|
||||
}
|
||||
|
||||
public save() {
|
||||
// if (this.storage.getItem('contact', this.getId())) {
|
||||
// this.storage.updateItem('contact', this.getId(), this.data);
|
||||
//
|
||||
// return 'updated';
|
||||
// }
|
||||
//
|
||||
// this.storage.setItem('contact', this.getId(), this.data);
|
||||
//
|
||||
// return 'created';
|
||||
}
|
||||
|
||||
public openWindow = () => {
|
||||
return this.account.openChatWindow(this);
|
||||
}
|
||||
|
||||
public addResource(resource:string) {
|
||||
let resources = this.data.get('resources') || [];
|
||||
|
||||
if (resource && resources.indexOf(resource) < 0) {
|
||||
resources.push(resource);
|
||||
|
||||
this.data.set('resources', resources);
|
||||
}
|
||||
}
|
||||
|
||||
public removeResource(resource:string) {
|
||||
let resources = this.data.get('resources') || [];
|
||||
|
||||
resources = $.grep(resources, function(r) {
|
||||
return resource !== r;
|
||||
});
|
||||
|
||||
this.data.set('resources', resources);
|
||||
}
|
||||
|
||||
public setResource = (resource:string) => {
|
||||
//this.addResource(resource);
|
||||
console.log('setResource', this.jid.bare + '/' + resource)
|
||||
this.jid = new JID(this.jid.bare + '/' + resource);
|
||||
|
||||
this.data.set('jid', this.jid.full);
|
||||
}
|
||||
|
||||
public setPresence(resource:string, presence:Presence) {
|
||||
Log.debug('set presence for ' + this.jid.bare + ' / ' + resource, presence);
|
||||
|
||||
let resources = this.data.get('resources') || {};
|
||||
|
||||
if (presence === Presence.offline) {
|
||||
delete resources[resource];
|
||||
} else if (resource) {
|
||||
resources[resource] = presence;
|
||||
}
|
||||
|
||||
if (this.getType() === 'groupchat') {
|
||||
// group chat doesn't have a presence
|
||||
return;
|
||||
}
|
||||
|
||||
presence = this.getHighestPresence();
|
||||
console.log('highest presence', presence);
|
||||
if (this.data.get('presence') === Presence.offline && presence !== Presence.offline) {
|
||||
// buddy has come online
|
||||
// @TODO
|
||||
// Notification.notify({
|
||||
// title: this.getName(),
|
||||
// message: Translation.t('has_come_online'),
|
||||
// source: this.getId()
|
||||
// });
|
||||
}
|
||||
|
||||
this.data.set('presence', presence);
|
||||
}
|
||||
|
||||
public sendMessage(message:Message) {
|
||||
// message.bid = this.getId();
|
||||
}
|
||||
|
||||
public getId():string {
|
||||
return this.jid.bare;
|
||||
}
|
||||
|
||||
public getJid():JID {
|
||||
return this.jid;
|
||||
}
|
||||
|
||||
public getFingerprint() {
|
||||
return this.data.get('fingerprint');
|
||||
}
|
||||
|
||||
public getMsgState() {
|
||||
return this.data.get('msgstate');
|
||||
}
|
||||
|
||||
public getPresence() {
|
||||
return this.data.get('presence');
|
||||
}
|
||||
|
||||
public getType() {
|
||||
return this.data.get('type');
|
||||
}
|
||||
|
||||
public getNumberOfUnreadMessages():number {
|
||||
|
||||
}
|
||||
|
||||
public getName():string {
|
||||
return this.data.get('name') || this.jid.bare;
|
||||
}
|
||||
|
||||
public getAvatar():Promise<{}> {
|
||||
|
||||
}
|
||||
|
||||
public getSubscription() {
|
||||
return this.data.get('subscription');
|
||||
}
|
||||
|
||||
public getCapabilitiesByRessource():Promise<{}> {
|
||||
// @TODO
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
public getVcard():Promise<{}> {
|
||||
return this.account.getConnection().loadVcard(this.getJid());
|
||||
}
|
||||
|
||||
public isEncrypted() {
|
||||
|
||||
}
|
||||
|
||||
public getStatus():string {
|
||||
return this.data.get('status');
|
||||
}
|
||||
|
||||
public setStatus(status:string) { console.trace(this.getId() + ', setStatus: ' + status)
|
||||
return this.data.set('status', status);
|
||||
}
|
||||
|
||||
public setTrust(trust:boolean) {
|
||||
this.data.set('trust', trust);
|
||||
}
|
||||
|
||||
public setName(name:string) {
|
||||
let oldName = this.getName();
|
||||
|
||||
this.data.set('name', name);
|
||||
|
||||
if (oldName !== name) {
|
||||
this.account.getConnection().setDisplayName(this.jid, name);
|
||||
}
|
||||
}
|
||||
|
||||
public setSubscription(subscription:string) {
|
||||
this.data.set('subscription', subscription);
|
||||
}
|
||||
|
||||
public registerHook(property:string, func:(newValue:any, oldValue:any)=>void) {
|
||||
this.data.registerHook(property, func);
|
||||
}
|
||||
|
||||
private getHighestPresence() {
|
||||
let maxPresence = Presence.offline;
|
||||
let resources = this.data.get('resources');
|
||||
|
||||
for (let resource in resources) {
|
||||
if(resources[resource] < maxPresence) {
|
||||
maxPresence = resources[resource];
|
||||
}
|
||||
}
|
||||
|
||||
return maxPresence;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
//@TODO duplicate of AbstractConnection
|
||||
enum Presence {
|
||||
online,
|
||||
chat,
|
||||
away,
|
||||
xa,
|
||||
dnd,
|
||||
offline
|
||||
}
|
||||
|
||||
export default class ContactData {
|
||||
public jid;
|
||||
public name;
|
||||
public presence:Presence = Presence.offline;
|
||||
public status:string = '';
|
||||
public subscription = 'none';
|
||||
public msgstate = 0;
|
||||
public trust:boolean = false;
|
||||
public fingerprint:string = null;
|
||||
public resources = {};
|
||||
public type = 'chat'
|
||||
|
||||
constructor(data:any) {
|
||||
$.extend(this, data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import {MessageInterface} from './MessageInterface'
|
||||
import {JIDInterface} from './JIDInterface'
|
||||
import {Presence} from './connection/AbstractConnection'
|
||||
|
||||
export interface ContactInterface {
|
||||
openWindow();
|
||||
|
||||
addResource(resource:string);
|
||||
|
||||
removeResource(resource:string);
|
||||
|
||||
setResource(resource:string);
|
||||
|
||||
setPresence(resource:string, presence:Presence);
|
||||
|
||||
sendMessage(message:MessageInterface);
|
||||
|
||||
getId():string;
|
||||
|
||||
getJid():JIDInterface;
|
||||
|
||||
getFingerprint();
|
||||
|
||||
getMsgState();
|
||||
|
||||
getPresence();
|
||||
|
||||
getType();
|
||||
|
||||
getNumberOfUnreadMessages():number;
|
||||
|
||||
getName():string;
|
||||
|
||||
getAvatar():Promise<{}>;
|
||||
|
||||
getSubscription();
|
||||
|
||||
getCapabilitiesByRessource():Promise<{}>;
|
||||
|
||||
getVcard():Promise<{}>;
|
||||
|
||||
isEncrypted();
|
||||
|
||||
getStatus():string;
|
||||
|
||||
setStatus(status:string);
|
||||
|
||||
setTrust(trust:boolean);
|
||||
|
||||
setName(name:string);
|
||||
|
||||
setSubscription(subscription:string);
|
||||
|
||||
registerHook(property:string, func:(newValue:any, oldValue:any)=>void);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import Options from './Options'
|
||||
|
||||
const EMOTICONS = [
|
||||
['O:-) O:)', 'innocent'],
|
||||
['>:-( >:( >:-( >:(', 'angry'],
|
||||
[':-) :)', 'slight_smile'],
|
||||
[':-D :D', 'grin'],
|
||||
[':-( :(', 'disappointed'],
|
||||
[';-) ;)', 'wink'],
|
||||
[':-P :P', 'stuck_out_tongue'],
|
||||
['=-O', 'astonished'],
|
||||
[':kiss: :-*', 'kissing_heart'],
|
||||
['8-) :cool:', 'sunglasses'],
|
||||
[':-X :X', 'zipper_mouth'],
|
||||
[':yes:', 'thumbsup'],
|
||||
[':no:', 'thumbsdown'],
|
||||
[':beer:', 'beer'],
|
||||
[':coffee:', 'coffee'],
|
||||
[':devil:', 'smiling_imp'],
|
||||
[':kiss: :kissing:', 'kissing'],
|
||||
['@->-- @->--', 'rose'],
|
||||
[':music:', 'musical_note'],
|
||||
[':love:', 'heart_eyes'],
|
||||
[':heart:', 'heart'],
|
||||
[':brokenheart:', 'broken_heart'],
|
||||
[':zzz:', 'zzz'],
|
||||
[':wait:', 'hand_splayed']
|
||||
]
|
||||
import * as emojione from '../lib/emojione/lib/js/emojione.js';
|
||||
|
||||
const EMOTICON_LIST = {
|
||||
'core': {
|
||||
':klaus:': ['klaus'],
|
||||
':jabber:': ['jabber'],
|
||||
':xmpp:': ['xmpp'],
|
||||
':jsxc:': ['jsxc'],
|
||||
':owncloud:': ['owncloud'],
|
||||
':nextcloud:': ['nextcloud']
|
||||
},
|
||||
'emojione': emojione.emojioneList
|
||||
}
|
||||
|
||||
export default class Emoticons {
|
||||
|
||||
private static initialised = false;
|
||||
|
||||
private static shortRegex = new RegExp(emojione.regShortNames.source + '|(' + Object.keys(EMOTICON_LIST.core).join('|') + ')', 'gi');
|
||||
|
||||
public static getDefaultEmoticonList() {
|
||||
let list = [];
|
||||
|
||||
EMOTICONS.forEach(emoticon => {
|
||||
list.push(emoticon[0].split(' ')[0]);
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static toImage(text:string):string {
|
||||
Emoticons.init();
|
||||
|
||||
text = Emoticons.standardToImage(text);
|
||||
text = Emoticons.shortnameToImage(text);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private static init() {
|
||||
if (Emoticons.initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.each(EMOTICONS, function(i, val) {
|
||||
// escape characters
|
||||
var reg = val[0].replace(/(\/|\||\*|\.|\+|\?|\^|\$|\(|\)|\[|\]|\{|\})/g, '\\$1');
|
||||
reg = '(' + reg.split(' ').join('|') + ')';
|
||||
EMOTICONS[i][2] = new RegExp(reg, 'g');
|
||||
});
|
||||
|
||||
Emoticons.initialised = true;
|
||||
}
|
||||
|
||||
private static standardToImage(text:string):string {
|
||||
// replace emoticons from XEP-0038 and pidgin with shortnames
|
||||
$.each(EMOTICONS, function(i, val) {
|
||||
text = text.replace(val[2], ':' + val[1] + ':');
|
||||
});
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private static shortnameToImage(text:string):string {
|
||||
text = text.replace(this.shortRegex, Emoticons.replaceShortnameWithImage);
|
||||
|
||||
var wrapper = $('<div>' + text + '</div>');
|
||||
if (wrapper.find('.jsxc_emoticon').length === 1 && wrapper.text().replace(/ /, '').length === 0 && wrapper.find('*').length === 1) {
|
||||
wrapper.find('.jsxc_emoticon').addClass('jsxc_large');
|
||||
text = wrapper.html();
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private static replaceShortnameWithImage = (shortname) => {
|
||||
if (typeof shortname === 'undefined' || shortname === '' || (!(shortname in EMOTICON_LIST.emojione) && !(shortname in EMOTICON_LIST.core))) {
|
||||
return shortname;
|
||||
}
|
||||
|
||||
var src, filename;
|
||||
|
||||
if (EMOTICON_LIST.core[shortname]) {
|
||||
filename = EMOTICON_LIST.core[shortname][EMOTICON_LIST.core[shortname].length - 1].replace(/^:([^:]+):$/, '$1');
|
||||
src = Options.get('root') + '/img/emotions/' + filename + '.svg';
|
||||
} else if (EMOTICON_LIST.emojione[shortname]) {
|
||||
filename = EMOTICON_LIST.emojione[shortname].fname;
|
||||
src = Options.get('root') + '/lib/emojione/assets/svg/' + filename + '.svg';
|
||||
}
|
||||
|
||||
var div = $('<div>');
|
||||
|
||||
div.addClass('jsxc-emoticon');
|
||||
div.css('background-image', 'url(' + src + ')');
|
||||
div.attr('title', shortname);
|
||||
|
||||
return div.prop('outerHTML');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
interface Identifiable {
|
||||
getId():string
|
||||
}
|
||||
|
||||
export default Identifiable;
|
||||
@@ -0,0 +1,65 @@
|
||||
import {JIDInterface} from './JIDInterface'
|
||||
|
||||
export default class JID implements JIDInterface {
|
||||
public readonly full:string;
|
||||
|
||||
public readonly bare:string;
|
||||
|
||||
public readonly node:string;
|
||||
|
||||
public readonly domain:string;
|
||||
|
||||
public readonly resource:string;
|
||||
|
||||
constructor(full:string) {
|
||||
let matches = /([^@]+)@([^/]+)(?:\/(.+))?/.exec(full);
|
||||
|
||||
this.node = this.unescapeNode(matches[1].toLowerCase());
|
||||
this.domain = matches[2].toLowerCase();
|
||||
this.resource = matches[3];
|
||||
|
||||
this.bare = this.node + '@' + this.domain;
|
||||
this.full = this.bare + ((this.resource) ? '/' + this.resource : '');
|
||||
}
|
||||
|
||||
public toString():string {
|
||||
return this.full;
|
||||
}
|
||||
|
||||
public toEscapedString():string {
|
||||
let bare = this.escapeNode(this.node) + '@' + this.domain;
|
||||
|
||||
return bare + ((this.resource) ? '/' + this.resource : '');
|
||||
}
|
||||
|
||||
public isBare():boolean {
|
||||
return this.full === this.bare;
|
||||
}
|
||||
|
||||
private escapeNode(node:string) {
|
||||
return node.replace(/^\s+|\s+$/g, '')
|
||||
.replace(/\\/g, "\\5c")
|
||||
.replace(/ /g, "\\20")
|
||||
.replace(/\"/g, "\\22")
|
||||
.replace(/\&/g, "\\26")
|
||||
.replace(/\'/g, "\\27")
|
||||
.replace(/\//g, "\\2f")
|
||||
.replace(/:/g, "\\3a")
|
||||
.replace(/</g, "\\3c")
|
||||
.replace(/>/g, "\\3e")
|
||||
.replace(/@/g, "\\40");
|
||||
}
|
||||
|
||||
private unescapeNode(node:string) {
|
||||
return node.replace(/\\20/g, " ")
|
||||
.replace(/\\22/g, '"')
|
||||
.replace(/\\26/g, "&")
|
||||
.replace(/\\27/g, "'")
|
||||
.replace(/\\2f/g, "/")
|
||||
.replace(/\\3a/g, ":")
|
||||
.replace(/\\3c/g, "<")
|
||||
.replace(/\\3e/g, ">")
|
||||
.replace(/\\40/g, "@")
|
||||
.replace(/\\5c/g, "\\");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
export interface JIDInterface {
|
||||
readonly full:string;
|
||||
|
||||
readonly bare:string;
|
||||
|
||||
readonly node:string;
|
||||
|
||||
readonly domain:string;
|
||||
|
||||
readonly resource:string;
|
||||
|
||||
toString():string;
|
||||
|
||||
isBare():boolean;
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
import Storage from './Storage';
|
||||
import Log from './util/Log';
|
||||
import Options from './Options';
|
||||
import Attachment from './Attachment';
|
||||
import StorageSingleton from './StorageSingleton';
|
||||
import JID from './JID'
|
||||
import * as CONST from './CONST'
|
||||
import Emoticons from './Emoticons'
|
||||
import Translation from './util/Translation'
|
||||
import Identifiable from './IdentifiableInterface'
|
||||
import Client from './Client'
|
||||
import Utils from './util/Utils'
|
||||
import {MessageInterface, DIRECTION, MSGTYPE} from './MessageInterface'
|
||||
|
||||
const MSGPOSTFIX = ':msg';
|
||||
|
||||
const ATREGEX = new RegExp('(xmpp:)?(' + CONST.REGEX.JID.source + ')(\\?[^\\s]+\\b)?', 'i');
|
||||
|
||||
interface MessagePayload {
|
||||
peer:JID,
|
||||
direction:DIRECTION,
|
||||
plaintextMessage?:string,
|
||||
htmlMessage?:string,
|
||||
errorMessage?:string,
|
||||
attachment?:Attachment,
|
||||
received?:boolean,
|
||||
encrypted?:boolean,
|
||||
forwarded?:boolean,
|
||||
stamp?:number,
|
||||
type?:MSGTYPE,
|
||||
}
|
||||
|
||||
export default class Message implements Identifiable, MessageInterface {
|
||||
|
||||
private uid:string;
|
||||
|
||||
private payload:MessagePayload = {
|
||||
received: false,
|
||||
encrypted: null,
|
||||
forwarded: false,
|
||||
stamp: new Date().getTime(),
|
||||
type: MSGTYPE.CHAT
|
||||
} as any;
|
||||
|
||||
static readonly DIRECTION = DIRECTION;
|
||||
|
||||
static readonly MSGTYPE = MSGTYPE;
|
||||
|
||||
private storage:Storage;
|
||||
|
||||
constructor(uid:string);
|
||||
constructor(data:MessagePayload);
|
||||
constructor() {
|
||||
this.storage = Client.getStorage();
|
||||
|
||||
if (typeof arguments[0] === 'string' && arguments[0].length > 0 && arguments.length === 1) {
|
||||
this.uid = arguments[0];
|
||||
|
||||
this.load(this.uid);
|
||||
} else if (typeof arguments[0] === 'object' && arguments[0] !== null) { console.log('arg', arguments[0])
|
||||
$.extend(this.payload, arguments[0]);
|
||||
}
|
||||
|
||||
if (!this.uid) {
|
||||
this.uid = new Date().getTime() + MSGPOSTFIX;
|
||||
}
|
||||
}
|
||||
|
||||
public getId() {
|
||||
return this.uid;
|
||||
}
|
||||
|
||||
public save() {
|
||||
let attachment = this.getAttachment();
|
||||
|
||||
if (attachment) {
|
||||
if (this.getDirection() === DIRECTION.OUT) {
|
||||
// save storage
|
||||
attachment.clearData();
|
||||
}
|
||||
|
||||
let saved = attachment.save();
|
||||
|
||||
if (!saved && this.getDirection() === DIRECTION.IN) {
|
||||
//@TODO inform user
|
||||
}
|
||||
}
|
||||
|
||||
let payloadCopy = $.extend({}, this.payload); //Object.assign
|
||||
if (payloadCopy.attachment) {
|
||||
payloadCopy.attachment = payloadCopy.attachment.getId();
|
||||
}
|
||||
|
||||
this.storage.setItem('msg', this.uid, {
|
||||
payload: payloadCopy
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete() {
|
||||
var data = this.storage.getItem('msg', this.uid);
|
||||
|
||||
if (data) {
|
||||
this.storage.removeItem('msg', this.uid);
|
||||
}
|
||||
}
|
||||
|
||||
public getCssId() {
|
||||
return this.uid.replace(/:/g, '-');
|
||||
}
|
||||
|
||||
public getDOM() {
|
||||
return $('#' + this.getCssId());
|
||||
}
|
||||
|
||||
public getStamp() {
|
||||
return this.payload.stamp;
|
||||
}
|
||||
|
||||
public getDirection():DIRECTION {
|
||||
return this.payload.direction;
|
||||
}
|
||||
|
||||
public getDirectionString():string {
|
||||
return DIRECTION[this.payload.direction].toLowerCase();
|
||||
}
|
||||
|
||||
public getAttachment():Attachment {
|
||||
return this.payload.attachment;
|
||||
}
|
||||
|
||||
public getPeer():JID {
|
||||
return this.payload.peer;
|
||||
}
|
||||
|
||||
public getType():MSGTYPE {
|
||||
return this.payload.type;
|
||||
}
|
||||
|
||||
public getTypeString():string {
|
||||
return MSGTYPE[this.payload.type].toLowerCase();
|
||||
}
|
||||
|
||||
public getHtmlMessage():string {
|
||||
return this.payload.htmlMessage;
|
||||
}
|
||||
|
||||
public getPlaintextMessage():string {
|
||||
return this.payload.plaintextMessage;
|
||||
}
|
||||
|
||||
public received() {
|
||||
this.payload.received = true;
|
||||
this.save();
|
||||
|
||||
this.getDOM().addClass('jsxc_received');
|
||||
}
|
||||
|
||||
public isReceived():boolean {
|
||||
return this.payload.received;
|
||||
}
|
||||
|
||||
public isForwarded():boolean {
|
||||
return this.payload.forwarded;
|
||||
}
|
||||
|
||||
public isEncrypted():boolean {
|
||||
return this.payload.encrypted;
|
||||
}
|
||||
|
||||
public hasAttachment():boolean {
|
||||
return !!this.payload.attachment;
|
||||
}
|
||||
|
||||
public setUnread() {
|
||||
|
||||
}
|
||||
|
||||
public getProcessedBody():string {
|
||||
let body = this.payload.plaintextMessage;
|
||||
|
||||
body = this.convertUrlToLink(body);
|
||||
|
||||
body = this.convertEmailToLink(body);
|
||||
|
||||
body = Emoticons.toImage(body);
|
||||
|
||||
body = this.replaceLineBreaks(body);
|
||||
|
||||
// hide unprocessed otr messages
|
||||
if (body.match(/^\?OTR([:,|?]|[?v0-9x]+)/)) {
|
||||
body = '<i title="' + body + '">' + Translation.t('Unreadable_OTR_message') + '</i>';
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
public getErrorMessage():string {
|
||||
return this.payload.errorMessage;
|
||||
}
|
||||
|
||||
private load(uid:string):void {
|
||||
var data = this.storage.getItem('msg', uid);
|
||||
window._storage = this.storage;
|
||||
if (!data) {
|
||||
Log.debug('Could not load message with uid ' + uid);
|
||||
|
||||
throw new Error('Could not load message with uid ' + uid)
|
||||
}
|
||||
|
||||
$.extend(this.payload, data.payload);
|
||||
|
||||
if (data.attachment) {
|
||||
this.payload.attachment = new Attachment(data.attachment);
|
||||
}
|
||||
}
|
||||
|
||||
private replaceLineBreaks(text) {
|
||||
return text.replace(/(\r\n|\r|\n)/g, '<br />');
|
||||
}
|
||||
|
||||
private convertUrlToLink(text) {
|
||||
return text.replace(CONST.REGEX.URL, function(url) {
|
||||
let href = (url.match(/^https?:\/\//i)) ? url : 'http://' + url;
|
||||
|
||||
return '<a href="' + href + '" target="_blank">' + url + '</a>';
|
||||
});
|
||||
}
|
||||
|
||||
private convertEmailToLink(text) {
|
||||
return text.replace(ATREGEX, function(undefined, protocol, jid, action) {
|
||||
if (protocol === 'xmpp:') {
|
||||
if (typeof action === 'string') {
|
||||
jid += action;
|
||||
}
|
||||
|
||||
return '<a href="xmpp:' + jid + '">xmpp:' + jid + '</a>';
|
||||
}
|
||||
|
||||
return '<a href="mailto:' + jid + '" target="_blank">mailto:' + jid + '</a>';
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import {JIDInterface} from './JIDInterface'
|
||||
|
||||
export enum DIRECTION {
|
||||
IN, OUT, SYS
|
||||
};
|
||||
|
||||
export enum MSGTYPE {
|
||||
CHAT, GROUPCHAT
|
||||
};
|
||||
|
||||
export interface MessageInterface {
|
||||
getId();
|
||||
|
||||
save();
|
||||
|
||||
delete();
|
||||
|
||||
getCssId();
|
||||
|
||||
getDOM();
|
||||
|
||||
getStamp();
|
||||
|
||||
getDirection():DIRECTION;
|
||||
|
||||
getDirectionString():string;
|
||||
|
||||
getAttachment():Attachment;
|
||||
|
||||
getPeer():JIDInterface;
|
||||
|
||||
getType():MSGTYPE;
|
||||
|
||||
getTypeString():string;
|
||||
|
||||
getHtmlMessage():string;
|
||||
|
||||
getPlaintextMessage():string;
|
||||
|
||||
received();
|
||||
|
||||
isReceived():boolean;
|
||||
|
||||
isForwarded():boolean;
|
||||
|
||||
isEncrypted():boolean;
|
||||
|
||||
hasAttachment():boolean;
|
||||
|
||||
setUnread();
|
||||
|
||||
getProcessedBody():string;
|
||||
|
||||
getErrorMessage():string;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import Storable from './StorableAbstract';
|
||||
import Identifiable from './IdentifiableInterface'
|
||||
import Storage from './Storage'
|
||||
|
||||
const SEP = ':';
|
||||
|
||||
export default class ModelManager <Element extends Storable> {
|
||||
|
||||
private id:string;
|
||||
|
||||
private elementIds;
|
||||
|
||||
constructor(private owner:Identifiable, private ElementClass:any, private storage:Storage) { //@REVIEW any -> Element?
|
||||
this.id = owner.getId() + SEP + ElementClass.constructor.name;
|
||||
|
||||
this.elementIds = this.storage.getItem(this.id);
|
||||
}
|
||||
|
||||
public get(id:string):Element {
|
||||
let data = this.storage.getItem(this.id + SEP + id);
|
||||
|
||||
return new this.ElementClass(data);
|
||||
}
|
||||
|
||||
public getAll():Element[] {
|
||||
let elements:Element[] = [];
|
||||
|
||||
for(let elementId in this.elementIds) {
|
||||
elements.push(this.get(elementId));
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
public add(element:Element) {
|
||||
this.elementIds.push(element.getId());
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
public remove(element:Element) {
|
||||
this.elementIds = $.grep(this.elementIds, function(e) {
|
||||
return e !== element.getId();
|
||||
})
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
private save() {
|
||||
this.storage.setItem(this.id, this.elementIds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import IdentifiableInterface from './IdentifiableInterface'
|
||||
import Storage from './Storage'
|
||||
import ContactDialog from './ui/dialogs/contact'
|
||||
|
||||
export const enum TYPE {
|
||||
normal, announcement, contact
|
||||
}
|
||||
|
||||
export const enum FUNCTION {
|
||||
contactRequest
|
||||
}
|
||||
let functions = {};
|
||||
functions[FUNCTION.contactRequest] = ContactDialog;
|
||||
|
||||
export interface NoticeData {
|
||||
title:string;
|
||||
description:string;
|
||||
fnName: FUNCTION;
|
||||
fnParams?:Array<string>;
|
||||
type?:TYPE;
|
||||
}
|
||||
|
||||
export class Notice implements IdentifiableInterface {
|
||||
|
||||
private storage:Storage;
|
||||
|
||||
private data:NoticeData;
|
||||
|
||||
constructor(storage:Storage, data:NoticeData);
|
||||
constructor(storage:Storage, id:string);
|
||||
constructor() {
|
||||
this.storage = arguments[0];
|
||||
|
||||
if (arguments.length === 2 && typeof arguments[1] === 'string') {
|
||||
this.data = this.storage.getItem(arguments[1]);
|
||||
} else {
|
||||
this.data = arguments[1];
|
||||
this.data.fnParams = this.data.fnParams || [];
|
||||
this.data.type = this.data.type || TYPE.normal;
|
||||
|
||||
this.storage.setItem(this.getId(), this.data);
|
||||
}
|
||||
}
|
||||
|
||||
public getId():string {
|
||||
return this.data.fnName + '|' + this.data.fnParams.toString();
|
||||
}
|
||||
|
||||
public getTitle():string {
|
||||
return this.data.title;
|
||||
}
|
||||
|
||||
public getDescription():string {
|
||||
return this.data.description;
|
||||
}
|
||||
|
||||
public getFnParams():Array<string> {
|
||||
return this.data.fnParams;
|
||||
}
|
||||
|
||||
public getType():TYPE {
|
||||
return this.data.type;
|
||||
}
|
||||
|
||||
public callFunction() {
|
||||
return functions[this.data.fnName].apply(this, this.data.fnParams);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
import Options from './Options'
|
||||
import Contact from './Contact'
|
||||
import Translation from './util/Translation'
|
||||
import Client from './Client'
|
||||
import * as CONST from './CONST'
|
||||
|
||||
interface NotificationSettings {
|
||||
title:string,
|
||||
message:string,
|
||||
duration?:number,
|
||||
force?:boolean,
|
||||
soundFile?:string,
|
||||
loop?:boolean,
|
||||
source?:string,
|
||||
icon?:string
|
||||
};
|
||||
|
||||
export default class Notification {
|
||||
private static inited = false;
|
||||
|
||||
private static popupTimeout;
|
||||
|
||||
private static popupDelay = 1000;
|
||||
|
||||
private static audioObject;
|
||||
|
||||
public static init() {
|
||||
if(Notification.inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(document).on('postmessagein.jsxc', function(event, bid, msg) {
|
||||
msg = (msg && msg.match(/^\?OTR/)) ? $.t('Encrypted_message') : msg;
|
||||
var data = jsxc.storage.getUserItem('buddy', bid);
|
||||
|
||||
Notification.notify({
|
||||
title: Translation.t('New_message_from'),
|
||||
message: msg,
|
||||
soundFile: CONST.SOUNDS.MSG,
|
||||
source: bid
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('callincoming.jingle', function() {
|
||||
Notification.playSound(CONST.SOUNDS.CALL, true, true);
|
||||
});
|
||||
|
||||
$(document).on('accept.call.jsxc reject.call.jsxc', function() {
|
||||
Notification.stopSound();
|
||||
});
|
||||
|
||||
if (!Notice.has('gui.showRequestNotification')) {
|
||||
Notice.add({
|
||||
msg: Translation.t('Notifications') + '?',
|
||||
description: Translation.t('Should_we_notify_you_')
|
||||
}, 'gui.showRequestNotification');
|
||||
}
|
||||
}
|
||||
|
||||
public static muteSound(external?) {
|
||||
$('#jsxc-menu .jsxc-muteNotification').text(Translation.t('Unmute'));
|
||||
|
||||
if (external !== true) {
|
||||
Options.set('muteNotification', true);
|
||||
}
|
||||
}
|
||||
|
||||
public static unmuteSound(external?) {
|
||||
$('#jsxc-menu .jsxc-muteNotification').text(Translation.t('Mute'));
|
||||
|
||||
if (external !== true) {
|
||||
Options.set('muteNotification', false);
|
||||
}
|
||||
}
|
||||
|
||||
public static notify(settings:NotificationSettings) {
|
||||
if (!Options.get('notification') || !Notification.hasPermission()) {
|
||||
return; // notifications disabled
|
||||
}
|
||||
|
||||
if (Client.hasFocus() && !settings.force) {
|
||||
return; // Tab is visible
|
||||
}
|
||||
|
||||
settings.icon = settings.icon || Options.get('root') + '/img/XMPP_logo.png';
|
||||
|
||||
if (typeof settings.source === 'string') {
|
||||
let contact = new Contact(settings.source);
|
||||
let avatar = contact.getAvatar();
|
||||
|
||||
if (typeof avatar === 'string' && avatar !== '0') {
|
||||
settings.icon = avatar;
|
||||
}
|
||||
}
|
||||
|
||||
settings.duration = settings.duration || Options.get('notification').duration;
|
||||
settings.title = Translation.t(settings.title);
|
||||
settings.message = Translation.t(settings.message);
|
||||
|
||||
Notification.popupTimeout = setTimeout(function() {
|
||||
Notification.showPopup(settings);
|
||||
}, Notification.popupDelay);
|
||||
}
|
||||
|
||||
private static showPopup(settings:NotificationSettings) {
|
||||
if (typeof settings.soundFile === 'string') {
|
||||
Notification.playSound(settings.soundFile, settings.loop, settings.force);
|
||||
}
|
||||
|
||||
var popup = new window.Notification(settings.title, {
|
||||
body: settings.message,
|
||||
icon: settings.icon
|
||||
});
|
||||
|
||||
if (settings.duration > 0) {
|
||||
setTimeout(function() {
|
||||
popup.close();
|
||||
}, settings.duration);
|
||||
}
|
||||
}
|
||||
|
||||
private static hasSupport() {
|
||||
return !!window.Notification;
|
||||
}
|
||||
|
||||
private static requestPermission() {
|
||||
window.Notification.requestPermission(function(status) {
|
||||
if (window.Notification.permission !== status) {
|
||||
window.Notification.permission = status;
|
||||
}
|
||||
|
||||
if (Notification.hasPermission()) {
|
||||
$(document).trigger('notificationready.jsxc');
|
||||
} else {
|
||||
$(document).trigger('notificationfailure.jsxc');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static hasPermission() {
|
||||
return window.Notification.permission === CONST.NOTIFICATION_GRANTED;
|
||||
}
|
||||
|
||||
private static playSound(soundFile:string, loop?:boolean, force?:boolean) {
|
||||
if (!jsxc.master) {
|
||||
// only master plays sound
|
||||
return;
|
||||
}
|
||||
|
||||
if (Options.get('muteNotification') || jsxc.storage.getUserItem('presence') === 'dnd') {
|
||||
// sound mute or own presence is dnd
|
||||
return;
|
||||
}
|
||||
|
||||
if (Client.hasFocus() && !force) {
|
||||
// tab is visible
|
||||
return;
|
||||
}
|
||||
|
||||
// stop current audio file
|
||||
Notification.stopSound();
|
||||
|
||||
var audio = new Audio(Options.get('root') + '/sound/' + soundFile);
|
||||
audio.loop = loop || false;
|
||||
audio.play();
|
||||
|
||||
Notification.audioObject = audio;
|
||||
}
|
||||
|
||||
private static stopSound() {
|
||||
var audio = Notification.audioObject;
|
||||
|
||||
if (typeof audio !== 'undefined' && audio !== null) {
|
||||
audio.pause();
|
||||
Notification.audioObject = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,39 @@
|
||||
/**
|
||||
* Set some options for the chat.
|
||||
*
|
||||
* @namespace jsxc.options
|
||||
*/
|
||||
jsxc.options = {
|
||||
export default class Options {
|
||||
|
||||
public static get(key) {
|
||||
if (jsxc && jsxc.bid) {
|
||||
var local = jsxc.storage.getUserItem('options') || {};
|
||||
|
||||
return (typeof local[key] !== 'undefined') ? local[key] : Options[key];
|
||||
}
|
||||
|
||||
return (typeof Options[key] !== 'undefined') ? Options[key] : {};
|
||||
};
|
||||
|
||||
public static set(key, value) {
|
||||
jsxc.storage.updateItem('options', key, value, true);
|
||||
};
|
||||
|
||||
/** name of container application (e.g. owncloud or SOGo) */
|
||||
app_name: 'web applications',
|
||||
private static app_name = 'web applications';
|
||||
|
||||
/** Timeout for the keepalive signal */
|
||||
timeout: 3000,
|
||||
private static timeout = 3000;
|
||||
|
||||
/** Timeout for the keepalive signal if the master is busy */
|
||||
busyTimeout: 15000,
|
||||
private static busyTimeout = 15000;
|
||||
|
||||
/** OTR options */
|
||||
otr: {
|
||||
private static otr = {
|
||||
enable: true,
|
||||
ERROR_START_AKE: false,
|
||||
debug: false,
|
||||
SEND_WHITESPACE_TAG: false,
|
||||
WHITESPACE_START_AKE: true
|
||||
},
|
||||
};
|
||||
|
||||
/** xmpp options */
|
||||
xmpp: {
|
||||
private static xmpp = {
|
||||
/** BOSH url */
|
||||
url: null,
|
||||
|
||||
@@ -48,16 +57,16 @@ jsxc.options = {
|
||||
|
||||
/** @deprecated since v2.1.0. Use now loginForm.enable. */
|
||||
onlogin: null
|
||||
},
|
||||
};
|
||||
|
||||
/** default xmpp priorities */
|
||||
priority: {
|
||||
private static priority = {
|
||||
online: 0,
|
||||
chat: 0,
|
||||
away: 0,
|
||||
xa: 0,
|
||||
dnd: 0
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* This function is called if a login form was found, but before any
|
||||
@@ -66,10 +75,10 @@ jsxc.options = {
|
||||
* @memberOf jsxc.options
|
||||
* @function
|
||||
*/
|
||||
formFound: null,
|
||||
private static formFound = null;
|
||||
|
||||
/** If all 3 properties are set and enable is true, the login form is used */
|
||||
loginForm: {
|
||||
private static loginForm = {
|
||||
/** False, disables login through login form */
|
||||
enable: true,
|
||||
|
||||
@@ -128,45 +137,45 @@ jsxc.options = {
|
||||
* roster state will be used.
|
||||
*/
|
||||
startMinimized: false
|
||||
},
|
||||
};
|
||||
|
||||
/** jquery object from logout element */
|
||||
logoutElement: null,
|
||||
private static logoutElement = null;
|
||||
|
||||
/** How many messages should be logged? */
|
||||
numberOfMsg: 10,
|
||||
private static numberOfMsg = 10;
|
||||
|
||||
/** Default language */
|
||||
defaultLang: 'en',
|
||||
private static defaultLang = 'en';
|
||||
|
||||
/** auto language detection */
|
||||
autoLang: true,
|
||||
private static autoLang = true;
|
||||
|
||||
/** Place for roster */
|
||||
rosterAppend: 'body',
|
||||
private static rosterAppend = 'body';
|
||||
|
||||
/** Should we use the HTML5 notification API? */
|
||||
notification: true,
|
||||
private static notification = true;
|
||||
|
||||
/** duration for notification */
|
||||
popupDuration: 6000,
|
||||
private static popupDuration = 6000;
|
||||
|
||||
/** Absolute path root of JSXC installation */
|
||||
root: '',
|
||||
private static root = '/jsxc4.0/';
|
||||
|
||||
/**
|
||||
* This function decides wether the roster will be displayed or not if no
|
||||
* connection is found.
|
||||
*/
|
||||
displayRosterMinimized: function() {
|
||||
private static displayRosterMinimized = function() {
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
/** Set to true if you want to hide offline buddies. */
|
||||
hideOffline: false,
|
||||
private static hideOffline = false;
|
||||
|
||||
/** Mute notification sound? */
|
||||
muteNotification: false,
|
||||
private static muteNotification = false;
|
||||
|
||||
/**
|
||||
* If no avatar is found, this function is called.
|
||||
@@ -174,9 +183,9 @@ jsxc.options = {
|
||||
* @param jid Jid of that user.
|
||||
* @this {jQuery} Elements to update with probable .jsxc_avatar elements
|
||||
*/
|
||||
defaultAvatar: function(jid) {
|
||||
private static defaultAvatar = function(jid) {
|
||||
jsxc.gui.avatarPlaceholder($(this).find('.jsxc_avatar'), jid);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* This callback processes all settings.
|
||||
@@ -193,7 +202,7 @@ jsxc.options = {
|
||||
* @param password {string} password
|
||||
* @param cb {loadSettingsCallback} Callback that handles the result
|
||||
*/
|
||||
loadSettings: null,
|
||||
private static loadSettings = null;
|
||||
|
||||
/**
|
||||
* Call this function to save user settings permanent.
|
||||
@@ -202,14 +211,14 @@ jsxc.options = {
|
||||
* @param data Holds all data as key/value
|
||||
* @param cb Called with true on success, false otherwise
|
||||
*/
|
||||
saveSettinsPermanent: function(data, cb) {
|
||||
private static saveSettinsPermanent = function(data, cb) {
|
||||
cb(true);
|
||||
},
|
||||
};
|
||||
|
||||
carbons: {
|
||||
private static carbons = {
|
||||
/** Enable carbon copies? */
|
||||
enable: true
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Processes user list.
|
||||
@@ -226,10 +235,10 @@ jsxc.options = {
|
||||
* @param {string} search Search token (start with)
|
||||
* @param {getUsers-cb} cb Called with list of users
|
||||
*/
|
||||
getUsers: null,
|
||||
private static getUsers = null;
|
||||
|
||||
/** Options for info in favicon */
|
||||
favicon: {
|
||||
private static favicon = {
|
||||
enable: true,
|
||||
|
||||
/** Favicon info background color */
|
||||
@@ -237,13 +246,13 @@ jsxc.options = {
|
||||
|
||||
/** Favicon info text color */
|
||||
textColor: '#fff'
|
||||
},
|
||||
};
|
||||
|
||||
/** @deprecated since v2.1.0. Use now RTCPeerConfig.url. */
|
||||
turnCredentialsPath: null,
|
||||
private static turnCredentialsPath = null;
|
||||
|
||||
/** RTCPeerConfiguration used for audio/video calls. */
|
||||
RTCPeerConfig: {
|
||||
private static RTCPeerConfig = {
|
||||
/** Time-to-live for config from url */
|
||||
ttl: 3600,
|
||||
|
||||
@@ -257,12 +266,12 @@ jsxc.options = {
|
||||
iceServers: [{
|
||||
urls: 'stun:stun.stunprotocol.org'
|
||||
}]
|
||||
},
|
||||
};
|
||||
|
||||
/** Link to an online user manual */
|
||||
onlineHelp: 'http://www.jsxc.org/manual.html',
|
||||
private static onlineHelp = 'http://www.jsxc.org/manual.html';
|
||||
|
||||
viewport: {
|
||||
private static viewport = {
|
||||
getSize: function() {
|
||||
var w = $(window).width() - $('#jsxc_windowListSB').width();
|
||||
var h = $(window).height();
|
||||
@@ -276,23 +285,23 @@ jsxc.options = {
|
||||
height: h
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/** Maximal storage size for attachments received via data channels (webrtc). */
|
||||
maxStorableSize: 1000000,
|
||||
private static maxStorableSize = 1000000;
|
||||
|
||||
/** Options for file transfer. */
|
||||
fileTransfer: {
|
||||
private static fileTransfer = {
|
||||
httpUpload: {
|
||||
enable: true
|
||||
},
|
||||
// @TODO add option to enable/disable data channels
|
||||
},
|
||||
};
|
||||
|
||||
/** Default option for chat state notifications */
|
||||
chatState: {
|
||||
private static chatState = {
|
||||
enable: true
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Download urls to screen media extensions.
|
||||
@@ -300,8 +309,10 @@ jsxc.options = {
|
||||
* @type {Object}
|
||||
* @see example extensions {@link https://github.com/otalk/getScreenMedia}
|
||||
*/
|
||||
screenMediaExtension: {
|
||||
private static screenMediaExtension = {
|
||||
firefox: '',
|
||||
chrome: ''
|
||||
}
|
||||
};
|
||||
|
||||
private static storage;
|
||||
};
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário