Comparar commits
65 Commits
v0.8.2
...
v1.0.0-beta2
| Autor | SHA1 | Data | |
|---|---|---|---|
| a69b70af1e | |||
| 341db9e625 | |||
| 67d2c12640 | |||
| c0fae24dcd | |||
| 05d9aaa01d | |||
| 8cd97ec3e1 | |||
| 58e2fccf95 | |||
| 4b541d462a | |||
| 310ac4e0a6 | |||
| 53b44961ea | |||
| 8271e64cf7 | |||
| 27438984e1 | |||
| 0fb7de74ce | |||
| 3db02b0560 | |||
| e2dfb6bc94 | |||
| 55dbbdb636 | |||
| 308ccc1426 | |||
| 7f1a011b1b | |||
| d102d41f6b | |||
| 91def2febc | |||
| 7ea444276b | |||
| f810a8a28f | |||
| 2acf47a872 | |||
| 906136245a | |||
| a053753e10 | |||
| e996296b7f | |||
| d4a31dc8fc | |||
| c8ca2734e0 | |||
| 03e8ae8d1d | |||
| d626eb355f | |||
| 862c124366 | |||
| 3c2cf893be | |||
| ac8f014377 | |||
| d0e16c0a2a | |||
| cb926a1dec | |||
| 7aac1d6c28 | |||
| 25a982f9c3 | |||
| 76da9c0fd1 | |||
| a9d167acda | |||
| 32960f39b0 | |||
| 3e1c1ded67 | |||
| e19da058f6 | |||
| 80b5a4a350 | |||
| 5c10a738cb | |||
| 855b776ca2 | |||
| 735016e676 | |||
| 46897f0e66 | |||
| f1918e06cb | |||
| 3405d0e3c2 | |||
| c280251e3c | |||
| 0954c245c3 | |||
| 1aa44434b3 | |||
| c1bd08b3e4 | |||
| f298364a37 | |||
| e061670880 | |||
| 6680283cea | |||
| cb6b1345e0 | |||
| 09a83236ab | |||
| a68bae3288 | |||
| a7f4073f0b | |||
| 8248854ce7 | |||
| 88f225f564 | |||
| 8c1ba13449 | |||
| eb7cef099b | |||
| 8ae8d2f7bf |
@@ -1 +1,3 @@
|
||||
node_modules
|
||||
*.zip
|
||||
*.zip.sig
|
||||
|
||||
+80
-5
@@ -1,6 +1,11 @@
|
||||
/* global module:false */
|
||||
module.exports = function(grunt) {
|
||||
|
||||
|
||||
var dep = grunt.file.readJSON('dep.json');
|
||||
var dep_files = dep.map(function(el) {
|
||||
return el.file;
|
||||
});
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
app: grunt.file.readJSON('package.json'),
|
||||
@@ -47,10 +52,53 @@ module.exports = function(grunt) {
|
||||
} ]
|
||||
}
|
||||
},
|
||||
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) {
|
||||
if (filepath === 'build/lib/otr/build/dep/crypto.js') {
|
||||
src += ';';
|
||||
}
|
||||
|
||||
var data = dep[dep_files.indexOf(filepath)];
|
||||
|
||||
return '/*!\n * Source: ' + filepath + ', license: ' + data.license + ', url: ' + data.url + ' */\n' + src;
|
||||
}
|
||||
},
|
||||
src: dep_files,
|
||||
dest: 'build/lib/jsxc.dep.js'
|
||||
},
|
||||
jsxc: {
|
||||
options: {
|
||||
banner: '/*! This file is concatenated for the browser. */\n\n'
|
||||
},
|
||||
src: ['build/jsxc.lib.js', 'build/jsxc.lib.webrtc.js'],
|
||||
dest: 'build/jsxc.js'
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
jsxc: {
|
||||
options: {
|
||||
mangle: false,
|
||||
sourceMap: true,
|
||||
preserveComments: 'some'
|
||||
},
|
||||
files: {
|
||||
'build/lib/jsxc.dep.min.js': ['build/lib/jsxc.dep.js'],
|
||||
'build/jsxc.min.js': ['build/jsxc.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
search: {
|
||||
console: {
|
||||
files: {
|
||||
src: ['*.js']
|
||||
src: [ '*.js' ]
|
||||
},
|
||||
options: {
|
||||
searchString: /console\.log\((?!'[<>]|msg)/g,
|
||||
@@ -60,18 +108,36 @@ module.exports = function(grunt) {
|
||||
},
|
||||
changelog: {
|
||||
files: {
|
||||
src: ['CHANGELOG.md']
|
||||
src: [ 'CHANGELOG.md' ]
|
||||
},
|
||||
options: {
|
||||
searchString: "<%= app.version %>",
|
||||
logFormat: 'console',
|
||||
onComplete: function(m) {
|
||||
if(m.numMatches === 0) {
|
||||
if (m.numMatches === 0) {
|
||||
grunt.fail.fatal("No entry in README.md for current version found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
compress: {
|
||||
main: {
|
||||
options: {
|
||||
archive: "jsxc-<%= app.version %>.zip"
|
||||
},
|
||||
files: [ {
|
||||
src: [ '**' ],
|
||||
expand: true,
|
||||
dest: 'jsxc/',
|
||||
cwd: 'build/'
|
||||
} ]
|
||||
}
|
||||
},
|
||||
shell: {
|
||||
hooks: {
|
||||
command: 'cp pre-commit .git/hooks/'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -79,11 +145,20 @@ module.exports = function(grunt) {
|
||||
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-shell');
|
||||
|
||||
// Default task.
|
||||
grunt.registerTask('default', [ 'jshint', 'search', 'clean', 'copy', 'usebanner', 'replace' ]);
|
||||
grunt.registerTask('default', [ 'jshint', 'search', 'clean', 'copy', 'usebanner', 'replace', 'concat', 'uglify', 'compress' ]);
|
||||
|
||||
// Create alpha/beta build
|
||||
grunt.registerTask('pre', [ 'jshint', 'search:console', 'clean', 'copy', 'usebanner', 'replace', 'concat', 'uglify', 'compress' ]);
|
||||
|
||||
// before commit
|
||||
grunt.registerTask('commit', [ 'jshint', 'search:console' ]);
|
||||
};
|
||||
|
||||
+2
-1
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*!
|
||||
* <%= app.name %> v<%= app.version %> - <%= grunt.template.today("yyyy-mm-dd") %>
|
||||
*
|
||||
* Copyright (c) <%= grunt.template.today("yyyy") %> <%= app.author %> <br>
|
||||
@@ -8,4 +8,5 @@
|
||||
*
|
||||
* @author <%= app.author %>
|
||||
* @version <%= app.version %>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 9.3 KiB |
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||
|
||||
<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="Layer_1"
|
||||
xml:space="preserve"
|
||||
height="147.22015"
|
||||
viewBox="0 0 192.89149 147.21771"
|
||||
width="192.89587"
|
||||
version="1.1"
|
||||
y="0px"
|
||||
x="0px"
|
||||
enable-background="new 0 0 176.486 181.437"
|
||||
inkscape:version="0.91pre2 r"
|
||||
sodipodi:docname="XMPP_logo.svg"><metadata
|
||||
id="metadata41"><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></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs39" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="640"
|
||||
inkscape:window-height="480"
|
||||
id="namedview37"
|
||||
showgrid="false"
|
||||
fit-margin-top="10"
|
||||
fit-margin-left="10"
|
||||
fit-margin-right="10"
|
||||
fit-margin-bottom="10"
|
||||
inkscape:zoom="1.3007054"
|
||||
inkscape:cx="71.332001"
|
||||
inkscape:cy="72.501142"
|
||||
inkscape:window-x="75"
|
||||
inkscape:window-y="34"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="Layer_1" /><linearGradient
|
||||
id="SVGID_1_"
|
||||
y2="0.00048828"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="-1807.2"
|
||||
gradientTransform="translate(1925.9953,9.9988343)"
|
||||
y1="125.86"
|
||||
x1="-1807.2"><stop
|
||||
stop-color="#1b3967"
|
||||
offset=".011"
|
||||
id="stop4" /><stop
|
||||
stop-color="#13b5ea"
|
||||
offset=".467"
|
||||
id="stop6" /><stop
|
||||
stop-color="#002b5c"
|
||||
offset=".9945"
|
||||
id="stop8" /></linearGradient><path
|
||||
d="m 146.28531,24.187835 c 0.077,1.313 -1.786,0.968 -1.786,2.293 0,38.551 -44.720002,96.831035 -89.847002,108.190035 l 0,1.182 C 114.60931,130.34287 181.38231,69.052835 182.89231,10.002834 l -36.6,14.189001 z"
|
||||
id="path10"
|
||||
style="fill:url(#SVGID_1_)"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 130.22531,27.958835 c 0.077,1.313 0.121,2.633 0.121,3.958 0,38.551 -30.700002,90.497035 -75.827002,101.860035 l 0,1.637 c 59.065002,-3.823 105.810002,-63.023035 105.810002,-109.200035 0,-2.375 -0.125,-4.729 -0.371,-7.056 l -29.73,8.796 z"
|
||||
id="path12"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#e96d1f" /><linearGradient
|
||||
id="SVGID_2_"
|
||||
y2="1.279e-13"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="-1073.2"
|
||||
gradientTransform="matrix(-1,0,0,1,-998.20465,9.9988343)"
|
||||
y1="126.85"
|
||||
x1="-1073.2"><stop
|
||||
stop-color="#1b3967"
|
||||
offset=".011"
|
||||
id="stop15" /><stop
|
||||
stop-color="#13b5ea"
|
||||
offset=".467"
|
||||
id="stop17" /><stop
|
||||
stop-color="#002b5c"
|
||||
offset=".9945"
|
||||
id="stop19" /></linearGradient><path
|
||||
d="m 46.594308,24.187835 c -0.077,1.313 1.787,0.968 1.787,2.293 0,38.551 46.558,97.366035 91.688002,108.730035 l 0,1.639 C 80.116308,131.32987 11.509308,69.049835 9.9993079,9.9998343 L 46.598308,24.188835 Z"
|
||||
id="path21"
|
||||
style="fill:url(#SVGID_2_)"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 64.726308,28.930835 c -0.076,1.313 -0.12,2.63 -0.12,3.957 0,38.551 30.699,90.497035 75.827002,101.860035 l 0,1.639 C 81.389308,133.59687 34.623308,73.362835 34.623308,27.186835 c 0,-2.375 0.128,-4.729 0.371,-7.056 l 29.73,8.798 z"
|
||||
id="path23"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#a0ce67" /><path
|
||||
d="m 34.708308,19.581835 7.617,2.722 c -0.041,0.962 -0.066,2.254 -0.066,3.225 0,41.219 37.271,98.204035 87.272002,107.120035 3.245,1.088 7.538,2.077 10.932,2.931 l 0,1.638 C 75.209308,131.65787 29.363308,65.351835 34.703308,19.577835 Z"
|
||||
id="path25"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#439639" /><path
|
||||
d="m 160.33531,18.758835 -7.833,2.625 c 0.041,0.963 0.191,2.203 0.191,3.173 0,41.219 -37.272,98.205035 -87.274002,107.120035 -3.243,1.089 -7.538,2.077 -10.93,2.932 l 0,1.639 C 122.83331,127.58787 165.66931,64.528835 160.32931,18.757835 Z"
|
||||
id="path27"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#d9541e" /></svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 4.5 KiB |
+276
-11
@@ -30,6 +30,10 @@ p.jsxc_center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
li.jsxc_sep {
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
/*############################
|
||||
*########## Dialog ##########
|
||||
*############################*/
|
||||
@@ -38,6 +42,15 @@ p.jsxc_center {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
#jsxc_dialog ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#jsxc_dialog ul, #jsxc_dialog li {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#jsxc_dialog p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
@@ -141,6 +154,8 @@ li .jsxc_name:hover {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-family: Arial;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.jsxc_avatar img {
|
||||
@@ -152,6 +167,36 @@ li .jsxc_name:hover {
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.jsxc_spot {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
text-indent: -99999em;
|
||||
margin-top: 3px;
|
||||
margin-right: 5px;
|
||||
border: 1px solid #000 !important;
|
||||
line-height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jsxc_spot.jsxc_online, .jsxc_spot.jsxc_chat {
|
||||
background-color: #00BFFF;
|
||||
}
|
||||
|
||||
.jsxc_spot.jsxc_away, .jsxc_spot.jsxc_xa {
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.jsxc_spot.jsxc_dnd {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.jsxc_spot.jsxc_offline {
|
||||
background-color: #A4A4A4;
|
||||
}
|
||||
|
||||
/*############################
|
||||
*########## Roster ##########
|
||||
*############################*/
|
||||
@@ -344,8 +389,64 @@ div#jsxc_roster>.jsxc_bottom ul li:last-child {
|
||||
color: black;
|
||||
font-size: 80%;
|
||||
padding: 2px;
|
||||
position: relative;
|
||||
-webkit-animation: bounce 2s 1s infinite;
|
||||
animation: bounce 2s 1s infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes bounce {
|
||||
0% {
|
||||
bottom: 0;
|
||||
-webkit-animation-timing-function: ease-in;
|
||||
}
|
||||
12% {
|
||||
bottom: 5px;
|
||||
-webkit-animation-timing-function: ease-out;
|
||||
}
|
||||
25% {
|
||||
bottom: 0px;
|
||||
-webkit-animation-timing-function: ease-in;
|
||||
}
|
||||
37% {
|
||||
bottom: 5px;
|
||||
-webkit-animation-timing-function: ease-out;
|
||||
}
|
||||
50% {
|
||||
bottom: 0px;
|
||||
-webkit-animation-timing-function: ease-in;
|
||||
}
|
||||
100% {
|
||||
bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0% {
|
||||
bottom: 0;
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
12% {
|
||||
bottom: 5px;
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
25% {
|
||||
bottom: 0px;
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
37% {
|
||||
bottom: 5px;
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
50% {
|
||||
bottom: 0px;
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
100% {
|
||||
bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#jsxc_presence {
|
||||
cursor: pointer;
|
||||
padding-left: 2px;
|
||||
@@ -380,6 +481,27 @@ ul#jsxc_buddylist .jsxc_name {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
ul#jsxc_buddylist li .jsxc_name:before {
|
||||
content: ' ';
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
display: inline-block;
|
||||
opacity: 0.0;
|
||||
-webkit-transition: width 0.5s, opacity 0.5s;
|
||||
transition: width 0.5s, opacity 0.5s;
|
||||
}
|
||||
|
||||
ul#jsxc_buddylist li.jsxc_unreadMsg .jsxc_name:before {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
background-color: orange;
|
||||
margin-right: 3px;
|
||||
opacity: 1.0;
|
||||
-webkit-transition: width 0.5s, opacity 0.5s;
|
||||
transition: width 0.5s, opacity 0.5s;
|
||||
}
|
||||
|
||||
ul#jsxc_buddylist li.jsxc_expand {
|
||||
height: 54px;
|
||||
}
|
||||
@@ -541,25 +663,30 @@ div#jsxc_toggleRoster {
|
||||
div#jsxc_windowList {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
width: 100%;
|
||||
right: 210px;
|
||||
left: 0px;
|
||||
z-index: 50;
|
||||
clip: rect(-10000px, 10000px, 30px, 30px);
|
||||
}
|
||||
|
||||
div#jsxc_windowList>ul {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
padding-right: 210px;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
height: 30px;
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
-webkit-transition: right 0.5s;
|
||||
transition: right 0.5s;
|
||||
}
|
||||
|
||||
div#jsxc_windowList>ul>li {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
display: block;
|
||||
float: right;
|
||||
display: inline-block;
|
||||
width: 250px;
|
||||
background-color: #282323;
|
||||
height: 30px;
|
||||
@@ -567,10 +694,45 @@ div#jsxc_windowList>ul>li {
|
||||
overflow: visible;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
div#jsxc_windowList>ul>li.jsxc_min {
|
||||
width: 200px;
|
||||
width: 200px !important;
|
||||
}
|
||||
|
||||
#jsxc_windowListSB {
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
#jsxc_windowListSB > div {
|
||||
box-sizing: border-box;
|
||||
width: 14px;
|
||||
height: 100%;
|
||||
background-color: #D3D3D3;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
#jsxc_windowListSB > div:hover {
|
||||
background-color: #c3c3c3;
|
||||
}
|
||||
#jsxc_windowListSB > div.jsxc_disabled {
|
||||
background-color: #f1f1f1 !important;
|
||||
color: #d1d1d1;
|
||||
cursor: default !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*############################
|
||||
@@ -622,6 +784,7 @@ div.jsxc_window .jsxc_emoticons {
|
||||
width: 30px;
|
||||
position: absolute;
|
||||
top: 240px;
|
||||
/*bottom: 0px;*/
|
||||
right: 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -653,6 +816,7 @@ div.jsxc_window .jsxc_emoticons ul {
|
||||
padding: 3px;
|
||||
border-radius: 3px;
|
||||
z-index: 200;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
div.jsxc_window .jsxc_emoticons ul:after {
|
||||
@@ -673,12 +837,15 @@ div.jsxc_window .jsxc_emoticons li {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.jsxc_window .jsxc_emoticons img {
|
||||
div.jsxc_window .jsxc_emoticons div {
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
background-size: 30px 30px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
div.jsxc_window .jsxc_emoticons img:hover {
|
||||
div.jsxc_window .jsxc_emoticons div:hover {
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
@@ -687,7 +854,8 @@ div.jsxc_window .jsxc_emoticons img:hover {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jsxc_window .jsxc_gradient {
|
||||
.jsxc_window .jsxc_gradient {
|
||||
display:none;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
@@ -717,13 +885,14 @@ div.jsxc_window .jsxc_avatar {
|
||||
|
||||
div.jsxc_window .jsxc_textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
div.jsxc_window .slimScrollDiv {
|
||||
margin: 0px 0px 6px 0px;
|
||||
left: auto !important;
|
||||
top: auto !important;
|
||||
}
|
||||
|
||||
div.jsxc_chatmessage {
|
||||
@@ -746,6 +915,7 @@ div.jsxc_chatmessage a {
|
||||
div.jsxc_chatmessage img {
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
background-size: 19px 19px;
|
||||
}
|
||||
|
||||
/** incoming message */
|
||||
@@ -901,6 +1071,7 @@ div.jsxc_settings li {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.jsxc_settings li:first-child {
|
||||
@@ -917,7 +1088,12 @@ div.jsxc_settings li.jsxc_disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
div.jsxc_transfer {
|
||||
.jsxc_tools > div.jsxc_disabled {
|
||||
opacity: 0.5;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
div.jsxc_transfer, div.jsxc_transfer.jsxc_disabled:hover {
|
||||
background-image: url('img/padlock_open_grey.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
@@ -975,4 +1151,93 @@ img.jsxc_vCard {
|
||||
float: right;
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
border: 5px solid white;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsxc_window .ui-resizable-w {
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.jsxc_window .ui-resizable-nw {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
z-index: 95 !important;
|
||||
}
|
||||
|
||||
.jsxc_window .ui-resizable-n {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 15px;
|
||||
z-index: 100;
|
||||
background: -moz-linear-gradient(top, rgba(164, 164, 164, 1) 0%,
|
||||
rgba(40, 35, 35, 0) 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(164,
|
||||
164, 164, 1)), color-stop(100%, rgba(40, 35, 35, 0)));
|
||||
/* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, rgba(164, 164, 164, 1) 0%,
|
||||
rgba(40, 35, 35, 0) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(164, 164, 164, 1) 0%,
|
||||
rgba(40, 35, 35, 0) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(164, 164, 164, 1) 0%,
|
||||
rgba(40, 35, 35, 0) 100%); /* IE10+ */
|
||||
background: linear-gradient(to bottom, #a4a4a4 0%, rgba(40, 35, 35, 0)
|
||||
100%); /* W3C */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a4a4a4',
|
||||
endColorstr='#00282323', GradientType=0); /* IE6-9 */
|
||||
}
|
||||
|
||||
.jsxc_emoticon {
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
background-size: 19px 19px !important;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.jsxc_angel { background: url('img/emotions/angel.png') }
|
||||
|
||||
.jsxc_angry { background: url('img/emotions/angry.png') }
|
||||
|
||||
.jsxc_smile { background: url('img/emotions/smile.png') }
|
||||
|
||||
.jsxc_grin { background: url('img/emotions/grin.png') }
|
||||
|
||||
.jsxc_sad { background: url('img/emotions/sad.png') }
|
||||
|
||||
.jsxc_wink { background: url('img/emotions/wink.png') }
|
||||
|
||||
.jsxc_tonguesmile { background: url('img/emotions/tonguesmile.png') }
|
||||
|
||||
.jsxc_surprised { background: url('img/emotions/surprised.png') }
|
||||
|
||||
.jsxc_kiss { background: url('img/emotions/kiss.png') }
|
||||
|
||||
.jsxc_sunglassess { background: url('img/emotions/sunglassess.png') }
|
||||
|
||||
.jsxc_crysad { background: url('img/emotions/crysad.png') }
|
||||
|
||||
.jsxc_doubt { background: url('img/emotions/doubt.png') }
|
||||
|
||||
.jsxc_zip { background: url('img/emotions/zip.png') }
|
||||
|
||||
.jsxc_thumbsup { background: url('img/emotions/thumbsup.png') }
|
||||
|
||||
.jsxc_thumbsdown { background: url('img/emotions/thumbsdown.png') }
|
||||
|
||||
.jsxc_beer { background: url('img/emotions/beer.png') }
|
||||
|
||||
.jsxc_devil { background: url('img/emotions/devil.png') }
|
||||
|
||||
.jsxc_kissing { background: url('img/emotions/kissing.png') }
|
||||
|
||||
.jsxc_rose { background: url('img/emotions/rose.png') }
|
||||
|
||||
.jsxc_music { background: url('img/emotions/music.png') }
|
||||
|
||||
.jsxc_love { background: url('img/emotions/love.png') }
|
||||
|
||||
.jsxc_tired { background: url('img/emotions/tired.png') }
|
||||
|
||||
+6929
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+1455
-684
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+211
-52
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* jsxc v0.8.2 - 2014-08-20
|
||||
/*!
|
||||
* jsxc v1.0.0-beta2 - 2014-10-31
|
||||
*
|
||||
* Copyright (c) 2014 Klaus Herberth <klaus@jsxc.org> <br>
|
||||
* Released under the MIT license
|
||||
@@ -7,15 +7,16 @@
|
||||
* Please see http://www.jsxc.org/
|
||||
*
|
||||
* @author Klaus Herberth <klaus@jsxc.org>
|
||||
* @version 0.8.2
|
||||
* @version 1.0.0-beta2
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/* jsxc, Strophe, SDPUtil, getUserMediaWithConstraints, setupRTC, jQuery */
|
||||
/* global jsxc, Strophe, SDPUtil, getUserMediaWithConstraints, setupRTC, jQuery, MediaStreamTrack */
|
||||
|
||||
var RTC = null, RTCPeerconnection = null;
|
||||
|
||||
jsxc.gui.template.incomingCall = '<h3>%%Incoming_call%%</h3>\
|
||||
<p>%%Do_you_want_to_accept_the_call_from%% {{cid_name}}?</p>\
|
||||
<p>%%Do_you_want_to_accept_the_call_from%% {{bid_name}}?</p>\
|
||||
<p class="jsxc_right">\
|
||||
<a href="#" class="button jsxc_reject">%%Reject%%</a> <a href="#" class="button creation jsxc_accept">%%Accept%%</a>\
|
||||
</p>';
|
||||
@@ -23,10 +24,28 @@ jsxc.gui.template.incomingCall = '<h3>%%Incoming_call%%</h3>\
|
||||
jsxc.gui.template.allowMediaAccess = '<p>%%Please_allow_access_to_microphone_and_camera%%</p>';
|
||||
|
||||
jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
<div class="jsxc_chatarea">\
|
||||
<ul></ul>\
|
||||
</div>\
|
||||
<div class="jsxc_videoContainer">\
|
||||
<video class="jsxc_localvideo" autoplay></video>\
|
||||
<video class="jsxc_remotevideo" autoplay></video>\
|
||||
<div class="jsxc_status"></div>\
|
||||
<div class="bubblingG">\
|
||||
<span id="bubblingG_1">\
|
||||
</span>\
|
||||
<span id="bubblingG_2">\
|
||||
</span>\
|
||||
<span id="bubblingG_3">\
|
||||
</span>\
|
||||
</div>\
|
||||
<div class="jsxc_noRemoteVideo">\
|
||||
<div>\
|
||||
<div></div>\
|
||||
<p>%%No_video_signal%%</p>\
|
||||
<div></div>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="jsxc_controlbar">\
|
||||
<button type="button" class="jsxc_hangUp">%%hang_up%%</button>\
|
||||
@@ -44,9 +63,9 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
<div class="jsxc_snapshotbar">\
|
||||
<p>No pictures yet!</p>\
|
||||
</div>\n\
|
||||
<div class="jsxc_chatarea">\
|
||||
<!--<div class="jsxc_chatarea">\
|
||||
<ul></ul>\
|
||||
</div>\
|
||||
</div>-->\
|
||||
<div class="jsxc_infobar"></div>\
|
||||
</div>\
|
||||
</div>';
|
||||
@@ -76,7 +95,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
AUTO_ACCEPT: false,
|
||||
|
||||
/** required disco features */
|
||||
reqVideoFeatures: [ 'urn:xmpp:jingle:apps:rtp:video', 'urn:xmpp:jingle:apps:rtp:audio', 'urn:xmpp:jingle:transports:ice-udp:1' ],
|
||||
reqVideoFeatures: [ 'urn:xmpp:jingle:apps:rtp:video', 'urn:xmpp:jingle:apps:rtp:audio', 'urn:xmpp:jingle:transports:ice-udp:1', 'urn:xmpp:jingle:apps:dtls:0' ],
|
||||
|
||||
/** bare jid to current jid mapping */
|
||||
chatJids: {},
|
||||
@@ -110,6 +129,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
self.conn.jingle.pc_constraints = RTC.pc_constraints;
|
||||
|
||||
$(document).on('message.jsxc', $.proxy(self.onMessage, self));
|
||||
$(document).on('presence.jsxc', $.proxy(self.onPresence, self));
|
||||
|
||||
$(document).on('mediaready.jingle', $.proxy(self.onMediaReady, self));
|
||||
$(document).on('mediafailure.jingle', $.proxy(self.onMediaFailure, self));
|
||||
@@ -126,6 +146,10 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
jsxc.error('[JINGLE]', error);
|
||||
});
|
||||
|
||||
if (self.conn.disco) {
|
||||
self.conn.disco.addFeature('urn:xmpp:jingle:apps:dtls:0');
|
||||
}
|
||||
|
||||
if (self.conn.caps) {
|
||||
$(document).on('caps.strophe', $.proxy(self.onCaps, self));
|
||||
}
|
||||
@@ -172,18 +196,48 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Return list of video capable resources.
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
* @param jid
|
||||
* @returns {Array}
|
||||
*/
|
||||
getCapableRes: function(jid) {
|
||||
var self = jsxc.webrtc;
|
||||
var bid = jsxc.jidToBid(jid);
|
||||
var res = jsxc.storage.getUserItem('res', bid) || [];
|
||||
|
||||
var available = [];
|
||||
$.each(res, function(r) {
|
||||
if (self.conn.caps.hasFeatureByJid(bid + '/' + r, self.reqVideoFeatures)) {
|
||||
available.push(r);
|
||||
}
|
||||
});
|
||||
|
||||
return available;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add "video" button to roster
|
||||
*
|
||||
* @private
|
||||
* @memberOf jsxc.webrtc
|
||||
* @param event
|
||||
* @param cid cid of roster item
|
||||
* @param data data wich belongs to cid
|
||||
* @param bid bid of roster item
|
||||
* @param data data wich belongs to bid
|
||||
* @param el the roster item
|
||||
*/
|
||||
onAddRosterItem: function(event, cid, data, el) {
|
||||
onAddRosterItem: function(event, bid, data, el) {
|
||||
var self = jsxc.webrtc;
|
||||
|
||||
if (!self.conn) {
|
||||
$(document).one('connectionReady.jsxc', function() {
|
||||
self.onAddRosterItem(null, bid, data, el);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var videoIcon = $('<div class="jsxc_video jsxc_disabled" title="' + jsxc.l.Start_video_call + '"></div>');
|
||||
|
||||
videoIcon.click(function() {
|
||||
@@ -194,7 +248,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
el.find('.jsxc_options.jsxc_left').append(videoIcon);
|
||||
|
||||
el.on('extra.jsxc', function() {
|
||||
self.updateIcon(cid);
|
||||
self.updateIcon(bid);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -209,6 +263,8 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
initWindow: function(event, win) {
|
||||
var self = jsxc.webrtc;
|
||||
|
||||
jsxc.debug('webrtc.initWindow');
|
||||
|
||||
if (!self.conn) {
|
||||
$(document).one('connectionReady.jsxc', function() {
|
||||
self.initWindow(null, win);
|
||||
@@ -219,39 +275,43 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
var div = $('<div>').addClass('jsxc_video');
|
||||
win.find('.jsxc_transfer:eq(1)').after(div);
|
||||
|
||||
self.updateIcon(jsxc.jidToCid(win.data('jid')));
|
||||
self.updateIcon(jsxc.jidToBid(win.data('jid')));
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable or disable "video" icon and assign full jid.
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
* @param cid CSS conform jid
|
||||
* @param bid CSS conform jid
|
||||
*/
|
||||
updateIcon: function(cid) {
|
||||
updateIcon: function(bid) {
|
||||
jsxc.debug('Update icon', bid);
|
||||
|
||||
var self = jsxc.webrtc;
|
||||
var win = jsxc.gui.getWindow(cid);
|
||||
var jid = win.data('jid') || jsxc.storage.getUserItem('buddy_' + cid).jid;
|
||||
var win = jsxc.gui.window.get(bid);
|
||||
var jid = win.data('jid') || jsxc.storage.getUserItem('buddy', bid).jid;
|
||||
|
||||
var el = win.find('.jsxc_video').add('#' + cid + ' .jsxc_video');
|
||||
var el = win.find('.jsxc_video').add(jsxc.gui.roster.getItem(bid).find('.jsxc_video'));
|
||||
|
||||
// only start video call to a full jid
|
||||
if (Strophe.getResourceFromJid(jid) === null) {
|
||||
var capableRes = self.getCapableRes(jid);
|
||||
var targetRes = Strophe.getResourceFromJid(jid);
|
||||
|
||||
var res = jsxc.storage.getUserItem('buddy_' + cid).res;
|
||||
|
||||
if (Array.isArray(res) && res.length === 1) {
|
||||
jid += '/' + res[0];
|
||||
}
|
||||
if (targetRes === null) {
|
||||
$.each(jsxc.storage.getUserItem('buddy', bid).res, function(index, val) {
|
||||
if (capableRes.indexOf(val) > -1) {
|
||||
targetRes = val;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
el.off('click');
|
||||
|
||||
if (self.conn.caps.hasFeatureByJid(jid, self.reqVideoFeatures)) {
|
||||
if (capableRes.indexOf(targetRes) > -1) {
|
||||
el.click(function() {
|
||||
self.startCall(jid);
|
||||
self.startCall(jid + '/' + targetRes);
|
||||
});
|
||||
|
||||
el.removeClass('jsxc_disabled');
|
||||
|
||||
el.attr('title', jsxc.translate('%%Start video call%%'));
|
||||
@@ -272,14 +332,32 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
*/
|
||||
onMessage: function(e, from) {
|
||||
var self = jsxc.webrtc;
|
||||
var bJid = Strophe.getBareJidFromJid(from);
|
||||
var bid = jsxc.jidToBid(from);
|
||||
|
||||
if (self.chatJids[bJid] !== from) {
|
||||
self.updateIcon(jsxc.jidToCid(bJid));
|
||||
self.chatJids[bJid] = from;
|
||||
jsxc.debug('webrtc.onmessage', from);
|
||||
|
||||
if (self.chatJids[bid] !== from) {
|
||||
self.updateIcon(bid);
|
||||
self.chatJids[bid] = from;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update icon on presence.
|
||||
*
|
||||
* @memberOf
|
||||
* @param ev
|
||||
* @param status
|
||||
* @private
|
||||
*/
|
||||
onPresence: function(ev, jid) {
|
||||
var self = jsxc.webrtc;
|
||||
|
||||
jsxc.debug('webrtc.onpresence', jid);
|
||||
|
||||
self.updateIcon(jsxc.jidToBid(jid));
|
||||
},
|
||||
|
||||
/**
|
||||
* Display status message to user.
|
||||
*
|
||||
@@ -338,7 +416,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
onCaps: function(event, jid) {
|
||||
var self = jsxc.webrtc;
|
||||
|
||||
self.updateIcon(jsxc.jidToCid(jid));
|
||||
self.updateIcon(jsxc.jidToBid(jid));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -369,6 +447,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
self.setStatus((stream.getVideoTracks().length > 0) ? 'Use local video device.' : 'No local video device.');
|
||||
|
||||
jsxc.debug('using video device "' + stream.getVideoTracks()[i].label + '"');
|
||||
$('#jsxc_dialog .jsxc_localvideo').show();
|
||||
}
|
||||
|
||||
$(document).one('cleanup.dialog.jsxc', $.proxy(self.hangUp, self));
|
||||
@@ -381,8 +460,11 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
* @private
|
||||
* @memberOf jsxc.webrtc
|
||||
*/
|
||||
onMediaFailure: function() {
|
||||
onMediaFailure: function(ev, err) {
|
||||
this.setStatus('media failure');
|
||||
|
||||
jsxc.gui.window.postMessage(jsxc.jidToBid(jsxc.webrtc.last_caller), 'sys', jsxc.translate('%%Media failure%%: ') + err.name);
|
||||
jsxc.debug('media failure: ' + err.name);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -398,10 +480,12 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
|
||||
var self = this;
|
||||
var sess = this.conn.jingle.sessions[sid];
|
||||
var jid = jsxc.jidToCid(sess.peerjid);
|
||||
var bid = jsxc.jidToBid(sess.peerjid);
|
||||
|
||||
jsxc.gui.window.postMessage(bid, 'sys', jsxc.translate('%%Incoming call.%%'));
|
||||
|
||||
// display notification
|
||||
jsxc.notification.notify(jsxc.translate('%%Incoming call%%'), jsxc.translate('%%from%% ' + jid));
|
||||
jsxc.notification.notify(jsxc.translate('%%Incoming call%%'), jsxc.translate('%%from%% ' + bid));
|
||||
|
||||
// send signal to partner
|
||||
sess.sendRinging();
|
||||
@@ -429,7 +513,9 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
return;
|
||||
}
|
||||
|
||||
var dialog = jsxc.gui.dialog.open(jsxc.gui.template.get('incomingCall', jsxc.jidToCid(jid)));
|
||||
var dialog = jsxc.gui.dialog.open(jsxc.gui.template.get('incomingCall', bid), {
|
||||
noClose: true
|
||||
});
|
||||
|
||||
dialog.find('.jsxc_accept').click(function() {
|
||||
$(document).trigger('accept.call.jsxc');
|
||||
@@ -459,22 +545,30 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
onCallTerminated: function(event, sid, reason, text) {
|
||||
this.setStatus('call terminated ' + sid + (reason ? (': ' + reason + ' ' + text) : ''));
|
||||
|
||||
var bid = jsxc.jidToBid(jsxc.webrtc.last_caller);
|
||||
|
||||
if (this.localStream) {
|
||||
this.localStream.stop();
|
||||
}
|
||||
|
||||
$('.jsxc_remotevideo')[0].src = "";
|
||||
$('.jsxc_localvideo')[0].src = "";
|
||||
if ($('.jsxc_videoContainer').length) {
|
||||
$('.jsxc_remotevideo')[0].src = "";
|
||||
$('.jsxc_localvideo')[0].src = "";
|
||||
}
|
||||
|
||||
this.conn.jingle.localStream = null;
|
||||
this.localStream = null;
|
||||
this.remoteStream = null;
|
||||
|
||||
$('#jsxc_windowList > ul').prepend($('#jsxc_dialog .jsxc_chatarea > ul > li').detach());
|
||||
var win = $('#jsxc_dialog .jsxc_chatarea > ul > li');
|
||||
$('#jsxc_windowList > ul').prepend(win.detach());
|
||||
win.find('.slimScrollDiv').resizable('enable');
|
||||
|
||||
$(document).off('cleanup.dialog.jsxc');
|
||||
$(document).off('error.jingle');
|
||||
jsxc.gui.dialog.close();
|
||||
|
||||
jsxc.gui.window.postMessage(bid, 'sys', jsxc.translate('%%Call terminated%%' + (reason ? (': %%' + reason + '%%') : '') + '.'));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -516,7 +610,9 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
this.setStatus(isAudioDevice ? 'Use remote audio device.' : 'No remote audio device');
|
||||
|
||||
if ($('.jsxc_remotevideo').length) {
|
||||
RTC.attachMediaStream($('.jsxc_remotevideo'), stream);
|
||||
RTC.attachMediaStream($('#jsxc_dialog .jsxc_remotevideo'), stream);
|
||||
|
||||
$('#jsxc_dialog .jsxc_' + (isVideoDevice ? 'remotevideo' : 'noRemoteVideo')).addClass('jsxc_deviceAvailable');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -550,7 +646,11 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
jsxc.debug('iceCon state for ' + sid, iceCon);
|
||||
jsxc.debug('sig state for ' + sid, sigState);
|
||||
|
||||
if (sigState === 'stable' && iceCon === 'connected') {
|
||||
if (sigState === 'stable' && (iceCon === 'connected' || iceCon === 'completed')) {
|
||||
|
||||
$('#jsxc_dialog .jsxc_deviceAvailable').show();
|
||||
$('#jsxc_dialog .bubblingG').hide();
|
||||
|
||||
var localSDP = sess.peerconnection.localDescription.sdp;
|
||||
var remoteSDP = sess.peerconnection.remoteDescription.sdp;
|
||||
|
||||
@@ -579,6 +679,15 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
text += '</p>';
|
||||
|
||||
$('#jsxc_dialog .jsxc_infobar').html(text);
|
||||
} else if (iceCon === 'failed') {
|
||||
jsxc.gui.window.postMessage(jsxc.jidToBid(sess.peerjid), 'sys', jsxc.translate('%%ICE connection failure%%.'));
|
||||
|
||||
$(document).off('cleanup.dialog.jsxc');
|
||||
|
||||
sess.sendTerminate('failed-transport');
|
||||
sess.terminate();
|
||||
|
||||
$(document).trigger('callterminated.jingle');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -597,8 +706,9 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
* @param jid full jid
|
||||
* @param um requested user media
|
||||
*/
|
||||
startCall: function(jid) {
|
||||
startCall: function(jid, um) {
|
||||
var self = this;
|
||||
|
||||
if (Strophe.getResourceFromJid(jid) === null) {
|
||||
@@ -612,6 +722,8 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
'finish.mediaready.jsxc': function() {
|
||||
self.setStatus('Initiate call');
|
||||
|
||||
jsxc.gui.window.postMessage(jsxc.jidToBid(jid), 'sys', jsxc.translate('%%Call started.%%'));
|
||||
|
||||
$(document).one('error.jingle', function(e, sid, error) {
|
||||
if (error.source !== 'offer') {
|
||||
return;
|
||||
@@ -630,7 +742,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
}
|
||||
});
|
||||
|
||||
this.reqUserMedia();
|
||||
self.reqUserMedia(um);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -638,10 +750,10 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
*/
|
||||
hangUp: function() {
|
||||
hangUp: function(reason, text) {
|
||||
$(document).off('cleanup.dialog.jsxc');
|
||||
|
||||
jsxc.webrtc.conn.jingle.terminate(null);
|
||||
jsxc.webrtc.conn.jingle.terminate(null, reason, text);
|
||||
$(document).trigger('callterminated.jingle');
|
||||
},
|
||||
|
||||
@@ -650,18 +762,35 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
*/
|
||||
reqUserMedia: function() {
|
||||
reqUserMedia: function(um) {
|
||||
if (this.localStream) {
|
||||
$(document).trigger('mediaready.jingle', [ this.localStream ]);
|
||||
return;
|
||||
}
|
||||
|
||||
um = um || [ 'video', 'audio' ];
|
||||
|
||||
jsxc.gui.dialog.open(jsxc.gui.template.get('allowMediaAccess'), {
|
||||
noClose: true
|
||||
});
|
||||
this.setStatus('please allow access to microphone and camera');
|
||||
|
||||
getUserMediaWithConstraints([ 'video', 'audio' ]);
|
||||
if (typeof MediaStreamTrack !== 'undefined' && typeof MediaStreamTrack.getSources !== 'undefined') {
|
||||
MediaStreamTrack.getSources(function(sourceInfo) {
|
||||
var availableDevices = sourceInfo.map(function(el) {
|
||||
|
||||
return el.kind;
|
||||
});
|
||||
|
||||
um = um.filter(function(el) {
|
||||
return availableDevices.indexOf(el) !== -1;
|
||||
});
|
||||
|
||||
getUserMediaWithConstraints(um);
|
||||
});
|
||||
} else {
|
||||
getUserMediaWithConstraints(um);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -685,7 +814,15 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
|
||||
ctx.drawImage(video[0], 0, 0);
|
||||
var img = $('<img/>');
|
||||
var url = canvas.toDataURL('image/jpeg');
|
||||
var url = null;
|
||||
|
||||
try {
|
||||
url = canvas.toDataURL('image/jpeg');
|
||||
} catch (err) {
|
||||
jsxc.warn('Error', err);
|
||||
return;
|
||||
}
|
||||
|
||||
img[0].src = url;
|
||||
var link = $('<a/>').attr({
|
||||
target: '_blank',
|
||||
@@ -743,6 +880,8 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
|
||||
if (self.remoteStream) {
|
||||
RTC.attachMediaStream(rv, self.remoteStream);
|
||||
|
||||
$('#jsxc_dialog .jsxc_' + (self.remoteStream.getVideoTracks().length > 0 ? 'remotevideo' : 'noRemoteVideo')).addClass('jsxc_deviceAvailable');
|
||||
}
|
||||
|
||||
var toggleMulti = function(elem, open) {
|
||||
@@ -759,7 +898,13 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
}
|
||||
};
|
||||
|
||||
var win = jsxc.gui.window.open(jsxc.jidToCid(jid));
|
||||
var win = jsxc.gui.window.open(jsxc.jidToBid(jid));
|
||||
|
||||
win.find('.slimScrollDiv').resizable('disable');
|
||||
win.find('.jsxc_textarea').slimScroll({
|
||||
height: 413
|
||||
});
|
||||
win.find('.jsxc_emoticons').css('top', (413 + 6) + 'px');
|
||||
|
||||
$('#jsxc_dialog .jsxc_chatarea ul').append(win.detach());
|
||||
|
||||
@@ -777,7 +922,21 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
});
|
||||
|
||||
$('#jsxc_dialog .jsxc_showchat').click(function() {
|
||||
toggleMulti($('#jsxc_dialog .jsxc_chatarea'));
|
||||
var chatarea = $('#jsxc_dialog .jsxc_chatarea');
|
||||
|
||||
if (chatarea.is(':hidden')) {
|
||||
chatarea.show();
|
||||
$('#jsxc_dialog .jsxc_webrtc').width('900');
|
||||
jsxc.gui.dialog.resize({
|
||||
width: '920px'
|
||||
});
|
||||
} else {
|
||||
chatarea.hide();
|
||||
$('#jsxc_dialog .jsxc_webrtc').width('650');
|
||||
jsxc.gui.dialog.resize({
|
||||
width: '660px'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#jsxc_dialog .jsxc_info').click(function() {
|
||||
@@ -844,7 +1003,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
Remote_IP: 'Remote IP',
|
||||
Local_Fingerprint: 'Local fingerprint',
|
||||
Remote_Fingerprint: 'Remote fingerprint',
|
||||
Video_call_not_possible: 'Video call not possible',
|
||||
Video_call_not_possible: 'Video call not possible. Your buddy does not support video calls.',
|
||||
Start_video_call: 'Start video call'
|
||||
});
|
||||
|
||||
@@ -865,7 +1024,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
Remote_IP: 'Remote IP',
|
||||
Local_Fingerprint: 'Lokaler Fingerprint',
|
||||
Remote_Fingerprint: 'Remote Fingerprint',
|
||||
Video_call_not_possible: 'Videoanruf nicht verfügbar',
|
||||
Video_call_not_possible: 'Videoanruf nicht verfügbar. Dein Gesprächspartner unterstützt keine Videotelefonie.',
|
||||
Start_video_call: 'Starte Videoanruf'
|
||||
});
|
||||
|
||||
|
||||
externo
+30
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
+224
-18
@@ -1,17 +1,34 @@
|
||||
.jsxc_webrtc {
|
||||
width: 900px;
|
||||
}
|
||||
|
||||
.jsxc_webrtc li .jsxc_name {
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.jsxc_webrtc li .jsxc_name:hover {
|
||||
color: #939393;
|
||||
}
|
||||
|
||||
.jsxc_videoContainer {
|
||||
width: 640px;
|
||||
height: 480px;
|
||||
position: relative;
|
||||
background-color: #a4a4a4;
|
||||
}
|
||||
|
||||
.jsxc_remotevideo {
|
||||
.jsxc_videoContainer video, .jsxc_videoContainer .jsxc_noRemoteVideo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_remotevideo, .jsxc_noRemoteVideo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: 9000;
|
||||
background-color: grey;
|
||||
background-color: #a4a4a4;
|
||||
}
|
||||
|
||||
.jsxc_localvideo {
|
||||
@@ -25,6 +42,49 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo p {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left:0px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo > div {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -100px;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo > div > div {
|
||||
background-color: #717171;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo > div > div:first-child {
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -25%;
|
||||
top: 10%;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo > div > div:last-child {
|
||||
position: absolute;
|
||||
bottom: -50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.jsxc_webrtc .jsxc_status {
|
||||
z-index: 9999;
|
||||
border-radius: 20px;
|
||||
@@ -40,6 +100,10 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.jsxc_webrtc .slimScrollDiv {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
div:-moz-full-screen {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -84,6 +148,14 @@ div:fullscreen.jsxc_localvideo {
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.jsxc_controlbar {
|
||||
width: 640px;
|
||||
}
|
||||
|
||||
.jsxc_controlbar .jsxc_showchat {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.jsxc_multi>div {
|
||||
display: none;
|
||||
}
|
||||
@@ -115,32 +187,33 @@ div:fullscreen.jsxc_localvideo {
|
||||
|
||||
.jsxc_chatarea {
|
||||
position: relative;
|
||||
height: 270px;
|
||||
display: none;
|
||||
float:right;
|
||||
height: 480px;
|
||||
width: 250px;
|
||||
background-color: #A4A4A4;
|
||||
}
|
||||
|
||||
.jsxc_chatarea > ul {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 0px;
|
||||
width: 250px;
|
||||
height: 270px;
|
||||
height: 480px;
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px 0px 0px -100px;
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_settings {
|
||||
display: none;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_close {
|
||||
display: none;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_video {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_bar {
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_window {
|
||||
@@ -163,11 +236,144 @@ div.jsxc_video:not(.jsxc_disabled):hover, #jsxc_buddylist .jsxc_options .jsxc_vi
|
||||
background-image: url('img/camera_icon_white.svg');
|
||||
}
|
||||
|
||||
div.jsxc_video.jsxc_disabled {
|
||||
opacity: 0.5;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
#jsxc_buddylist .jsxc_options .jsxc_video.jsxc_disabled {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
.bubblingG {
|
||||
text-align: center;
|
||||
width:129px;
|
||||
height:80px;
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
margin-left: -64px;
|
||||
}
|
||||
|
||||
.bubblingG span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 40px auto;
|
||||
background: #000000;
|
||||
-moz-border-radius: 81px;
|
||||
-moz-animation: bubblingG 1.3s infinite alternate;
|
||||
-webkit-border-radius: 81px;
|
||||
-webkit-animation: bubblingG 1.3s infinite alternate;
|
||||
-ms-border-radius: 81px;
|
||||
-ms-animation: bubblingG 1.3s infinite alternate;
|
||||
-o-border-radius: 81px;
|
||||
-o-animation: bubblingG 1.3s infinite alternate;
|
||||
border-radius: 81px;
|
||||
animation: bubblingG 1.3s infinite alternate;
|
||||
}
|
||||
|
||||
#bubblingG_1 {
|
||||
-moz-animation-delay: 0s;
|
||||
-webkit-animation-delay: 0s;
|
||||
-ms-animation-delay: 0s;
|
||||
-o-animation-delay: 0s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
#bubblingG_2 {
|
||||
-moz-animation-delay: 0.39s;
|
||||
-webkit-animation-delay: 0.39s;
|
||||
-ms-animation-delay: 0.39s;
|
||||
-o-animation-delay: 0.39s;
|
||||
animation-delay: 0.39s;
|
||||
}
|
||||
|
||||
#bubblingG_3 {
|
||||
-moz-animation-delay: 0.78s;
|
||||
-webkit-animation-delay: 0.78s;
|
||||
-ms-animation-delay: 0.78s;
|
||||
-o-animation-delay: 0.78s;
|
||||
animation-delay: 0.78s;
|
||||
}
|
||||
|
||||
@-moz-keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
-moz-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
-moz-transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@-webkit-keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
-webkit-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
-webkit-transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@-ms-keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
-ms-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
-ms-transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@-o-keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
-o-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
-o-transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,35 +2,81 @@
|
||||
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
||||
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
|
||||
*
|
||||
* Version: 1.0.0
|
||||
*
|
||||
* Version: 1.3.3 + pr#94
|
||||
*
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
jQuery.fn.extend({
|
||||
$.fn.extend({
|
||||
slimScroll: function(options) {
|
||||
|
||||
var defaults = {
|
||||
wheelStep : 20,
|
||||
|
||||
// width in pixels of the visible scroll area
|
||||
width : 'auto',
|
||||
|
||||
// height in pixels of the visible scroll area
|
||||
height : '250px',
|
||||
|
||||
// width in pixels of the scrollbar and rail
|
||||
size : '7px',
|
||||
|
||||
// scrollbar color, accepts any hex/color value
|
||||
color: '#000',
|
||||
|
||||
// scrollbar position - left/right
|
||||
position : 'right',
|
||||
|
||||
// distance in pixels between the side edge and the scrollbar
|
||||
distance : '1px',
|
||||
|
||||
// default scroll position on load - top / bottom / $('selector')
|
||||
start : 'top',
|
||||
|
||||
// sets scrollbar opacity
|
||||
opacity : .4,
|
||||
|
||||
// enables always-on mode for the scrollbar
|
||||
alwaysVisible : false,
|
||||
disableFadeOut: false,
|
||||
|
||||
// check if we should hide the scrollbar when user is hovering over
|
||||
disableFadeOut : false,
|
||||
|
||||
// sets visibility of the rail
|
||||
railVisible : false,
|
||||
|
||||
// sets rail color
|
||||
railColor : '#333',
|
||||
railOpacity : '0.2',
|
||||
|
||||
// sets rail opacity
|
||||
railOpacity : .2,
|
||||
|
||||
// whether we should use jQuery UI Draggable to enable bar dragging
|
||||
railDraggable : true,
|
||||
|
||||
// defautlt CSS class of the slimscroll rail
|
||||
railClass : 'slimScrollRail',
|
||||
|
||||
// defautlt CSS class of the slimscroll bar
|
||||
barClass : 'slimScrollBar',
|
||||
|
||||
// defautlt CSS class of the slimscroll wrapper
|
||||
wrapperClass : 'slimScrollDiv',
|
||||
|
||||
// check if mousewheel should scroll the window if we reach top/bottom
|
||||
allowPageScroll : false,
|
||||
scroll : 0,
|
||||
touchScrollStep : 200
|
||||
|
||||
// scroll amount applied to each mouse wheel step
|
||||
wheelStep : 20,
|
||||
|
||||
// scroll amount applied when user is using gestures
|
||||
touchScrollStep : 200,
|
||||
|
||||
// sets border radius
|
||||
borderRadius: '7px',
|
||||
|
||||
// sets border radius of the rail
|
||||
railBorderRadius : '7px'
|
||||
};
|
||||
|
||||
var o = $.extend(defaults, options);
|
||||
@@ -38,7 +84,7 @@
|
||||
// do it for every element that matches selector
|
||||
this.each(function(){
|
||||
|
||||
var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
|
||||
var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
|
||||
barHeight, percentScroll, lastScroll,
|
||||
divS = '<div></div>',
|
||||
minBarHeight = 30,
|
||||
@@ -48,20 +94,33 @@
|
||||
var me = $(this);
|
||||
|
||||
// ensure we are not binding it again
|
||||
if (me.parent().hasClass('slimScrollDiv'))
|
||||
{
|
||||
if (me.parent().hasClass(o.wrapperClass))
|
||||
{
|
||||
// start from last bar position
|
||||
var offset = me.scrollTop();
|
||||
|
||||
// find bar and rail
|
||||
bar = me.parent().find('.slimScrollBar');
|
||||
rail = me.parent().find('.slimScrollRail');
|
||||
|
||||
bar = me.parent().find('.' + o.barClass);
|
||||
rail = me.parent().find('.' + o.railClass);
|
||||
|
||||
getBarHeight();
|
||||
|
||||
// check if we should scroll existing instance
|
||||
if (options)
|
||||
if ($.isPlainObject(options))
|
||||
{
|
||||
// Pass height: auto to an existing slimscroll object to force a resize after contents have changed
|
||||
if ( 'height' in options && options.height == 'auto' ) {
|
||||
me.parent().css('height', 'auto');
|
||||
me.css('height', 'auto');
|
||||
var height = me.parent().parent().height();
|
||||
me.parent().css('height', height);
|
||||
me.css('height', height);
|
||||
} else if ('height' in options) {
|
||||
var h = options.height;
|
||||
me.parent().css('height', h);
|
||||
me.css('height', h);
|
||||
}
|
||||
|
||||
if ('scrollTo' in options)
|
||||
{
|
||||
// jump to a static point
|
||||
@@ -72,6 +131,14 @@
|
||||
// jump by value pixels
|
||||
offset += parseInt(o.scrollBy);
|
||||
}
|
||||
else if ('destroy' in options)
|
||||
{
|
||||
// remove slimscroll elements
|
||||
bar.remove();
|
||||
rail.remove();
|
||||
me.unwrap();
|
||||
return;
|
||||
}
|
||||
|
||||
// scroll content by the given offset
|
||||
scrollContent(offset, false, true);
|
||||
@@ -79,9 +146,16 @@
|
||||
|
||||
return;
|
||||
}
|
||||
else if ($.isPlainObject(options))
|
||||
{
|
||||
if ('destroy' in options)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// optionally set height to the parent's height
|
||||
o.height = (o.height == 'auto') ? me.parent().innerHeight() : o.height;
|
||||
o.height = (o.height == 'auto') ? me.parent().height() : o.height;
|
||||
|
||||
// wrap content
|
||||
var wrapper = $(divS)
|
||||
@@ -101,7 +175,7 @@
|
||||
});
|
||||
|
||||
// create scrollbar rail
|
||||
var rail = $(divS)
|
||||
var rail = $(divS)
|
||||
.addClass(o.railClass)
|
||||
.css({
|
||||
width: o.size,
|
||||
@@ -109,7 +183,7 @@
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none',
|
||||
'border-radius': o.size,
|
||||
'border-radius': o.railBorderRadius,
|
||||
background: o.railColor,
|
||||
opacity: o.railOpacity,
|
||||
zIndex: 90
|
||||
@@ -125,10 +199,10 @@
|
||||
top: 0,
|
||||
opacity: o.opacity,
|
||||
display: o.alwaysVisible ? 'block' : 'none',
|
||||
'border-radius' : o.size,
|
||||
BorderRadius: o.size,
|
||||
MozBorderRadius: o.size,
|
||||
WebkitBorderRadius: o.size,
|
||||
'border-radius' : o.borderRadius,
|
||||
BorderRadius: o.borderRadius,
|
||||
MozBorderRadius: o.borderRadius,
|
||||
WebkitBorderRadius: o.borderRadius,
|
||||
zIndex: 99
|
||||
});
|
||||
|
||||
@@ -144,18 +218,31 @@
|
||||
me.parent().append(bar);
|
||||
me.parent().append(rail);
|
||||
|
||||
// make it draggable
|
||||
bar.draggable({
|
||||
axis: 'y',
|
||||
containment: 'parent',
|
||||
start: function() { isDragg = true; },
|
||||
stop: function() { isDragg = false; hideBar(); },
|
||||
drag: function(e)
|
||||
{
|
||||
// scroll content
|
||||
scrollContent(0, $(this).position().top, false);
|
||||
}
|
||||
});
|
||||
// make it draggable and no longer dependent on the jqueryUI
|
||||
if (o.railDraggable){
|
||||
bar.bind("mousedown", function(e) {
|
||||
var $doc = $(document);
|
||||
isDragg = true;
|
||||
t = parseFloat(bar.css('top'));
|
||||
pageY = e.pageY;
|
||||
|
||||
$doc.bind("mousemove.slimscroll", function(e){
|
||||
currTop = t + e.pageY - pageY;
|
||||
bar.css('top', currTop);
|
||||
scrollContent(0, bar.position().top, false);// scroll content
|
||||
});
|
||||
|
||||
$doc.bind("mouseup.slimscroll", function(e) {
|
||||
isDragg = false;hideBar();
|
||||
$doc.unbind('.slimscroll');
|
||||
});
|
||||
return false;
|
||||
}).bind("selectstart.slimscroll", function(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// on rail over
|
||||
rail.hover(function(){
|
||||
@@ -191,18 +278,44 @@
|
||||
});
|
||||
|
||||
me.bind('touchmove', function(e){
|
||||
// prevent scrolling the page
|
||||
e.originalEvent.preventDefault();
|
||||
// prevent scrolling the page if necessary
|
||||
if(!releaseScroll)
|
||||
{
|
||||
e.originalEvent.preventDefault();
|
||||
}
|
||||
if (e.originalEvent.touches.length)
|
||||
{
|
||||
// see how far user swiped
|
||||
var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep;
|
||||
// scroll content
|
||||
scrollContent(diff, true);
|
||||
touchDif = e.originalEvent.touches[0].pageY;
|
||||
}
|
||||
});
|
||||
|
||||
var _onWheel = function(e)
|
||||
// set up initial height
|
||||
getBarHeight();
|
||||
|
||||
// check start position
|
||||
if (o.start === 'bottom')
|
||||
{
|
||||
// scroll content to bottom
|
||||
bar.css({ top: me.outerHeight() - bar.outerHeight() });
|
||||
scrollContent(0, true);
|
||||
}
|
||||
else if (o.start !== 'top')
|
||||
{
|
||||
// assume jQuery selector
|
||||
scrollContent($(o.start).position().top, null, true);
|
||||
|
||||
// make sure bar stays hidden
|
||||
if (!o.alwaysVisible) { bar.hide(); }
|
||||
}
|
||||
|
||||
// attach scroll events
|
||||
attachWheel();
|
||||
|
||||
function _onWheel(e)
|
||||
{
|
||||
// use mouse wheel only when mouse is over
|
||||
if (!isOverPanel) { return; }
|
||||
@@ -213,8 +326,11 @@
|
||||
if (e.wheelDelta) { delta = -e.wheelDelta/120; }
|
||||
if (e.detail) { delta = e.detail / 3; }
|
||||
|
||||
// scroll content
|
||||
scrollContent(delta, true);
|
||||
var target = e.target || e.srcTarget || e.srcElement;
|
||||
if ($(target).closest('.' + o.wrapperClass).is(me.parent())) {
|
||||
// scroll content
|
||||
scrollContent(delta, true);
|
||||
}
|
||||
|
||||
// stop window scroll
|
||||
if (e.preventDefault && !releaseScroll) { e.preventDefault(); }
|
||||
@@ -223,16 +339,24 @@
|
||||
|
||||
function scrollContent(y, isWheel, isJump)
|
||||
{
|
||||
releaseScroll = false;
|
||||
var delta = y;
|
||||
var maxTop = me.outerHeight() - bar.outerHeight();
|
||||
|
||||
|
||||
if (isWheel)
|
||||
{
|
||||
// move bar with mouse wheel
|
||||
delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();
|
||||
|
||||
// move bar, make sure it doesn't go out
|
||||
// move bar, make sure it doesn't go out
|
||||
delta = Math.min(Math.max(delta, 0), maxTop);
|
||||
|
||||
// if scrolling down, make sure a fractional change to the
|
||||
// scroll position isn't rounded away when the scrollbar's CSS is set
|
||||
// this flooring of delta would happened automatically when
|
||||
// bar.css is set below, but we floor here for clarity
|
||||
delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);
|
||||
|
||||
// scroll the scrollbar
|
||||
bar.css({ top: delta + 'px' });
|
||||
}
|
||||
@@ -245,7 +369,6 @@
|
||||
{
|
||||
delta = y;
|
||||
var offsetTop = delta / me[0].scrollHeight * me.outerHeight();
|
||||
|
||||
offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);
|
||||
bar.css({ top: offsetTop + 'px' });
|
||||
}
|
||||
@@ -253,6 +376,9 @@
|
||||
// scroll content
|
||||
me.scrollTop(delta);
|
||||
|
||||
// fire scrolling event
|
||||
me.trigger('slimscrolling', ~~delta);
|
||||
|
||||
// ensure bar is visible
|
||||
showBar();
|
||||
|
||||
@@ -260,31 +386,29 @@
|
||||
hideBar();
|
||||
}
|
||||
|
||||
var attachWheel = function()
|
||||
function attachWheel()
|
||||
{
|
||||
if (window.addEventListener)
|
||||
{
|
||||
this.addEventListener('DOMMouseScroll', _onWheel, false );
|
||||
this.addEventListener('mousewheel', _onWheel, false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
document.attachEvent("onmousewheel", _onWheel)
|
||||
}
|
||||
}
|
||||
|
||||
// attach scroll events
|
||||
attachWheel();
|
||||
|
||||
function getBarHeight()
|
||||
{
|
||||
// calculate scrollbar height and make sure it is not too small
|
||||
barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight);
|
||||
bar.css({ height: barHeight + 'px' });
|
||||
}
|
||||
|
||||
// set up initial height
|
||||
getBarHeight();
|
||||
// hide scrollbar if content is not long enough
|
||||
var display = barHeight == me.outerHeight() ? 'none' : 'block';
|
||||
bar.css({ display: display });
|
||||
}
|
||||
|
||||
function showBar()
|
||||
{
|
||||
@@ -293,18 +417,22 @@
|
||||
clearTimeout(queueHide);
|
||||
|
||||
// when bar reached top or bottom
|
||||
if (percentScroll == ~~ percentScroll)
|
||||
if (percentScroll == ~~percentScroll)
|
||||
{
|
||||
//release wheel
|
||||
//release wheel
|
||||
releaseScroll = o.allowPageScroll;
|
||||
|
||||
|
||||
// publish approporiate event
|
||||
if (lastScroll != percentScroll)
|
||||
{
|
||||
var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
|
||||
var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
|
||||
me.trigger('slimscroll', msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
releaseScroll = false;
|
||||
}
|
||||
lastScroll = percentScroll;
|
||||
|
||||
// show only when required
|
||||
@@ -324,7 +452,7 @@
|
||||
{
|
||||
queueHide = setTimeout(function(){
|
||||
if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg)
|
||||
{
|
||||
{
|
||||
bar.fadeOut('slow');
|
||||
rail.fadeOut('slow');
|
||||
}
|
||||
@@ -332,30 +460,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
// check start position
|
||||
if (o.start == 'bottom')
|
||||
{
|
||||
// scroll content to bottom
|
||||
bar.css({ top: me.outerHeight() - bar.outerHeight() });
|
||||
scrollContent(0, true);
|
||||
}
|
||||
else if (typeof o.start == 'object')
|
||||
{
|
||||
// scroll content
|
||||
scrollContent($(o.start).position().top, null, true);
|
||||
|
||||
// make sure bar stays hidden
|
||||
if (!o.alwaysVisible) { bar.hide(); }
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// maintain chainability
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.fn.extend({
|
||||
slimscroll: jQuery.fn.slimScroll
|
||||
$.fn.extend({
|
||||
slimscroll: $.fn.slimScroll
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
+16644
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+67
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
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
|
||||
otr.js v0.2.11 - 2014-03-24
|
||||
otr.js v0.2.13 - 2014-09-07
|
||||
(c) 2014 - Arlo Breault <arlolra@gmail.com>
|
||||
Freely distributed under the MPL v2.0 license.
|
||||
|
||||
@@ -141,6 +141,17 @@
|
||||
child.__super__ = parent.prototype
|
||||
}
|
||||
|
||||
// assumes 32-bit
|
||||
function intCompare(x, y) {
|
||||
var z = ~(x ^ y)
|
||||
z &= z >> 16
|
||||
z &= z >> 8
|
||||
z &= z >> 4
|
||||
z &= z >> 2
|
||||
z &= z >> 1
|
||||
return z & 1
|
||||
}
|
||||
|
||||
// constant-time string comparison
|
||||
HLP.compare = function (str1, str2) {
|
||||
if (str1.length !== str2.length)
|
||||
@@ -148,7 +159,7 @@
|
||||
var i = 0, result = 0
|
||||
for (; i < str1.length; i++)
|
||||
result |= str1[i].charCodeAt(0) ^ str2[i].charCodeAt(0)
|
||||
return result === 0
|
||||
return intCompare(result, 0)
|
||||
}
|
||||
|
||||
HLP.randomExponent = function () {
|
||||
@@ -1160,7 +1171,7 @@
|
||||
HLP.debug.call(this.otr, 'success')
|
||||
|
||||
if (BigInt.equals(this.their_y, this.our_dh.publicKey))
|
||||
return this.otr.error('equal keys - we have a problem.', true)
|
||||
return this.otr.error('equal keys - we have a problem.')
|
||||
|
||||
this.otr.our_old_dh = this.our_dh
|
||||
this.otr.their_priv_pk = this.their_priv_pk
|
||||
@@ -1267,7 +1278,7 @@
|
||||
|
||||
// verify gy is legal 2 <= gy <= N-2
|
||||
if (!HLP.checkGroup(this.their_y, N_MINUS_2))
|
||||
return this.otr.error('Illegal g^y.', true)
|
||||
return this.otr.error('Illegal g^y.')
|
||||
|
||||
this.createKeys(this.their_y)
|
||||
|
||||
@@ -1303,11 +1314,11 @@
|
||||
var hash = CryptoJS.SHA256(CryptoJS.enc.Latin1.parse(gxmpi))
|
||||
|
||||
if (!HLP.compare(this.hashed, hash.toString(CryptoJS.enc.Latin1)))
|
||||
return this.otr.error('Hashed g^x does not match.', true)
|
||||
return this.otr.error('Hashed g^x does not match.')
|
||||
|
||||
// verify gx is legal 2 <= g^x <= N-2
|
||||
if (!HLP.checkGroup(this.their_y, N_MINUS_2))
|
||||
return this.otr.error('Illegal g^x.', true)
|
||||
return this.otr.error('Illegal g^x.')
|
||||
|
||||
this.createKeys(this.their_y)
|
||||
|
||||
@@ -1321,7 +1332,7 @@
|
||||
, this.m1
|
||||
, HLP.packCtr(0)
|
||||
)
|
||||
if (vsm[0]) return this.otr.error(vsm[0], true)
|
||||
if (vsm[0]) return this.otr.error(vsm[0])
|
||||
|
||||
// store their key
|
||||
this.their_keyid = vsm[1]
|
||||
@@ -1363,7 +1374,7 @@
|
||||
, this.m1_prime
|
||||
, HLP.packCtr(0)
|
||||
)
|
||||
if (vsm[0]) return this.otr.error(vsm[0], true)
|
||||
if (vsm[0]) return this.otr.error(vsm[0])
|
||||
|
||||
// store their key
|
||||
this.their_keyid = vsm[1]
|
||||
@@ -1920,6 +1931,11 @@
|
||||
var MAX_INT = Math.pow(2, 53) - 1 // doubles
|
||||
var MAX_UINT = Math.pow(2, 31) - 1 // bitwise operators
|
||||
|
||||
// an internal callback
|
||||
function OTRCB(cb) {
|
||||
this.cb = cb
|
||||
}
|
||||
|
||||
// OTR contructor
|
||||
function OTR(options) {
|
||||
if (!(this instanceof OTR)) return new OTR(options)
|
||||
@@ -2090,9 +2106,10 @@
|
||||
})
|
||||
})
|
||||
this.sm.on('send', function (ssid, send) {
|
||||
if (self.ssid === ssid)
|
||||
if (self.ssid === ssid) {
|
||||
send = self.prepareMsg(send)
|
||||
self.io(send)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2108,8 +2125,13 @@
|
||||
;(function send(first) {
|
||||
if (!first) {
|
||||
if (!self.outgoing.length) return
|
||||
var elem = self.outgoing.shift()
|
||||
var elem = self.outgoing.shift(), cb = null
|
||||
if (elem.meta instanceof OTRCB) {
|
||||
cb = elem.meta.cb
|
||||
elem.meta = null
|
||||
}
|
||||
self.trigger('io', [elem.msg, elem.meta])
|
||||
if (cb) cb()
|
||||
}
|
||||
setTimeout(send, first ? 0 : self.send_interval)
|
||||
}(true))
|
||||
@@ -2142,7 +2164,7 @@
|
||||
this.sendenc = HLP.mask(HLP.h1(sendbyte, secbytes), 0, 128) // f16 bytes
|
||||
this.sendmac = CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.sendenc))
|
||||
this.sendmac = this.sendmac.toString(CryptoJS.enc.Latin1)
|
||||
this.sendmacused = false
|
||||
|
||||
this.rcvenc = HLP.mask(HLP.h1(rcvbyte, secbytes), 0, 128)
|
||||
this.rcvmac = CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.rcvenc))
|
||||
this.rcvmac = this.rcvmac.toString(CryptoJS.enc.Latin1)
|
||||
@@ -2161,7 +2183,6 @@
|
||||
// reveal old mac keys
|
||||
var self = this
|
||||
this.sessKeys[1].forEach(function (sk) {
|
||||
if (sk && sk.sendmacused) self.oldMacKeys.push(sk.sendmac)
|
||||
if (sk && sk.rcvmacused) self.oldMacKeys.push(sk.rcvmac)
|
||||
})
|
||||
|
||||
@@ -2189,7 +2210,6 @@
|
||||
// reveal old mac keys
|
||||
var self = this
|
||||
this.sessKeys.forEach(function (sk) {
|
||||
if (sk[1] && sk[1].sendmacused) self.oldMacKeys.push(sk[1].sendmac)
|
||||
if (sk[1] && sk[1].rcvmacused) self.oldMacKeys.push(sk[1].rcvmac)
|
||||
})
|
||||
|
||||
@@ -2207,12 +2227,12 @@
|
||||
|
||||
OTR.prototype.prepareMsg = function (msg, esk) {
|
||||
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED || this.their_keyid === 0)
|
||||
return this.error('Not ready to encrypt.')
|
||||
return this.notify('Not ready to encrypt.')
|
||||
|
||||
var sessKeys = this.sessKeys[1][0]
|
||||
|
||||
if (sessKeys.send_counter >= MAX_INT)
|
||||
return this.error('Should have rekeyed by now.')
|
||||
return this.notify('Should have rekeyed by now.')
|
||||
|
||||
sessKeys.send_counter += 1
|
||||
|
||||
@@ -2233,7 +2253,7 @@
|
||||
send += ctr.substring(0, 8)
|
||||
|
||||
if (Math.ceil(msg.length / 8) >= MAX_UINT) // * 16 / 128
|
||||
return this.error('Message is too long.')
|
||||
return this.notify('Message is too long.')
|
||||
|
||||
var aes = HLP.encryptAes(
|
||||
CryptoJS.enc.Latin1.parse(msg)
|
||||
@@ -2245,8 +2265,6 @@
|
||||
send += HLP.make1Mac(send, sessKeys.sendmac)
|
||||
send += HLP.packData(this.oldMacKeys.splice(0).join(''))
|
||||
|
||||
sessKeys.sendmacused = true
|
||||
|
||||
send = HLP.wrapMsg(
|
||||
send
|
||||
, this.fragment_size
|
||||
@@ -2254,7 +2272,7 @@
|
||||
, this.our_instance_tag
|
||||
, this.their_instance_tag
|
||||
)
|
||||
if (send[0]) return this.error(send[0])
|
||||
if (send[0]) return this.notify(send[0])
|
||||
|
||||
// emit extra symmetric key
|
||||
if (esk) this.trigger('file', ['send', sessKeys.extra_symkey, esk])
|
||||
@@ -2275,7 +2293,7 @@
|
||||
var ign = (msg[0] === '\x01')
|
||||
|
||||
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED || msg.length !== 8) {
|
||||
if (!ign) this.error('Received an unreadable encrypted message.', true)
|
||||
if (!ign) this.error('Received an unreadable encrypted message.')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2283,12 +2301,12 @@
|
||||
var their_keyid = this.their_keyid - HLP.readLen(msg[1])
|
||||
|
||||
if (our_keyid < 0 || our_keyid > 1) {
|
||||
if (!ign) this.error('Not of our latest keys.', true)
|
||||
if (!ign) this.error('Not of our latest keys.')
|
||||
return
|
||||
}
|
||||
|
||||
if (their_keyid < 0 || their_keyid > 1) {
|
||||
if (!ign) this.error('Not of your latest keys.', true)
|
||||
if (!ign) this.error('Not of your latest keys.')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2383,10 +2401,10 @@
|
||||
|
||||
OTR.prototype.smpSecret = function (secret, question) {
|
||||
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED)
|
||||
return this.error('Must be encrypted for SMP.')
|
||||
return this.notify('Must be encrypted for SMP.')
|
||||
|
||||
if (typeof secret !== 'string' || secret.length < 1)
|
||||
return this.error('Secret is required.')
|
||||
return this.notify('Secret is required.')
|
||||
|
||||
if (!this.sm) this._smInit()
|
||||
|
||||
@@ -2443,7 +2461,7 @@
|
||||
break
|
||||
case CONST.MSGSTATE_FINISHED:
|
||||
this.storedMgs.push({msg: msg, meta: meta})
|
||||
this.error('Message cannot be sent at this time.')
|
||||
this.notify('Message cannot be sent at this time.', 'warn')
|
||||
return
|
||||
case CONST.MSGSTATE_ENCRYPTED:
|
||||
msg = this.prepareMsg(msg)
|
||||
@@ -2464,18 +2482,26 @@
|
||||
|
||||
switch (msg.cls) {
|
||||
case 'error':
|
||||
this.error(msg.msg)
|
||||
this.notify(msg.msg)
|
||||
return
|
||||
case 'ake':
|
||||
if ( msg.version === CONST.OTR_VERSION_3 &&
|
||||
this.checkInstanceTags(msg.instance_tags)
|
||||
) return // ignore
|
||||
) {
|
||||
this.notify(
|
||||
'Received a message intended for a different session.', 'warn')
|
||||
return // ignore
|
||||
}
|
||||
this.ake.handleAKE(msg)
|
||||
return
|
||||
case 'data':
|
||||
if ( msg.version === CONST.OTR_VERSION_3 &&
|
||||
this.checkInstanceTags(msg.instance_tags)
|
||||
) return // ignore
|
||||
) {
|
||||
this.notify(
|
||||
'Received a message intended for a different session.', 'warn')
|
||||
return // ignore
|
||||
}
|
||||
msg.msg = this.handleDataMsg(msg)
|
||||
msg.encrypted = true
|
||||
break
|
||||
@@ -2487,7 +2513,7 @@
|
||||
// check for encrypted
|
||||
if ( this.REQUIRE_ENCRYPTION ||
|
||||
this.msgstate !== CONST.MSGSTATE_PLAINTEXT
|
||||
) this.error('Received an unencrypted message.')
|
||||
) this.notify('Received an unencrypted message.', 'warn')
|
||||
|
||||
// received a plaintext message
|
||||
// stop sending the whitespace tag
|
||||
@@ -2522,20 +2548,19 @@
|
||||
} else if (this.ALLOW_V2 && ~msg.ver.indexOf(CONST.OTR_VERSION_2)) {
|
||||
this.ake.initiateAKE(CONST.OTR_VERSION_2)
|
||||
} else {
|
||||
// is this an error?
|
||||
this.error('OTR conversation requested, ' +
|
||||
'but no compatible protocol version found.')
|
||||
this.notify('OTR conversation requested, ' +
|
||||
'but no compatible protocol version found.', 'warn')
|
||||
}
|
||||
}
|
||||
|
||||
OTR.prototype.error = function (err, send) {
|
||||
if (send) {
|
||||
if (!this.debug) err = "An OTR error has occurred."
|
||||
err = '?OTR Error:' + err
|
||||
this.io(err)
|
||||
return
|
||||
}
|
||||
this.trigger('error', [err])
|
||||
OTR.prototype.error = function (err) {
|
||||
if (!this.debug) err = 'An OTR error has occurred.'
|
||||
this.io('?OTR Error:' + err)
|
||||
this.notify(err)
|
||||
}
|
||||
|
||||
OTR.prototype.notify = function (err, severity) {
|
||||
this.trigger('error', [err, severity || 'error'])
|
||||
}
|
||||
|
||||
OTR.prototype.sendStored = function () {
|
||||
@@ -2548,18 +2573,18 @@
|
||||
|
||||
OTR.prototype.sendFile = function (filename) {
|
||||
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED)
|
||||
return this.error('Not ready to encrypt.')
|
||||
return this.notify('Not ready to encrypt.')
|
||||
|
||||
if (this.ake.otr_version !== CONST.OTR_VERSION_3)
|
||||
return this.error('Protocol v3 required.')
|
||||
return this.notify('Protocol v3 required.')
|
||||
|
||||
if (!filename) return this.error('Please specify a filename.')
|
||||
if (!filename) return this.notify('Please specify a filename.')
|
||||
|
||||
// utf8 filenames
|
||||
var l1name = CryptoJS.enc.Utf8.parse(filename)
|
||||
l1name = l1name.toString(CryptoJS.enc.Latin1)
|
||||
|
||||
if (l1name.length >= 65532) return this.error('filename is too long.')
|
||||
if (l1name.length >= 65532) return this.notify('Filename is too long.')
|
||||
|
||||
var msg = '\x00' // null byte
|
||||
msg += '\x00\x08' // type 8 tlv
|
||||
@@ -2571,9 +2596,11 @@
|
||||
this.io(msg)
|
||||
}
|
||||
|
||||
OTR.prototype.endOtr = function () {
|
||||
OTR.prototype.endOtr = function (cb) {
|
||||
if (this.msgstate === CONST.MSGSTATE_ENCRYPTED) {
|
||||
this.sendMsg('\x00\x00\x01\x00\x00')
|
||||
if (typeof cb === 'function')
|
||||
cb = new OTRCB(cb)
|
||||
this.sendMsg('\x00\x00\x01\x00\x00', cb)
|
||||
if (this.sm) {
|
||||
if (this.smw) this.sm.worker.terminate() // destroy webworker
|
||||
this.sm = null
|
||||
|
||||
externo
+3
-3
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -50,6 +50,17 @@
|
||||
child.__super__ = parent.prototype
|
||||
}
|
||||
|
||||
// assumes 32-bit
|
||||
function intCompare(x, y) {
|
||||
var z = ~(x ^ y)
|
||||
z &= z >> 16
|
||||
z &= z >> 8
|
||||
z &= z >> 4
|
||||
z &= z >> 2
|
||||
z &= z >> 1
|
||||
return z & 1
|
||||
}
|
||||
|
||||
// constant-time string comparison
|
||||
HLP.compare = function (str1, str2) {
|
||||
if (str1.length !== str2.length)
|
||||
@@ -57,7 +68,7 @@
|
||||
var i = 0, result = 0
|
||||
for (; i < str1.length; i++)
|
||||
result |= str1[i].charCodeAt(0) ^ str2[i].charCodeAt(0)
|
||||
return result === 0
|
||||
return intCompare(result, 0)
|
||||
}
|
||||
|
||||
HLP.randomExponent = function () {
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
*
|
||||
* Authors: - Michael Weibel <michael.weibel@gmail.com> - Klaus Herberth <klaus@jsxc.org>
|
||||
* Copyright: - Michael Weibel <michael.weibel@gmail.com>
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
@@ -7,6 +7,9 @@ TraceablePeerConnection = function(ice_config, constraints) {
|
||||
var RTCPeerconnection = navigator.mozGetUserMedia ? mozRTCPeerConnection : webkitRTCPeerConnection;
|
||||
this.peerconnection = new RTCPeerconnection(ice_config, constraints);
|
||||
this.updateLog = [];
|
||||
this.stats = {};
|
||||
this.statsinterval = null;
|
||||
this.maxstats = 300; // limit to 300 values, i.e. 5 minutes; set to 0 to disable
|
||||
|
||||
// override as desired
|
||||
this.trace = function(what, info) {
|
||||
@@ -14,47 +17,47 @@ TraceablePeerConnection = function(ice_config, constraints) {
|
||||
self.updateLog.push({
|
||||
time: new Date(),
|
||||
type: what,
|
||||
value: info
|
||||
value: info || ""
|
||||
});
|
||||
};
|
||||
this.onicecandidate = null;
|
||||
this.peerconnection.onicecandidate = function (event) {
|
||||
self.trace('onicecandidate', event.candidate);
|
||||
self.trace('onicecandidate', JSON.stringify(event.candidate, null, ' '));
|
||||
if (self.onicecandidate !== null) {
|
||||
self.onicecandidate(event);
|
||||
}
|
||||
};
|
||||
this.onaddstream = null;
|
||||
this.peerconnection.onaddstream = function (event) {
|
||||
self.trace('onaddstream', event.stream);
|
||||
self.trace('onaddstream', event.stream.id);
|
||||
if (self.onaddstream !== null) {
|
||||
self.onaddstream(event);
|
||||
}
|
||||
};
|
||||
this.onremovestream = null;
|
||||
this.peerconnection.onremovestream = function (event) {
|
||||
self.trace('onremovestream', event.stream);
|
||||
self.trace('onremovestream', event.stream.id);
|
||||
if (self.onremovestream !== null) {
|
||||
self.onremovestream(event);
|
||||
}
|
||||
};
|
||||
this.onsignalingstatechange = null;
|
||||
this.peerconnection.onsignalingstatechange = function (event) {
|
||||
self.trace('onsignalingstatechange', event);
|
||||
self.trace('onsignalingstatechange', self.signalingState);
|
||||
if (self.onsignalingstatechange !== null) {
|
||||
self.onsignalingstatechange(event);
|
||||
}
|
||||
};
|
||||
this.oniceconnectionstatechange = null;
|
||||
this.peerconnection.oniceconnectionstatechange = function (event) {
|
||||
self.trace('oniceconnectionstatechange', event);
|
||||
self.trace('oniceconnectionstatechange', self.iceConnectionState);
|
||||
if (self.oniceconnectionstatechange !== null) {
|
||||
self.oniceconnectionstatechange(event);
|
||||
}
|
||||
};
|
||||
this.onnegotiationneeded = null;
|
||||
this.peerconnection.onnegotiationneeded = function (event) {
|
||||
self.trace('onnegotiationneeded', event);
|
||||
self.trace('onnegotiationneeded');
|
||||
if (self.onnegotiationneeded !== null) {
|
||||
self.onnegotiationneeded(event);
|
||||
}
|
||||
@@ -66,20 +69,56 @@ TraceablePeerConnection = function(ice_config, constraints) {
|
||||
self.ondatachannel(event);
|
||||
}
|
||||
}
|
||||
if (!navigator.mozGetUserMedia) {
|
||||
this.statsinterval = window.setInterval(function() {
|
||||
self.peerconnection.getStats(function(stats) {
|
||||
var results = stats.result();
|
||||
for (var i = 0; i < results.length; ++i) {
|
||||
//console.log(results[i].type, results[i].id, results[i].names())
|
||||
var now = new Date();
|
||||
results[i].names().forEach(function (name) {
|
||||
var id = results[i].id + '-' + name;
|
||||
if (!self.stats[id]) {
|
||||
self.stats[id] = {
|
||||
startTime: now,
|
||||
endTime: now,
|
||||
values: [],
|
||||
times: []
|
||||
};
|
||||
}
|
||||
self.stats[id].values.push(results[i].stat(name));
|
||||
self.stats[id].times.push(now.getTime());
|
||||
if (self.stats[id].values.length > self.maxstats) {
|
||||
self.stats[id].values.shift();
|
||||
self.stats[id].times.shift();
|
||||
}
|
||||
self.stats[id].endTime = now;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
TraceablePeerConnection.prototype.__defineGetter__('signalingState', function() { return this.peerconnection.signalingState; });
|
||||
TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function() { return this.peerconnection.iceConnectionState; });
|
||||
TraceablePeerConnection.prototype.__defineGetter__('localDescription', function() { return this.peerconnection.localDescription; });
|
||||
TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function() { return this.peerconnection.remoteDescription; });
|
||||
dumpSDP = function(description) {
|
||||
return 'type: ' + description.type + '\r\n' + description.sdp;
|
||||
}
|
||||
|
||||
if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) {
|
||||
TraceablePeerConnection.prototype.__defineGetter__('signalingState', function() { return this.peerconnection.signalingState; });
|
||||
TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function() { return this.peerconnection.iceConnectionState; });
|
||||
TraceablePeerConnection.prototype.__defineGetter__('localDescription', function() { return this.peerconnection.localDescription; });
|
||||
TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function() { return this.peerconnection.remoteDescription; });
|
||||
}
|
||||
|
||||
TraceablePeerConnection.prototype.addStream = function (stream) {
|
||||
this.trace('addStream', stream);
|
||||
this.trace('addStream', stream.id);
|
||||
this.peerconnection.addStream(stream);
|
||||
};
|
||||
|
||||
TraceablePeerConnection.prototype.removeStream = function (stream) {
|
||||
this.trace('removeStream', stream);
|
||||
this.trace('removeStream', stream.id);
|
||||
this.peerconnection.removeStream(stream);
|
||||
};
|
||||
|
||||
@@ -90,7 +129,7 @@ TraceablePeerConnection.prototype.createDataChannel = function (label, opts) {
|
||||
|
||||
TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) {
|
||||
var self = this;
|
||||
this.trace('setLocalDescription', description);
|
||||
this.trace('setLocalDescription', dumpSDP(description));
|
||||
this.peerconnection.setLocalDescription(description,
|
||||
function () {
|
||||
self.trace('setLocalDescriptionOnSuccess');
|
||||
@@ -101,11 +140,16 @@ TraceablePeerConnection.prototype.setLocalDescription = function (description, s
|
||||
failureCallback(err);
|
||||
}
|
||||
);
|
||||
/*
|
||||
if (this.statsinterval === null && this.maxstats > 0) {
|
||||
// start gathering stats
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) {
|
||||
var self = this;
|
||||
this.trace('setRemoteDescription', description);
|
||||
this.trace('setRemoteDescription', dumpSDP(description));
|
||||
this.peerconnection.setRemoteDescription(description,
|
||||
function () {
|
||||
self.trace('setRemoteDescriptionOnSuccess');
|
||||
@@ -116,20 +160,29 @@ TraceablePeerConnection.prototype.setRemoteDescription = function (description,
|
||||
failureCallback(err);
|
||||
}
|
||||
);
|
||||
/*
|
||||
if (this.statsinterval === null && this.maxstats > 0) {
|
||||
// start gathering stats
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
TraceablePeerConnection.prototype.close = function () {
|
||||
this.trace('stop');
|
||||
if (this.statsinterval !== null) {
|
||||
window.clearInterval(this.statsinterval);
|
||||
this.statsinterval = null;
|
||||
}
|
||||
this.peerconnection.close();
|
||||
};
|
||||
|
||||
TraceablePeerConnection.prototype.createOffer = function (successCallback, failureCallback, constraints) {
|
||||
var self = this;
|
||||
this.trace('createOffer', constraints);
|
||||
this.trace('createOffer', JSON.stringify(constraints, null, ' '));
|
||||
this.peerconnection.createOffer(
|
||||
function (sdp) {
|
||||
self.trace('createOfferOnSuccess', sdp);
|
||||
successCallback(sdp);
|
||||
function (offer) {
|
||||
self.trace('createOfferOnSuccess', dumpSDP(offer));
|
||||
successCallback(offer);
|
||||
},
|
||||
function(err) {
|
||||
self.trace('createOfferOnFailure', err);
|
||||
@@ -141,11 +194,11 @@ TraceablePeerConnection.prototype.createOffer = function (successCallback, failu
|
||||
|
||||
TraceablePeerConnection.prototype.createAnswer = function (successCallback, failureCallback, constraints) {
|
||||
var self = this;
|
||||
this.trace('createAnswer', constraints);
|
||||
this.trace('createAnswer', JSON.stringify(constraints, null, ' '));
|
||||
this.peerconnection.createAnswer(
|
||||
function (sdp) {
|
||||
self.trace('createAnswerOnSuccess', sdp);
|
||||
successCallback(sdp);
|
||||
function (answer) {
|
||||
self.trace('createAnswerOnSuccess', dumpSDP(answer));
|
||||
successCallback(answer);
|
||||
},
|
||||
function(err) {
|
||||
self.trace('createAnswerOnFailure', err);
|
||||
@@ -157,7 +210,7 @@ TraceablePeerConnection.prototype.createAnswer = function (successCallback, fail
|
||||
|
||||
TraceablePeerConnection.prototype.addIceCandidate = function (candidate, successCallback, failureCallback) {
|
||||
var self = this;
|
||||
this.trace('addIceCandidate', candidate);
|
||||
this.trace('addIceCandidate', JSON.stringify(candidate, null, ' '));
|
||||
this.peerconnection.addIceCandidate(candidate);
|
||||
/* maybe later
|
||||
this.peerconnection.addIceCandidate(candidate,
|
||||
@@ -173,11 +226,14 @@ TraceablePeerConnection.prototype.addIceCandidate = function (candidate, success
|
||||
*/
|
||||
};
|
||||
|
||||
TraceablePeerConnection.prototype.getStats = function(callback) {
|
||||
this.peerconnection.getStats(callback);
|
||||
TraceablePeerConnection.prototype.getStats = function(callback, errback) {
|
||||
if (navigator.mozGetUserMedia) {
|
||||
// ignore for now...
|
||||
} else {
|
||||
this.peerconnection.getStats(callback);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// mozilla chrome compat layer -- very similar to adapter.js
|
||||
setupRTC = function (){
|
||||
var RTC = null;
|
||||
@@ -320,11 +376,11 @@ getUserMediaWithConstraints = function(um, resolution, bandwidth, fps) {
|
||||
},
|
||||
function (error) {
|
||||
console.warn('Failed to get access to local media. Error ', error);
|
||||
$(document).trigger('mediafailure.jingle');
|
||||
$(document).trigger('mediafailure.jingle', [error]);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('GUM failed: ', e);
|
||||
$(document).trigger('mediafailure.jingle');
|
||||
}
|
||||
}
|
||||
}(jQuery));
|
||||
}(jQuery));
|
||||
|
||||
@@ -91,9 +91,13 @@ Strophe.addConnectionPlugin('jingle', {
|
||||
sess.ice_config = this.ice_config;
|
||||
|
||||
sess.initiate($(iq).attr('from'), false);
|
||||
// FIXME: setRemoteDescription should only be done when this call is to be accepted
|
||||
sess.setRemoteDescription($(iq).find('>jingle'), 'offer');
|
||||
|
||||
if ($(iq).find('>jingle>muted[xmlns="http://jitsi.org/protocol/meet#startmuted"]').length) {
|
||||
console.log('got a request to start muted');
|
||||
sess.startmuted = true;
|
||||
}
|
||||
|
||||
this.sessions[sess.sid] = sess;
|
||||
this.jid2session[sess.peerjid] = sess;
|
||||
|
||||
@@ -209,6 +213,7 @@ Strophe.addConnectionPlugin('jingle', {
|
||||
// validity have to be fetched before creating the peerconnection
|
||||
// TODO: implement refresh via updateIce as described in
|
||||
// https://code.google.com/p/webrtc/issues/detail?id=1650
|
||||
var self = this;
|
||||
this.connection.sendIQ(
|
||||
$iq({type: 'get', to: this.connection.domain})
|
||||
.c('services', {xmlns: 'urn:xmpp:extdisco:1'}).c('service', {host: 'turn.' + this.connection.domain}),
|
||||
@@ -248,7 +253,7 @@ Strophe.addConnectionPlugin('jingle', {
|
||||
break;
|
||||
}
|
||||
});
|
||||
this.ice_config.iceServers = iceservers;
|
||||
self.ice_config.iceServers = iceservers;
|
||||
},
|
||||
function (err) {
|
||||
console.warn('getting turn credentials failed', err);
|
||||
|
||||
@@ -75,15 +75,7 @@ SDP.prototype.toJingle = function (elem, thecreator) {
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
tmp = lines[i].split(' ');
|
||||
var semantics = tmp.shift().substr(8);
|
||||
// new plan
|
||||
elem.c('group', {xmlns: 'urn:xmpp:jingle:apps:grouping:0', type: semantics, semantics:semantics});
|
||||
for (j = 0; j < tmp.length; j++) {
|
||||
elem.c('content', {name: tmp[j]}).up();
|
||||
}
|
||||
elem.up();
|
||||
|
||||
// temporary plan, to be removed
|
||||
elem.c('group', {xmlns: 'urn:ietf:rfc:5888', type: semantics});
|
||||
elem.c('group', {xmlns: 'urn:xmpp:jingle:apps:grouping:0', semantics:semantics});
|
||||
for (j = 0; j < tmp.length; j++) {
|
||||
elem.c('content', {name: tmp[j]}).up();
|
||||
}
|
||||
@@ -620,6 +612,9 @@ SDPUtil = {
|
||||
case 'generation':
|
||||
candidate.generation = elems[i + 1];
|
||||
break;
|
||||
case 'tcptype':
|
||||
candidate.tcptype = elems[i + 1];
|
||||
break;
|
||||
default: // TODO
|
||||
console.log('parse_icecandidate not translating "' + elems[i] + '" = "' + elems[i + 1] + '"');
|
||||
}
|
||||
@@ -647,6 +642,12 @@ SDPUtil = {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (cand.hasOwnAttribute('tcptype')) {
|
||||
line += 'tcptype';
|
||||
line += ' ';
|
||||
line += cand.tcptype;
|
||||
line += ' ';
|
||||
}
|
||||
line += 'generation';
|
||||
line += ' ';
|
||||
line += cand.hasOwnAttribute('generation') ? cand.generation : '0';
|
||||
@@ -729,8 +730,10 @@ SDPUtil = {
|
||||
candidateToJingle: function (line) {
|
||||
// a=candidate:2979166662 1 udp 2113937151 192.168.2.100 57698 typ host generation 0
|
||||
// <candidate component=... foundation=... generation=... id=... ip=... network=... port=... priority=... protocol=... type=.../>
|
||||
if (line.substring(0, 12) != 'a=candidate:') {
|
||||
console.log('parseCandidate called with a line that is not a candidate line');
|
||||
if (line.indexOf('candidate:') === 0) {
|
||||
line = 'a=' + line;
|
||||
} else if (line.substring(0, 12) != 'a=candidate:') {
|
||||
console.log('parseCandidate called with a line that is not a candidate line');
|
||||
console.log(line);
|
||||
return null;
|
||||
}
|
||||
@@ -752,6 +755,9 @@ SDPUtil = {
|
||||
candidate.port = elems[5];
|
||||
// elems[6] => "typ"
|
||||
candidate.type = elems[7];
|
||||
|
||||
candidate.generation = '0'; // fippo from jitsi-meet: default, may be overwritten below
|
||||
|
||||
for (i = 8; i < elems.length; i += 2) {
|
||||
switch (elems[i]) {
|
||||
case 'raddr':
|
||||
@@ -763,6 +769,9 @@ SDPUtil = {
|
||||
case 'generation':
|
||||
candidate.generation = elems[i + 1];
|
||||
break;
|
||||
case 'tcptype':
|
||||
candidate.tcptype = elems[i + 1];
|
||||
break;
|
||||
default: // TODO
|
||||
console.log('not translating "' + elems[i] + '" = "' + elems[i + 1] + '"');
|
||||
}
|
||||
@@ -810,4 +819,4 @@ SDPUtil = {
|
||||
return line + '\r\n';
|
||||
}
|
||||
};
|
||||
}(jQuery));
|
||||
}(jQuery));
|
||||
|
||||
@@ -23,7 +23,7 @@ JingleSession = function(me, sid, connection) {
|
||||
this.stopTime = null;
|
||||
this.media_constraints = null;
|
||||
this.pc_constraints = null;
|
||||
this.ice_config = {},
|
||||
this.ice_config = {};
|
||||
this.drip_container = [];
|
||||
|
||||
this.usetrickle = true;
|
||||
@@ -40,8 +40,18 @@ JingleSession = function(me, sid, connection) {
|
||||
|
||||
this.addssrc = [];
|
||||
this.removessrc = [];
|
||||
this.pendingop = null;
|
||||
|
||||
this.wait = true;
|
||||
|
||||
// XEP-0172 support, non-standard
|
||||
this.nickname = null;
|
||||
|
||||
// non-standard "please start muted" support for colibri/meet
|
||||
this.startmuted = false;
|
||||
|
||||
// Filter for testcases with ICE Candidates
|
||||
this.filter_candidates = null;
|
||||
}
|
||||
|
||||
JingleSession.prototype.initiate = function (peerjid, isInitiator) {
|
||||
@@ -159,6 +169,7 @@ JingleSession.prototype.accept = function () {
|
||||
this.peerconnection.setLocalDescription(new RTCSessionDescription({type: 'answer', sdp: sdp}),
|
||||
function () {
|
||||
//console.log('setLocalDescription success');
|
||||
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
||||
},
|
||||
function (e) {
|
||||
console.error('setLocalDescription failed', e);
|
||||
@@ -197,118 +208,50 @@ JingleSession.prototype.sendIceCandidate = function (candidate) {
|
||||
this.hadturncandidate = true;
|
||||
}
|
||||
|
||||
if (this.usetrickle) {
|
||||
if (this.usedrip) {
|
||||
if (this.drip_container.length === 0) {
|
||||
// start 10ms callout
|
||||
window.setTimeout(function () {
|
||||
if (self.drip_container.length === 0) return;
|
||||
var allcands = self.drip_container;
|
||||
self.drip_container = [];
|
||||
var cand = $iq({to: self.peerjid, type: 'set'})
|
||||
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
|
||||
action: 'transport-info',
|
||||
initiator: self.initiator,
|
||||
sid: self.sid});
|
||||
for (var mid = 0; mid < self.localSDP.media.length; mid++) {
|
||||
var cands = allcands.filter(function (el) { return el.sdpMLineIndex == mid; });
|
||||
if (cands.length > 0) {
|
||||
var ice = SDPUtil.iceparams(self.localSDP.media[mid], self.localSDP.session);
|
||||
ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';
|
||||
cand.c('content', {creator: self.initiator == self.me ? 'initiator' : 'responder',
|
||||
name: cands[0].sdpMid
|
||||
}).c('transport', ice);
|
||||
for (var i = 0; i < cands.length; i++) {
|
||||
cand.c('candidate', SDPUtil.candidateToJingle(cands[i].candidate)).up();
|
||||
}
|
||||
// add fingerprint
|
||||
if (SDPUtil.find_line(self.localSDP.media[mid], 'a=fingerprint:', self.localSDP.session)) {
|
||||
var tmp = SDPUtil.parse_fingerprint(SDPUtil.find_line(self.localSDP.media[mid], 'a=fingerprint:', self.localSDP.session));
|
||||
tmp.required = true;
|
||||
cand.c('fingerprint').t(tmp.fingerprint);
|
||||
delete tmp.fingerprint;
|
||||
cand.attrs(tmp);
|
||||
cand.up();
|
||||
}
|
||||
cand.up(); // transport
|
||||
cand.up(); // content
|
||||
}
|
||||
}
|
||||
// might merge last-candidate notification into this, but it is called alot later. See webrtc issue #2340
|
||||
//console.log('was this the last candidate', self.lasticecandidate);
|
||||
self.connection.sendIQ(cand,
|
||||
function () {
|
||||
var ack = {};
|
||||
ack.source = 'transportinfo';
|
||||
$(document).trigger('ack.jingle', [self.sid, ack]);
|
||||
},
|
||||
function (stanza) {
|
||||
var error = ($(stanza).find('error').length) ? {
|
||||
code: $(stanza).find('error').attr('code'),
|
||||
reason: $(stanza).find('error :first')[0].tagName,
|
||||
}:{};
|
||||
error.source = 'transportinfo';
|
||||
$(document).trigger('error.jingle', [self.sid, error]);
|
||||
},
|
||||
10000);
|
||||
}, 10);
|
||||
if(this.filter_candidates === null || jcand.type === this.filter_candidates) {
|
||||
if (this.usetrickle) {
|
||||
console.log('sendIceCandidate using trickle');
|
||||
if (this.usedrip) {
|
||||
if (this.drip_container.length === 0) {
|
||||
// start 20ms callout
|
||||
window.setTimeout(function () {
|
||||
console.log('sending drip container');
|
||||
if (self.drip_container.length === 0) return;
|
||||
self.sendIceCandidates(self.drip_container);
|
||||
self.drip_container = [];
|
||||
}, 20);
|
||||
|
||||
}
|
||||
this.drip_container.push(event.candidate);
|
||||
return;
|
||||
} else {
|
||||
console.log('sending single candidate');
|
||||
self.sendIceCandidates([event.candidate]);
|
||||
}
|
||||
this.drip_container.push(event.candidate);
|
||||
return;
|
||||
}
|
||||
// map to transport-info
|
||||
var cand = $iq({to: this.peerjid, type: 'set'})
|
||||
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
|
||||
action: 'transport-info',
|
||||
initiator: this.initiator,
|
||||
sid: this.sid})
|
||||
.c('content', {creator: this.initiator == this.me ? 'initiator' : 'responder',
|
||||
name: candidate.sdpMid
|
||||
})
|
||||
.c('transport', ice)
|
||||
.c('candidate', jcand);
|
||||
cand.up();
|
||||
// add fingerprint
|
||||
if (SDPUtil.find_line(this.localSDP.media[candidate.sdpMLineIndex], 'a=fingerprint:', this.localSDP.session)) {
|
||||
var tmp = SDPUtil.parse_fingerprint(SDPUtil.find_line(this.localSDP.media[candidate.sdpMLineIndex], 'a=fingerprint:', this.localSDP.session));
|
||||
tmp.required = true;
|
||||
cand.c('fingerprint').t(tmp.fingerprint);
|
||||
delete tmp.fingerprint;
|
||||
cand.attrs(tmp);
|
||||
cand.up();
|
||||
}
|
||||
this.connection.sendIQ(cand,
|
||||
function () {
|
||||
var ack = {};
|
||||
ack.source = 'transportinfo';
|
||||
$(document).trigger('ack.jingle', [self.sid, ack]);
|
||||
},
|
||||
function (stanza) {
|
||||
console.error('transport info error');
|
||||
var error = ($(stanza).find('error').length) ? {
|
||||
code: $(stanza).find('error').attr('code'),
|
||||
reason: $(stanza).find('error :first')[0].tagName,
|
||||
}:{};
|
||||
error.source = 'transportinfo';
|
||||
$(document).trigger('error.jingle', [self.sid, error]);
|
||||
},
|
||||
10000);
|
||||
}
|
||||
} else {
|
||||
//console.log('sendIceCandidate: last candidate.');
|
||||
console.log('sendIceCandidate: last candidate...');
|
||||
if (!this.usetrickle) {
|
||||
//console.log('should send full offer now...');
|
||||
console.log('should send full offer now...');
|
||||
var init = $iq({to: this.peerjid,
|
||||
type: 'set'})
|
||||
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
|
||||
action: this.peerconnection.localDescription.type == 'offer' ? 'session-initiate' : 'session-accept',
|
||||
initiator: this.initiator,
|
||||
sid: this.sid});
|
||||
if (this.nickname != null) {
|
||||
init.c('nick', {xmlns:'http://jabber.org/protocol/nick'}).t(this.nickname).up();
|
||||
}
|
||||
if (this.startmuted) {
|
||||
init.c('muted', {xmlns:'http://jitsi.org/protocol/meet#startmuted'}).up();
|
||||
}
|
||||
this.localSDP = new SDP(this.peerconnection.localDescription.sdp);
|
||||
this.localSDP.toJingle(init, this.initiator == this.me ? 'initiator' : 'responder');
|
||||
console.log('try to send ack(offer)...');
|
||||
this.connection.sendIQ(init,
|
||||
function () {
|
||||
//console.log('session initiate ack');
|
||||
console.log('Sent session initiate (ACK, offer)...');
|
||||
var ack = {};
|
||||
ack.source = 'offer';
|
||||
$(document).trigger('ack.jingle', [self.sid, ack]);
|
||||
@@ -330,11 +273,65 @@ JingleSession.prototype.sendIceCandidate = function (candidate) {
|
||||
console.log('Have we encountered any relay candidates? ' + this.hadturncandidate);
|
||||
|
||||
if (!(this.hadstuncandidate || this.hadturncandidate) && this.peerconnection.signalingState != 'closed') {
|
||||
console.log('no candidates found!');
|
||||
$(document).trigger('nostuncandidates.jingle', [this.sid]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
JingleSession.prototype.sendIceCandidates = function (candidates) {
|
||||
console.log('sendIceCandidates', candidates);
|
||||
var cand = $iq({to: this.peerjid, type: 'set'})
|
||||
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
|
||||
action: 'transport-info',
|
||||
initiator: this.initiator,
|
||||
sid: this.sid});
|
||||
for (var mid = 0; mid < this.localSDP.media.length; mid++) {
|
||||
var cands = candidates.filter(function (el) { return el.sdpMLineIndex == mid; });
|
||||
if (cands.length > 0) {
|
||||
var ice = SDPUtil.iceparams(this.localSDP.media[mid], this.localSDP.session);
|
||||
ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';
|
||||
cand.c('content', {creator: this.initiator == this.me ? 'initiator' : 'responder',
|
||||
name: cands[0].sdpMid
|
||||
}).c('transport', ice);
|
||||
for (var i = 0; i < cands.length; i++) {
|
||||
cand.c('candidate', SDPUtil.candidateToJingle(cands[i].candidate)).up();
|
||||
}
|
||||
// add fingerprint
|
||||
if (SDPUtil.find_line(this.localSDP.media[mid], 'a=fingerprint:', this.localSDP.session)) {
|
||||
var tmp = SDPUtil.parse_fingerprint(SDPUtil.find_line(this.localSDP.media[mid], 'a=fingerprint:', this.localSDP.session));
|
||||
tmp.required = true;
|
||||
cand.c('fingerprint').t(tmp.fingerprint);
|
||||
delete tmp.fingerprint;
|
||||
cand.attrs(tmp);
|
||||
cand.up();
|
||||
}
|
||||
cand.up(); // transport
|
||||
cand.up(); // content
|
||||
}
|
||||
}
|
||||
// might merge last-candidate notification into this, but it is called alot later. See webrtc issue #2340
|
||||
//console.log('was this the last candidate', this.lasticecandidate);
|
||||
console.log('try to send ack(transportinfo)...');
|
||||
this.connection.sendIQ(cand,
|
||||
function () {
|
||||
var ack = {};
|
||||
ack.source = 'transportinfo';
|
||||
console.log('Sent session initiate (ACK, transportinfo)...');
|
||||
$(document).trigger('ack.jingle', [this.sid, ack]);
|
||||
},
|
||||
function (stanza) {
|
||||
var error = ($(stanza).find('error').length) ? {
|
||||
code: $(stanza).find('error').attr('code'),
|
||||
reason: $(stanza).find('error :first')[0].tagName,
|
||||
}:{};
|
||||
error.source = 'transportinfo';
|
||||
$(document).trigger('error.jingle', [this.sid, error]);
|
||||
},
|
||||
10000);
|
||||
};
|
||||
|
||||
|
||||
JingleSession.prototype.sendOffer = function () {
|
||||
//console.log('sendOffer...');
|
||||
var self = this;
|
||||
@@ -360,6 +357,12 @@ JingleSession.prototype.createdOffer = function (sdp) {
|
||||
action: 'session-initiate',
|
||||
initiator: this.initiator,
|
||||
sid: this.sid});
|
||||
if (this.nickname != null) {
|
||||
init.c('nick', {xmlns:'http://jabber.org/protocol/nick'}).t(this.nickname).up();
|
||||
}
|
||||
if (this.startmuted) {
|
||||
init.c('muted', {xmlns:'http://jitsi.org/protocol/meet#startmuted'}).up();
|
||||
}
|
||||
this.localSDP.toJingle(init, this.initiator == this.me ? 'initiator' : 'responder');
|
||||
this.connection.sendIQ(init,
|
||||
function () {
|
||||
@@ -382,6 +385,7 @@ JingleSession.prototype.createdOffer = function (sdp) {
|
||||
sdp.sdp = this.localSDP.raw;
|
||||
this.peerconnection.setLocalDescription(sdp,
|
||||
function () {
|
||||
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
||||
//console.log('setLocalDescription success');
|
||||
},
|
||||
function (e) {
|
||||
@@ -566,11 +570,31 @@ JingleSession.prototype.sendAnswer = function (provisional) {
|
||||
|
||||
JingleSession.prototype.createdAnswer = function (sdp, provisional) {
|
||||
//console.log('createAnswer callback');
|
||||
console.log(sdp);
|
||||
var self = this;
|
||||
this.localSDP = new SDP(sdp.sdp);
|
||||
//this.localSDP.mangle();
|
||||
this.usepranswer = provisional === true;
|
||||
|
||||
if (this.startmuted) {
|
||||
console.log('we got a request to start muted...');
|
||||
this.connection.jingle.localStream.getAudioTracks().forEach(function (track) {
|
||||
track.enabled = false;
|
||||
});
|
||||
// doing this freezes local video, too (which probably means it should be replaced
|
||||
// by a symbol
|
||||
this.connection.jingle.localStream.getVideoTracks().forEach(function (track) {
|
||||
track.enabled = false;
|
||||
});
|
||||
|
||||
// set video to recvonly
|
||||
this.localSDP.media[1] = this.localSDP.media[1].replace('a=sendrecv', 'a=recvonly');
|
||||
// and remove a=ssrc lines. Weird things happen otherwise
|
||||
SDPUtil.find_lines(this.localSDP.media[1], 'a=ssrc:').forEach(function (line) {
|
||||
self.localSDP.media[1] = self.localSDP.media[1].replace(line + '\r\n', '');
|
||||
});
|
||||
this.localSDP.raw = this.localSDP.session + this.localSDP.media.join('');
|
||||
}
|
||||
|
||||
if (this.usetrickle) {
|
||||
if (!this.usepranswer) {
|
||||
var accept = $iq({to: this.peerjid,
|
||||
@@ -601,12 +625,13 @@ JingleSession.prototype.createdAnswer = function (sdp, provisional) {
|
||||
for (var i = 0; i < this.localSDP.media.length; i++) {
|
||||
this.localSDP.media[i] = this.localSDP.media[i].replace('a=sendrecv\r\n', 'a=inactive\r\n');
|
||||
}
|
||||
this.localSDP.raw = this.localSDP.session + '\r\n' + this.localSDP.media.join('');
|
||||
this.localSDP.raw = this.localSDP.session + this.localSDP.media.join('');
|
||||
}
|
||||
}
|
||||
sdp.sdp = this.localSDP.raw;
|
||||
this.peerconnection.setLocalDescription(sdp,
|
||||
function () {
|
||||
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
||||
//console.log('setLocalDescription success');
|
||||
},
|
||||
function (e) {
|
||||
@@ -727,8 +752,8 @@ JingleSession.prototype.removeSource = function (elem) {
|
||||
|
||||
JingleSession.prototype.modifySources = function() {
|
||||
var self = this;
|
||||
if (!(this.addssrc.length || this.removessrc.length)) return;
|
||||
if (this.peerconnection.signalingState == 'closed') return;
|
||||
if (!(this.addssrc.length || this.removessrc.length || this.pendingop !== null)) return;
|
||||
if (!(this.peerconnection.signalingState == 'stable' && this.peerconnection.iceConnectionState == 'connected')) {
|
||||
console.warn('modifySources not yet', this.peerconnection.signalingState, this.peerconnection.iceConnectionState);
|
||||
this.wait = true;
|
||||
@@ -764,9 +789,28 @@ JingleSession.prototype.modifySources = function() {
|
||||
function() {
|
||||
self.peerconnection.createAnswer(
|
||||
function(modifiedAnswer) {
|
||||
// change video direction, see https://github.com/jitsi/jitmeet/issues/41
|
||||
if (self.pendingop !== null) {
|
||||
var sdp = new SDP(modifiedAnswer.sdp);
|
||||
if (sdp.media.length > 1) {
|
||||
switch(self.pendingop) {
|
||||
case 'mute':
|
||||
sdp.media[1] = sdp.media[1].replace('a=sendrecv', 'a=recvonly');
|
||||
break;
|
||||
case 'unmute':
|
||||
sdp.media[1] = sdp.media[1].replace('a=recvonly', 'a=sendrecv');
|
||||
break;
|
||||
}
|
||||
sdp.raw = sdp.session + sdp.media.join('');
|
||||
modifiedAnswer.sdp = sdp.raw;
|
||||
}
|
||||
self.pendingop = null;
|
||||
}
|
||||
|
||||
self.peerconnection.setLocalDescription(modifiedAnswer,
|
||||
function() {
|
||||
//console.log('modified setLocalDescription ok');
|
||||
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
||||
},
|
||||
function(error) {
|
||||
console.log('modified setLocalDescription failed');
|
||||
@@ -784,6 +828,17 @@ JingleSession.prototype.modifySources = function() {
|
||||
);
|
||||
};
|
||||
|
||||
// SDP-based mute by going recvonly/sendrecv
|
||||
// FIXME: should probably black out the screen as well
|
||||
JingleSession.prototype.hardMuteVideo = function (muted) {
|
||||
this.pendingop = muted ? 'mute' : 'unmute';
|
||||
this.modifySources();
|
||||
|
||||
this.connection.jingle.localStream.getVideoTracks().forEach(function (track) {
|
||||
track.enabled = !muted;
|
||||
});
|
||||
};
|
||||
|
||||
JingleSession.prototype.sendMute = function (muted, content) {
|
||||
var info = $iq({to: this.peerjid,
|
||||
type: 'set'})
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
* Klaus Herberth, 2014
|
||||
*/
|
||||
|
||||
// This code was written by Tyler Akins and has been placed in the
|
||||
// public domain. It would be nice if you left this header intact.
|
||||
// Base64 code from Tyler Akins -- http://rumkin.com
|
||||
/*! This code was written by Tyler Akins and has been placed in the
|
||||
public domain. It would be nice if you left this header intact.
|
||||
Base64 code from Tyler Akins -- http://rumkin.com
|
||||
*/
|
||||
|
||||
var Base64 = (function () {
|
||||
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
@@ -84,7 +85,7 @@ var Base64 = (function () {
|
||||
return obj;
|
||||
})();
|
||||
|
||||
/*
|
||||
/*!
|
||||
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
|
||||
* in FIPS PUB 180-1
|
||||
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
|
||||
@@ -261,7 +262,7 @@ function binb2b64(binarray)
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
/*!
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* Digest Algorithm, as defined in RFC 1321.
|
||||
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
|
||||
@@ -469,7 +470,7 @@ var MD5 = (function () {
|
||||
return obj;
|
||||
})();
|
||||
|
||||
/*
|
||||
/*!
|
||||
This program is distributed under the terms of the MIT license.
|
||||
Please see the LICENSE file for details.
|
||||
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
[
|
||||
{
|
||||
"file": "build/lib/strophe.js",
|
||||
"license": "multiple",
|
||||
"url": "http://strophe.im/strophejs/"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/strophe.muc.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/strophe.disco.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/strophe.caps.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/strophe.vcard.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/strophe/strophejs-plugins"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/strophe.jingle/strophe.jingle.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/ESTOS/strophe.jingle"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/strophe.jingle/strophe.jingle.session.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/ESTOS/strophe.jingle"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/strophe.jingle/strophe.jingle.sdp.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/ESTOS/strophe.jingle"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/strophe.jingle/strophe.jingle.adapter.js",
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/ESTOS/strophe.jingle"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/otr/build/dep/salsa20.js",
|
||||
"license": "AGPL3",
|
||||
"url": "https://github.com/neoatlantis/node-salsa20"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/otr/build/dep/bigint.js",
|
||||
"license": "public domain",
|
||||
"url": "www.leemon.com"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/otr/build/dep/crypto.js",
|
||||
"license": "code.google.com/p/crypto-js/wiki/license",
|
||||
"url": "code.google.com/p/crypto-js"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/otr/build/dep/eventemitter.js",
|
||||
"license": "MIT",
|
||||
"url": "http://git.io/ee"
|
||||
},
|
||||
{
|
||||
"file": "build/lib/otr/build/otr.js",
|
||||
"license": "MPL v2.0",
|
||||
"url": "https://arlolra.github.io/otr/"
|
||||
}
|
||||
]
|
||||
@@ -20,6 +20,9 @@
|
||||
<script src="../lib/jquery.colorbox-min.js"></script>
|
||||
<script src="../lib/jquery.slimscroll.js"></script>
|
||||
<script src="../lib/jquery.fullscreen.js"></script>
|
||||
|
||||
<!-- Nightly files:
|
||||
|
||||
<script src="../lib/strophe.js"></script>
|
||||
<script src="../lib/strophe.muc.js"></script>
|
||||
<script src="../lib/strophe.disco.js"></script>
|
||||
@@ -35,7 +38,12 @@
|
||||
<script src="../lib/otr/build/dep/eventemitter.js"></script>
|
||||
<script src="../lib/otr/build/otr.js"></script>
|
||||
<script src="../jsxc.lib.js"></script>
|
||||
<script src="../jsxc.lib.webrtc.js"></script>
|
||||
<script src="../jsxc.lib.webrtc.js"></script>
|
||||
-->
|
||||
|
||||
<!-- Build files: -->
|
||||
<script src="../build/jsxc.dep.js"></script>
|
||||
<script src="../build/jsxc.js"></script>
|
||||
|
||||
<script src="js/example.js"></script>
|
||||
|
||||
|
||||
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 9.3 KiB |
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||
|
||||
<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="Layer_1"
|
||||
xml:space="preserve"
|
||||
height="147.22015"
|
||||
viewBox="0 0 192.89149 147.21771"
|
||||
width="192.89587"
|
||||
version="1.1"
|
||||
y="0px"
|
||||
x="0px"
|
||||
enable-background="new 0 0 176.486 181.437"
|
||||
inkscape:version="0.91pre2 r"
|
||||
sodipodi:docname="XMPP_logo.svg"><metadata
|
||||
id="metadata41"><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></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs39" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="640"
|
||||
inkscape:window-height="480"
|
||||
id="namedview37"
|
||||
showgrid="false"
|
||||
fit-margin-top="10"
|
||||
fit-margin-left="10"
|
||||
fit-margin-right="10"
|
||||
fit-margin-bottom="10"
|
||||
inkscape:zoom="1.3007054"
|
||||
inkscape:cx="71.332001"
|
||||
inkscape:cy="72.501142"
|
||||
inkscape:window-x="75"
|
||||
inkscape:window-y="34"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="Layer_1" /><linearGradient
|
||||
id="SVGID_1_"
|
||||
y2="0.00048828"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="-1807.2"
|
||||
gradientTransform="translate(1925.9953,9.9988343)"
|
||||
y1="125.86"
|
||||
x1="-1807.2"><stop
|
||||
stop-color="#1b3967"
|
||||
offset=".011"
|
||||
id="stop4" /><stop
|
||||
stop-color="#13b5ea"
|
||||
offset=".467"
|
||||
id="stop6" /><stop
|
||||
stop-color="#002b5c"
|
||||
offset=".9945"
|
||||
id="stop8" /></linearGradient><path
|
||||
d="m 146.28531,24.187835 c 0.077,1.313 -1.786,0.968 -1.786,2.293 0,38.551 -44.720002,96.831035 -89.847002,108.190035 l 0,1.182 C 114.60931,130.34287 181.38231,69.052835 182.89231,10.002834 l -36.6,14.189001 z"
|
||||
id="path10"
|
||||
style="fill:url(#SVGID_1_)"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 130.22531,27.958835 c 0.077,1.313 0.121,2.633 0.121,3.958 0,38.551 -30.700002,90.497035 -75.827002,101.860035 l 0,1.637 c 59.065002,-3.823 105.810002,-63.023035 105.810002,-109.200035 0,-2.375 -0.125,-4.729 -0.371,-7.056 l -29.73,8.796 z"
|
||||
id="path12"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#e96d1f" /><linearGradient
|
||||
id="SVGID_2_"
|
||||
y2="1.279e-13"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="-1073.2"
|
||||
gradientTransform="matrix(-1,0,0,1,-998.20465,9.9988343)"
|
||||
y1="126.85"
|
||||
x1="-1073.2"><stop
|
||||
stop-color="#1b3967"
|
||||
offset=".011"
|
||||
id="stop15" /><stop
|
||||
stop-color="#13b5ea"
|
||||
offset=".467"
|
||||
id="stop17" /><stop
|
||||
stop-color="#002b5c"
|
||||
offset=".9945"
|
||||
id="stop19" /></linearGradient><path
|
||||
d="m 46.594308,24.187835 c -0.077,1.313 1.787,0.968 1.787,2.293 0,38.551 46.558,97.366035 91.688002,108.730035 l 0,1.639 C 80.116308,131.32987 11.509308,69.049835 9.9993079,9.9998343 L 46.598308,24.188835 Z"
|
||||
id="path21"
|
||||
style="fill:url(#SVGID_2_)"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 64.726308,28.930835 c -0.076,1.313 -0.12,2.63 -0.12,3.957 0,38.551 30.699,90.497035 75.827002,101.860035 l 0,1.639 C 81.389308,133.59687 34.623308,73.362835 34.623308,27.186835 c 0,-2.375 0.128,-4.729 0.371,-7.056 l 29.73,8.798 z"
|
||||
id="path23"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#a0ce67" /><path
|
||||
d="m 34.708308,19.581835 7.617,2.722 c -0.041,0.962 -0.066,2.254 -0.066,3.225 0,41.219 37.271,98.204035 87.272002,107.120035 3.245,1.088 7.538,2.077 10.932,2.931 l 0,1.638 C 75.209308,131.65787 29.363308,65.351835 34.703308,19.577835 Z"
|
||||
id="path25"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#439639" /><path
|
||||
d="m 160.33531,18.758835 -7.833,2.625 c 0.041,0.963 0.191,2.203 0.191,3.173 0,41.219 -37.272,98.205035 -87.274002,107.120035 -3.243,1.089 -7.538,2.077 -10.93,2.932 l 0,1.639 C 122.83331,127.58787 165.66931,64.528835 160.32931,18.757835 Z"
|
||||
id="path27"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#d9541e" /></svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 4.5 KiB |
+276
-11
@@ -30,6 +30,10 @@ p.jsxc_center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
li.jsxc_sep {
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
/*############################
|
||||
*########## Dialog ##########
|
||||
*############################*/
|
||||
@@ -38,6 +42,15 @@ p.jsxc_center {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
#jsxc_dialog ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#jsxc_dialog ul, #jsxc_dialog li {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#jsxc_dialog p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
@@ -141,6 +154,8 @@ li .jsxc_name:hover {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-family: Arial;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.jsxc_avatar img {
|
||||
@@ -152,6 +167,36 @@ li .jsxc_name:hover {
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.jsxc_spot {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
text-indent: -99999em;
|
||||
margin-top: 3px;
|
||||
margin-right: 5px;
|
||||
border: 1px solid #000 !important;
|
||||
line-height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jsxc_spot.jsxc_online, .jsxc_spot.jsxc_chat {
|
||||
background-color: #00BFFF;
|
||||
}
|
||||
|
||||
.jsxc_spot.jsxc_away, .jsxc_spot.jsxc_xa {
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.jsxc_spot.jsxc_dnd {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.jsxc_spot.jsxc_offline {
|
||||
background-color: #A4A4A4;
|
||||
}
|
||||
|
||||
/*############################
|
||||
*########## Roster ##########
|
||||
*############################*/
|
||||
@@ -344,8 +389,64 @@ div#jsxc_roster>.jsxc_bottom ul li:last-child {
|
||||
color: black;
|
||||
font-size: 80%;
|
||||
padding: 2px;
|
||||
position: relative;
|
||||
-webkit-animation: bounce 2s 1s infinite;
|
||||
animation: bounce 2s 1s infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes bounce {
|
||||
0% {
|
||||
bottom: 0;
|
||||
-webkit-animation-timing-function: ease-in;
|
||||
}
|
||||
12% {
|
||||
bottom: 5px;
|
||||
-webkit-animation-timing-function: ease-out;
|
||||
}
|
||||
25% {
|
||||
bottom: 0px;
|
||||
-webkit-animation-timing-function: ease-in;
|
||||
}
|
||||
37% {
|
||||
bottom: 5px;
|
||||
-webkit-animation-timing-function: ease-out;
|
||||
}
|
||||
50% {
|
||||
bottom: 0px;
|
||||
-webkit-animation-timing-function: ease-in;
|
||||
}
|
||||
100% {
|
||||
bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0% {
|
||||
bottom: 0;
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
12% {
|
||||
bottom: 5px;
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
25% {
|
||||
bottom: 0px;
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
37% {
|
||||
bottom: 5px;
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
50% {
|
||||
bottom: 0px;
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
100% {
|
||||
bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#jsxc_presence {
|
||||
cursor: pointer;
|
||||
padding-left: 2px;
|
||||
@@ -380,6 +481,27 @@ ul#jsxc_buddylist .jsxc_name {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
ul#jsxc_buddylist li .jsxc_name:before {
|
||||
content: ' ';
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
display: inline-block;
|
||||
opacity: 0.0;
|
||||
-webkit-transition: width 0.5s, opacity 0.5s;
|
||||
transition: width 0.5s, opacity 0.5s;
|
||||
}
|
||||
|
||||
ul#jsxc_buddylist li.jsxc_unreadMsg .jsxc_name:before {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
background-color: orange;
|
||||
margin-right: 3px;
|
||||
opacity: 1.0;
|
||||
-webkit-transition: width 0.5s, opacity 0.5s;
|
||||
transition: width 0.5s, opacity 0.5s;
|
||||
}
|
||||
|
||||
ul#jsxc_buddylist li.jsxc_expand {
|
||||
height: 54px;
|
||||
}
|
||||
@@ -541,25 +663,30 @@ div#jsxc_toggleRoster {
|
||||
div#jsxc_windowList {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
width: 100%;
|
||||
right: 210px;
|
||||
left: 0px;
|
||||
z-index: 50;
|
||||
clip: rect(-10000px, 10000px, 30px, 30px);
|
||||
}
|
||||
|
||||
div#jsxc_windowList>ul {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
padding-right: 210px;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
height: 30px;
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
-webkit-transition: right 0.5s;
|
||||
transition: right 0.5s;
|
||||
}
|
||||
|
||||
div#jsxc_windowList>ul>li {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
display: block;
|
||||
float: right;
|
||||
display: inline-block;
|
||||
width: 250px;
|
||||
background-color: #282323;
|
||||
height: 30px;
|
||||
@@ -567,10 +694,45 @@ div#jsxc_windowList>ul>li {
|
||||
overflow: visible;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
div#jsxc_windowList>ul>li.jsxc_min {
|
||||
width: 200px;
|
||||
width: 200px !important;
|
||||
}
|
||||
|
||||
#jsxc_windowListSB {
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
#jsxc_windowListSB > div {
|
||||
box-sizing: border-box;
|
||||
width: 14px;
|
||||
height: 100%;
|
||||
background-color: #D3D3D3;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
#jsxc_windowListSB > div:hover {
|
||||
background-color: #c3c3c3;
|
||||
}
|
||||
#jsxc_windowListSB > div.jsxc_disabled {
|
||||
background-color: #f1f1f1 !important;
|
||||
color: #d1d1d1;
|
||||
cursor: default !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*############################
|
||||
@@ -622,6 +784,7 @@ div.jsxc_window .jsxc_emoticons {
|
||||
width: 30px;
|
||||
position: absolute;
|
||||
top: 240px;
|
||||
/*bottom: 0px;*/
|
||||
right: 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -653,6 +816,7 @@ div.jsxc_window .jsxc_emoticons ul {
|
||||
padding: 3px;
|
||||
border-radius: 3px;
|
||||
z-index: 200;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
div.jsxc_window .jsxc_emoticons ul:after {
|
||||
@@ -673,12 +837,15 @@ div.jsxc_window .jsxc_emoticons li {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.jsxc_window .jsxc_emoticons img {
|
||||
div.jsxc_window .jsxc_emoticons div {
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
background-size: 30px 30px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
div.jsxc_window .jsxc_emoticons img:hover {
|
||||
div.jsxc_window .jsxc_emoticons div:hover {
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
@@ -687,7 +854,8 @@ div.jsxc_window .jsxc_emoticons img:hover {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jsxc_window .jsxc_gradient {
|
||||
.jsxc_window .jsxc_gradient {
|
||||
display:none;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
@@ -717,13 +885,14 @@ div.jsxc_window .jsxc_avatar {
|
||||
|
||||
div.jsxc_window .jsxc_textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
div.jsxc_window .slimScrollDiv {
|
||||
margin: 0px 0px 6px 0px;
|
||||
left: auto !important;
|
||||
top: auto !important;
|
||||
}
|
||||
|
||||
div.jsxc_chatmessage {
|
||||
@@ -746,6 +915,7 @@ div.jsxc_chatmessage a {
|
||||
div.jsxc_chatmessage img {
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
background-size: 19px 19px;
|
||||
}
|
||||
|
||||
/** incoming message */
|
||||
@@ -901,6 +1071,7 @@ div.jsxc_settings li {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.jsxc_settings li:first-child {
|
||||
@@ -917,7 +1088,12 @@ div.jsxc_settings li.jsxc_disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
div.jsxc_transfer {
|
||||
.jsxc_tools > div.jsxc_disabled {
|
||||
opacity: 0.5;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
div.jsxc_transfer, div.jsxc_transfer.jsxc_disabled:hover {
|
||||
background-image: url('img/padlock_open_grey.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
@@ -975,4 +1151,93 @@ img.jsxc_vCard {
|
||||
float: right;
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
border: 5px solid white;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsxc_window .ui-resizable-w {
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.jsxc_window .ui-resizable-nw {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
z-index: 95 !important;
|
||||
}
|
||||
|
||||
.jsxc_window .ui-resizable-n {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 15px;
|
||||
z-index: 100;
|
||||
background: -moz-linear-gradient(top, rgba(164, 164, 164, 1) 0%,
|
||||
rgba(40, 35, 35, 0) 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(164,
|
||||
164, 164, 1)), color-stop(100%, rgba(40, 35, 35, 0)));
|
||||
/* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, rgba(164, 164, 164, 1) 0%,
|
||||
rgba(40, 35, 35, 0) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(164, 164, 164, 1) 0%,
|
||||
rgba(40, 35, 35, 0) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(164, 164, 164, 1) 0%,
|
||||
rgba(40, 35, 35, 0) 100%); /* IE10+ */
|
||||
background: linear-gradient(to bottom, #a4a4a4 0%, rgba(40, 35, 35, 0)
|
||||
100%); /* W3C */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a4a4a4',
|
||||
endColorstr='#00282323', GradientType=0); /* IE6-9 */
|
||||
}
|
||||
|
||||
.jsxc_emoticon {
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
background-size: 19px 19px !important;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.jsxc_angel { background: url('img/emotions/angel.png') }
|
||||
|
||||
.jsxc_angry { background: url('img/emotions/angry.png') }
|
||||
|
||||
.jsxc_smile { background: url('img/emotions/smile.png') }
|
||||
|
||||
.jsxc_grin { background: url('img/emotions/grin.png') }
|
||||
|
||||
.jsxc_sad { background: url('img/emotions/sad.png') }
|
||||
|
||||
.jsxc_wink { background: url('img/emotions/wink.png') }
|
||||
|
||||
.jsxc_tonguesmile { background: url('img/emotions/tonguesmile.png') }
|
||||
|
||||
.jsxc_surprised { background: url('img/emotions/surprised.png') }
|
||||
|
||||
.jsxc_kiss { background: url('img/emotions/kiss.png') }
|
||||
|
||||
.jsxc_sunglassess { background: url('img/emotions/sunglassess.png') }
|
||||
|
||||
.jsxc_crysad { background: url('img/emotions/crysad.png') }
|
||||
|
||||
.jsxc_doubt { background: url('img/emotions/doubt.png') }
|
||||
|
||||
.jsxc_zip { background: url('img/emotions/zip.png') }
|
||||
|
||||
.jsxc_thumbsup { background: url('img/emotions/thumbsup.png') }
|
||||
|
||||
.jsxc_thumbsdown { background: url('img/emotions/thumbsdown.png') }
|
||||
|
||||
.jsxc_beer { background: url('img/emotions/beer.png') }
|
||||
|
||||
.jsxc_devil { background: url('img/emotions/devil.png') }
|
||||
|
||||
.jsxc_kissing { background: url('img/emotions/kissing.png') }
|
||||
|
||||
.jsxc_rose { background: url('img/emotions/rose.png') }
|
||||
|
||||
.jsxc_music { background: url('img/emotions/music.png') }
|
||||
|
||||
.jsxc_love { background: url('img/emotions/love.png') }
|
||||
|
||||
.jsxc_tired { background: url('img/emotions/tired.png') }
|
||||
|
||||
+1450
-680
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+207
-49
@@ -1,9 +1,9 @@
|
||||
/* jsxc, Strophe, SDPUtil, getUserMediaWithConstraints, setupRTC, jQuery */
|
||||
/* global jsxc, Strophe, SDPUtil, getUserMediaWithConstraints, setupRTC, jQuery, MediaStreamTrack */
|
||||
|
||||
var RTC = null, RTCPeerconnection = null;
|
||||
|
||||
jsxc.gui.template.incomingCall = '<h3>%%Incoming_call%%</h3>\
|
||||
<p>%%Do_you_want_to_accept_the_call_from%% {{cid_name}}?</p>\
|
||||
<p>%%Do_you_want_to_accept_the_call_from%% {{bid_name}}?</p>\
|
||||
<p class="jsxc_right">\
|
||||
<a href="#" class="button jsxc_reject">%%Reject%%</a> <a href="#" class="button creation jsxc_accept">%%Accept%%</a>\
|
||||
</p>';
|
||||
@@ -11,10 +11,28 @@ jsxc.gui.template.incomingCall = '<h3>%%Incoming_call%%</h3>\
|
||||
jsxc.gui.template.allowMediaAccess = '<p>%%Please_allow_access_to_microphone_and_camera%%</p>';
|
||||
|
||||
jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
<div class="jsxc_chatarea">\
|
||||
<ul></ul>\
|
||||
</div>\
|
||||
<div class="jsxc_videoContainer">\
|
||||
<video class="jsxc_localvideo" autoplay></video>\
|
||||
<video class="jsxc_remotevideo" autoplay></video>\
|
||||
<div class="jsxc_status"></div>\
|
||||
<div class="bubblingG">\
|
||||
<span id="bubblingG_1">\
|
||||
</span>\
|
||||
<span id="bubblingG_2">\
|
||||
</span>\
|
||||
<span id="bubblingG_3">\
|
||||
</span>\
|
||||
</div>\
|
||||
<div class="jsxc_noRemoteVideo">\
|
||||
<div>\
|
||||
<div></div>\
|
||||
<p>%%No_video_signal%%</p>\
|
||||
<div></div>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="jsxc_controlbar">\
|
||||
<button type="button" class="jsxc_hangUp">%%hang_up%%</button>\
|
||||
@@ -32,9 +50,9 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
<div class="jsxc_snapshotbar">\
|
||||
<p>No pictures yet!</p>\
|
||||
</div>\n\
|
||||
<div class="jsxc_chatarea">\
|
||||
<!--<div class="jsxc_chatarea">\
|
||||
<ul></ul>\
|
||||
</div>\
|
||||
</div>-->\
|
||||
<div class="jsxc_infobar"></div>\
|
||||
</div>\
|
||||
</div>';
|
||||
@@ -64,7 +82,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
AUTO_ACCEPT: false,
|
||||
|
||||
/** required disco features */
|
||||
reqVideoFeatures: [ 'urn:xmpp:jingle:apps:rtp:video', 'urn:xmpp:jingle:apps:rtp:audio', 'urn:xmpp:jingle:transports:ice-udp:1' ],
|
||||
reqVideoFeatures: [ 'urn:xmpp:jingle:apps:rtp:video', 'urn:xmpp:jingle:apps:rtp:audio', 'urn:xmpp:jingle:transports:ice-udp:1', 'urn:xmpp:jingle:apps:dtls:0' ],
|
||||
|
||||
/** bare jid to current jid mapping */
|
||||
chatJids: {},
|
||||
@@ -98,6 +116,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
self.conn.jingle.pc_constraints = RTC.pc_constraints;
|
||||
|
||||
$(document).on('message.jsxc', $.proxy(self.onMessage, self));
|
||||
$(document).on('presence.jsxc', $.proxy(self.onPresence, self));
|
||||
|
||||
$(document).on('mediaready.jingle', $.proxy(self.onMediaReady, self));
|
||||
$(document).on('mediafailure.jingle', $.proxy(self.onMediaFailure, self));
|
||||
@@ -114,6 +133,10 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
jsxc.error('[JINGLE]', error);
|
||||
});
|
||||
|
||||
if (self.conn.disco) {
|
||||
self.conn.disco.addFeature('urn:xmpp:jingle:apps:dtls:0');
|
||||
}
|
||||
|
||||
if (self.conn.caps) {
|
||||
$(document).on('caps.strophe', $.proxy(self.onCaps, self));
|
||||
}
|
||||
@@ -160,18 +183,48 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Return list of video capable resources.
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
* @param jid
|
||||
* @returns {Array}
|
||||
*/
|
||||
getCapableRes: function(jid) {
|
||||
var self = jsxc.webrtc;
|
||||
var bid = jsxc.jidToBid(jid);
|
||||
var res = jsxc.storage.getUserItem('res', bid) || [];
|
||||
|
||||
var available = [];
|
||||
$.each(res, function(r) {
|
||||
if (self.conn.caps.hasFeatureByJid(bid + '/' + r, self.reqVideoFeatures)) {
|
||||
available.push(r);
|
||||
}
|
||||
});
|
||||
|
||||
return available;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add "video" button to roster
|
||||
*
|
||||
* @private
|
||||
* @memberOf jsxc.webrtc
|
||||
* @param event
|
||||
* @param cid cid of roster item
|
||||
* @param data data wich belongs to cid
|
||||
* @param bid bid of roster item
|
||||
* @param data data wich belongs to bid
|
||||
* @param el the roster item
|
||||
*/
|
||||
onAddRosterItem: function(event, cid, data, el) {
|
||||
onAddRosterItem: function(event, bid, data, el) {
|
||||
var self = jsxc.webrtc;
|
||||
|
||||
if (!self.conn) {
|
||||
$(document).one('connectionReady.jsxc', function() {
|
||||
self.onAddRosterItem(null, bid, data, el);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var videoIcon = $('<div class="jsxc_video jsxc_disabled" title="' + jsxc.l.Start_video_call + '"></div>');
|
||||
|
||||
videoIcon.click(function() {
|
||||
@@ -182,7 +235,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
el.find('.jsxc_options.jsxc_left').append(videoIcon);
|
||||
|
||||
el.on('extra.jsxc', function() {
|
||||
self.updateIcon(cid);
|
||||
self.updateIcon(bid);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -197,6 +250,8 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
initWindow: function(event, win) {
|
||||
var self = jsxc.webrtc;
|
||||
|
||||
jsxc.debug('webrtc.initWindow');
|
||||
|
||||
if (!self.conn) {
|
||||
$(document).one('connectionReady.jsxc', function() {
|
||||
self.initWindow(null, win);
|
||||
@@ -207,39 +262,43 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
var div = $('<div>').addClass('jsxc_video');
|
||||
win.find('.jsxc_transfer:eq(1)').after(div);
|
||||
|
||||
self.updateIcon(jsxc.jidToCid(win.data('jid')));
|
||||
self.updateIcon(jsxc.jidToBid(win.data('jid')));
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable or disable "video" icon and assign full jid.
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
* @param cid CSS conform jid
|
||||
* @param bid CSS conform jid
|
||||
*/
|
||||
updateIcon: function(cid) {
|
||||
updateIcon: function(bid) {
|
||||
jsxc.debug('Update icon', bid);
|
||||
|
||||
var self = jsxc.webrtc;
|
||||
var win = jsxc.gui.getWindow(cid);
|
||||
var jid = win.data('jid') || jsxc.storage.getUserItem('buddy_' + cid).jid;
|
||||
var win = jsxc.gui.window.get(bid);
|
||||
var jid = win.data('jid') || jsxc.storage.getUserItem('buddy', bid).jid;
|
||||
|
||||
var el = win.find('.jsxc_video').add('#' + cid + ' .jsxc_video');
|
||||
var el = win.find('.jsxc_video').add(jsxc.gui.roster.getItem(bid).find('.jsxc_video'));
|
||||
|
||||
// only start video call to a full jid
|
||||
if (Strophe.getResourceFromJid(jid) === null) {
|
||||
var capableRes = self.getCapableRes(jid);
|
||||
var targetRes = Strophe.getResourceFromJid(jid);
|
||||
|
||||
var res = jsxc.storage.getUserItem('buddy_' + cid).res;
|
||||
|
||||
if (Array.isArray(res) && res.length === 1) {
|
||||
jid += '/' + res[0];
|
||||
}
|
||||
if (targetRes === null) {
|
||||
$.each(jsxc.storage.getUserItem('buddy', bid).res, function(index, val) {
|
||||
if (capableRes.indexOf(val) > -1) {
|
||||
targetRes = val;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
el.off('click');
|
||||
|
||||
if (self.conn.caps.hasFeatureByJid(jid, self.reqVideoFeatures)) {
|
||||
if (capableRes.indexOf(targetRes) > -1) {
|
||||
el.click(function() {
|
||||
self.startCall(jid);
|
||||
self.startCall(jid + '/' + targetRes);
|
||||
});
|
||||
|
||||
el.removeClass('jsxc_disabled');
|
||||
|
||||
el.attr('title', jsxc.translate('%%Start video call%%'));
|
||||
@@ -260,14 +319,32 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
*/
|
||||
onMessage: function(e, from) {
|
||||
var self = jsxc.webrtc;
|
||||
var bJid = Strophe.getBareJidFromJid(from);
|
||||
var bid = jsxc.jidToBid(from);
|
||||
|
||||
if (self.chatJids[bJid] !== from) {
|
||||
self.updateIcon(jsxc.jidToCid(bJid));
|
||||
self.chatJids[bJid] = from;
|
||||
jsxc.debug('webrtc.onmessage', from);
|
||||
|
||||
if (self.chatJids[bid] !== from) {
|
||||
self.updateIcon(bid);
|
||||
self.chatJids[bid] = from;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update icon on presence.
|
||||
*
|
||||
* @memberOf
|
||||
* @param ev
|
||||
* @param status
|
||||
* @private
|
||||
*/
|
||||
onPresence: function(ev, jid) {
|
||||
var self = jsxc.webrtc;
|
||||
|
||||
jsxc.debug('webrtc.onpresence', jid);
|
||||
|
||||
self.updateIcon(jsxc.jidToBid(jid));
|
||||
},
|
||||
|
||||
/**
|
||||
* Display status message to user.
|
||||
*
|
||||
@@ -326,7 +403,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
onCaps: function(event, jid) {
|
||||
var self = jsxc.webrtc;
|
||||
|
||||
self.updateIcon(jsxc.jidToCid(jid));
|
||||
self.updateIcon(jsxc.jidToBid(jid));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -357,6 +434,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
self.setStatus((stream.getVideoTracks().length > 0) ? 'Use local video device.' : 'No local video device.');
|
||||
|
||||
jsxc.debug('using video device "' + stream.getVideoTracks()[i].label + '"');
|
||||
$('#jsxc_dialog .jsxc_localvideo').show();
|
||||
}
|
||||
|
||||
$(document).one('cleanup.dialog.jsxc', $.proxy(self.hangUp, self));
|
||||
@@ -369,8 +447,11 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
* @private
|
||||
* @memberOf jsxc.webrtc
|
||||
*/
|
||||
onMediaFailure: function() {
|
||||
onMediaFailure: function(ev, err) {
|
||||
this.setStatus('media failure');
|
||||
|
||||
jsxc.gui.window.postMessage(jsxc.jidToBid(jsxc.webrtc.last_caller), 'sys', jsxc.translate('%%Media failure%%: ') + err.name);
|
||||
jsxc.debug('media failure: ' + err.name);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -386,10 +467,12 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
|
||||
var self = this;
|
||||
var sess = this.conn.jingle.sessions[sid];
|
||||
var jid = jsxc.jidToCid(sess.peerjid);
|
||||
var bid = jsxc.jidToBid(sess.peerjid);
|
||||
|
||||
jsxc.gui.window.postMessage(bid, 'sys', jsxc.translate('%%Incoming call.%%'));
|
||||
|
||||
// display notification
|
||||
jsxc.notification.notify(jsxc.translate('%%Incoming call%%'), jsxc.translate('%%from%% ' + jid));
|
||||
jsxc.notification.notify(jsxc.translate('%%Incoming call%%'), jsxc.translate('%%from%% ' + bid));
|
||||
|
||||
// send signal to partner
|
||||
sess.sendRinging();
|
||||
@@ -417,7 +500,9 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
return;
|
||||
}
|
||||
|
||||
var dialog = jsxc.gui.dialog.open(jsxc.gui.template.get('incomingCall', jsxc.jidToCid(jid)));
|
||||
var dialog = jsxc.gui.dialog.open(jsxc.gui.template.get('incomingCall', bid), {
|
||||
noClose: true
|
||||
});
|
||||
|
||||
dialog.find('.jsxc_accept').click(function() {
|
||||
$(document).trigger('accept.call.jsxc');
|
||||
@@ -447,22 +532,30 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
onCallTerminated: function(event, sid, reason, text) {
|
||||
this.setStatus('call terminated ' + sid + (reason ? (': ' + reason + ' ' + text) : ''));
|
||||
|
||||
var bid = jsxc.jidToBid(jsxc.webrtc.last_caller);
|
||||
|
||||
if (this.localStream) {
|
||||
this.localStream.stop();
|
||||
}
|
||||
|
||||
$('.jsxc_remotevideo')[0].src = "";
|
||||
$('.jsxc_localvideo')[0].src = "";
|
||||
if ($('.jsxc_videoContainer').length) {
|
||||
$('.jsxc_remotevideo')[0].src = "";
|
||||
$('.jsxc_localvideo')[0].src = "";
|
||||
}
|
||||
|
||||
this.conn.jingle.localStream = null;
|
||||
this.localStream = null;
|
||||
this.remoteStream = null;
|
||||
|
||||
$('#jsxc_windowList > ul').prepend($('#jsxc_dialog .jsxc_chatarea > ul > li').detach());
|
||||
var win = $('#jsxc_dialog .jsxc_chatarea > ul > li');
|
||||
$('#jsxc_windowList > ul').prepend(win.detach());
|
||||
win.find('.slimScrollDiv').resizable('enable');
|
||||
|
||||
$(document).off('cleanup.dialog.jsxc');
|
||||
$(document).off('error.jingle');
|
||||
jsxc.gui.dialog.close();
|
||||
|
||||
jsxc.gui.window.postMessage(bid, 'sys', jsxc.translate('%%Call terminated%%' + (reason ? (': %%' + reason + '%%') : '') + '.'));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -504,7 +597,9 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
this.setStatus(isAudioDevice ? 'Use remote audio device.' : 'No remote audio device');
|
||||
|
||||
if ($('.jsxc_remotevideo').length) {
|
||||
RTC.attachMediaStream($('.jsxc_remotevideo'), stream);
|
||||
RTC.attachMediaStream($('#jsxc_dialog .jsxc_remotevideo'), stream);
|
||||
|
||||
$('#jsxc_dialog .jsxc_' + (isVideoDevice ? 'remotevideo' : 'noRemoteVideo')).addClass('jsxc_deviceAvailable');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -538,7 +633,11 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
jsxc.debug('iceCon state for ' + sid, iceCon);
|
||||
jsxc.debug('sig state for ' + sid, sigState);
|
||||
|
||||
if (sigState === 'stable' && iceCon === 'connected') {
|
||||
if (sigState === 'stable' && (iceCon === 'connected' || iceCon === 'completed')) {
|
||||
|
||||
$('#jsxc_dialog .jsxc_deviceAvailable').show();
|
||||
$('#jsxc_dialog .bubblingG').hide();
|
||||
|
||||
var localSDP = sess.peerconnection.localDescription.sdp;
|
||||
var remoteSDP = sess.peerconnection.remoteDescription.sdp;
|
||||
|
||||
@@ -567,6 +666,15 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
text += '</p>';
|
||||
|
||||
$('#jsxc_dialog .jsxc_infobar').html(text);
|
||||
} else if (iceCon === 'failed') {
|
||||
jsxc.gui.window.postMessage(jsxc.jidToBid(sess.peerjid), 'sys', jsxc.translate('%%ICE connection failure%%.'));
|
||||
|
||||
$(document).off('cleanup.dialog.jsxc');
|
||||
|
||||
sess.sendTerminate('failed-transport');
|
||||
sess.terminate();
|
||||
|
||||
$(document).trigger('callterminated.jingle');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -585,8 +693,9 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
* @param jid full jid
|
||||
* @param um requested user media
|
||||
*/
|
||||
startCall: function(jid) {
|
||||
startCall: function(jid, um) {
|
||||
var self = this;
|
||||
|
||||
if (Strophe.getResourceFromJid(jid) === null) {
|
||||
@@ -600,6 +709,8 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
'finish.mediaready.jsxc': function() {
|
||||
self.setStatus('Initiate call');
|
||||
|
||||
jsxc.gui.window.postMessage(jsxc.jidToBid(jid), 'sys', jsxc.translate('%%Call started.%%'));
|
||||
|
||||
$(document).one('error.jingle', function(e, sid, error) {
|
||||
if (error.source !== 'offer') {
|
||||
return;
|
||||
@@ -618,7 +729,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
}
|
||||
});
|
||||
|
||||
this.reqUserMedia();
|
||||
self.reqUserMedia(um);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -626,10 +737,10 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
*/
|
||||
hangUp: function() {
|
||||
hangUp: function(reason, text) {
|
||||
$(document).off('cleanup.dialog.jsxc');
|
||||
|
||||
jsxc.webrtc.conn.jingle.terminate(null);
|
||||
jsxc.webrtc.conn.jingle.terminate(null, reason, text);
|
||||
$(document).trigger('callterminated.jingle');
|
||||
},
|
||||
|
||||
@@ -638,18 +749,35 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
*
|
||||
* @memberOf jsxc.webrtc
|
||||
*/
|
||||
reqUserMedia: function() {
|
||||
reqUserMedia: function(um) {
|
||||
if (this.localStream) {
|
||||
$(document).trigger('mediaready.jingle', [ this.localStream ]);
|
||||
return;
|
||||
}
|
||||
|
||||
um = um || [ 'video', 'audio' ];
|
||||
|
||||
jsxc.gui.dialog.open(jsxc.gui.template.get('allowMediaAccess'), {
|
||||
noClose: true
|
||||
});
|
||||
this.setStatus('please allow access to microphone and camera');
|
||||
|
||||
getUserMediaWithConstraints([ 'video', 'audio' ]);
|
||||
if (typeof MediaStreamTrack !== 'undefined' && typeof MediaStreamTrack.getSources !== 'undefined') {
|
||||
MediaStreamTrack.getSources(function(sourceInfo) {
|
||||
var availableDevices = sourceInfo.map(function(el) {
|
||||
|
||||
return el.kind;
|
||||
});
|
||||
|
||||
um = um.filter(function(el) {
|
||||
return availableDevices.indexOf(el) !== -1;
|
||||
});
|
||||
|
||||
getUserMediaWithConstraints(um);
|
||||
});
|
||||
} else {
|
||||
getUserMediaWithConstraints(um);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -673,7 +801,15 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
|
||||
ctx.drawImage(video[0], 0, 0);
|
||||
var img = $('<img/>');
|
||||
var url = canvas.toDataURL('image/jpeg');
|
||||
var url = null;
|
||||
|
||||
try {
|
||||
url = canvas.toDataURL('image/jpeg');
|
||||
} catch (err) {
|
||||
jsxc.warn('Error', err);
|
||||
return;
|
||||
}
|
||||
|
||||
img[0].src = url;
|
||||
var link = $('<a/>').attr({
|
||||
target: '_blank',
|
||||
@@ -731,6 +867,8 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
|
||||
if (self.remoteStream) {
|
||||
RTC.attachMediaStream(rv, self.remoteStream);
|
||||
|
||||
$('#jsxc_dialog .jsxc_' + (self.remoteStream.getVideoTracks().length > 0 ? 'remotevideo' : 'noRemoteVideo')).addClass('jsxc_deviceAvailable');
|
||||
}
|
||||
|
||||
var toggleMulti = function(elem, open) {
|
||||
@@ -747,7 +885,13 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
}
|
||||
};
|
||||
|
||||
var win = jsxc.gui.window.open(jsxc.jidToCid(jid));
|
||||
var win = jsxc.gui.window.open(jsxc.jidToBid(jid));
|
||||
|
||||
win.find('.slimScrollDiv').resizable('disable');
|
||||
win.find('.jsxc_textarea').slimScroll({
|
||||
height: 413
|
||||
});
|
||||
win.find('.jsxc_emoticons').css('top', (413 + 6) + 'px');
|
||||
|
||||
$('#jsxc_dialog .jsxc_chatarea ul').append(win.detach());
|
||||
|
||||
@@ -765,7 +909,21 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
});
|
||||
|
||||
$('#jsxc_dialog .jsxc_showchat').click(function() {
|
||||
toggleMulti($('#jsxc_dialog .jsxc_chatarea'));
|
||||
var chatarea = $('#jsxc_dialog .jsxc_chatarea');
|
||||
|
||||
if (chatarea.is(':hidden')) {
|
||||
chatarea.show();
|
||||
$('#jsxc_dialog .jsxc_webrtc').width('900');
|
||||
jsxc.gui.dialog.resize({
|
||||
width: '920px'
|
||||
});
|
||||
} else {
|
||||
chatarea.hide();
|
||||
$('#jsxc_dialog .jsxc_webrtc').width('650');
|
||||
jsxc.gui.dialog.resize({
|
||||
width: '660px'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#jsxc_dialog .jsxc_info').click(function() {
|
||||
@@ -832,7 +990,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
Remote_IP: 'Remote IP',
|
||||
Local_Fingerprint: 'Local fingerprint',
|
||||
Remote_Fingerprint: 'Remote fingerprint',
|
||||
Video_call_not_possible: 'Video call not possible',
|
||||
Video_call_not_possible: 'Video call not possible. Your buddy does not support video calls.',
|
||||
Start_video_call: 'Start video call'
|
||||
});
|
||||
|
||||
@@ -853,7 +1011,7 @@ jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
|
||||
Remote_IP: 'Remote IP',
|
||||
Local_Fingerprint: 'Lokaler Fingerprint',
|
||||
Remote_Fingerprint: 'Remote Fingerprint',
|
||||
Video_call_not_possible: 'Videoanruf nicht verfügbar',
|
||||
Video_call_not_possible: 'Videoanruf nicht verfügbar. Dein Gesprächspartner unterstützt keine Videotelefonie.',
|
||||
Start_video_call: 'Starte Videoanruf'
|
||||
});
|
||||
|
||||
|
||||
+224
-18
@@ -1,17 +1,34 @@
|
||||
.jsxc_webrtc {
|
||||
width: 900px;
|
||||
}
|
||||
|
||||
.jsxc_webrtc li .jsxc_name {
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.jsxc_webrtc li .jsxc_name:hover {
|
||||
color: #939393;
|
||||
}
|
||||
|
||||
.jsxc_videoContainer {
|
||||
width: 640px;
|
||||
height: 480px;
|
||||
position: relative;
|
||||
background-color: #a4a4a4;
|
||||
}
|
||||
|
||||
.jsxc_remotevideo {
|
||||
.jsxc_videoContainer video, .jsxc_videoContainer .jsxc_noRemoteVideo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsxc_remotevideo, .jsxc_noRemoteVideo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: 9000;
|
||||
background-color: grey;
|
||||
background-color: #a4a4a4;
|
||||
}
|
||||
|
||||
.jsxc_localvideo {
|
||||
@@ -25,6 +42,49 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo p {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left:0px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo > div {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -100px;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo > div > div {
|
||||
background-color: #717171;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo > div > div:first-child {
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -25%;
|
||||
top: 10%;
|
||||
}
|
||||
|
||||
.jsxc_noRemoteVideo > div > div:last-child {
|
||||
position: absolute;
|
||||
bottom: -50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.jsxc_webrtc .jsxc_status {
|
||||
z-index: 9999;
|
||||
border-radius: 20px;
|
||||
@@ -40,6 +100,10 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.jsxc_webrtc .slimScrollDiv {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
div:-moz-full-screen {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -84,6 +148,14 @@ div:fullscreen.jsxc_localvideo {
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.jsxc_controlbar {
|
||||
width: 640px;
|
||||
}
|
||||
|
||||
.jsxc_controlbar .jsxc_showchat {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.jsxc_multi>div {
|
||||
display: none;
|
||||
}
|
||||
@@ -115,32 +187,33 @@ div:fullscreen.jsxc_localvideo {
|
||||
|
||||
.jsxc_chatarea {
|
||||
position: relative;
|
||||
height: 270px;
|
||||
display: none;
|
||||
float:right;
|
||||
height: 480px;
|
||||
width: 250px;
|
||||
background-color: #A4A4A4;
|
||||
}
|
||||
|
||||
.jsxc_chatarea > ul {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 0px;
|
||||
width: 250px;
|
||||
height: 270px;
|
||||
height: 480px;
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px 0px 0px -100px;
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_settings {
|
||||
display: none;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_close {
|
||||
display: none;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_video {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_bar {
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
.jsxc_chatarea .jsxc_window {
|
||||
@@ -163,11 +236,144 @@ div.jsxc_video:not(.jsxc_disabled):hover, #jsxc_buddylist .jsxc_options .jsxc_vi
|
||||
background-image: url('img/camera_icon_white.svg');
|
||||
}
|
||||
|
||||
div.jsxc_video.jsxc_disabled {
|
||||
opacity: 0.5;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
#jsxc_buddylist .jsxc_options .jsxc_video.jsxc_disabled {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
.bubblingG {
|
||||
text-align: center;
|
||||
width:129px;
|
||||
height:80px;
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
margin-left: -64px;
|
||||
}
|
||||
|
||||
.bubblingG span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 40px auto;
|
||||
background: #000000;
|
||||
-moz-border-radius: 81px;
|
||||
-moz-animation: bubblingG 1.3s infinite alternate;
|
||||
-webkit-border-radius: 81px;
|
||||
-webkit-animation: bubblingG 1.3s infinite alternate;
|
||||
-ms-border-radius: 81px;
|
||||
-ms-animation: bubblingG 1.3s infinite alternate;
|
||||
-o-border-radius: 81px;
|
||||
-o-animation: bubblingG 1.3s infinite alternate;
|
||||
border-radius: 81px;
|
||||
animation: bubblingG 1.3s infinite alternate;
|
||||
}
|
||||
|
||||
#bubblingG_1 {
|
||||
-moz-animation-delay: 0s;
|
||||
-webkit-animation-delay: 0s;
|
||||
-ms-animation-delay: 0s;
|
||||
-o-animation-delay: 0s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
#bubblingG_2 {
|
||||
-moz-animation-delay: 0.39s;
|
||||
-webkit-animation-delay: 0.39s;
|
||||
-ms-animation-delay: 0.39s;
|
||||
-o-animation-delay: 0.39s;
|
||||
animation-delay: 0.39s;
|
||||
}
|
||||
|
||||
#bubblingG_3 {
|
||||
-moz-animation-delay: 0.78s;
|
||||
-webkit-animation-delay: 0.78s;
|
||||
-ms-animation-delay: 0.78s;
|
||||
-o-animation-delay: 0.78s;
|
||||
animation-delay: 0.78s;
|
||||
}
|
||||
|
||||
@-moz-keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
-moz-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
-moz-transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@-webkit-keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
-webkit-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
-webkit-transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@-ms-keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
-ms-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
-ms-transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@-o-keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
-o-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
-o-transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@keyframes bubblingG {
|
||||
0% {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color:#000000;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
background-color:#FFFFFF;
|
||||
transform: translateY(-34px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+186
-73
@@ -2,35 +2,81 @@
|
||||
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
||||
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
|
||||
*
|
||||
* Version: 1.0.0
|
||||
*
|
||||
* Version: 1.3.3 + pr#94
|
||||
*
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
jQuery.fn.extend({
|
||||
$.fn.extend({
|
||||
slimScroll: function(options) {
|
||||
|
||||
var defaults = {
|
||||
wheelStep : 20,
|
||||
|
||||
// width in pixels of the visible scroll area
|
||||
width : 'auto',
|
||||
|
||||
// height in pixels of the visible scroll area
|
||||
height : '250px',
|
||||
|
||||
// width in pixels of the scrollbar and rail
|
||||
size : '7px',
|
||||
|
||||
// scrollbar color, accepts any hex/color value
|
||||
color: '#000',
|
||||
|
||||
// scrollbar position - left/right
|
||||
position : 'right',
|
||||
|
||||
// distance in pixels between the side edge and the scrollbar
|
||||
distance : '1px',
|
||||
|
||||
// default scroll position on load - top / bottom / $('selector')
|
||||
start : 'top',
|
||||
|
||||
// sets scrollbar opacity
|
||||
opacity : .4,
|
||||
|
||||
// enables always-on mode for the scrollbar
|
||||
alwaysVisible : false,
|
||||
disableFadeOut: false,
|
||||
|
||||
// check if we should hide the scrollbar when user is hovering over
|
||||
disableFadeOut : false,
|
||||
|
||||
// sets visibility of the rail
|
||||
railVisible : false,
|
||||
|
||||
// sets rail color
|
||||
railColor : '#333',
|
||||
railOpacity : '0.2',
|
||||
|
||||
// sets rail opacity
|
||||
railOpacity : .2,
|
||||
|
||||
// whether we should use jQuery UI Draggable to enable bar dragging
|
||||
railDraggable : true,
|
||||
|
||||
// defautlt CSS class of the slimscroll rail
|
||||
railClass : 'slimScrollRail',
|
||||
|
||||
// defautlt CSS class of the slimscroll bar
|
||||
barClass : 'slimScrollBar',
|
||||
|
||||
// defautlt CSS class of the slimscroll wrapper
|
||||
wrapperClass : 'slimScrollDiv',
|
||||
|
||||
// check if mousewheel should scroll the window if we reach top/bottom
|
||||
allowPageScroll : false,
|
||||
scroll : 0,
|
||||
touchScrollStep : 200
|
||||
|
||||
// scroll amount applied to each mouse wheel step
|
||||
wheelStep : 20,
|
||||
|
||||
// scroll amount applied when user is using gestures
|
||||
touchScrollStep : 200,
|
||||
|
||||
// sets border radius
|
||||
borderRadius: '7px',
|
||||
|
||||
// sets border radius of the rail
|
||||
railBorderRadius : '7px'
|
||||
};
|
||||
|
||||
var o = $.extend(defaults, options);
|
||||
@@ -38,7 +84,7 @@
|
||||
// do it for every element that matches selector
|
||||
this.each(function(){
|
||||
|
||||
var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
|
||||
var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
|
||||
barHeight, percentScroll, lastScroll,
|
||||
divS = '<div></div>',
|
||||
minBarHeight = 30,
|
||||
@@ -48,20 +94,33 @@
|
||||
var me = $(this);
|
||||
|
||||
// ensure we are not binding it again
|
||||
if (me.parent().hasClass('slimScrollDiv'))
|
||||
{
|
||||
if (me.parent().hasClass(o.wrapperClass))
|
||||
{
|
||||
// start from last bar position
|
||||
var offset = me.scrollTop();
|
||||
|
||||
// find bar and rail
|
||||
bar = me.parent().find('.slimScrollBar');
|
||||
rail = me.parent().find('.slimScrollRail');
|
||||
|
||||
bar = me.parent().find('.' + o.barClass);
|
||||
rail = me.parent().find('.' + o.railClass);
|
||||
|
||||
getBarHeight();
|
||||
|
||||
// check if we should scroll existing instance
|
||||
if (options)
|
||||
if ($.isPlainObject(options))
|
||||
{
|
||||
// Pass height: auto to an existing slimscroll object to force a resize after contents have changed
|
||||
if ( 'height' in options && options.height == 'auto' ) {
|
||||
me.parent().css('height', 'auto');
|
||||
me.css('height', 'auto');
|
||||
var height = me.parent().parent().height();
|
||||
me.parent().css('height', height);
|
||||
me.css('height', height);
|
||||
} else if ('height' in options) {
|
||||
var h = options.height;
|
||||
me.parent().css('height', h);
|
||||
me.css('height', h);
|
||||
}
|
||||
|
||||
if ('scrollTo' in options)
|
||||
{
|
||||
// jump to a static point
|
||||
@@ -72,6 +131,14 @@
|
||||
// jump by value pixels
|
||||
offset += parseInt(o.scrollBy);
|
||||
}
|
||||
else if ('destroy' in options)
|
||||
{
|
||||
// remove slimscroll elements
|
||||
bar.remove();
|
||||
rail.remove();
|
||||
me.unwrap();
|
||||
return;
|
||||
}
|
||||
|
||||
// scroll content by the given offset
|
||||
scrollContent(offset, false, true);
|
||||
@@ -79,9 +146,16 @@
|
||||
|
||||
return;
|
||||
}
|
||||
else if ($.isPlainObject(options))
|
||||
{
|
||||
if ('destroy' in options)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// optionally set height to the parent's height
|
||||
o.height = (o.height == 'auto') ? me.parent().innerHeight() : o.height;
|
||||
o.height = (o.height == 'auto') ? me.parent().height() : o.height;
|
||||
|
||||
// wrap content
|
||||
var wrapper = $(divS)
|
||||
@@ -101,7 +175,7 @@
|
||||
});
|
||||
|
||||
// create scrollbar rail
|
||||
var rail = $(divS)
|
||||
var rail = $(divS)
|
||||
.addClass(o.railClass)
|
||||
.css({
|
||||
width: o.size,
|
||||
@@ -109,7 +183,7 @@
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none',
|
||||
'border-radius': o.size,
|
||||
'border-radius': o.railBorderRadius,
|
||||
background: o.railColor,
|
||||
opacity: o.railOpacity,
|
||||
zIndex: 90
|
||||
@@ -125,10 +199,10 @@
|
||||
top: 0,
|
||||
opacity: o.opacity,
|
||||
display: o.alwaysVisible ? 'block' : 'none',
|
||||
'border-radius' : o.size,
|
||||
BorderRadius: o.size,
|
||||
MozBorderRadius: o.size,
|
||||
WebkitBorderRadius: o.size,
|
||||
'border-radius' : o.borderRadius,
|
||||
BorderRadius: o.borderRadius,
|
||||
MozBorderRadius: o.borderRadius,
|
||||
WebkitBorderRadius: o.borderRadius,
|
||||
zIndex: 99
|
||||
});
|
||||
|
||||
@@ -144,18 +218,31 @@
|
||||
me.parent().append(bar);
|
||||
me.parent().append(rail);
|
||||
|
||||
// make it draggable
|
||||
bar.draggable({
|
||||
axis: 'y',
|
||||
containment: 'parent',
|
||||
start: function() { isDragg = true; },
|
||||
stop: function() { isDragg = false; hideBar(); },
|
||||
drag: function(e)
|
||||
{
|
||||
// scroll content
|
||||
scrollContent(0, $(this).position().top, false);
|
||||
}
|
||||
});
|
||||
// make it draggable and no longer dependent on the jqueryUI
|
||||
if (o.railDraggable){
|
||||
bar.bind("mousedown", function(e) {
|
||||
var $doc = $(document);
|
||||
isDragg = true;
|
||||
t = parseFloat(bar.css('top'));
|
||||
pageY = e.pageY;
|
||||
|
||||
$doc.bind("mousemove.slimscroll", function(e){
|
||||
currTop = t + e.pageY - pageY;
|
||||
bar.css('top', currTop);
|
||||
scrollContent(0, bar.position().top, false);// scroll content
|
||||
});
|
||||
|
||||
$doc.bind("mouseup.slimscroll", function(e) {
|
||||
isDragg = false;hideBar();
|
||||
$doc.unbind('.slimscroll');
|
||||
});
|
||||
return false;
|
||||
}).bind("selectstart.slimscroll", function(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// on rail over
|
||||
rail.hover(function(){
|
||||
@@ -191,18 +278,44 @@
|
||||
});
|
||||
|
||||
me.bind('touchmove', function(e){
|
||||
// prevent scrolling the page
|
||||
e.originalEvent.preventDefault();
|
||||
// prevent scrolling the page if necessary
|
||||
if(!releaseScroll)
|
||||
{
|
||||
e.originalEvent.preventDefault();
|
||||
}
|
||||
if (e.originalEvent.touches.length)
|
||||
{
|
||||
// see how far user swiped
|
||||
var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep;
|
||||
// scroll content
|
||||
scrollContent(diff, true);
|
||||
touchDif = e.originalEvent.touches[0].pageY;
|
||||
}
|
||||
});
|
||||
|
||||
var _onWheel = function(e)
|
||||
// set up initial height
|
||||
getBarHeight();
|
||||
|
||||
// check start position
|
||||
if (o.start === 'bottom')
|
||||
{
|
||||
// scroll content to bottom
|
||||
bar.css({ top: me.outerHeight() - bar.outerHeight() });
|
||||
scrollContent(0, true);
|
||||
}
|
||||
else if (o.start !== 'top')
|
||||
{
|
||||
// assume jQuery selector
|
||||
scrollContent($(o.start).position().top, null, true);
|
||||
|
||||
// make sure bar stays hidden
|
||||
if (!o.alwaysVisible) { bar.hide(); }
|
||||
}
|
||||
|
||||
// attach scroll events
|
||||
attachWheel();
|
||||
|
||||
function _onWheel(e)
|
||||
{
|
||||
// use mouse wheel only when mouse is over
|
||||
if (!isOverPanel) { return; }
|
||||
@@ -213,8 +326,11 @@
|
||||
if (e.wheelDelta) { delta = -e.wheelDelta/120; }
|
||||
if (e.detail) { delta = e.detail / 3; }
|
||||
|
||||
// scroll content
|
||||
scrollContent(delta, true);
|
||||
var target = e.target || e.srcTarget || e.srcElement;
|
||||
if ($(target).closest('.' + o.wrapperClass).is(me.parent())) {
|
||||
// scroll content
|
||||
scrollContent(delta, true);
|
||||
}
|
||||
|
||||
// stop window scroll
|
||||
if (e.preventDefault && !releaseScroll) { e.preventDefault(); }
|
||||
@@ -223,16 +339,24 @@
|
||||
|
||||
function scrollContent(y, isWheel, isJump)
|
||||
{
|
||||
releaseScroll = false;
|
||||
var delta = y;
|
||||
var maxTop = me.outerHeight() - bar.outerHeight();
|
||||
|
||||
|
||||
if (isWheel)
|
||||
{
|
||||
// move bar with mouse wheel
|
||||
delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();
|
||||
|
||||
// move bar, make sure it doesn't go out
|
||||
// move bar, make sure it doesn't go out
|
||||
delta = Math.min(Math.max(delta, 0), maxTop);
|
||||
|
||||
// if scrolling down, make sure a fractional change to the
|
||||
// scroll position isn't rounded away when the scrollbar's CSS is set
|
||||
// this flooring of delta would happened automatically when
|
||||
// bar.css is set below, but we floor here for clarity
|
||||
delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);
|
||||
|
||||
// scroll the scrollbar
|
||||
bar.css({ top: delta + 'px' });
|
||||
}
|
||||
@@ -245,7 +369,6 @@
|
||||
{
|
||||
delta = y;
|
||||
var offsetTop = delta / me[0].scrollHeight * me.outerHeight();
|
||||
|
||||
offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);
|
||||
bar.css({ top: offsetTop + 'px' });
|
||||
}
|
||||
@@ -253,6 +376,9 @@
|
||||
// scroll content
|
||||
me.scrollTop(delta);
|
||||
|
||||
// fire scrolling event
|
||||
me.trigger('slimscrolling', ~~delta);
|
||||
|
||||
// ensure bar is visible
|
||||
showBar();
|
||||
|
||||
@@ -260,31 +386,29 @@
|
||||
hideBar();
|
||||
}
|
||||
|
||||
var attachWheel = function()
|
||||
function attachWheel()
|
||||
{
|
||||
if (window.addEventListener)
|
||||
{
|
||||
this.addEventListener('DOMMouseScroll', _onWheel, false );
|
||||
this.addEventListener('mousewheel', _onWheel, false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
document.attachEvent("onmousewheel", _onWheel)
|
||||
}
|
||||
}
|
||||
|
||||
// attach scroll events
|
||||
attachWheel();
|
||||
|
||||
function getBarHeight()
|
||||
{
|
||||
// calculate scrollbar height and make sure it is not too small
|
||||
barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight);
|
||||
bar.css({ height: barHeight + 'px' });
|
||||
}
|
||||
|
||||
// set up initial height
|
||||
getBarHeight();
|
||||
// hide scrollbar if content is not long enough
|
||||
var display = barHeight == me.outerHeight() ? 'none' : 'block';
|
||||
bar.css({ display: display });
|
||||
}
|
||||
|
||||
function showBar()
|
||||
{
|
||||
@@ -293,18 +417,22 @@
|
||||
clearTimeout(queueHide);
|
||||
|
||||
// when bar reached top or bottom
|
||||
if (percentScroll == ~~ percentScroll)
|
||||
if (percentScroll == ~~percentScroll)
|
||||
{
|
||||
//release wheel
|
||||
//release wheel
|
||||
releaseScroll = o.allowPageScroll;
|
||||
|
||||
|
||||
// publish approporiate event
|
||||
if (lastScroll != percentScroll)
|
||||
{
|
||||
var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
|
||||
var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
|
||||
me.trigger('slimscroll', msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
releaseScroll = false;
|
||||
}
|
||||
lastScroll = percentScroll;
|
||||
|
||||
// show only when required
|
||||
@@ -324,7 +452,7 @@
|
||||
{
|
||||
queueHide = setTimeout(function(){
|
||||
if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg)
|
||||
{
|
||||
{
|
||||
bar.fadeOut('slow');
|
||||
rail.fadeOut('slow');
|
||||
}
|
||||
@@ -332,30 +460,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
// check start position
|
||||
if (o.start == 'bottom')
|
||||
{
|
||||
// scroll content to bottom
|
||||
bar.css({ top: me.outerHeight() - bar.outerHeight() });
|
||||
scrollContent(0, true);
|
||||
}
|
||||
else if (typeof o.start == 'object')
|
||||
{
|
||||
// scroll content
|
||||
scrollContent($(o.start).position().top, null, true);
|
||||
|
||||
// make sure bar stays hidden
|
||||
if (!o.alwaysVisible) { bar.hide(); }
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// maintain chainability
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.fn.extend({
|
||||
slimscroll: jQuery.fn.slimScroll
|
||||
$.fn.extend({
|
||||
slimscroll: $.fn.slimScroll
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
+1
-1
Submodule lib/otr updated: 7650bb3f50...1b34e35691
@@ -7,6 +7,8 @@
|
||||
*
|
||||
* Authors: - Michael Weibel <michael.weibel@gmail.com> - Klaus Herberth <klaus@jsxc.org>
|
||||
* Copyright: - Michael Weibel <michael.weibel@gmail.com>
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
+1
-1
Submodule lib/strophe.jingle updated: 0c1544d6d7...af28b2bf51
+7
-6
@@ -3,9 +3,10 @@
|
||||
* Klaus Herberth, 2014
|
||||
*/
|
||||
|
||||
// This code was written by Tyler Akins and has been placed in the
|
||||
// public domain. It would be nice if you left this header intact.
|
||||
// Base64 code from Tyler Akins -- http://rumkin.com
|
||||
/*! This code was written by Tyler Akins and has been placed in the
|
||||
public domain. It would be nice if you left this header intact.
|
||||
Base64 code from Tyler Akins -- http://rumkin.com
|
||||
*/
|
||||
|
||||
var Base64 = (function () {
|
||||
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
@@ -84,7 +85,7 @@ var Base64 = (function () {
|
||||
return obj;
|
||||
})();
|
||||
|
||||
/*
|
||||
/*!
|
||||
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
|
||||
* in FIPS PUB 180-1
|
||||
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
|
||||
@@ -261,7 +262,7 @@ function binb2b64(binarray)
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
/*!
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* Digest Algorithm, as defined in RFC 1321.
|
||||
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
|
||||
@@ -469,7 +470,7 @@ var MD5 = (function () {
|
||||
return obj;
|
||||
})();
|
||||
|
||||
/*
|
||||
/*!
|
||||
This program is distributed under the terms of the MIT license.
|
||||
Please see the LICENSE file for details.
|
||||
|
||||
|
||||
+5
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsxc",
|
||||
"version": "0.8.2",
|
||||
"version": "1.0.0-beta2",
|
||||
"description": "Real-time chat app",
|
||||
"homepage": "http://www.jsxc.org/",
|
||||
"bugs": "https://github.com/sualko/jsxc/issues",
|
||||
@@ -15,9 +15,13 @@
|
||||
"grunt-banner": "~0.2.2",
|
||||
"grunt-cli": "~0.1.13",
|
||||
"grunt-contrib-clean": "~0.5.0",
|
||||
"grunt-contrib-compress": "^0.10.0",
|
||||
"grunt-contrib-concat": "^0.5.0",
|
||||
"grunt-contrib-copy": "~0.5.0",
|
||||
"grunt-contrib-jshint": "~0.9.2",
|
||||
"grunt-contrib-uglify": "^0.6.0",
|
||||
"grunt-search": "^0.1.6",
|
||||
"grunt-shell": "^1.1.1",
|
||||
"grunt-text-replace": "~0.3.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
grunt commit
|
||||
Referência em uma Nova Issue
Bloquear um usuário