Render the brand heading as a component

This commit is contained in:
JC Brand 2020-10-01 17:00:38 +02:00
parent 24ddbefb63
commit 383b6a27c3
15 changed files with 164 additions and 173 deletions

9
package-lock.json generated
View File

@ -11874,6 +11874,15 @@
"minimalistic-assert": "^1.0.1"
}
},
"haunted": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/haunted/-/haunted-4.7.0.tgz",
"integrity": "sha512-ajsUengbSL2ELljJ2VLU2o5BfG/drzZV+BvSLALvIBx+24owmxC5iW7+SK/Y667JaVmratEPR010bYpGKAt7ow==",
"dev": true,
"requires": {
"lit-html": "^1.0.0"
}
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",

View File

@ -79,6 +79,7 @@
"exports-loader": "^0.7.0",
"fast-text-encoding": "^1.0.2",
"file-loader": "^6.0.0",
"haunted": "^4.7.0",
"html-webpack-plugin": "^4.3.0",
"http-server": "^0.12.3",
"imports-loader": "^0.8.0",

View File

@ -67,9 +67,21 @@
#controlbox {
order: -1;
color: var(--controlbox-text-color);
converse-brand-heading {
width: 100%;
display: block;
}
.brand-name-wrapper {
font-size: 200%;
}
.brand-name-wrapper--fullscreen {
font-size: 100%;
}
.open-rooms-toggle, .open-rooms-toggle .fa {
color: var(--groupchats-header-color) !important;
&:hover {
@ -78,7 +90,7 @@
}
.box-flyout {
background-color: white;
background-color: var(--controlbox-pane-background-color);
}
margin-right: calc(3 * var(--chat-gutter));
@ -178,11 +190,7 @@
}
#converse-login-panel {
flex-direction: column;
.brand-heading {
color: var(--global-background-color);
}
flex-direction: row;
}
.toggle-register-login {
@ -411,10 +419,6 @@
}
}
.brand-heading-container {
width: 100%;
}
.controlbox-head {
display: flex;
flex-direction: row-reverse;
@ -497,7 +501,7 @@
line-height: var(--line-height-huge);
}
.brand-heading-container {
converse-brand-heading {
@include make-col(12);
margin-top: 5em;
margin-bottom: 1em;

View File

@ -137,7 +137,7 @@ body.converse-fullscreen {
width: 100%;
}
.brand-heading-container {
converse-brand-heading {
text-align: center;
}
@ -147,43 +147,62 @@ body.converse-fullscreen {
align-items: flex-start;
font-family: var(--branding-font);
color: var(--link-color);
margin-bottom: 1em;
margin-bottom: 0.75em;
.brand-name {
color: var(--link-color);
display: flex;
flex-direction: column;
align-items: center;
margin-top: -0.5em;
}
.brand-name-wrapper {
display: flex;
white-space: nowrap;
margin: auto;
}
.brand-name__text {
font-size: 120%;
vertical-align: text-bottom;
}
.brand-name {
color: var(--link-color);
display: flex;
flex-direction: column;
align-items: center;
margin-top: -0.25em;
.converse-svg-logo {
color: var(--link-color);
height: 1.5em;
margin-right: 0.25em;
margin-bottom: -0.25em;
.cls-1 {
isolation: isolate;
}
.cls-2 {
opacity: 0.5;
mix-blend-mode: multiply;
}
.cls-3 {
fill: var(--link-color);
}
.cls-4 {
fill: var(--link-color);
}
}
}
.byline {
font-family: var(--heading-font);
font-size: 0.3em;
margin-bottom: 0.75em;
margin-left: -2.7em;
opacity: 0.55;
word-spacing: 5px;
}
}
.brand-heading--inverse {
.brand-subtitle {
color: var(--text-color);
}
.brand-name__text {
font-size: 120%;
vertical-align: text-bottom;
}
.converse-svg-logo {
color: var(--link-color);
height: 1.5em;
margin-right: 0.25em;
margin-bottom: -0.25em;
.cls-1 {
isolation: isolate;
}
.cls-2 {
opacity: 0.5;
mix-blend-mode: multiply;
}
.cls-3 {
fill: var(--link-color);
}
.cls-4 {
fill: var(--link-color);
}
}
}
.brand-heading--inverse {
.converse-svg-logo {
margin-bottom: 0em;
margin-top: -0.2em;

View File

@ -260,27 +260,14 @@ describe("Chatboxes", function () {
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse);
const contact_jid = mock.cur_names[7].replace(/ /g,'.').toLowerCase() + '@montague.lit';
await u.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length);
await mock.openChatBoxFor(_converse, contact_jid);
const controlview = _converse.chatboxviews.get('controlbox'), // The controlbox is currently open
chatview = _converse.chatboxviews.get(contact_jid);
const chatview = _converse.chatboxviews.get(contact_jid);
spyOn(chatview, 'close').and.callThrough();
spyOn(controlview, 'close').and.callThrough();
spyOn(_converse.api, "trigger").and.callThrough();
// We need to rebind all events otherwise our spy won't be called
controlview.delegateEvents();
chatview.delegateEvents();
controlview.el.querySelector('.close-chatbox-button').click();
expect(controlview.close).toHaveBeenCalled();
await new Promise(resolve => _converse.api.listen.once('chatBoxClosed', resolve));
expect(_converse.api.trigger).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
chatview.el.querySelector('.close-chatbox-button').click();
expect(chatview.close).toHaveBeenCalled();
await new Promise(resolve => _converse.api.listen.once('chatBoxClosed', resolve));

View File

@ -33,6 +33,27 @@ describe("The Controlbox", function () {
done();
}));
it("can be closed by clicking a DOM element with class 'close-chatbox-button'",
mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
await mock.openControlBox(_converse);
const controlview = _converse.chatboxviews.get('controlbox');
spyOn(controlview, 'close').and.callThrough();
spyOn(_converse.api, "trigger").and.callThrough();
// We need to rebind all events otherwise our spy won't be called
controlview.delegateEvents();
controlview.el.querySelector('.close-chatbox-button').click();
expect(controlview.close).toHaveBeenCalled();
await new Promise(resolve => _converse.api.listen.once('chatBoxClosed', resolve));
expect(_converse.api.trigger).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
done();
}));
describe("The \"Contacts\" section", function () {
it("can be used to add contact and it checks for case-sensivity",

View File

@ -0,0 +1,42 @@
import { api } from "@converse/headless/converse-core";
import { component } from 'haunted';
import { html } from 'lit-html';
export const ConverseBrandHeading = (o) => {
const is_fullscreen = api.settings.get('view_mode') === 'fullscreen';
return html`
<a class="brand-heading" href="https://conversejs.org" target="_blank" rel="noopener">
<span class="brand-name-wrapper ${is_fullscreen ? 'brand-name-wrapper--fullscreen' : '' }">
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Converse</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>
<span class="brand-name">
<span class="brand-name__text">converse<span class="subdued">.js</span></span>
${ is_fullscreen ? html`<p class="byline">messaging freedom</p>` : '' }
</span>
</span>
</a>
${ is_fullscreen ? html`
<p class="brand-subtitle">${o.version_name}</p>
<p class="brand-subtitle"><a target="_blank" rel="nofollow" href="https://conversejs.org">Open Source</a> XMPP chat client brought to you by <a target="_blank" rel="nofollow" href="https://opkode.com">Opkode</a> </p>
<p class="brand-subtitle"><a target="_blank" rel="nofollow" href="https://hosted.weblate.org/projects/conversejs/#languages">Translate</a> it into your own language</p>` : '' }
`;
}
api.elements.define('converse-brand-heading', component(ConverseBrandHeading, {'useShadowDOM': false}));

View File

@ -4,16 +4,17 @@
* @license Mozilla Public License (MPLv2)
*/
import "converse-chatview";
import "./components/brand-heading";
import bootstrap from "bootstrap.native";
import log from "@converse/headless/log";
import tpl_brand_heading from "templates/converse_brand_heading.html";
import tpl_controlbox from "templates/controlbox.html";
import tpl_controlbox from "templates/controlbox.js";
import tpl_controlbox_toggle from "templates/controlbox_toggle.html";
import tpl_login_panel from "templates/login_panel.js";
import { Model } from '@converse/skeletor/src/model.js';
import { View } from "@converse/skeletor/src/view";
import { __ } from './i18n';
import { _converse, api, converse } from "@converse/headless/converse-core";
import { render } from 'lit-html';
const { Strophe, dayjs } = converse.env;
const u = converse.env.utils;
@ -198,7 +199,12 @@ converse.plugins.add('converse-controlbox', {
this.model.set('closed', !api.settings.get('show_controlbox_by_default'));
}
}
this.el.innerHTML = tpl_controlbox(Object.assign(this.model.toJSON()));
const tpl_result = tpl_controlbox({
'sticky_controlbox': api.settings.get('sticky_controlbox'),
...this.model.toJSON()
});
render(tpl_result, this.el);
if (!this.model.get('closed')) {
this.show();
@ -221,22 +227,6 @@ converse.plugins.add('converse-controlbox', {
}
},
createBrandHeadingHTML () {
return tpl_brand_heading({
'sticky_controlbox': api.settings.get('sticky_controlbox')
});
},
insertBrandHeading () {
const heading_el = this.el.querySelector('.brand-heading-container');
if (heading_el === null) {
const el = this.el.querySelector('.controlbox-head');
el.insertAdjacentHTML('beforeend', this.createBrandHeadingHTML());
} else {
heading_el.outerHTML = this.createBrandHeadingHTML();
}
},
renderLoginPanel () {
this.el.classList.add("logged-out");
if (this.loginpanel) {
@ -248,7 +238,6 @@ converse.plugins.add('converse-controlbox', {
const panes = this.el.querySelector('.controlbox-panes');
panes.innerHTML = '';
panes.appendChild(this.loginpanel.render().el);
this.insertBrandHeading();
}
this.loginpanel.initPopovers();
return this;

View File

@ -7,8 +7,7 @@ import "@converse/headless/converse-muc";
import "converse-chatview";
import "converse-controlbox";
import "converse-singleton";
import { _converse, api, converse } from "@converse/headless/converse-core";
import tpl_brand_heading from "templates/inverse_brand_heading.html";
import { api, converse } from "@converse/headless/converse-core";
converse.plugins.add('converse-fullscreen', {
@ -17,30 +16,6 @@ converse.plugins.add('converse-fullscreen', {
return _converse.isUniView();
},
overrides: {
// overrides mentioned here will be picked up by converse.js's
// plugin architecture they will replace existing methods on the
// relevant objects or classes.
//
// new functions which don't exist yet can also be added.
ControlBoxView: {
createBrandHeadingHTML() {
return tpl_brand_heading({
'version_name': _converse.VERSION_NAME
});
},
insertBrandHeading () {
const el = _converse.root.getElementById('converse-login-panel');
el.parentNode.insertAdjacentHTML(
'afterbegin',
this.createBrandHeadingHTML()
);
}
}
},
initialize () {
api.settings.extend({
chatview_avatar_height: 50,

View File

@ -1,8 +0,0 @@
<div class="flyout box-flyout">
<div class="chat-head controlbox-head">
{[ if (!o.sticky_controlbox) { ]}
<a class="chatbox-btn close-chatbox-button fa fa-times"></a>
{[ } ]}
</div>
<div class="controlbox-panes"></div>
</div>

View File

@ -0,0 +1,9 @@
import { html } from 'lit-html';
export default (o) => html`
<div class="flyout box-flyout">
<div class="chat-head controlbox-head">
${o.sticky_controlbox ? '' : html`<a class="chatbox-btn close-chatbox-button fa fa-times"></a>` }
</div>
<div class="controlbox-panes"></div>
</div>`;

View File

@ -1,26 +0,0 @@
<span class="brand-heading-container">
<a class="brand-heading" href="https://conversejs.org" target="_blank" rel="noopener">
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Converse</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>
<span class="brand-name">
<span class="brand-name__text">converse<span class="subdued">.js</span></span>
</span>
</a>
</span>

View File

@ -1,32 +0,0 @@
<div>
<div class="container brand-heading-container">
<h1 class="brand-heading brand-heading--inverse">
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Converse</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>
<span class="brand-name">
<span class="brand-name__text">converse<span class="subdued">.js</span></span>
<p class="byline">messaging freedom</p>
</span>
</h1>
<p class="brand-subtitle">{{{o.version_name}}}</p>
<p class="brand-subtitle"><a target="_blank" rel="nofollow" href="https://conversejs.org">Open Source</a> XMPP chat client brought to you by <a target="_blank" rel="nofollow" href="https://opkode.com">Opkode</a> </p>
<p class="brand-subtitle"><a target="_blank" rel="nofollow" href="https://hosted.weblate.org/projects/conversejs/#languages">Translate</a> it into your own language</p>
</div>
</div>

View File

@ -87,6 +87,7 @@ const form_fields = (o) => {
export default (o) => html`
<converse-brand-heading></converse-brand-heading>
<form id="converse-login" class="converse-form" method="post">
<div class="conn-feedback fade-in ${ !o.conn_feedback_subject ? 'hidden' : o.conn_feedback_class }">
<p class="feedback-subject">${ o.conn_feedback_subject }</p>

View File

@ -56,7 +56,7 @@ export default (o) => {
<span class="modal-alert"></span>
<br/>
<div class="container brand-heading-container">
<div class="container">
<h6 class="brand-heading">Converse</h6>
<p class="brand-subtitle">${o.version_name}</p>
<p class="brand-subtitle">${unsafeHTML(xss.filterXSS(first_subtitle, {'whiteList': {'a': []}}))}</p>