Merge branch 'master' into webpack
This commit is contained in:
commit
f7c3351e2b
|
@ -10,6 +10,7 @@
|
|||
- #968 Use nickname from VCard when joining a room
|
||||
- #1091 There's now only one CSS file for all view modes.
|
||||
- #1094 Show room members who aren't currently online
|
||||
- #1106 Support for Roster Versioning
|
||||
- It's now also possible to edit your VCard via the UI
|
||||
- Automatically grow/shrink input as text is entered/removed
|
||||
- MP4 and MP3 files when sent as XEP-0066 Out of Band Data, are now playable directly in chat
|
||||
|
|
210
bootstrap.py
210
bootstrap.py
|
@ -1,210 +0,0 @@
|
|||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2006 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
##############################################################################
|
||||
"""Bootstrap a buildout-based project
|
||||
|
||||
Simply run this script in a directory containing a buildout.cfg.
|
||||
The script accepts buildout command-line options, so you can
|
||||
use the -c option to specify an alternate configuration file.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
__version__ = '2015-07-01'
|
||||
# See zc.buildout's changelog if this version is up to date.
|
||||
|
||||
tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
|
||||
|
||||
usage = '''\
|
||||
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
|
||||
|
||||
Bootstraps a buildout-based project.
|
||||
|
||||
Simply run this script in a directory containing a buildout.cfg, using the
|
||||
Python that you want bin/buildout to use.
|
||||
|
||||
Note that by using --find-links to point to local resources, you can keep
|
||||
this script from going over the network.
|
||||
'''
|
||||
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("--version",
|
||||
action="store_true", default=False,
|
||||
help=("Return bootstrap.py version."))
|
||||
parser.add_option("-t", "--accept-buildout-test-releases",
|
||||
dest='accept_buildout_test_releases',
|
||||
action="store_true", default=False,
|
||||
help=("Normally, if you do not specify a --version, the "
|
||||
"bootstrap script and buildout gets the newest "
|
||||
"*final* versions of zc.buildout and its recipes and "
|
||||
"extensions for you. If you use this flag, "
|
||||
"bootstrap and buildout will get the newest releases "
|
||||
"even if they are alphas or betas."))
|
||||
parser.add_option("-c", "--config-file",
|
||||
help=("Specify the path to the buildout configuration "
|
||||
"file to be used."))
|
||||
parser.add_option("-f", "--find-links",
|
||||
help=("Specify a URL to search for buildout releases"))
|
||||
parser.add_option("--allow-site-packages",
|
||||
action="store_true", default=False,
|
||||
help=("Let bootstrap.py use existing site packages"))
|
||||
parser.add_option("--buildout-version",
|
||||
help="Use a specific zc.buildout version")
|
||||
parser.add_option("--setuptools-version",
|
||||
help="Use a specific setuptools version")
|
||||
parser.add_option("--setuptools-to-dir",
|
||||
help=("Allow for re-use of existing directory of "
|
||||
"setuptools versions"))
|
||||
|
||||
options, args = parser.parse_args()
|
||||
if options.version:
|
||||
print("bootstrap.py version %s" % __version__)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
######################################################################
|
||||
# load/install setuptools
|
||||
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib2 import urlopen
|
||||
|
||||
ez = {}
|
||||
if os.path.exists('ez_setup.py'):
|
||||
exec(open('ez_setup.py').read(), ez)
|
||||
else:
|
||||
exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
|
||||
|
||||
if not options.allow_site_packages:
|
||||
# ez_setup imports site, which adds site packages
|
||||
# this will remove them from the path to ensure that incompatible versions
|
||||
# of setuptools are not in the path
|
||||
import site
|
||||
# inside a virtualenv, there is no 'getsitepackages'.
|
||||
# We can't remove these reliably
|
||||
if hasattr(site, 'getsitepackages'):
|
||||
for sitepackage_path in site.getsitepackages():
|
||||
# Strip all site-packages directories from sys.path that
|
||||
# are not sys.prefix; this is because on Windows
|
||||
# sys.prefix is a site-package directory.
|
||||
if sitepackage_path != sys.prefix:
|
||||
sys.path[:] = [x for x in sys.path
|
||||
if sitepackage_path not in x]
|
||||
|
||||
setup_args = dict(to_dir=tmpeggs, download_delay=0)
|
||||
|
||||
if options.setuptools_version is not None:
|
||||
setup_args['version'] = options.setuptools_version
|
||||
if options.setuptools_to_dir is not None:
|
||||
setup_args['to_dir'] = options.setuptools_to_dir
|
||||
|
||||
ez['use_setuptools'](**setup_args)
|
||||
import setuptools
|
||||
import pkg_resources
|
||||
|
||||
# This does not (always?) update the default working set. We will
|
||||
# do it.
|
||||
for path in sys.path:
|
||||
if path not in pkg_resources.working_set.entries:
|
||||
pkg_resources.working_set.add_entry(path)
|
||||
|
||||
######################################################################
|
||||
# Install buildout
|
||||
|
||||
ws = pkg_resources.working_set
|
||||
|
||||
setuptools_path = ws.find(
|
||||
pkg_resources.Requirement.parse('setuptools')).location
|
||||
|
||||
# Fix sys.path here as easy_install.pth added before PYTHONPATH
|
||||
cmd = [sys.executable, '-c',
|
||||
'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
|
||||
'from setuptools.command.easy_install import main; main()',
|
||||
'-mZqNxd', tmpeggs]
|
||||
|
||||
find_links = os.environ.get(
|
||||
'bootstrap-testing-find-links',
|
||||
options.find_links or
|
||||
('http://downloads.buildout.org/'
|
||||
if options.accept_buildout_test_releases else None)
|
||||
)
|
||||
if find_links:
|
||||
cmd.extend(['-f', find_links])
|
||||
|
||||
requirement = 'zc.buildout'
|
||||
version = options.buildout_version
|
||||
if version is None and not options.accept_buildout_test_releases:
|
||||
# Figure out the most recent final version of zc.buildout.
|
||||
import setuptools.package_index
|
||||
_final_parts = '*final-', '*final'
|
||||
|
||||
def _final_version(parsed_version):
|
||||
try:
|
||||
return not parsed_version.is_prerelease
|
||||
except AttributeError:
|
||||
# Older setuptools
|
||||
for part in parsed_version:
|
||||
if (part[:1] == '*') and (part not in _final_parts):
|
||||
return False
|
||||
return True
|
||||
|
||||
index = setuptools.package_index.PackageIndex(
|
||||
search_path=[setuptools_path])
|
||||
if find_links:
|
||||
index.add_find_links((find_links,))
|
||||
req = pkg_resources.Requirement.parse(requirement)
|
||||
if index.obtain(req) is not None:
|
||||
best = []
|
||||
bestv = None
|
||||
for dist in index[req.project_name]:
|
||||
distv = dist.parsed_version
|
||||
if _final_version(distv):
|
||||
if bestv is None or distv > bestv:
|
||||
best = [dist]
|
||||
bestv = distv
|
||||
elif distv == bestv:
|
||||
best.append(dist)
|
||||
if best:
|
||||
best.sort()
|
||||
version = best[-1].version
|
||||
if version:
|
||||
requirement = '=='.join((requirement, version))
|
||||
cmd.append(requirement)
|
||||
|
||||
import subprocess
|
||||
if subprocess.call(cmd) != 0:
|
||||
raise Exception(
|
||||
"Failed to execute command:\n%s" % repr(cmd)[1:-1])
|
||||
|
||||
######################################################################
|
||||
# Import and run buildout
|
||||
|
||||
ws.add_entry(tmpeggs)
|
||||
ws.require(requirement)
|
||||
import zc.buildout.buildout
|
||||
|
||||
if not [a for a in args if '=' not in a]:
|
||||
args.append('bootstrap')
|
||||
|
||||
# if -c was provided, we push it back into args for buildout' main function
|
||||
if options.config_file is not None:
|
||||
args[0:0] = ['-c', options.config_file]
|
||||
|
||||
zc.buildout.buildout.main(args)
|
||||
shutil.rmtree(tmpeggs)
|
10
buildout.cfg
10
buildout.cfg
|
@ -11,12 +11,4 @@ eggs =
|
|||
sphinx-bootstrap-theme
|
||||
|
||||
[versions]
|
||||
docutils = 0.13.1
|
||||
Jinja2 = 2.9.5
|
||||
MarkupSafe = 0.23
|
||||
Pygments = 2.2.0
|
||||
six = 1.10.0
|
||||
setuptools = 28.6.1
|
||||
Sphinx = 1.5.2
|
||||
z3c.recipe.egg = 2.0.3
|
||||
zc.buildout = 2.5.3
|
||||
Sphinx = 1.7.5
|
||||
|
|
221
css/converse.css
221
css/converse.css
|
@ -6870,9 +6870,11 @@ body.reset {
|
|||
z-index: 1031; }
|
||||
#conversejs.converse-overlayed > .row {
|
||||
flex-direction: row-reverse; }
|
||||
#conversejs.converse-fullscreen .converse-chatboxes {
|
||||
#conversejs.converse-fullscreen .converse-chatboxes, #conversejs.converse-mobile .converse-chatboxes {
|
||||
width: 100vw;
|
||||
right: 15px; }
|
||||
#conversejs.converse-overlayed {
|
||||
height: 3em; }
|
||||
#conversejs .brand-heading {
|
||||
font-family: "Century Gothic", futura, "URW Gothic L", Verdana, sans-serif; }
|
||||
#conversejs .brand-heading .icon-conversejs {
|
||||
|
@ -6883,7 +6885,6 @@ body.reset {
|
|||
z-index: 1031;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
height: 3em;
|
||||
right: 0; }
|
||||
#conversejs ::-webkit-input-placeholder {
|
||||
/* Chrome/Opera/Safari */
|
||||
|
@ -7285,6 +7286,8 @@ body.reset {
|
|||
#conversejs #user-profile-modal label {
|
||||
font-weight: bold; }
|
||||
|
||||
#conversejs .chatbox-navback {
|
||||
display: none; }
|
||||
#conversejs .flyout {
|
||||
border-radius: 4px;
|
||||
position: absolute; }
|
||||
|
@ -7324,15 +7327,10 @@ body.reset {
|
|||
height: 36px;
|
||||
width: 36px;
|
||||
margin-right: 0.5em; }
|
||||
#conversejs .chat-head .chatbox-title .chatroom-description {
|
||||
font-size: 80%; }
|
||||
#conversejs .chat-head .chatbox-buttons {
|
||||
flex-direction: row-reverse;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 1px;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
flex: 0 0 33.3333333333%;
|
||||
max-width: 33.3333333333%;
|
||||
padding: 0; }
|
||||
#conversejs .chat-head .user-custom-message {
|
||||
color: white;
|
||||
|
@ -7629,6 +7627,14 @@ body.reset {
|
|||
#conversejs.converse-overlayed .chat-head {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; } }
|
||||
#conversejs.converse-embedded .chat-head .chatbox-title,
|
||||
#conversejs.converse-overlayed .chat-head .chatbox-title {
|
||||
flex: 0 0 66.6666666667%;
|
||||
max-width: 66.6666666667%; }
|
||||
#conversejs.converse-embedded .chat-head .chatbox-buttons,
|
||||
#conversejs.converse-overlayed .chat-head .chatbox-buttons {
|
||||
flex: 0 0 33.3333333333%;
|
||||
max-width: 33.3333333333%; }
|
||||
#conversejs.converse-embedded .chatbox,
|
||||
#conversejs.converse-overlayed .chatbox {
|
||||
min-width: 250px !important;
|
||||
|
@ -7689,13 +7695,16 @@ body.reset {
|
|||
height: 62px;
|
||||
font-size: 20px;
|
||||
padding: 0; }
|
||||
#conversejs.converse-fullscreen .chat-head .chatbox-buttons {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%; }
|
||||
#conversejs.converse-fullscreen .chat-head .user-custom-message {
|
||||
font-size: 50%;
|
||||
height: auto;
|
||||
line-height: 16px; }
|
||||
#conversejs.converse-fullscreen .chat-head .chatbox-title {
|
||||
flex: 0 0 83.3333333333%;
|
||||
max-width: 83.3333333333%; }
|
||||
#conversejs.converse-fullscreen .chat-head .chatbox-buttons {
|
||||
flex: 0 0 16.6666666667%;
|
||||
max-width: 16.6666666667%; }
|
||||
#conversejs.converse-fullscreen .chat-textarea {
|
||||
max-height: 400px; }
|
||||
#conversejs.converse-fullscreen .emoji-picker {
|
||||
|
@ -7751,23 +7760,43 @@ body.reset {
|
|||
padding-left: 10px;
|
||||
padding-right: 10px; }
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
@media (max-width: 767.98px) {
|
||||
#conversejs:not(.converse-embedded) > .row {
|
||||
flex-direction: row-reverse; }
|
||||
#conversejs:not(.converse-embedded) #converse-login-panel .converse-form {
|
||||
padding: 3em 2em 3em; }
|
||||
#conversejs:not(.converse-embedded) .sidebar {
|
||||
display: block; }
|
||||
#conversejs:not(.converse-embedded) .chatbox {
|
||||
width: calc(100% - 50px); }
|
||||
#conversejs:not(.converse-embedded) .chatbox .row .box-flyout {
|
||||
left: 50px;
|
||||
bottom: 0;
|
||||
height: 100vh;
|
||||
box-shadow: none; } }
|
||||
@media screen and (max-width: 767px) {
|
||||
#conversejs:not(.converse-embedded).converse-fullscreen .chatbox {
|
||||
width: calc(100% - 50px); } }
|
||||
box-shadow: none; }
|
||||
|
||||
#conversejs.converse-mobile .chatbox .box-flyout .chatbox-navback,
|
||||
#conversejs.converse-overlayed .chatbox .box-flyout .chatbox-navback,
|
||||
#conversejs.converse-embedded .chatbox .box-flyout .chatbox-navback,
|
||||
#conversejs.converse-fullscreen .chatbox .box-flyout .chatbox-navback {
|
||||
display: flex;
|
||||
flex: 0 0 16.6666666667%;
|
||||
max-width: 16.6666666667%; }
|
||||
#conversejs.converse-mobile .chatbox .box-flyout .chatbox-navback .fa-arrow-left:before,
|
||||
#conversejs.converse-overlayed .chatbox .box-flyout .chatbox-navback .fa-arrow-left:before,
|
||||
#conversejs.converse-embedded .chatbox .box-flyout .chatbox-navback .fa-arrow-left:before,
|
||||
#conversejs.converse-fullscreen .chatbox .box-flyout .chatbox-navback .fa-arrow-left:before {
|
||||
color: white; }
|
||||
#conversejs.converse-mobile .chatbox .box-flyout .chatbox-title,
|
||||
#conversejs.converse-overlayed .chatbox .box-flyout .chatbox-title,
|
||||
#conversejs.converse-embedded .chatbox .box-flyout .chatbox-title,
|
||||
#conversejs.converse-fullscreen .chatbox .box-flyout .chatbox-title {
|
||||
flex: 0 0 58.3333333333%;
|
||||
max-width: 58.3333333333%; }
|
||||
#conversejs.converse-mobile .chatbox .box-flyout .chatbox-buttons,
|
||||
#conversejs.converse-overlayed .chatbox .box-flyout .chatbox-buttons,
|
||||
#conversejs.converse-embedded .chatbox .box-flyout .chatbox-buttons,
|
||||
#conversejs.converse-fullscreen .chatbox .box-flyout .chatbox-buttons {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%; } }
|
||||
#conversejs .set-xmpp-status .fa-circle, #conversejs .xmpp-status .fa-circle, #conversejs .roster-contacts .fa-circle {
|
||||
color: #3AA569; }
|
||||
#conversejs .set-xmpp-status .fa-minus-circle, #conversejs .xmpp-status .fa-minus-circle, #conversejs .roster-contacts .fa-minus-circle {
|
||||
|
@ -8006,7 +8035,6 @@ body.reset {
|
|||
#conversejs:not(.converse-embedded) .converse-chatboxes .converse-chatroom {
|
||||
font-size: 14px; }
|
||||
#conversejs:not(.converse-embedded) .converse-chatboxes .chatbox .box-flyout {
|
||||
top: -100vh;
|
||||
margin-left: 15px;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
|
@ -8024,21 +8052,21 @@ body.reset {
|
|||
display: none; }
|
||||
#conversejs:not(.converse-embedded) .converse-chatboxes.sidebar-open #controlbox .controlbox-pane {
|
||||
display: block; } }
|
||||
#conversejs:not(.converse-fullscreen) #controlbox {
|
||||
#conversejs.converse-overlayed #controlbox {
|
||||
order: -1;
|
||||
min-width: 250px !important;
|
||||
width: 250px; }
|
||||
#conversejs:not(.converse-fullscreen) #controlbox .box-flyout {
|
||||
#conversejs.converse-overlayed #controlbox .box-flyout {
|
||||
min-width: 250px !important;
|
||||
width: 250px; }
|
||||
#conversejs:not(.converse-fullscreen) #controlbox:not(.logged-out) .controlbox-head {
|
||||
#conversejs.converse-overlayed #controlbox:not(.logged-out) .controlbox-head {
|
||||
height: 15px; }
|
||||
#conversejs:not(.converse-fullscreen) #controlbox .controlbox-head {
|
||||
#conversejs.converse-overlayed #controlbox .controlbox-head {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between; }
|
||||
#conversejs:not(.converse-fullscreen) #controlbox .controlbox-head .brand-heading {
|
||||
#conversejs.converse-overlayed #controlbox .controlbox-head .brand-heading {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 1px;
|
||||
|
@ -8048,19 +8076,20 @@ body.reset {
|
|||
max-width: 66.6666666667%;
|
||||
color: #666;
|
||||
font-size: 2em; }
|
||||
#conversejs:not(.converse-fullscreen) #controlbox .controlbox-head .chatbox-btn {
|
||||
#conversejs.converse-overlayed #controlbox .controlbox-head .chatbox-btn {
|
||||
color: #578EA9;
|
||||
margin: 0; }
|
||||
#conversejs:not(.converse-fullscreen) #controlbox #converse-register, #conversejs:not(.converse-fullscreen) #controlbox #converse-login {
|
||||
#conversejs.converse-overlayed #controlbox #converse-register, #conversejs.converse-overlayed #controlbox #converse-login {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
padding-bottom: 0; }
|
||||
#conversejs:not(.converse-fullscreen) #controlbox #converse-register .button-cancel {
|
||||
#conversejs.converse-overlayed #controlbox #converse-register .button-cancel {
|
||||
font-size: 90%; }
|
||||
#conversejs:not(.converse-fullscreen) #controlbox .controlbox-panes {
|
||||
#conversejs.converse-overlayed #controlbox .controlbox-panes {
|
||||
border-radius: 4px; }
|
||||
|
||||
#conversejs.converse-fullscreen #controlbox {
|
||||
#conversejs.converse-fullscreen #controlbox,
|
||||
#conversejs.converse-mobile #controlbox {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 1px;
|
||||
|
@ -8068,43 +8097,56 @@ body.reset {
|
|||
padding-left: 15px;
|
||||
margin: 0; }
|
||||
@media (min-width: 768px) {
|
||||
#conversejs.converse-fullscreen #controlbox {
|
||||
#conversejs.converse-fullscreen #controlbox,
|
||||
#conversejs.converse-mobile #controlbox {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%; } }
|
||||
@media (min-width: 1200px) {
|
||||
#conversejs.converse-fullscreen #controlbox {
|
||||
#conversejs.converse-fullscreen #controlbox,
|
||||
#conversejs.converse-mobile #controlbox {
|
||||
flex: 0 0 16.6666666667%;
|
||||
max-width: 16.6666666667%; } }
|
||||
#conversejs.converse-fullscreen #controlbox.logged-out {
|
||||
#conversejs.converse-fullscreen #controlbox.logged-out,
|
||||
#conversejs.converse-mobile #controlbox.logged-out {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%; }
|
||||
#conversejs.converse-fullscreen #controlbox .controlbox-pane {
|
||||
#conversejs.converse-fullscreen #controlbox .controlbox-pane,
|
||||
#conversejs.converse-mobile #controlbox .controlbox-pane {
|
||||
border-radius: 0; }
|
||||
#conversejs.converse-fullscreen #controlbox .flyout {
|
||||
#conversejs.converse-fullscreen #controlbox .flyout,
|
||||
#conversejs.converse-mobile #controlbox .flyout {
|
||||
border-radius: 0; }
|
||||
#conversejs.converse-fullscreen #controlbox #converse-login-panel {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-login-panel,
|
||||
#conversejs.converse-mobile #controlbox #converse-login-panel {
|
||||
border-radius: 0; }
|
||||
#conversejs.converse-fullscreen #controlbox #converse-login-panel .converse-form {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-login-panel .converse-form,
|
||||
#conversejs.converse-mobile #controlbox #converse-login-panel .converse-form {
|
||||
padding: 3em 2em 3em; }
|
||||
#conversejs.converse-fullscreen #controlbox .toggle-register-login {
|
||||
#conversejs.converse-fullscreen #controlbox .toggle-register-login,
|
||||
#conversejs.converse-mobile #controlbox .toggle-register-login {
|
||||
line-height: 24px; }
|
||||
#conversejs.converse-fullscreen #controlbox .brand-heading-container {
|
||||
#conversejs.converse-fullscreen #controlbox .brand-heading-container,
|
||||
#conversejs.converse-mobile #controlbox .brand-heading-container {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
text-align: center; }
|
||||
#conversejs.converse-fullscreen #controlbox .brand-heading-container .brand-heading {
|
||||
#conversejs.converse-fullscreen #controlbox .brand-heading-container .brand-heading,
|
||||
#conversejs.converse-mobile #controlbox .brand-heading-container .brand-heading {
|
||||
font-size: 150%;
|
||||
font-size: 600%;
|
||||
padding: 0.7em 0 0 0;
|
||||
opacity: 0.8;
|
||||
color: #387592; }
|
||||
#conversejs.converse-fullscreen #controlbox .brand-heading-container .brand-subtitle {
|
||||
#conversejs.converse-fullscreen #controlbox .brand-heading-container .brand-subtitle,
|
||||
#conversejs.converse-mobile #controlbox .brand-heading-container .brand-subtitle {
|
||||
font-size: 90%;
|
||||
padding: 0.5em; }
|
||||
@media screen and (max-width: 480px) {
|
||||
#conversejs.converse-fullscreen #controlbox .brand-heading-container .brand-heading {
|
||||
#conversejs.converse-fullscreen #controlbox .brand-heading-container .brand-heading,
|
||||
#conversejs.converse-mobile #controlbox .brand-heading-container .brand-heading {
|
||||
font-size: 400%; } }
|
||||
#conversejs.converse-fullscreen #controlbox.logged-out {
|
||||
#conversejs.converse-fullscreen #controlbox.logged-out,
|
||||
#conversejs.converse-mobile #controlbox.logged-out {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
opacity: 0;
|
||||
|
@ -8122,16 +8164,21 @@ body.reset {
|
|||
-moz-animation-timing-function: ease;
|
||||
animation-timing-function: ease;
|
||||
width: 100%; }
|
||||
#conversejs.converse-fullscreen #controlbox.logged-out .box-flyout {
|
||||
#conversejs.converse-fullscreen #controlbox.logged-out .box-flyout,
|
||||
#conversejs.converse-mobile #controlbox.logged-out .box-flyout {
|
||||
width: 100%; }
|
||||
#conversejs.converse-fullscreen #controlbox .box-flyout {
|
||||
#conversejs.converse-fullscreen #controlbox .box-flyout,
|
||||
#conversejs.converse-mobile #controlbox .box-flyout {
|
||||
border: 0;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
background-color: #578EA9; }
|
||||
#conversejs.converse-fullscreen #controlbox .box-flyout .controlbox-head {
|
||||
#conversejs.converse-fullscreen #controlbox .box-flyout .controlbox-head,
|
||||
#conversejs.converse-mobile #controlbox .box-flyout .controlbox-head {
|
||||
display: none; }
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register, #conversejs.converse-fullscreen #controlbox #converse-login {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register, #conversejs.converse-fullscreen #controlbox #converse-login,
|
||||
#conversejs.converse-mobile #controlbox #converse-register,
|
||||
#conversejs.converse-mobile #controlbox #converse-login {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 1px;
|
||||
|
@ -8141,25 +8188,39 @@ body.reset {
|
|||
max-width: 66.6666666667%;
|
||||
margin-left: 16.6666666667%; }
|
||||
@media (min-width: 576px) {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register, #conversejs.converse-fullscreen #controlbox #converse-login {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register, #conversejs.converse-fullscreen #controlbox #converse-login,
|
||||
#conversejs.converse-mobile #controlbox #converse-register,
|
||||
#conversejs.converse-mobile #controlbox #converse-login {
|
||||
flex: 0 0 66.6666666667%;
|
||||
max-width: 66.6666666667%;
|
||||
margin-left: 16.6666666667%; } }
|
||||
@media (min-width: 768px) {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register, #conversejs.converse-fullscreen #controlbox #converse-login {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register, #conversejs.converse-fullscreen #controlbox #converse-login,
|
||||
#conversejs.converse-mobile #controlbox #converse-register,
|
||||
#conversejs.converse-mobile #controlbox #converse-login {
|
||||
flex: 0 0 66.6666666667%;
|
||||
max-width: 66.6666666667%;
|
||||
margin-left: 16.6666666667%; } }
|
||||
@media (min-width: 992px) {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register, #conversejs.converse-fullscreen #controlbox #converse-login {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register, #conversejs.converse-fullscreen #controlbox #converse-login,
|
||||
#conversejs.converse-mobile #controlbox #converse-register,
|
||||
#conversejs.converse-mobile #controlbox #converse-login {
|
||||
flex: 0 0 50%;
|
||||
max-width: 50%;
|
||||
margin-left: 25%; } }
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register .title, #conversejs.converse-fullscreen #controlbox #converse-register .instructions, #conversejs.converse-fullscreen #controlbox #converse-login .title, #conversejs.converse-fullscreen #controlbox #converse-login .instructions {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register .title, #conversejs.converse-fullscreen #controlbox #converse-register .instructions, #conversejs.converse-fullscreen #controlbox #converse-login .title, #conversejs.converse-fullscreen #controlbox #converse-login .instructions,
|
||||
#conversejs.converse-mobile #controlbox #converse-register .title,
|
||||
#conversejs.converse-mobile #controlbox #converse-register .instructions,
|
||||
#conversejs.converse-mobile #controlbox #converse-login .title,
|
||||
#conversejs.converse-mobile #controlbox #converse-login .instructions {
|
||||
margin: 1em 0; }
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register input[type=submit],
|
||||
#conversejs.converse-fullscreen #controlbox #converse-register input[type=button], #conversejs.converse-fullscreen #controlbox #converse-login input[type=submit],
|
||||
#conversejs.converse-fullscreen #controlbox #converse-login input[type=button] {
|
||||
#conversejs.converse-fullscreen #controlbox #converse-login input[type=button],
|
||||
#conversejs.converse-mobile #controlbox #converse-register input[type=submit],
|
||||
#conversejs.converse-mobile #controlbox #converse-register input[type=button],
|
||||
#conversejs.converse-mobile #controlbox #converse-login input[type=submit],
|
||||
#conversejs.converse-mobile #controlbox #converse-login input[type=button] {
|
||||
width: auto; }
|
||||
|
||||
#conversejs .list-container {
|
||||
|
@ -8494,10 +8555,18 @@ body.reset {
|
|||
border-left: 1px solid #666;
|
||||
border-bottom-right-radius: 4px;
|
||||
padding: 0.5em; }
|
||||
#conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .occupants .occupants-heading,
|
||||
#conversejs .chatroom .box-flyout .chatroom-body .occupants .occupants-heading {
|
||||
font-family: "Century Gothic", futura, "URW Gothic L", Verdana, sans-serif;
|
||||
padding: 0.3em 0; }
|
||||
#conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .occupants .occupants-header,
|
||||
#conversejs .chatroom .box-flyout .chatroom-body .occupants .occupants-header {
|
||||
display: flex;
|
||||
flex-direction: column; }
|
||||
#conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .occupants .occupants-header .hide-occupants,
|
||||
#conversejs .chatroom .box-flyout .chatroom-body .occupants .occupants-header .hide-occupants {
|
||||
align-self: flex-end;
|
||||
cursor: pointer; }
|
||||
#conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .occupants .occupants-header .occupants-heading,
|
||||
#conversejs .chatroom .box-flyout .chatroom-body .occupants .occupants-header .occupants-heading {
|
||||
font-family: "Century Gothic", futura, "URW Gothic L", Verdana, sans-serif;
|
||||
padding: 0.3em 0; }
|
||||
#conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .occupants .chatroom-features,
|
||||
#conversejs .chatroom .box-flyout .chatroom-body .occupants .chatroom-features {
|
||||
width: 100%; }
|
||||
|
@ -8643,25 +8712,49 @@ body.reset {
|
|||
max-width: 66.6666666667%; }
|
||||
#conversejs.converse-overlayed .chatbox.chatroom .chatbox-title .chatroom-description {
|
||||
font-size: 80%; }
|
||||
#conversejs.converse-overlayed .chatbox.chatroom .chatbox-buttons {
|
||||
flex: 0 0 33.3333333333%;
|
||||
max-width: 33.3333333333%; }
|
||||
#conversejs.converse-overlayed .chatbox.chatroom .chatroom-body .occupants .chatroom-features .feature {
|
||||
font-size: 12px; }
|
||||
#conversejs.converse-overlayed .chatbox.chatroom .chatroom-body .chat-area {
|
||||
min-width: 250px; }
|
||||
|
||||
/* ******************* Fullpage styles *************************** */
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout .chatbox-title {
|
||||
flex: 0 0 75%;
|
||||
max-width: 75%; }
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout .chatbox-buttons {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%; }
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
#conversejs.converse-mobile .chatroom .box-flyout .chatbox-navback,
|
||||
#conversejs.converse-overlayed .chatroom .box-flyout .chatbox-navback,
|
||||
#conversejs.converse-embedded .chatroom .box-flyout .chatbox-navback,
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout .chatbox-navback {
|
||||
flex: 0 0 16.6666666667%;
|
||||
max-width: 16.6666666667%; }
|
||||
#conversejs.converse-mobile .chatroom .box-flyout .chatbox-title,
|
||||
#conversejs.converse-overlayed .chatroom .box-flyout .chatbox-title,
|
||||
#conversejs.converse-embedded .chatroom .box-flyout .chatbox-title,
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout .chatbox-title {
|
||||
flex: 0 0 58.3333333333%;
|
||||
max-width: 58.3333333333%; }
|
||||
#conversejs.converse-mobile .chatroom .box-flyout .chatbox-buttons,
|
||||
#conversejs.converse-overlayed .chatroom .box-flyout .chatbox-buttons,
|
||||
#conversejs.converse-embedded .chatroom .box-flyout .chatbox-buttons,
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout .chatbox-buttons {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%; } }
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout,
|
||||
#conversejs.converse-mobile .chatroom .box-flyout {
|
||||
background-color: #E77051;
|
||||
border: 1.2em solid #E77051;
|
||||
border-top: 0.8em solid #E77051;
|
||||
width: 100%; }
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout .chatbox-title,
|
||||
#conversejs.converse-mobile .chatroom .box-flyout .chatbox-title {
|
||||
flex: 0 0 75%;
|
||||
max-width: 75%; }
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout .chatbox-title .chatroom-description,
|
||||
#conversejs.converse-mobile .chatroom .box-flyout .chatbox-title .chatroom-description {
|
||||
font-size: 70%; }
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout .chatbox-title .chatroom-description,
|
||||
#conversejs.converse-mobile .chatroom .box-flyout .chatbox-title .chatroom-description {
|
||||
font-size: 70%; }
|
||||
#conversejs.converse-fullscreen .chatroom .box-flyout .chatroom-body,
|
||||
#conversejs.converse-mobile .chatroom .box-flyout .chatroom-body {
|
||||
border-top-left-radius: 4px;
|
||||
|
|
6
dev.html
6
dev.html
|
@ -11,11 +11,7 @@
|
|||
<link rel="shortcut icon" type="image/ico" href="css/images/favicon.ico"/>
|
||||
<link type="text/css" rel="stylesheet" media="screen" href="css/fullpage.css" />
|
||||
<link type="text/css" rel="stylesheet" media="screen" href="css/converse.css" />
|
||||
|
||||
<![if gte IE 11]>
|
||||
<link type="text/css" rel="stylesheet" media="screen" href="css/converse.css" />
|
||||
<script src="dist/converse.js"></script>
|
||||
<![endif]>
|
||||
<script src="dist/converse.js"></script>
|
||||
</head>
|
||||
|
||||
<body class="reset">
|
||||
|
|
5816
dist/converse-no-dependencies.js
vendored
5816
dist/converse-no-dependencies.js
vendored
File diff suppressed because it is too large
Load Diff
6041
dist/converse.js
vendored
6041
dist/converse.js
vendored
File diff suppressed because it is too large
Load Diff
|
@ -672,7 +672,7 @@ geouri_regex
|
|||
Regular expression used to extract geo coordinates from links to openstreetmap.
|
||||
|
||||
geouri_replacement
|
||||
----------------
|
||||
------------------
|
||||
|
||||
* Default: ``'https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2'``
|
||||
|
||||
|
@ -711,48 +711,6 @@ Makes sense to set this to ``true`` when also using the non-core
|
|||
``converse-roomslist`` plugin, which shows a list of currently open (i.e.
|
||||
"joined") rooms.
|
||||
|
||||
include_offline_state
|
||||
---------------------
|
||||
|
||||
* Default: `false`
|
||||
|
||||
Originally, converse.js included an `offline` state which the user could
|
||||
choose (along with `online`, `busy` and `away`).
|
||||
|
||||
Eventually it was however decided to remove this state, since the `offline`
|
||||
state doesn't propagate across tabs like the others do.
|
||||
|
||||
What's meant by "propagate across tabs", is that when you set the state to
|
||||
`offline` in one tab, and you have instances of converse.js open in other tabs
|
||||
in your browser, then those instances will not have their states changed to
|
||||
`offline` as well. For the other statees the change is however propagated.
|
||||
|
||||
The reason for this is that according to the XMPP spec, there is no `offline`
|
||||
state. The only defined states are:
|
||||
|
||||
* away -- The entity or resource is temporarily away.
|
||||
* chat -- The entity or resource is actively interested in chattiIng.
|
||||
* dnd -- The entity or resource is busy (dnd = "Do Not Disturb").
|
||||
* xa -- The entity or resource is away for an extended period (xa = "eXtended Away").
|
||||
|
||||
Read the `relevant section in the XMPP spec <https://xmpp.org/rfcs/rfc6121.html#presence-syntax-children-show>`_
|
||||
for more info.
|
||||
|
||||
What used to happen in converse.js when the `offline` state was chosen, is
|
||||
that a presence stanza with a `type` of `unavailable` was sent out.
|
||||
|
||||
This is actually exactly what happens when you log out of converse.js as well,
|
||||
with the notable exception that in the `offline` state, the connection is not
|
||||
terminated. So you can at any time change your state to something else and
|
||||
start chatting again.
|
||||
|
||||
This might be useful to people, however the fact that the `offline` state
|
||||
doesn't propagate across tabs means that the user experience is inconsistent,
|
||||
confusing and appears "broken".
|
||||
|
||||
If you are however aware of this issue and still want to allow the `offline`
|
||||
state, then you can set this option to `true` to enable it.
|
||||
|
||||
.. _`i18n`:
|
||||
|
||||
i18n
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
Events and promises
|
||||
===================
|
||||
|
||||
Converse.js and its plugins emit various events which you can listen to via the
|
||||
Converse and its plugins emit various events which you can listen to via the
|
||||
:ref:`listen-grouping`.
|
||||
|
||||
Some of these events are also available as `ES2015 Promises <http://es6-features.org/#PromiseUsage>`_,
|
||||
|
@ -294,24 +294,6 @@ Also available as an `ES2015 Promise <http://es6-features.org/#PromiseUsage>`_:
|
|||
// Your code here...
|
||||
});
|
||||
|
||||
reconnecting
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Fired once converse.js has determined that it will attempt to reconnect (and
|
||||
each subsequent time, if it attempts repeatedly).
|
||||
|
||||
reconnected
|
||||
~~~~~~~~~~~
|
||||
|
||||
After the connection has dropped and converse.js has reconnected.
|
||||
Any Strophe stanza handlers (as registered via `converse.listen.stanza`) will
|
||||
have to be registered anew.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
_converse.api.listen.on('reconnected', function () { ... });
|
||||
|
||||
|
||||
privateChatsAutoJoined
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -330,6 +312,33 @@ Also available as an `ES2015 Promise <http://es6-features.org/#PromiseUsage>`_.
|
|||
// Your code here...
|
||||
});
|
||||
|
||||
|
||||
reconnecting
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Fired once converse.js has determined that it will attempt to reconnect (and
|
||||
each subsequent time, if it attempts repeatedly).
|
||||
|
||||
reconnected
|
||||
~~~~~~~~~~~
|
||||
|
||||
After the connection has dropped and converse.js has reconnected.
|
||||
Any Strophe stanza handlers (as registered via `converse.listen.stanza`) will
|
||||
have to be registered anew.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
_converse.api.listen.on('reconnected', function () { ... });
|
||||
|
||||
registeredGlobalEventHandlers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Called once Converse has registered its global event handlers (for events such
|
||||
as window resize or unload).
|
||||
|
||||
Plugins can listen to this event as cue to register their own global event
|
||||
handlers.
|
||||
|
||||
roomsAutoJoined
|
||||
---------------
|
||||
|
||||
|
@ -466,6 +475,14 @@ Similar to `rosterInitialized`, but instead pertaining to reconnection. This
|
|||
event indicates that the Backbone collections representing the roster and its
|
||||
groups are now again available after converse.js has reconnected.
|
||||
|
||||
serviceDiscovered
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
When converse.js has learned of a service provided by the XMPP server. See XEP-0030.
|
||||
|
||||
``_converse.api.listen.on('serviceDiscovered', function (service) { ... });``
|
||||
|
||||
|
||||
.. _`statusInitialized`:
|
||||
|
||||
statusInitialized
|
||||
|
@ -497,12 +514,12 @@ When own custom status message has changed.
|
|||
|
||||
``_converse.api.listen.on('statusMessageChanged', function (message) { ... });``
|
||||
|
||||
serviceDiscovered
|
||||
~~~~~~~~~~~~~~~~~
|
||||
streamFeaturesAdded
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When converse.js has learned of a service provided by the XMPP server. See XEP-0030.
|
||||
|
||||
``_converse.api.listen.on('serviceDiscovered', function (service) { ... });``
|
||||
Emitted as soon as Converse has processed the stream features as advertised by
|
||||
the server. If you want to check whether a stream feature is supported before
|
||||
proceeding, then you'll first want to wait for this event.
|
||||
|
||||
windowStateChanged
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -19,7 +19,7 @@ and a private chat with a URL fragment such as
|
|||
Off-the-record encryption
|
||||
=========================
|
||||
|
||||
Converse.js supports `Off-the-record (OTR) <https://otr.cypherpunks.ca/>`_
|
||||
Converse supports `Off-the-record (OTR) <https://otr.cypherpunks.ca/>`_
|
||||
encrypted messaging.
|
||||
|
||||
The OTR protocol not only **encrypts your messages**, it provides ways to
|
||||
|
@ -38,17 +38,17 @@ secure crypto.
|
|||
For harsh but fairly valid criticism of JavaScript cryptography, read:
|
||||
`JavaScript Cryptography Considered Harmful <http://www.matasano.com/articles/javascript-cryptography/>`_.
|
||||
|
||||
To get an idea on how this applies to OTR support in Converse.js, please read
|
||||
To get an idea on how this applies to OTR support in Converse, please read
|
||||
`my thoughts on it <https://opkode.com/media/blog/2013/11/11/conversejs-otr-support>`_.
|
||||
|
||||
For now, suffice to say that although its useful to have OTR support in
|
||||
Converse.js in order to avoid most eavesdroppers, if you need serious
|
||||
Converse in order to avoid most eavesdroppers, if you need serious
|
||||
communications privacy, then you're much better off using native software.
|
||||
|
||||
Notifications
|
||||
=============
|
||||
|
||||
From version 0.8.1 Converse.js can play a sound notification when you receive a
|
||||
From version 0.8.1 Converse can play a sound notification when you receive a
|
||||
message.
|
||||
|
||||
For more info, refer to the :ref:`play-sounds` configuration setting.
|
||||
|
@ -61,13 +61,10 @@ For more info, refer to the :ref:`show-desktop-notifications` configuration sett
|
|||
Multilingual Support
|
||||
====================
|
||||
|
||||
Converse.js is translated into multiple languages. The default build,
|
||||
``converse.min.js``, includes all languages.
|
||||
|
||||
Languages increase the size of the Converse.js significantly.
|
||||
|
||||
If you only need one, or a subset of the available languages, it's better to
|
||||
make a custom build which includes only those languages that you need.
|
||||
Converse is translated into multiple languages. Translations are supplied in
|
||||
JSON format and are loaded on demand. Converse will expect to find the
|
||||
translations in the ``/locales`` path of your site. This can be changed via the
|
||||
:ref:`locales-url` configuration setting.
|
||||
|
||||
Moderating chatrooms
|
||||
====================
|
||||
|
@ -103,7 +100,7 @@ Here are the different commands that may be used to moderate a chatroom:
|
|||
Passwordless login with client certificates
|
||||
===========================================
|
||||
|
||||
Converse.js supports the SASL-EXTERNAL authentication mechanism, which can be
|
||||
Converse supports the SASL-EXTERNAL authentication mechanism, which can be
|
||||
used together with x509 client certificates to enable passwordless login or
|
||||
even 2-factor authentication.
|
||||
|
||||
|
|
1946
package-lock.json
generated
1946
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -73,7 +73,7 @@
|
|||
"sinon": "^2.1.0",
|
||||
"sizzle": "^2.3.3",
|
||||
"snabbdom": "0.7.1",
|
||||
"strophe.js": "1.2.14",
|
||||
"strophe.js": "1.2.15",
|
||||
"strophejs-plugin-ping": "0.0.1",
|
||||
"strophejs-plugin-register": "0.0.1",
|
||||
"strophejs-plugin-rsm": "0.0.1",
|
||||
|
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
|||
zc.buildout==2.11.4
|
|
@ -1,4 +1,7 @@
|
|||
#conversejs {
|
||||
.chatbox-navback {
|
||||
display: none;
|
||||
}
|
||||
.flyout {
|
||||
border-radius: $chatbox-border-radius;
|
||||
position: absolute;
|
||||
|
@ -51,10 +54,13 @@
|
|||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.chatbox-title {
|
||||
.chatroom-description {
|
||||
font-size: 80%;
|
||||
}
|
||||
}
|
||||
.chatbox-buttons {
|
||||
flex-direction: row-reverse;
|
||||
@include make-col-ready();
|
||||
@include make-col(4);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
@ -443,7 +449,14 @@
|
|||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
.chatbox-title {
|
||||
@include make-col(8);
|
||||
}
|
||||
.chatbox-buttons {
|
||||
@include make-col(4);
|
||||
}
|
||||
}
|
||||
|
||||
.chatbox {
|
||||
min-width: $overlayed-chat-width!important;
|
||||
width: $overlayed-chat-width;
|
||||
|
@ -536,9 +549,6 @@
|
|||
}
|
||||
.chat-head {
|
||||
height: $fullpage-chat-head-height;
|
||||
.chatbox-buttons {
|
||||
@include make-col(3);
|
||||
}
|
||||
font-size: $font-size-huge;
|
||||
padding: 0;
|
||||
.user-custom-message {
|
||||
|
@ -546,6 +556,12 @@
|
|||
height: auto;
|
||||
line-height: $line-height;
|
||||
}
|
||||
.chatbox-title {
|
||||
@include make-col(10);
|
||||
}
|
||||
.chatbox-buttons {
|
||||
@include make-col(2);
|
||||
}
|
||||
}
|
||||
.chat-textarea {
|
||||
max-height: $fullpage-max-chat-textarea-height;
|
||||
|
@ -623,22 +639,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
@include media-breakpoint-down(sm) {
|
||||
#conversejs:not(.converse-embedded) {
|
||||
> .row {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
#converse-login-panel {
|
||||
.converse-form {
|
||||
padding: 3em 2em 3em;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.chatbox {
|
||||
width: calc(100% - 50px);
|
||||
.row {
|
||||
|
@ -651,12 +661,29 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
#conversejs:not(.converse-embedded).converse-fullscreen {
|
||||
#conversejs.converse-mobile,
|
||||
#conversejs.converse-overlayed,
|
||||
#conversejs.converse-embedded,
|
||||
#conversejs.converse-fullscreen {
|
||||
.chatbox {
|
||||
width: calc(100% - 50px);
|
||||
.box-flyout {
|
||||
.chatbox-navback {
|
||||
display: flex;
|
||||
@include make-col(2);
|
||||
.fa-arrow-left {
|
||||
&:before {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.chatbox-title {
|
||||
@include make-col(7);
|
||||
}
|
||||
.chatbox-buttons {
|
||||
@include make-col(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,9 +120,17 @@
|
|||
border-bottom-right-radius: $chatbox-border-radius;
|
||||
padding: 0.5em;
|
||||
|
||||
.occupants-heading {
|
||||
font-family: $heading-font;
|
||||
padding: 0.3em 0;
|
||||
.occupants-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.hide-occupants {
|
||||
align-self: flex-end;
|
||||
cursor: pointer;
|
||||
}
|
||||
.occupants-heading {
|
||||
font-family: $heading-font;
|
||||
padding: 0.3em 0;
|
||||
}
|
||||
}
|
||||
|
||||
.chatroom-features {
|
||||
|
@ -292,6 +300,9 @@
|
|||
font-size: 80%;
|
||||
}
|
||||
}
|
||||
.chatbox-buttons {
|
||||
@include make-col(4);
|
||||
}
|
||||
.chatroom-body {
|
||||
.occupants {
|
||||
.chatroom-features {
|
||||
|
@ -308,7 +319,39 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* ******************* Fullpage styles *************************** */
|
||||
#conversejs.converse-fullscreen {
|
||||
.chatroom {
|
||||
.box-flyout {
|
||||
.chatbox-title {
|
||||
@include make-col(9);
|
||||
}
|
||||
.chatbox-buttons {
|
||||
@include make-col(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
#conversejs.converse-mobile,
|
||||
#conversejs.converse-overlayed,
|
||||
#conversejs.converse-embedded,
|
||||
#conversejs.converse-fullscreen {
|
||||
.chatroom {
|
||||
.box-flyout {
|
||||
.chatbox-navback {
|
||||
@include make-col(2);
|
||||
}
|
||||
.chatbox-title {
|
||||
@include make-col(7);
|
||||
}
|
||||
.chatbox-buttons {
|
||||
@include make-col(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#conversejs.converse-fullscreen,
|
||||
#conversejs.converse-mobile {
|
||||
|
@ -321,7 +364,6 @@
|
|||
width: 100%;
|
||||
|
||||
.chatbox-title {
|
||||
@include make-col(9);
|
||||
.chatroom-description {
|
||||
font-size: 70%;
|
||||
}
|
||||
|
|
|
@ -357,7 +357,6 @@
|
|||
|
||||
.chatbox {
|
||||
.box-flyout {
|
||||
top: -100vh;
|
||||
margin-left: 15px; // Counteracts Bootstrap margins, but
|
||||
// not clear why needed...
|
||||
left: 0;
|
||||
|
@ -393,7 +392,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
#conversejs:not(.converse-fullscreen) {
|
||||
#conversejs.converse-overlayed {
|
||||
#controlbox {
|
||||
order: -1;
|
||||
min-width: $controlbox-width !important;
|
||||
|
@ -445,7 +444,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
#conversejs.converse-fullscreen {
|
||||
#conversejs.converse-fullscreen,
|
||||
#conversejs.converse-mobile {
|
||||
#controlbox {
|
||||
@include make-col-ready();
|
||||
@include media-breakpoint-up(md) {
|
||||
|
|
|
@ -67,12 +67,16 @@ body.reset {
|
|||
}
|
||||
}
|
||||
|
||||
&.converse-fullscreen {
|
||||
&.converse-fullscreen,
|
||||
&.converse-mobile {
|
||||
.converse-chatboxes {
|
||||
width: 100vw;
|
||||
right: 15px; // Hack due to padding added by bootstrap
|
||||
}
|
||||
}
|
||||
&.converse-overlayed {
|
||||
height: 3em;
|
||||
}
|
||||
|
||||
.brand-heading {
|
||||
font-family: $heading-font;
|
||||
|
@ -89,7 +93,6 @@ body.reset {
|
|||
z-index: 1031; // One more than bootstrap navbar
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
height: 3em;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -3170,7 +3170,7 @@
|
|||
|
||||
test_utils.openControlBox();
|
||||
var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
||||
roomspanel.el.querySelector('.trigger-add-chatrooms-modal').click();
|
||||
roomspanel.el.querySelector('.show-add-muc-modal').click();
|
||||
test_utils.closeControlBox(_converse);
|
||||
const modal = roomspanel.add_room_modal;
|
||||
test_utils.waitUntil(function () {
|
||||
|
@ -3205,7 +3205,7 @@
|
|||
|
||||
test_utils.openControlBox();
|
||||
var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
||||
roomspanel.el.querySelector('.trigger-list-chatrooms-modal').click();
|
||||
roomspanel.el.querySelector('.show-list-muc-modal').click();
|
||||
test_utils.closeControlBox(_converse);
|
||||
const modal = roomspanel.list_rooms_modal;
|
||||
test_utils.waitUntil(function () {
|
||||
|
|
|
@ -209,7 +209,7 @@
|
|||
* </iq>
|
||||
*/
|
||||
spyOn(_converse.roster, "updateContact").and.callThrough();
|
||||
stanza = $iq({'type': 'set', 'from': 'dummy@localhost'})
|
||||
stanza = $iq({'type': 'set', 'from': _converse.connection.jid})
|
||||
.c('query', {'xmlns': 'jabber:iq:roster'})
|
||||
.c('item', {
|
||||
'jid': 'contact@example.org',
|
||||
|
|
|
@ -35,6 +35,68 @@
|
|||
|
||||
describe("The Contacts Roster", function () {
|
||||
|
||||
it("supports roster versioning",
|
||||
mock.initConverseWithPromises(
|
||||
null, ['rosterGroupsFetched'], {},
|
||||
function (done, _converse) {
|
||||
|
||||
var IQ_stanzas = _converse.connection.IQ_stanzas;
|
||||
var stanza;
|
||||
|
||||
test_utils.waitUntil(() => {
|
||||
const node = _.filter(IQ_stanzas, function (iq) {
|
||||
return iq.nodeTree.querySelector('iq query[xmlns="jabber:iq:roster"]');
|
||||
}).pop();
|
||||
if (node) {
|
||||
stanza = node.nodeTree;
|
||||
return true;
|
||||
}
|
||||
}).then(() => {
|
||||
expect(_converse.roster.data.get('version')).toBeUndefined();
|
||||
expect(stanza.outerHTML).toBe(
|
||||
`<iq type="get" id="${stanza.getAttribute('id')}" xmlns="jabber:client">`+
|
||||
`<query xmlns="jabber:iq:roster"/>`+
|
||||
`</iq>`);
|
||||
let result = $iq({
|
||||
'to': _converse.connection.jid,
|
||||
'type': 'result',
|
||||
'id': stanza.getAttribute('id')
|
||||
}).c('query', {
|
||||
'xmlns': 'jabber:iq:roster',
|
||||
'ver': 'ver7'
|
||||
}).c('item', {'jid': 'nurse@example.com'}).up()
|
||||
.c('item', {'jid': 'romeo@example.com'})
|
||||
_converse.connection._dataRecv(test_utils.createRequest(result));
|
||||
expect(_converse.roster.data.get('version')).toBe('ver7');
|
||||
expect(_converse.roster.models.length).toBe(2);
|
||||
|
||||
_converse.roster.fetchFromServer();
|
||||
stanza = _converse.connection.IQ_stanzas.pop().nodeTree;
|
||||
expect(stanza.outerHTML).toBe(
|
||||
`<iq type="get" id="${stanza.getAttribute('id')}" xmlns="jabber:client">`+
|
||||
`<query xmlns="jabber:iq:roster" ver="ver7"/>`+
|
||||
`</iq>`);
|
||||
|
||||
result = $iq({
|
||||
'to': _converse.connection.jid,
|
||||
'type': 'result',
|
||||
'id': stanza.getAttribute('id')
|
||||
});
|
||||
_converse.connection._dataRecv(test_utils.createRequest(result));
|
||||
|
||||
const roster_push = $iq({
|
||||
'to': _converse.connection.jid,
|
||||
'type': 'set',
|
||||
}).c('query', {'xmlns': 'jabber:iq:roster', 'ver': 'ver34'})
|
||||
.c('item', {'jid': 'romeo@example.com', 'subscription': 'remove'});
|
||||
_converse.connection._dataRecv(test_utils.createRequest(roster_push));
|
||||
expect(_converse.roster.data.get('version')).toBe('ver34');
|
||||
expect(_converse.roster.models.length).toBe(1);
|
||||
expect(_converse.roster.at(0).get('jid')).toBe('nurse@example.com');
|
||||
done();
|
||||
});
|
||||
}));
|
||||
|
||||
describe("The live filter", function () {
|
||||
|
||||
it("will only appear when roster contacts flow over the visible area",
|
||||
|
|
|
@ -62,7 +62,9 @@
|
|||
// Refer to docs/source/configuration.rst for explanations of these
|
||||
// configuration settings.
|
||||
_converse.api.settings.update({
|
||||
auto_join_private_chats: [],
|
||||
'filter_by_resource': false,
|
||||
'auto_join_private_chats': [],
|
||||
'forward_messages': false,
|
||||
});
|
||||
_converse.api.promises.add([
|
||||
'chatBoxesFetched',
|
||||
|
@ -720,9 +722,6 @@
|
|||
_converse.root.appendChild(el);
|
||||
}
|
||||
}
|
||||
if (_.includes(['mobile', 'fullscreen'], _converse.view_mode)) {
|
||||
el.classList.add('fullscreen');
|
||||
}
|
||||
el.innerHTML = '';
|
||||
this.setElement(el, false);
|
||||
} else {
|
||||
|
|
|
@ -100,10 +100,11 @@
|
|||
{ __ } = _converse;
|
||||
|
||||
_converse.api.settings.update({
|
||||
'use_emojione': false,
|
||||
'emojione_image_path': emojione.imagePathPNG,
|
||||
'show_send_button': false,
|
||||
'show_toolbar': true,
|
||||
'time_format': 'HH:mm',
|
||||
'use_emojione': false,
|
||||
'visible_toolbar_buttons': {
|
||||
'call': false,
|
||||
'clear': true,
|
||||
|
@ -320,16 +321,17 @@
|
|||
|
||||
events: {
|
||||
'change input.fileupload': 'onFileSelection',
|
||||
'click .chatbox-navback': 'showControlBox',
|
||||
'click .close-chatbox-button': 'close',
|
||||
'click .show-user-details-modal': 'showUserDetailsModal',
|
||||
'click .new-msgs-indicator': 'viewUnreadMessages',
|
||||
'click .send-button': 'onFormSubmitted',
|
||||
'click .show-user-details-modal': 'showUserDetailsModal',
|
||||
'click .spoiler-toggle': 'toggleSpoilerMessage',
|
||||
'click .toggle-call': 'toggleCall',
|
||||
'click .toggle-clear': 'clearMessages',
|
||||
'click .toggle-compose-spoiler': 'toggleComposeSpoilerMessage',
|
||||
'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
|
||||
'click .toggle-smiley': 'toggleEmojiMenu',
|
||||
'click .spoiler-toggle': 'toggleSpoilerMessage',
|
||||
'click .upload-file': 'toggleFileUpload',
|
||||
'keypress .chat-textarea': 'keyPressed',
|
||||
'input .chat-textarea': 'inputChanged'
|
||||
|
@ -412,6 +414,13 @@
|
|||
this.renderToolbar();
|
||||
},
|
||||
|
||||
showControlBox () {
|
||||
// Used in mobile view, to navigate back to the controlbox
|
||||
const view = _converse.chatboxviews.get('controlbox');
|
||||
view.show();
|
||||
this.hide();
|
||||
},
|
||||
|
||||
showUserDetailsModal (ev) {
|
||||
if (_.isUndefined(this.user_details_modal)) {
|
||||
this.user_details_modal = new _converse.UserDetailsModal({model: this.model});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Converse.js
|
||||
// https://conversejs.org
|
||||
//
|
||||
// Copyright (c) 2012-2018, the Converse.js developers
|
||||
// Copyright (c) 2013-2018, the Converse.js developers
|
||||
// Licensed under the Mozilla Public License (MPLv2)
|
||||
|
||||
(function (root, factory) {
|
||||
|
@ -151,6 +151,64 @@
|
|||
_converse.DEFAULT_IMAGE_TYPE = 'image/png';
|
||||
_converse.DEFAULT_IMAGE = "iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAIAAABt+uBvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwHCy455JBsggAABkJJREFUeNrtnM1PE1sUwHvvTD8otWLHST/Gimi1CEgr6M6FEWuIBo2pujDVsNDEP8GN/4MbN7oxrlipG2OCgZgYlxAbkRYw1KqkIDRCSkM7nXvvW8x7vjyNeQ9m7p1p3z1LQk/v/Dhz7vkEXL161cHl9wI5Ag6IA+KAOCAOiAPigDggLhwQB2S+iNZ+PcYY/SWEEP2HAAAIoSAIoihCCP+ngDDGtVotGAz29/cfOXJEUZSOjg6n06lp2sbGRqlUWlhYyGazS0tLbrdbEASrzgksyeYJId3d3el0uqenRxRFAAAA4KdfIIRgjD9+/Pj8+fOpqSndslofEIQwHA6Pjo4mEon//qmFhYXHjx8vLi4ihBgDEnp7e9l8E0Jo165dQ0NDd+/eDYVC2/qsJElDQ0OEkKWlpa2tLZamxAhQo9EIBoOjo6MXL17csZLe3l5FUT59+lQul5l5JRaAVFWNRqN37tw5ceKEQVWRSOTw4cOFQuHbt2+iKLYCIISQLMu3b99OJpOmKAwEAgcPHszn8+vr6wzsiG6UQQhxuVyXLl0aGBgwUW0sFstkMl6v90fo1KyAMMYDAwPnzp0zXfPg4GAqlWo0Gk0MiBAiy/L58+edTqf5Aa4onj59OhaLYYybFRCEMBaL0fNxBw4cSCQStN0QRUBut3t4eJjq6U+dOiVJElVPRBFQIBDo6+ujCqirqyscDlONGykC2lYyYSR6pBoQQapHZwAoHo/TuARYAOrs7GQASFEUqn6aIiBJkhgA6ujooFpUo6iaTa7koFwnaoWadLNe81tbWwzoaJrWrICWl5cZAFpbW6OabVAEtLi4yABQsVjUNK0pAWWzWQaAcrlcswKanZ1VVZUqHYRQEwOq1Wpv3ryhCmh6erpcLjdrNl+v1ycnJ+l5UELI27dvv3//3qxxEADgy5cvExMT9Mznw4cPtFtAdAPFarU6Pj5eKpVM17yxsfHy5cvV1VXazXu62gVBKBQKT58+rdVqJqrFGL948eLdu3dU8/g/H4FBUaJYLAqC0NPTY9brMD4+PjY25mDSracOCABACJmZmXE6nUePHjWu8NWrV48ePSKEsGlAs7Agfd5nenq6Wq0mk0kjDzY2NvbkyRMIIbP2PLvhBUEQ8vl8NpuNx+M+n29bzhVjvLKycv/+/YmJCcazQuwA6YzW1tYmJyf1SY+2trZ/rRk1Go1SqfT69esHDx4UCgVmNaa/zZ/9ABUhRFXVYDB48uTJeDweiUQkSfL7/T9MA2NcqVTK5fLy8vL8/PzU1FSxWHS5XJaM4wGr9sUwxqqqer3eUCgkSZJuUBBCfTRvc3OzXC6vrKxUKhWn02nhCJ5lM4oQQo/HgxD6+vXr58+fHf8sDOp+HQDg8XgclorFU676dKLlo6yWRdItIBwQB8QBcUCtfosRQjRNQwhhjPUC4w46WXryBSHU1zgEQWBz99EFhDGu1+t+v//48ePxeFxRlD179ng8nh0Efgiher2+vr6ur3HMzMysrq7uTJVdACGEurq6Ll++nEgkPB7Pj9jPoDHqOxyqqubz+WfPnuVyuV9XPeyeagAAAoHArVu3BgcHab8CuVzu4cOHpVKJUnfA5GweY+xyuc6cOXPv3r1IJMLAR8iyPDw8XK/Xi8Wiqqqmm5KZgBBC7e3tN27cuHbtGuPVpf7+/lAoNDs7W61WzfVKpgHSSzw3b95MpVKW3MfRaDQSiczNzVUqFRMZmQOIEOL1eq9fv3727FlL1t50URRFluX5+flqtWpWEGAOIFEUU6nUlStXLKSjy759+xwOx9zcnKZpphzGHMzhcDiTydgk9r1w4YIp7RPTAAmCkMlk2FeLf/tIEKbTab/fbwtAhJBoNGrutpNx6e7uPnTokC1eMU3T0um0DZPMkZER6wERQnw+n/FFSxpy7Nix3bt3WwwIIcRgIWnHkkwmjecfRgGx7DtuV/r6+iwGhDHev3+/bQF1dnYaH6E2CkiWZdsC2rt3r8WAHA5HW1ubbQGZcjajgOwTH/4qNko1Wlg4IA6IA+KAOKBWBUQIsfNojyliKIoRRfH9+/dut9umf3wzpoUNNQ4BAJubmwz+ic+OxefzWWlBhJD29nbug7iT5sIBcUAcEAfEAXFAHBAHxOVn+QMrmWpuPZx12gAAAABJRU5ErkJggg==";
|
||||
|
||||
_converse.TIMEOUTS = { // Set as module attr so that we can override in tests.
|
||||
'PAUSED': 10000,
|
||||
'INACTIVE': 90000
|
||||
};
|
||||
|
||||
// XEP-0085 Chat states
|
||||
// http://xmpp.org/extensions/xep-0085.html
|
||||
_converse.INACTIVE = 'inactive';
|
||||
_converse.ACTIVE = 'active';
|
||||
_converse.COMPOSING = 'composing';
|
||||
_converse.PAUSED = 'paused';
|
||||
_converse.GONE = 'gone';
|
||||
|
||||
// Default configuration values
|
||||
// ----------------------------
|
||||
_converse.default_settings = {
|
||||
allow_non_roster_messaging: false,
|
||||
animate: true,
|
||||
authentication: 'login', // Available values are "login", "prebind", "anonymous" and "external".
|
||||
auto_away: 0, // Seconds after which user status is set to 'away'
|
||||
auto_login: false, // Currently only used in connection with anonymous login
|
||||
auto_reconnect: true,
|
||||
auto_xa: 0, // Seconds after which user status is set to 'xa'
|
||||
blacklisted_plugins: [],
|
||||
bosh_service_url: undefined,
|
||||
connection_options: {},
|
||||
credentials_url: null, // URL from where login credentials can be fetched
|
||||
csi_waiting_time: 0, // Support for XEP-0352. Seconds before client is considered idle and CSI is sent out.
|
||||
debug: false,
|
||||
default_state: 'online',
|
||||
expose_rid_and_sid: false,
|
||||
geouri_regex: /https:\/\/www.openstreetmap.org\/.*#map=[0-9]+\/([\-0-9.]+)\/([\-0-9.]+)\S*/g,
|
||||
geouri_replacement: 'https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2',
|
||||
jid: undefined,
|
||||
keepalive: true,
|
||||
locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
|
||||
locales: [
|
||||
'af', 'ar', 'bg', 'ca', 'de', 'es', 'eu', 'en', 'fr', 'he',
|
||||
'hu', 'id', 'it', 'ja', 'nb', 'nl',
|
||||
'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'
|
||||
],
|
||||
message_carbons: true,
|
||||
nickname: undefined,
|
||||
password: undefined,
|
||||
prebind_url: null,
|
||||
priority: 0,
|
||||
rid: undefined,
|
||||
root: window.document,
|
||||
sid: undefined,
|
||||
storage: 'session',
|
||||
strict_plugin_dependencies: false,
|
||||
trusted: true,
|
||||
view_mode: 'overlayed', // Choices are 'overlayed', 'fullscreen', 'mobile'
|
||||
websocket_url: undefined,
|
||||
whitelisted_plugins: []
|
||||
};
|
||||
|
||||
|
||||
_converse.log = function (message, level, style='') {
|
||||
/* Logs messages to the browser's developer console.
|
||||
*
|
||||
|
@ -276,73 +334,6 @@
|
|||
unloadevent = 'unload';
|
||||
}
|
||||
|
||||
// Instance level constants
|
||||
this.TIMEOUTS = { // Set as module attr so that we can override in tests.
|
||||
'PAUSED': 10000,
|
||||
'INACTIVE': 90000
|
||||
};
|
||||
|
||||
// XEP-0085 Chat states
|
||||
// http://xmpp.org/extensions/xep-0085.html
|
||||
this.INACTIVE = 'inactive';
|
||||
this.ACTIVE = 'active';
|
||||
this.COMPOSING = 'composing';
|
||||
this.PAUSED = 'paused';
|
||||
this.GONE = 'gone';
|
||||
|
||||
// Default configuration values
|
||||
// ----------------------------
|
||||
this.default_settings = {
|
||||
allow_contact_requests: true,
|
||||
allow_non_roster_messaging: false,
|
||||
animate: true,
|
||||
authentication: 'login', // Available values are "login", "prebind", "anonymous" and "external".
|
||||
auto_away: 0, // Seconds after which user status is set to 'away'
|
||||
auto_login: false, // Currently only used in connection with anonymous login
|
||||
auto_reconnect: true,
|
||||
auto_subscribe: false,
|
||||
auto_xa: 0, // Seconds after which user status is set to 'xa'
|
||||
blacklisted_plugins: [],
|
||||
bosh_service_url: undefined,
|
||||
connection_options: {},
|
||||
credentials_url: null, // URL from where login credentials can be fetched
|
||||
csi_waiting_time: 0, // Support for XEP-0352. Seconds before client is considered idle and CSI is sent out.
|
||||
debug: false,
|
||||
default_state: 'online',
|
||||
expose_rid_and_sid: false,
|
||||
filter_by_resource: false,
|
||||
forward_messages: false,
|
||||
geouri_regex: /https:\/\/www.openstreetmap.org\/.*#map=[0-9]+\/([\-0-9.]+)\/([\-0-9.]+)\S*/g,
|
||||
geouri_replacement: 'https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2',
|
||||
hide_offline_users: false,
|
||||
include_offline_state: false,
|
||||
jid: undefined,
|
||||
keepalive: true,
|
||||
locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
|
||||
locales: [
|
||||
'af', 'ar', 'bg', 'ca', 'de', 'es', 'eu', 'en', 'fr', 'he',
|
||||
'hu', 'id', 'it', 'ja', 'nb', 'nl',
|
||||
'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'
|
||||
],
|
||||
message_carbons: true,
|
||||
nickname: undefined,
|
||||
password: undefined,
|
||||
prebind_url: null,
|
||||
priority: 0,
|
||||
registration_domain: '',
|
||||
rid: undefined,
|
||||
root: window.document,
|
||||
show_only_online_users: false,
|
||||
show_send_button: false,
|
||||
sid: undefined,
|
||||
storage: 'session',
|
||||
strict_plugin_dependencies: false,
|
||||
synchronize_availability: true,
|
||||
trusted: true,
|
||||
view_mode: 'overlayed', // Choices are 'overlayed', 'fullscreen', 'mobile'
|
||||
websocket_url: undefined,
|
||||
whitelisted_plugins: []
|
||||
};
|
||||
_.assignIn(this, this.default_settings);
|
||||
// Allow only whitelisted configuration attributes to be overwritten
|
||||
_.assignIn(this, _.pick(settings, _.keys(this.default_settings)));
|
||||
|
@ -649,6 +640,7 @@
|
|||
_converse.session.id = id; // Appears to be necessary for backbone.browserStorage
|
||||
_converse.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
|
||||
_converse.session.fetch();
|
||||
_converse.emit('sessionInitialized');
|
||||
};
|
||||
|
||||
this.clearSession = function () {
|
||||
|
@ -725,6 +717,7 @@
|
|||
if( document[hidden] !== undefined ) {
|
||||
_.partial(_converse.saveWindowState, _, hidden)({type: document[hidden] ? "blur" : "focus"});
|
||||
}
|
||||
_converse.emit('registeredGlobalEventHandlers');
|
||||
};
|
||||
|
||||
this.enableCarbons = function () {
|
||||
|
|
|
@ -37,24 +37,24 @@
|
|||
this.waitUntilFeaturesDiscovered = utils.getResolveablePromise();
|
||||
|
||||
this.dataforms = new Backbone.Collection();
|
||||
this.dataforms.browserStorage = new Backbone.BrowserStorage[_converse.storage](
|
||||
this.dataforms.browserStorage = new Backbone.BrowserStorage.session(
|
||||
b64_sha1(`converse.dataforms-{this.get('jid')}`)
|
||||
);
|
||||
|
||||
this.features = new Backbone.Collection();
|
||||
this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](
|
||||
this.features.browserStorage = new Backbone.BrowserStorage.session(
|
||||
b64_sha1(`converse.features-${this.get('jid')}`)
|
||||
);
|
||||
this.features.on('add', this.onFeatureAdded, this);
|
||||
|
||||
this.identities = new Backbone.Collection();
|
||||
this.identities.browserStorage = new Backbone.BrowserStorage[_converse.storage](
|
||||
this.identities.browserStorage = new Backbone.BrowserStorage.session(
|
||||
b64_sha1(`converse.identities-${this.get('jid')}`)
|
||||
);
|
||||
this.fetchFeatures();
|
||||
|
||||
this.items = new _converse.DiscoEntities();
|
||||
this.items.browserStorage = new Backbone.BrowserStorage[_converse.storage](
|
||||
this.items.browserStorage = new Backbone.BrowserStorage.session(
|
||||
b64_sha1(`converse.disco-items-${this.get('jid')}`)
|
||||
);
|
||||
this.items.fetch();
|
||||
|
@ -217,12 +217,34 @@
|
|||
return this;
|
||||
}
|
||||
|
||||
function initStreamFeatures () {
|
||||
_converse.stream_features = new Backbone.Collection();
|
||||
_converse.stream_features.browserStorage = new Backbone.BrowserStorage.session(
|
||||
b64_sha1(`converse.stream-features-${_converse.bare_jid}`)
|
||||
);
|
||||
_converse.stream_features.fetch({
|
||||
success (collection) {
|
||||
if (collection.length === 0 && _converse.connection.features) {
|
||||
_.forEach(
|
||||
_converse.connection.features.childNodes,
|
||||
(feature) => {
|
||||
_converse.stream_features.create({
|
||||
'name': feature.nodeName,
|
||||
'xmlns': feature.getAttribute('xmlns')
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
_converse.emit('streamFeaturesAdded');
|
||||
}
|
||||
|
||||
function initializeDisco () {
|
||||
addClientFeatures();
|
||||
_converse.connection.addHandler(onDiscoInfoRequest, Strophe.NS.DISCO_INFO, 'iq', 'get', null, null);
|
||||
|
||||
_converse.disco_entities = new _converse.DiscoEntities();
|
||||
_converse.disco_entities.browserStorage = new Backbone.BrowserStorage[_converse.storage](
|
||||
_converse.disco_entities.browserStorage = new Backbone.BrowserStorage.session(
|
||||
b64_sha1(`converse.disco-entities-${_converse.bare_jid}`)
|
||||
);
|
||||
|
||||
|
@ -236,6 +258,7 @@
|
|||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||
}
|
||||
|
||||
_converse.api.listen.on('sessionInitialized', initStreamFeatures);
|
||||
_converse.api.listen.on('reconnected', initializeDisco);
|
||||
_converse.api.listen.on('connected', initializeDisco);
|
||||
|
||||
|
@ -291,6 +314,15 @@
|
|||
* @namespace
|
||||
*/
|
||||
'disco': {
|
||||
'stream': {
|
||||
'getFeature': function (name, xmlns) {
|
||||
if (_.isNil(name) || _.isNil(xmlns)) {
|
||||
throw new Error("name and xmlns need to be provided when calling disco.stream.getFeature");
|
||||
}
|
||||
return _converse.stream_features.findWhere({'name': name, 'xmlns': xmlns});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The "own" grouping
|
||||
* @namespace
|
||||
|
|
|
@ -52,16 +52,6 @@
|
|||
//
|
||||
// New functions which don't exist yet can also be added.
|
||||
|
||||
registerGlobalEventHandlers () {
|
||||
const { _converse } = this.__super__;
|
||||
window.addEventListener("resize", _.debounce(function (ev) {
|
||||
if (_converse.connection.connected) {
|
||||
_converse.chatboxviews.trimChats();
|
||||
}
|
||||
}, 200));
|
||||
return this.__super__.registerGlobalEventHandlers.apply(this, arguments);
|
||||
},
|
||||
|
||||
ChatBox: {
|
||||
initialize () {
|
||||
this.__super__.initialize.apply(this, arguments);
|
||||
|
@ -541,6 +531,15 @@
|
|||
_converse.emit('minimizedChatsInitialized');
|
||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||
|
||||
|
||||
_converse.on('registeredGlobalEventHandlers', function () {
|
||||
window.addEventListener("resize", _.debounce(function (ev) {
|
||||
if (_converse.connection.connected) {
|
||||
_converse.chatboxviews.trimChats();
|
||||
}
|
||||
}, 200));
|
||||
});
|
||||
|
||||
_converse.on('controlBoxOpened', function (chatbox) {
|
||||
// Wrapped in anon method because at scan time, chatboxviews
|
||||
// attr not set yet.
|
||||
|
|
|
@ -492,8 +492,10 @@
|
|||
is_chatroom: true,
|
||||
events: {
|
||||
'change input.fileupload': 'onFileSelection',
|
||||
'click .chatbox-navback': 'showControlBox',
|
||||
'click .close-chatbox-button': 'close',
|
||||
'click .configure-chatroom-button': 'getAndRenderConfigurationForm',
|
||||
'click .hide-occupants': 'hideOccupants',
|
||||
'click .new-msgs-indicator': 'viewUnreadMessages',
|
||||
'click .occupant-nick': 'onOccupantClicked',
|
||||
'click .send-button': 'onFormSubmitted',
|
||||
|
@ -697,15 +699,32 @@
|
|||
setOccupantsVisibility () {
|
||||
const icon_el = this.el.querySelector('.toggle-occupants');
|
||||
if (this.model.get('hidden_occupants')) {
|
||||
this.el.querySelector('.chat-area').classList.add('full');
|
||||
u.removeClass('fa-angle-double-right', icon_el);
|
||||
u.addClass('fa-angle-double-left', icon_el);
|
||||
u.addClass('full', this.el.querySelector('.chat-area'));
|
||||
u.hideElement(this.el.querySelector('.occupants'));
|
||||
} else {
|
||||
this.el.querySelector('.chat-area').classList.remove('full');
|
||||
this.el.querySelector('.occupants').classList.remove('hidden');
|
||||
u.addClass('fa-angle-double-right', icon_el);
|
||||
u.removeClass('fa-angle-double-left', icon_el);
|
||||
u.removeClass('full', this.el.querySelector('.chat-area'));
|
||||
u.removeClass('hidden', this.el.querySelector('.occupants'));
|
||||
}
|
||||
this.occupantsview.setOccupantsHeight();
|
||||
},
|
||||
|
||||
hideOccupants (ev, preserve_state) {
|
||||
/* Show or hide the right sidebar containing the chat
|
||||
* occupants (and the invite widget).
|
||||
*/
|
||||
if (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
this.model.save({'hidden_occupants': true});
|
||||
this.setOccupantsVisibility();
|
||||
this.scrollDown();
|
||||
},
|
||||
|
||||
toggleOccupants (ev, preserve_state) {
|
||||
/* Show or hide the right sidebar containing the chat
|
||||
* occupants (and the invite widget).
|
||||
|
@ -1535,8 +1554,8 @@
|
|||
className: 'controlbox-section',
|
||||
id: 'chatrooms',
|
||||
events: {
|
||||
'click a.chatbox-btn.fa-users': 'showAddRoomModal',
|
||||
'click a.chatbox-btn.fa-list-ul': 'showListRoomsModal',
|
||||
'click a.chatbox-btn.show-add-muc-modal': 'showAddRoomModal',
|
||||
'click a.chatbox-btn.show-list-muc-modal': 'showListRoomsModal',
|
||||
'click a.room-info': 'toggleRoomInfo'
|
||||
},
|
||||
|
||||
|
|
|
@ -985,13 +985,18 @@
|
|||
},
|
||||
|
||||
onAvatarChanged () {
|
||||
const vcard = _converse.vcards.findWhere({'jid': this.get('from')});
|
||||
if (!vcard) { return; }
|
||||
|
||||
const hash = this.get('image_hash');
|
||||
if (hash && vcard.get('image_hash') !== hash) {
|
||||
_converse.api.vcard.update(vcard);
|
||||
const vcards = [];
|
||||
if (this.get('jid')) {
|
||||
vcards.push(this.updateVCard(_converse.vcards.findWhere({'jid': this.get('jid')})));
|
||||
}
|
||||
vcards.push(this.updateVCard(_converse.vcards.findWhere({'jid': this.get('from')})));
|
||||
|
||||
_.forEach(_.filter(vcards, undefined), (vcard) => {
|
||||
if (hash && vcard.get('image_hash') !== hash) {
|
||||
_converse.api.vcard.update(vcard);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getDisplayName () {
|
||||
|
@ -1032,6 +1037,7 @@
|
|||
// Remove absent occupants who've been removed from
|
||||
// the members lists.
|
||||
const occupant = this.findOccupant({'jid': removed_jid});
|
||||
if (!occupant) { return; }
|
||||
if (occupant.get('show') === 'offline') {
|
||||
occupant.destroy();
|
||||
}
|
||||
|
|
|
@ -62,16 +62,21 @@
|
|||
|
||||
LoginPanel: {
|
||||
|
||||
render: function (cfg) {
|
||||
insertRegisterLink () {
|
||||
const { _converse } = this.__super__;
|
||||
if (_.isUndefined(this.registerlinkview)) {
|
||||
this.registerlinkview = new _converse.RegisterLinkView({'model': this.model});
|
||||
this.registerlinkview.render();
|
||||
this.el.querySelector('.buttons').insertAdjacentElement('beforeend', this.registerlinkview.el);
|
||||
}
|
||||
this.registerlinkview.render();
|
||||
},
|
||||
|
||||
render (cfg) {
|
||||
const { _converse } = this.__super__;
|
||||
this.__super__.render.apply(this, arguments);
|
||||
if (_converse.allow_registration) {
|
||||
if (_.isUndefined(this.registerlinkview)) {
|
||||
this.registerlinkview = new _converse.RegisterLinkView({'model': this.model});
|
||||
this.registerlinkview.render();
|
||||
this.el.querySelector('.buttons').insertAdjacentElement('beforeend', this.registerlinkview.el);
|
||||
}
|
||||
this.registerlinkview.render();
|
||||
if (_converse.allow_registration && !_converse.auto_login) {
|
||||
this.insertRegisterLink();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -139,9 +144,10 @@
|
|||
_converse.CONNECTION_STATUS[Strophe.Status.NOTACCEPTABLE] = 'NOTACCEPTABLE';
|
||||
|
||||
_converse.api.settings.update({
|
||||
allow_registration: true,
|
||||
domain_placeholder: __(" e.g. conversejs.org"), // Placeholder text shown in the domain input on the registration form
|
||||
providers_link: 'https://xmpp.net/directory.php', // Link to XMPP providers shown on registration page
|
||||
'allow_registration': true,
|
||||
'domain_placeholder': __(" e.g. conversejs.org"), // Placeholder text shown in the domain input on the registration form
|
||||
'providers_link': 'https://xmpp.net/directory.php', // Link to XMPP providers shown on registration page
|
||||
'registration_domain': ''
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
const { _converse } = this,
|
||||
{ __ } = _converse;
|
||||
|
||||
_converse.api.settings.update({
|
||||
'allow_contact_requests': true,
|
||||
'auto_subscribe': false,
|
||||
'synchronize_availability': true,
|
||||
});
|
||||
|
||||
_converse.api.promises.add([
|
||||
'cachedRoster',
|
||||
'roster',
|
||||
|
@ -48,6 +54,13 @@
|
|||
_converse.roster = new _converse.RosterContacts();
|
||||
_converse.roster.browserStorage = new Backbone.BrowserStorage[_converse.storage](
|
||||
b64_sha1(`converse.contacts-${_converse.bare_jid}`));
|
||||
|
||||
_converse.roster.data = new Backbone.Model();
|
||||
const id = b64_sha1(`converse-roster-model-${_converse.bare_jid}`);
|
||||
_converse.roster.data.id = id;
|
||||
_converse.roster.data.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
|
||||
_converse.roster.data.fetch();
|
||||
|
||||
_converse.rostergroups = new _converse.RosterGroups();
|
||||
_converse.rostergroups.browserStorage = new Backbone.BrowserStorage[_converse.storage](
|
||||
b64_sha1(`converse.roster.groups${_converse.bare_jid}`));
|
||||
|
@ -330,28 +343,28 @@
|
|||
|
||||
onConnected () {
|
||||
/* Called as soon as the connection has been established
|
||||
* (either after initial login, or after reconnection).
|
||||
*
|
||||
* Use the opportunity to register stanza handlers.
|
||||
*/
|
||||
* (either after initial login, or after reconnection).
|
||||
*
|
||||
* Use the opportunity to register stanza handlers.
|
||||
*/
|
||||
this.registerRosterHandler();
|
||||
this.registerRosterXHandler();
|
||||
},
|
||||
|
||||
registerRosterHandler () {
|
||||
/* Register a handler for roster IQ "set" stanzas, which update
|
||||
* roster contacts.
|
||||
*/
|
||||
_converse.connection.addHandler(
|
||||
_converse.roster.onRosterPush.bind(_converse.roster),
|
||||
Strophe.NS.ROSTER, 'iq', "set"
|
||||
);
|
||||
* roster contacts.
|
||||
*/
|
||||
_converse.connection.addHandler((iq) => {
|
||||
_converse.roster.onRosterPush(iq);
|
||||
return true;
|
||||
}, Strophe.NS.ROSTER, 'iq', "set");
|
||||
},
|
||||
|
||||
registerRosterXHandler () {
|
||||
/* Register a handler for RosterX message stanzas, which are
|
||||
* used to suggest roster contacts to a user.
|
||||
*/
|
||||
* used to suggest roster contacts to a user.
|
||||
*/
|
||||
let t = 0;
|
||||
_converse.connection.addHandler(
|
||||
function (msg) {
|
||||
|
@ -375,12 +388,14 @@
|
|||
* Returns a promise which resolves once the contacts have been
|
||||
* fetched.
|
||||
*/
|
||||
const that = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.fetch({
|
||||
'add': true,
|
||||
'silent': true,
|
||||
success (collection) {
|
||||
if (collection.length === 0) {
|
||||
if (collection.length === 0 ||
|
||||
(that.rosterVersioningSupported() && !_converse.session.get('roster_fetched'))) {
|
||||
_converse.send_initial_presence = true;
|
||||
_converse.roster.fetchFromServer().then(resolve).catch(reject);
|
||||
} else {
|
||||
|
@ -506,30 +521,44 @@
|
|||
|
||||
onRosterPush (iq) {
|
||||
/* Handle roster updates from the XMPP server.
|
||||
* See: https://xmpp.org/rfcs/rfc6121.html#roster-syntax-actions-push
|
||||
*
|
||||
* Parameters:
|
||||
* (XMLElement) IQ - The IQ stanza received from the XMPP server.
|
||||
*/
|
||||
* See: https://xmpp.org/rfcs/rfc6121.html#roster-syntax-actions-push
|
||||
*
|
||||
* Parameters:
|
||||
* (XMLElement) IQ - The IQ stanza received from the XMPP server.
|
||||
*/
|
||||
const id = iq.getAttribute('id');
|
||||
const from = iq.getAttribute('from');
|
||||
if (from && from !== "" && Strophe.getBareJidFromJid(from) !== _converse.bare_jid) {
|
||||
// Receiving client MUST ignore stanza unless it has no from or from = user's bare JID.
|
||||
// XXX: Some naughty servers apparently send from a full
|
||||
// JID so we need to explicitly compare bare jids here.
|
||||
// https://github.com/jcbrand/converse.js/issues/493
|
||||
_converse.connection.send(
|
||||
$iq({type: 'error', id, from: _converse.connection.jid})
|
||||
.c('error', {'type': 'cancel'})
|
||||
.c('service-unavailable', {'xmlns': Strophe.NS.ROSTER })
|
||||
);
|
||||
return true;
|
||||
if (from && from !== _converse.connection.jid) {
|
||||
// https://tools.ietf.org/html/rfc6121#page-15
|
||||
//
|
||||
// A receiving client MUST ignore the stanza unless it has no 'from'
|
||||
// attribute (i.e., implicitly from the bare JID of the user's
|
||||
// account) or it has a 'from' attribute whose value matches the
|
||||
// user's bare JID <user@domainpart>.
|
||||
return;
|
||||
}
|
||||
_converse.connection.send($iq({type: 'result', id, from: _converse.connection.jid}));
|
||||
const items = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"] item`, iq);
|
||||
_.each(items, this.updateContact.bind(this));
|
||||
|
||||
const query = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"]`, iq).pop();
|
||||
this.data.save('version', query.getAttribute('ver'));
|
||||
|
||||
const items = sizzle(`item`, query);
|
||||
if (items.length > 1) {
|
||||
_converse.log(iq, Strophe.LogLevel.ERROR);
|
||||
throw new Error('Roster push query may not contain more than one "item" element.');
|
||||
}
|
||||
if (items.length === 0) {
|
||||
_converse.log(iq, Strophe.LogLevel.WARN);
|
||||
_converse.log('Received a roster push stanza without an "item" element.', Strophe.LogLevel.WARN);
|
||||
return;
|
||||
}
|
||||
this.updateContact(items.pop());
|
||||
_converse.emit('rosterPush', iq);
|
||||
return true;
|
||||
return;
|
||||
},
|
||||
|
||||
rosterVersioningSupported () {
|
||||
return _converse.api.disco.stream.getFeature('ver', 'urn:xmpp:features:rosterver') && this.data.get('version');
|
||||
},
|
||||
|
||||
fetchFromServer () {
|
||||
|
@ -539,7 +568,9 @@
|
|||
'type': 'get',
|
||||
'id': _converse.connection.getUniqueId('roster')
|
||||
}).c('query', {xmlns: Strophe.NS.ROSTER});
|
||||
|
||||
if (this.rosterVersioningSupported()) {
|
||||
iq.attrs({'ver': this.data.get('version')});
|
||||
}
|
||||
const callback = _.flow(this.onReceivedFromServer.bind(this), resolve);
|
||||
const errback = function (iq) {
|
||||
const errmsg = "Error while trying to fetch roster from the server";
|
||||
|
@ -552,17 +583,22 @@
|
|||
|
||||
onReceivedFromServer (iq) {
|
||||
/* An IQ stanza containing the roster has been received from
|
||||
* the XMPP server.
|
||||
*/
|
||||
const items = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"] item`, iq);
|
||||
_.each(items, this.updateContact.bind(this));
|
||||
* the XMPP server.
|
||||
*/
|
||||
const query = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"]`, iq).pop();
|
||||
if (query) {
|
||||
const items = sizzle(`item`, query);
|
||||
_.each(items, (item) => this.updateContact(item));
|
||||
this.data.save('version', query.getAttribute('ver'));
|
||||
_converse.session.save('roster_fetched', true);
|
||||
}
|
||||
_converse.emit('roster', iq);
|
||||
},
|
||||
|
||||
updateContact (item) {
|
||||
/* Update or create RosterContact models based on items
|
||||
* received in the IQ from the server.
|
||||
*/
|
||||
* received in the IQ from the server.
|
||||
*/
|
||||
const jid = item.getAttribute('jid');
|
||||
if (this.isSelf(jid)) { return; }
|
||||
|
||||
|
|
|
@ -80,7 +80,9 @@
|
|||
_converse.api.settings.update({
|
||||
'allow_chat_pending_contacts': true,
|
||||
'allow_contact_removal': true,
|
||||
'hide_offline_users': false,
|
||||
'roster_groups': true,
|
||||
'show_only_online_users': false,
|
||||
'show_toolbar': true,
|
||||
'xhr_user_search_url': null
|
||||
});
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
// Converse.js (A browser based XMPP chat client)
|
||||
// Converse.js
|
||||
// http://conversejs.org
|
||||
//
|
||||
// Copyright (c) 2012-2017, JC Brand <jc@opkode.com>
|
||||
// Copyright (c) 2012-2018, the Converse.js developers
|
||||
// Licensed under the Mozilla Public License (MPLv2)
|
||||
//
|
||||
/*global Backbone, define, window, JSON */
|
||||
|
||||
/* converse-singleton
|
||||
* ******************
|
||||
|
@ -39,10 +37,6 @@
|
|||
// NB: These plugins need to have already been loaded via require.js.
|
||||
dependencies: ['converse-chatboxes', 'converse-muc', 'converse-muc-views', 'converse-controlbox', 'converse-rosterview'],
|
||||
|
||||
enabled (_converse) {
|
||||
return _.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode);
|
||||
},
|
||||
|
||||
overrides: {
|
||||
// overrides mentioned here will be picked up by converse.js's
|
||||
// plugin architecture they will replace existing methods on the
|
||||
|
@ -50,21 +44,32 @@
|
|||
//
|
||||
// new functions which don't exist yet can also be added.
|
||||
ChatBoxes: {
|
||||
|
||||
chatBoxMayBeShown (chatbox) {
|
||||
return !chatbox.get('hidden');
|
||||
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
|
||||
return !chatbox.get('hidden');
|
||||
} else {
|
||||
return this.__super__.chatBoxMayBeShown.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
createChatBox (jid, attrs) {
|
||||
/* Make sure new chat boxes are hidden by default. */
|
||||
attrs = attrs || {};
|
||||
attrs.hidden = true;
|
||||
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
|
||||
attrs = attrs || {};
|
||||
attrs.hidden = true;
|
||||
}
|
||||
return this.__super__.createChatBox.call(this, jid, attrs);
|
||||
}
|
||||
},
|
||||
|
||||
ChatBoxView: {
|
||||
shouldShowOnTextMessage () {
|
||||
return false;
|
||||
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
|
||||
return false;
|
||||
} else {
|
||||
return this.__super__.shouldShowOnTextMessage.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
_show (focus) {
|
||||
|
@ -72,16 +77,20 @@
|
|||
* time. So before opening a chat, we make sure all other
|
||||
* chats are hidden.
|
||||
*/
|
||||
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
|
||||
this.model.set('hidden', false);
|
||||
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
|
||||
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
|
||||
this.model.set('hidden', false);
|
||||
}
|
||||
return this.__super__._show.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
ChatRoomView: {
|
||||
show (focus) {
|
||||
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
|
||||
this.model.set('hidden', false);
|
||||
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
|
||||
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
|
||||
this.model.set('hidden', false);
|
||||
}
|
||||
return this.__super__.show.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Converse.js
|
||||
// http://conversejs.org
|
||||
//
|
||||
// Copyright (c) 2012-2018, the Converse.js developers
|
||||
// Copyright (c) 2013-2018, the Converse.js developers
|
||||
// Licensed under the Mozilla Public License (MPLv2)
|
||||
|
||||
(function (root, factory) {
|
||||
|
@ -68,7 +68,9 @@
|
|||
'image_type': _.get(vcard.querySelector('PHOTO TYPE'), 'textContent'),
|
||||
'url': _.get(vcard.querySelector('URL'), 'textContent'),
|
||||
'role': _.get(vcard.querySelector('ROLE'), 'textContent'),
|
||||
'email': _.get(vcard.querySelector('EMAIL USERID'), 'textContent')
|
||||
'email': _.get(vcard.querySelector('EMAIL USERID'), 'textContent'),
|
||||
'vcard_updated': moment().format(),
|
||||
'vcard_error': undefined
|
||||
};
|
||||
}
|
||||
if (result.image) {
|
||||
|
@ -82,7 +84,11 @@
|
|||
|
||||
function onVCardError (_converse, jid, iq, errback) {
|
||||
if (errback) {
|
||||
errback({'stanza': iq, 'jid': jid});
|
||||
errback({
|
||||
'stanza': iq,
|
||||
'jid': jid,
|
||||
'vcard_error': moment().format()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,8 +147,11 @@
|
|||
'get' (model, force) {
|
||||
if (_.isString(model)) {
|
||||
return getVCard(_converse, model);
|
||||
} else if (!model.get('vcard_updated') || force) {
|
||||
const jid = model.get('jid') || model.get('muc_jid');
|
||||
} else if (force ||
|
||||
!model.get('vcard_updated') ||
|
||||
!moment(model.get('vcard_error')).isSame(new Date(), "day")) {
|
||||
|
||||
const jid = model.get('jid');
|
||||
if (!jid) {
|
||||
throw new Error("No JID to get vcard for!");
|
||||
}
|
||||
|
@ -155,10 +164,8 @@
|
|||
'update' (model, force) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.get(model, force).then((vcard) => {
|
||||
model.save(_.extend(
|
||||
_.pick(vcard, ['fullname', 'nickname', 'email', 'url', 'role', 'image_type', 'image', 'image_hash']),
|
||||
{'vcard_updated': moment().format()}
|
||||
));
|
||||
delete vcard['stanza']
|
||||
model.save(vcard);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<div class="chat-head chat-head-chatbox row no-gutters">
|
||||
<div class="col">
|
||||
<div class="chatbox-navback"><i class="fa fa-arrow-left"></i></div>
|
||||
<div class="chatbox-title">
|
||||
<div class="row no-gutters">
|
||||
<canvas class="avatar" height="36" width="36"></canvas>
|
||||
<div class="col chat-title" title="{{{o.jid}}}">
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<div class="chatbox-navback"><i class="fa fa-arrow-left"></i></div>
|
||||
<div class="chatbox-title">
|
||||
<div class="chat-title" title="{{{o.jid}}}">
|
||||
{[ if (o.name && o.name !== o.Strophe.getNodeFromJid(o.jid)) { ]}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<!-- <div class="occupants"> -->
|
||||
<p class="occupants-heading">{{{o.label_occupants}}}</p>
|
||||
<div class="occupants-header">
|
||||
<i class="hide-occupants fa fa-times"></i>
|
||||
<p class="occupants-heading">{{{o.label_occupants}}}</p>
|
||||
</div>
|
||||
<ul class="occupant-list"></ul>
|
||||
<div class="chatroom-features"></div>
|
||||
<!-- </div> -->
|
||||
|
|
|
@ -8,5 +8,5 @@
|
|||
<li class="toggle-call fa fa-phone" title="{{{o.label_start_call}}}"></li>
|
||||
{[ } ]}
|
||||
{[ if (o.show_occupants_toggle) { ]}
|
||||
<li class="toggle-occupants fa fa-users" title="{{{o.label_hide_occupants}}}"></li>
|
||||
<li class="toggle-occupants fa fa-angle-double-right" title="{{{o.label_hide_occupants}}}"></li>
|
||||
{[ } ]}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<!-- <div id="chatrooms"> -->
|
||||
<div class="d-flex controlbox-padded">
|
||||
<span class="w-100 controlbox-heading">{{{o.heading_chatrooms}}}</span>
|
||||
<a class="chatbox-btn trigger-list-chatrooms-modal fa fa-list-ul" title="{{{o.title_list_rooms}}}" data-toggle="modal" data-target="#list-chatrooms-modal"></a>
|
||||
<a class="chatbox-btn trigger-add-chatrooms-modal fa fa-users" title="{{{o.title_new_room}}}" data-toggle="modal" data-target="#add-chatrooms-modal"></a>
|
||||
<a class="chatbox-btn show-list-muc-modal fa fa-list-ul" title="{{{o.title_list_rooms}}}" data-toggle="modal" data-target="#list-chatrooms-modal"></a>
|
||||
<a class="chatbox-btn show-add-muc-modal fa fa-plus" title="{{{o.title_new_room}}}" data-toggle="modal" data-target="#add-chatrooms-modal"></a>
|
||||
</div>
|
||||
<div class="list-container open-rooms-list rooms-list-container"></div>
|
||||
<div class="list-container bookmarks-list rooms-list-container"></div>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
var _ = converse.env._;
|
||||
var Promise = converse.env.Promise;
|
||||
var Strophe = converse.env.Strophe;
|
||||
var moment = converse.env.moment;
|
||||
var $iq = converse.env.$iq;
|
||||
var mock = {};
|
||||
|
||||
|
@ -62,6 +63,18 @@
|
|||
this.IQ_ids.push(id);
|
||||
return id;
|
||||
}
|
||||
c.features = Strophe.xmlHtmlNode(
|
||||
'<stream:features xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">'+
|
||||
'<ver xmlns="urn:xmpp:features:rosterver"/>'+
|
||||
'<csi xmlns="urn:xmpp:csi:0"/>'+
|
||||
'<c xmlns="http://jabber.org/protocol/caps" ver="UwBpfJpEt3IoLYfWma/o/p3FFRo=" hash="sha-1" node="http://prosody.im"/>'+
|
||||
'<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">'+
|
||||
'<required/>'+
|
||||
'</bind>'+
|
||||
'<session xmlns="urn:ietf:params:xml:ns:xmpp-session">'+
|
||||
'<optional/>'+
|
||||
'</session>'+
|
||||
'</stream:features>').firstChild;
|
||||
|
||||
c._proto._connect = function () {
|
||||
c.authenticated = true;
|
||||
|
@ -99,6 +112,7 @@
|
|||
}, settings || {}));
|
||||
|
||||
_converse.ChatBoxViews.prototype.trimChat = function () {};
|
||||
|
||||
_converse.api.vcard.get = function (model, force) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let jid;
|
||||
|
@ -120,11 +134,13 @@
|
|||
}
|
||||
var vcard = $iq().c('vCard').c('FN').t(fullname).nodeTree;
|
||||
var result = {
|
||||
'stanza': vcard,
|
||||
'vcard': vcard,
|
||||
'fullname': _.get(vcard.querySelector('FN'), 'textContent'),
|
||||
'image': _.get(vcard.querySelector('PHOTO BINVAL'), 'textContent'),
|
||||
'image_type': _.get(vcard.querySelector('PHOTO TYPE'), 'textContent'),
|
||||
'url': _.get(vcard.querySelector('URL'), 'textContent')
|
||||
'url': _.get(vcard.querySelector('URL'), 'textContent'),
|
||||
'vcard_updated': moment().format(),
|
||||
'vcard_error': undefined
|
||||
};
|
||||
resolve(result);
|
||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
return new Promise(function (resolve, reject) {
|
||||
utils.openControlBox(_converse);
|
||||
var roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
||||
roomspanel.el.querySelector('.trigger-add-chatrooms-modal').click();
|
||||
roomspanel.el.querySelector('.show-add-muc-modal').click();
|
||||
utils.closeControlBox(_converse);
|
||||
const modal = roomspanel.add_room_modal;
|
||||
utils.waitUntil(function () {
|
||||
|
|
Loading…
Reference in New Issue
Block a user