Commit 11cd6b83 authored by JC Brand's avatar JC Brand

Fixes #2193.

Translations called at the top of template files don't apply, since the
trnaslations aren't yet fetched at that point.
parent 3e8b3f73
......@@ -1544,7 +1544,7 @@ Object.assign(converse, {
/^converse\?loglevel=(debug|info|warn|error|fatal)$/, 'loglevel',
l => log.setLogLevel(l)
);
initLocale();
await initLocale();
_converse.connfeedback = new _converse.ConnectionFeedback();
/* When reloading the page:
......
......@@ -4,40 +4,43 @@ import { __ } from '@converse/headless/i18n';
import { modal_header_close_button } from "./buttons"
import xss from "xss/dist/xss";
const i18n_join = __('Join');
const i18n_enter = __('Enter a new Groupchat');
const i18n_nickname = __('Nickname');
const i18n_required_field = __('This field is required');
const nickname_input = (o) => html`
<div class="form-group" >
<label for="nickname">${i18n_nickname}:</label>
<input type="text" title="${i18n_required_field}" required="required" name="nickname" value="${o.nick || ''}" class="form-control"/>
</div>
`;
const nickname_input = (o) => {
const i18n_nickname = __('Nickname');
const i18n_required_field = __('This field is required');
return html`
<div class="form-group" >
<label for="nickname">${i18n_nickname}:</label>
<input type="text" title="${i18n_required_field}" required="required" name="nickname" value="${o.nick || ''}" class="form-control"/>
</div>
`;
}
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="add-chatroom-modal-label">${i18n_enter}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
<span class="modal-alert"></span>
<form class="converse-form add-chatroom">
<div class="form-group">
<label for="chatroom">${o.label_room_address}:</label>
${ (o.muc_roomid_policy_error_msg) ? html`<label class="roomid-policy-error">${o.muc_roomid_policy_error_msg}</label>` : '' }
<input type="text" required="required" name="chatroom" class="form-control roomjid-input" placeholder="${o.chatroom_placeholder}"/>
</div>
${ o.muc_roomid_policy_hint ? html`<div class="form-group">${unsafeHTML(xss.filterXSS(o.muc_roomid_policy_hint, {'whiteList': {b: [], br: [], em: []}}))}</div>` : '' }
${ !o._converse.locked_muc_nickname ? nickname_input(o) : '' }
<input type="submit" class="btn btn-primary" name="join" value="${i18n_join || ''}" ?disabled=${o.muc_roomid_policy_error_msg}>
</form>
export default (o) => {
const i18n_join = __('Join');
const i18n_enter = __('Enter a new Groupchat');
return html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="add-chatroom-modal-label">${i18n_enter}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
<span class="modal-alert"></span>
<form class="converse-form add-chatroom">
<div class="form-group">
<label for="chatroom">${o.label_room_address}:</label>
${ (o.muc_roomid_policy_error_msg) ? html`<label class="roomid-policy-error">${o.muc_roomid_policy_error_msg}</label>` : '' }
<input type="text" required="required" name="chatroom" class="form-control roomjid-input" placeholder="${o.chatroom_placeholder}"/>
</div>
${ o.muc_roomid_policy_hint ? html`<div class="form-group">${unsafeHTML(xss.filterXSS(o.muc_roomid_policy_hint, {'whiteList': {b: [], br: [], em: []}}))}</div>` : '' }
${ !o._converse.locked_muc_nickname ? nickname_input(o) : '' }
<input type="submit" class="btn btn-primary" name="join" value="${i18n_join || ''}" ?disabled=${o.muc_roomid_policy_error_msg}>
</form>
</div>
</div>
</div>
</div>
`;
`;
}
......@@ -2,51 +2,52 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
import { modal_header_close_button } from "./buttons"
const i18n_contact_placeholder = __('name@example.org');
const i18n_add = __('Add');
const i18n_error_message = __('Please enter a valid XMPP address');
const i18n_new_contact = __('Add a Contact');
const i18n_xmpp_address = __('XMPP Address');
const i18n_nickname = __('Nickname');
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addContactModalLabel">${i18n_new_contact}</h5>
${modal_header_close_button}
</div>
<form class="converse-form add-xmpp-contact">
<div class="modal-body">
<span class="modal-alert"></span>
<div class="form-group add-xmpp-contact__jid">
<label class="clearfix" for="jid">${i18n_xmpp_address}:</label>
<div class="suggestion-box suggestion-box__jid">
<ul class="suggestion-box__results suggestion-box__results--above" hidden=""></ul>
<input type="text" name="jid" ?required=${(!o._converse.xhr_user_search_url)}
value="${o.jid || ''}"
class="form-control suggestion-box__input"
placeholder="${i18n_contact_placeholder}"/>
<span class="suggestion-box__additions visually-hidden" role="status" aria-live="assertive" aria-relevant="additions"></span>
export default (o) => {
const i18n_contact_placeholder = __('name@example.org');
const i18n_add = __('Add');
const i18n_error_message = __('Please enter a valid XMPP address');
const i18n_new_contact = __('Add a Contact');
const i18n_xmpp_address = __('XMPP Address');
const i18n_nickname = __('Nickname');
return html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addContactModalLabel">${i18n_new_contact}</h5>
${modal_header_close_button}
</div>
<form class="converse-form add-xmpp-contact">
<div class="modal-body">
<span class="modal-alert"></span>
<div class="form-group add-xmpp-contact__jid">
<label class="clearfix" for="jid">${i18n_xmpp_address}:</label>
<div class="suggestion-box suggestion-box__jid">
<ul class="suggestion-box__results suggestion-box__results--above" hidden=""></ul>
<input type="text" name="jid" ?required=${(!o._converse.xhr_user_search_url)}
value="${o.jid || ''}"
class="form-control suggestion-box__input"
placeholder="${i18n_contact_placeholder}"/>
<span class="suggestion-box__additions visually-hidden" role="status" aria-live="assertive" aria-relevant="additions"></span>
</div>
</div>
</div>
<div class="form-group add-xmpp-contact__name">
<label class="clearfix" for="name">${i18n_nickname}:</label>
<div class="suggestion-box suggestion-box__name">
<ul class="suggestion-box__results suggestion-box__results--above" hidden=""></ul>
<input type="text" name="name" value="${o.nickname || ''}"
class="form-control suggestion-box__input"
placeholder="${i18n_nickname}"/>
<span class="suggestion-box__additions visually-hidden" role="status" aria-live="assertive" aria-relevant="additions"></span>
<div class="form-group add-xmpp-contact__name">
<label class="clearfix" for="name">${i18n_nickname}:</label>
<div class="suggestion-box suggestion-box__name">
<ul class="suggestion-box__results suggestion-box__results--above" hidden=""></ul>
<input type="text" name="name" value="${o.nickname || ''}"
class="form-control suggestion-box__input"
placeholder="${i18n_nickname}"/>
<span class="suggestion-box__additions visually-hidden" role="status" aria-live="assertive" aria-relevant="additions"></span>
</div>
</div>
<div class="form-group">
<div class="invalid-feedback">${i18n_error_message}</div>
</div>
<button type="submit" class="btn btn-primary">${i18n_add}</button>
</div>
<div class="form-group">
<div class="invalid-feedback">${i18n_error_message}</div>
</div>
<button type="submit" class="btn btn-primary">${i18n_add}</button>
</div>
</form>
</form>
</div>
</div>
</div>
`;
`;
}
......@@ -2,36 +2,38 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const desc_bookmarks = __('Click to toggle the bookmarks list');
const info_remove_bookmark = __('Unbookmark this groupchat');
const label_bookmarks = __('Bookmarks');
const open_title = __('Click to open this groupchat');
const bookmark_item = (o) => {
const info_remove_bookmark = __('Unbookmark this groupchat');
const open_title = __('Click to open this groupchat');
return html`
<div class="list-item controlbox-padded room-item available-chatroom d-flex flex-row ${ (o.is_hidden(o.bm)) ? 'hidden' : ''}" data-room-jid="${o.bm.get('jid')}">
<a class="list-item-link open-room w-100" data-room-jid="${o.bm.get('jid')}"
title="${open_title}"
@click=${o.openRoom}>${o.bm.getDisplayName()}</a>
<a class="list-item-action remove-bookmark fa fa-bookmark align-self-center ${ o.bm.get('bookmarked') ? 'button-on' : '' }"
data-room-jid="${o.bm.get('jid')}"
data-bookmark-name="${o.bm.getDisplayName()}"
title="${info_remove_bookmark}"
@click=${o.removeBookmark}></a>
</div>
`;
}
const bookmark_item = (o) => html`
<div class="list-item controlbox-padded room-item available-chatroom d-flex flex-row ${ (o.is_hidden(o.bm)) ? 'hidden' : ''}" data-room-jid="${o.bm.get('jid')}">
<a class="list-item-link open-room w-100" data-room-jid="${o.bm.get('jid')}"
title="${open_title}"
@click=${o.openRoom}>${o.bm.getDisplayName()}</a>
<a class="list-item-action remove-bookmark fa fa-bookmark align-self-center ${ o.bm.get('bookmarked') ? 'button-on' : '' }"
data-room-jid="${o.bm.get('jid')}"
data-bookmark-name="${o.bm.getDisplayName()}"
title="${info_remove_bookmark}"
@click=${o.removeBookmark}></a>
</div>
`;
export default (o) => html`
<div class="list-container list-container--bookmarks ${ !o.hidden && 'hidden' || '' }">
<a class="list-toggle bookmarks-toggle controlbox-padded"
title="${desc_bookmarks}"
@click=${o.toggleBookmarksList}>
export default (o) => {
const desc_bookmarks = __('Click to toggle the bookmarks list');
const label_bookmarks = __('Bookmarks');
return html`
<div class="list-container list-container--bookmarks ${ !o.hidden && 'hidden' || '' }">
<a class="list-toggle bookmarks-toggle controlbox-padded"
title="${desc_bookmarks}"
@click=${o.toggleBookmarksList}>
<span class="fa ${(o.toggle_state === o._converse.OPENED) ? 'fa-caret-down' : 'fa-caret-right' }">
</span> ${label_bookmarks}</a>
<div class="items-list bookmarks rooms-list ${ (o.toggle_state !== o._converse.OPENED) ? 'hidden' : '' }">
${ o.bookmarks.map(bm => bookmark_item(Object.assign({bm}, o))) }
<span class="fa ${(o.toggle_state === o._converse.OPENED) ? 'fa-caret-down' : 'fa-caret-right' }">
</span> ${label_bookmarks}</a>
<div class="items-list bookmarks rooms-list ${ (o.toggle_state !== o._converse.OPENED) ? 'hidden' : '' }">
${ o.bookmarks.map(bm => bookmark_item(Object.assign({bm}, o))) }
</div>
</div>
</div>
`;
`;
}
import { __ } from '@converse/headless/i18n';
import { html } from "lit-html";
const i18n_close = __('Close');
export const modal_close_button = html`<button type="button" class="btn btn-secondary" data-dismiss="modal">${i18n_close}</button>`;
export const modal_close_button = html`<button type="button" class="btn btn-secondary" data-dismiss="modal">${__('Close')}</button>`;
export const modal_header_close_button = html`<button type="button" class="close" data-dismiss="modal" aria-label="${i18n_close}"><span aria-hidden="true">×</span></button>`;
export const modal_header_close_button = html`<button type="button" class="close" data-dismiss="modal" aria-label="${__('Close')}"><span aria-hidden="true">×</span></button>`;
......@@ -3,10 +3,8 @@ import { __ } from '@converse/headless/i18n';
import { renderAvatar } from './../templates/directives/avatar';
const i18n_new_messages = __('New messages');
export default (o) => {
const i18n_new_messages = __('New messages');
return html`
${ o.is_first_unread ? html`<div class="message date-separator"><hr class="separator"><span class="separator-text">${ i18n_new_messages }</span></div>` : '' }
<div class="message chat-msg ${ o.getExtraMessageClasses() }"
......
......@@ -3,19 +3,17 @@ import { __ } from '@converse/headless/i18n';
import { until } from 'lit-html/directives/until.js';
import avatar from "./avatar.js";
const i18n_profile = __('The User\'s Profile Image');
const avatar_data = {
'alt_text': i18n_profile,
'extra_classes': '',
'height': 40,
'width': 40,
}
const tpl_standalone_btns = (o) => o.standalone_btns.reverse().map(b => until(b, ''));
export default (o) => {
const i18n_profile = __('The User\'s Profile Image');
const avatar_data = {
'alt_text': i18n_profile,
'extra_classes': '',
'height': 40,
'width': 40,
}
const tpl_standalone_btns = (o) => o.standalone_btns.reverse().map(b => until(b, ''));
return html`
<div class="chatbox-title ${ o.status ? '' : "chatbox-title--no-desc"}">
<div class="chatbox-title--row">
......
......@@ -5,83 +5,85 @@ import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
import xss from "xss/dist/xss";
const i18n_address = __('Groupchat address (JID)');
const i18n_archiving = __('Message archiving');
const i18n_archiving_help = __('Messages are archived on the server');
const i18n_desc = __('Description');
const i18n_features = __('Features');
const i18n_hidden = __('Hidden');
const i18n_hidden_help = __('This groupchat is not publicly searchable');
const i18n_members_help = __('This groupchat is restricted to members only');
const i18n_members_only = __('Members only');
const i18n_moderated = __('Moderated');
const i18n_moderated_help = __('Participants entering this groupchat need to request permission to write');
const i18n_name = __('Name');
const i18n_no_pass_help = __('This groupchat does not require a password upon entry');
const i18n_no_password_required = __('No password required');
const i18n_not_anonymous = __('Not anonymous');
const i18n_not_anonymous_help = __('All other groupchat participants can see your XMPP address');
const i18n_not_moderated = __('Not moderated');
const i18n_not_moderated_help = __('Participants entering this groupchat can write right away');
const i18n_online_users = __('Online users');
const i18n_open = __('Open');
const i18n_open_help = __('Anyone can join this groupchat');
const i18n_password_help = __('This groupchat requires a password before entry');
const i18n_password_protected = __('Password protected');
const i18n_persistent = __('Persistent');
const i18n_persistent_help = __('This groupchat persists even if it\'s unoccupied');
const i18n_public = __('Public');
const i18n_semi_anon = __('Semi-anonymous');
const i18n_semi_anon_help = __('Only moderators can see your XMPP address');
const i18n_temporary = __('Temporary');
const i18n_temporary_help = __('This groupchat will disappear once the last person leaves');
const i18n_topic = __('Topic');
const i18n_topic_author = __('Topic author');
const subject = (o) => {
const i18n_topic = __('Topic');
const i18n_topic_author = __('Topic author');
return html`
<p class="room-info"><strong>${i18n_topic}</strong>: ${unsafeHTML(xss.filterXSS(o.subject.text, {'whiteList': {}}))}</p>
<p class="room-info"><strong>${i18n_topic_author}</strong>: ${o.subject && o.subject.author}</p>
`;
}
const subject = (o) => html`
<p class="room-info"><strong>${i18n_topic}</strong>: ${unsafeHTML(xss.filterXSS(o.subject.text, {'whiteList': {}}))}</p>
<p class="room-info"><strong>${i18n_topic_author}</strong>: ${o.subject && o.subject.author}</p>
`;
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="room-details-modal-label">${o.display_name}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
<span class="modal-alert"></span>
<div class="room-info">
<p class="room-info"><strong>${i18n_name}</strong>: ${o.name}</p>
<p class="room-info"><strong>${i18n_address}</strong>: ${o.jid}</p>
<p class="room-info"><strong>${i18n_desc}</strong>: ${o.config.description}</p>
${ (o.subject) ? subject(o) : '' }
<p class="room-info"><strong>${i18n_online_users}</strong>: ${o.num_occupants}</p>
<p class="room-info"><strong>${i18n_features}</strong>:
<div class="chatroom-features">
<ul class="features-list">
${ o.features.passwordprotected ? html`<li class="feature" ><span class="fa fa-lock"></span>${i18n_password_protected} - <em>${i18n_password_help}</em></li>` : '' }
${ o.features.unsecured ? html`<li class="feature" ><span class="fa fa-unlock"></span>${i18n_no_password_required} - <em>${i18n_no_pass_help}</em></li>` : '' }
${ o.features.hidden ? html`<li class="feature" ><span class="fa fa-eye-slash"></span>${i18n_hidden} - <em>${i18n_hidden_help}</em></li>` : '' }
${ o.features.public_room ? html`<li class="feature" ><span class="fa fa-eye"></span>${i18n_public} - <em>${o.__('This groupchat is publicly searchable') }</em></li>` : '' }
${ o.features.membersonly ? html`<li class="feature" ><span class="fa fa-address-book"></span>${i18n_members_only} - <em>${i18n_members_help}</em></li>` : '' }
${ o.features.open ? html`<li class="feature" ><span class="fa fa-globe"></span>${i18n_open} - <em>${i18n_open_help}</em></li>` : '' }
${ o.features.persistent ? html`<li class="feature" ><span class="fa fa-save"></span>${i18n_persistent} - <em>${i18n_persistent_help}</em></li>` : '' }
${ o.features.temporary ? html`<li class="feature" ><span class="fa fa-snowflake-o"></span>${i18n_temporary} - <em>${i18n_temporary_help}</em></li>` : '' }
${ o.features.nonanonymous ? html`<li class="feature" ><span class="fa fa-id-card"></span>${i18n_not_anonymous} - <em>${i18n_not_anonymous_help}</em></li>` : '' }
${ o.features.semianonymous ? html`<li class="feature" ><span class="fa fa-user-secret"></span>${i18n_semi_anon} - <em>${i18n_semi_anon_help}</em></li>` : '' }
${ o.features.moderated ? html`<li class="feature" ><span class="fa fa-gavel"></span>${i18n_moderated} - <em>${i18n_moderated_help}</em></li>` : '' }
${ o.features.unmoderated ? html`<li class="feature" ><span class="fa fa-info-circle"></span>${i18n_not_moderated} - <em>${i18n_not_moderated_help}</em></li>` : '' }
${ o.features.mam_enabled ? html`<li class="feature" ><span class="fa fa-database"></span>${i18n_archiving} - <em>${i18n_archiving_help}</em></li>` : '' }
</ul>
</div>
</p>
export default (o) => {
const i18n_address = __('Groupchat address (JID)');
const i18n_archiving = __('Message archiving');
const i18n_archiving_help = __('Messages are archived on the server');
const i18n_desc = __('Description');
const i18n_features = __('Features');
const i18n_hidden = __('Hidden');
const i18n_hidden_help = __('This groupchat is not publicly searchable');
const i18n_members_help = __('This groupchat is restricted to members only');
const i18n_members_only = __('Members only');
const i18n_moderated = __('Moderated');
const i18n_moderated_help = __('Participants entering this groupchat need to request permission to write');
const i18n_name = __('Name');
const i18n_no_pass_help = __('This groupchat does not require a password upon entry');
const i18n_no_password_required = __('No password required');
const i18n_not_anonymous = __('Not anonymous');
const i18n_not_anonymous_help = __('All other groupchat participants can see your XMPP address');
const i18n_not_moderated = __('Not moderated');
const i18n_not_moderated_help = __('Participants entering this groupchat can write right away');
const i18n_online_users = __('Online users');
const i18n_open = __('Open');
const i18n_open_help = __('Anyone can join this groupchat');
const i18n_password_help = __('This groupchat requires a password before entry');
const i18n_password_protected = __('Password protected');
const i18n_persistent = __('Persistent');
const i18n_persistent_help = __('This groupchat persists even if it\'s unoccupied');
const i18n_public = __('Public');
const i18n_semi_anon = __('Semi-anonymous');
const i18n_semi_anon_help = __('Only moderators can see your XMPP address');
const i18n_temporary = __('Temporary');
const i18n_temporary_help = __('This groupchat will disappear once the last person leaves');
return html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="room-details-modal-label">${o.display_name}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
<span class="modal-alert"></span>
<div class="room-info">
<p class="room-info"><strong>${i18n_name}</strong>: ${o.name}</p>
<p class="room-info"><strong>${i18n_address}</strong>: ${o.jid}</p>
<p class="room-info"><strong>${i18n_desc}</strong>: ${o.config.description}</p>
${ (o.subject) ? subject(o) : '' }
<p class="room-info"><strong>${i18n_online_users}</strong>: ${o.num_occupants}</p>
<p class="room-info"><strong>${i18n_features}</strong>:
<div class="chatroom-features">
<ul class="features-list">
${ o.features.passwordprotected ? html`<li class="feature" ><span class="fa fa-lock"></span>${i18n_password_protected} - <em>${i18n_password_help}</em></li>` : '' }
${ o.features.unsecured ? html`<li class="feature" ><span class="fa fa-unlock"></span>${i18n_no_password_required} - <em>${i18n_no_pass_help}</em></li>` : '' }
${ o.features.hidden ? html`<li class="feature" ><span class="fa fa-eye-slash"></span>${i18n_hidden} - <em>${i18n_hidden_help}</em></li>` : '' }
${ o.features.public_room ? html`<li class="feature" ><span class="fa fa-eye"></span>${i18n_public} - <em>${o.__('This groupchat is publicly searchable') }</em></li>` : '' }
${ o.features.membersonly ? html`<li class="feature" ><span class="fa fa-address-book"></span>${i18n_members_only} - <em>${i18n_members_help}</em></li>` : '' }
${ o.features.open ? html`<li class="feature" ><span class="fa fa-globe"></span>${i18n_open} - <em>${i18n_open_help}</em></li>` : '' }
${ o.features.persistent ? html`<li class="feature" ><span class="fa fa-save"></span>${i18n_persistent} - <em>${i18n_persistent_help}</em></li>` : '' }
${ o.features.temporary ? html`<li class="feature" ><span class="fa fa-snowflake-o"></span>${i18n_temporary} - <em>${i18n_temporary_help}</em></li>` : '' }
${ o.features.nonanonymous ? html`<li class="feature" ><span class="fa fa-id-card"></span>${i18n_not_anonymous} - <em>${i18n_not_anonymous_help}</em></li>` : '' }
${ o.features.semianonymous ? html`<li class="feature" ><span class="fa fa-user-secret"></span>${i18n_semi_anon} - <em>${i18n_semi_anon_help}</em></li>` : '' }
${ o.features.moderated ? html`<li class="feature" ><span class="fa fa-gavel"></span>${i18n_moderated} - <em>${i18n_moderated_help}</em></li>` : '' }
${ o.features.unmoderated ? html`<li class="feature" ><span class="fa fa-info-circle"></span>${i18n_not_moderated} - <em>${i18n_not_moderated_help}</em></li>` : '' }
${ o.features.mam_enabled ? html`<li class="feature" ><span class="fa fa-database"></span>${i18n_archiving} - <em>${i18n_archiving_help}</em></li>` : '' }
</ul>
</div>
</p>
</div>
</div>
<div class="modal-footer">${modal_close_button}</div>
</div>
<div class="modal-footer">${modal_close_button}</div>
</div>
</div>
`;
`;
}
......@@ -5,14 +5,14 @@ import { until } from 'lit-html/directives/until.js';
import { converse } from "@converse/headless/converse-core";
const u = converse.env.utils;
const i18n_hide_topic = __('Hide the groupchat topic');
const i18n_bookmarked = __('This groupchat is bookmarked');
const tpl_standalone_btns = (o) => o.standalone_btns.reverse().map(b => until(b, ''));
export default (o) => {
const i18n_hide_topic = __('Hide the groupchat topic');
const i18n_bookmarked = __('This groupchat is bookmarked');
const subject = o.subject ? u.addHyperlinks(o.subject.text) : '';
const show_subject = (subject && !o.subject_hidden);
return html`
......
......@@ -4,10 +4,6 @@ import { html } from "lit-html";
const u = converse.env.utils;
const i18n_search = __('Search');
const i18n_search_results = __('Search results');
const skintones = ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'];
const emoji_category = (o) => {
return html`
......@@ -37,14 +33,17 @@ const emoji_item = (o) => {
`;
}
export const tpl_search_results = (o) => html`
<span ?hidden=${!o.query} class="emoji-lists__container emojis-lists__container--search">
<a id="emoji-picker-search-results" class="emoji-category__heading">${i18n_search_results}</a>
<ul class="emoji-picker">
${ o.search_results.map(emoji => emoji_item(Object.assign({emoji}, o))) }
</ul>
</span>
`;
export const tpl_search_results = (o) => {
const i18n_search_results = __('Search results');
return html`
<span ?hidden=${!o.query} class="emoji-lists__container emojis-lists__container--search">
<a id="emoji-picker-search-results" class="emoji-category__heading">${i18n_search_results}</a>
<ul class="emoji-picker">
${ o.search_results.map(emoji => emoji_item(Object.assign({emoji}, o))) }
</ul>
</span>
`;
}
const emojis_for_category = (o) => {
return html`
......@@ -72,6 +71,8 @@ const skintone_emoji = (o) => {
export const tpl_emoji_picker = (o) => {
const i18n_search = __('Search');
const skintones = ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'];
return html`
<div class="emoji-picker__header">
<input class="form-control emoji-search" name="emoji-search" placeholder="${i18n_search}"
......
......@@ -2,15 +2,16 @@ import { __ } from '@converse/headless/i18n';
import { html } from "lit-html";
import { renderAvatar } from './../templates/directives/avatar';
const i18n_uploading = __('Uploading file:')
export default (o) => html`
<div class="message chat-msg" data-isodate="${o.time}" data-msgid="${o.msgid}">
${ renderAvatar(this) }
<div class="chat-msg__content">
<span class="chat-msg__text">${i18n_uploading} <strong>${o.filename}</strong>, ${o.filesize}</span>
<progress value="${o.progress}"/>
export default (o) => {
const i18n_uploading = __('Uploading file:')
return html`
<div class="message chat-msg" data-isodate="${o.time}" data-msgid="${o.msgid}">
${ renderAvatar(this) }
<div class="chat-msg__content">
<span class="chat-msg__text">${i18n_uploading} <strong>${o.filename}</strong>, ${o.filesize}</span>
<progress value="${o.progress}"/>
</div>
</div>
</div>
`;
`;
}
import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const tpl_headline_box = (o) => html`
<div class="list-item controlbox-padded d-flex flex-row"
......
import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
import tpl_headline_list from "templates/headline_list.js";
......
......@@ -3,14 +3,11 @@ import { __ } from '@converse/headless/i18n';
import { modal_close_button, modal_header_close_button } from "./buttons"
const i18n_image = __('Image: ');
export default (o) => html`
<div class="modal-dialog fit-content" role="document">
<div class="modal-content fit-content">
<div class="modal-header">
<h4 class="modal-title" id="message-versions-modal-label">${i18n_image}<a target="_blank" rel="noopener" href="${o.src}">${o.src}</a></h4>
<h4 class="modal-title" id="message-versions-modal-label">${__('Image: ')}<a target="_blank" rel="noopener" href="${o.src}">${o.src}</a></h4>
${modal_header_close_button}
</div>
<div class="modal-body fit-content">
......
......@@ -4,66 +4,72 @@ import { repeat } from 'lit-html/directives/repeat.js';
import { modal_close_button, modal_header_close_button } from "./buttons"
import spinner from "./spinner.js";
const i18n_info_title = __('Show more information on this groupchat');
const i18n_list_chatrooms = __('Query for Groupchats');
const i18n_open_title = __('Click to open this groupchat');
const i18n_query = __('Show groupchats');
const i18n_server_address = __('Server address');
const form = (o) => html`
<form class="converse-form list-chatrooms"
@submit=${o.submitForm}>
<div class="form-group">
<label for="chatroom">${i18n_server_address}:</label>
<input type="text"
@change=${o.setDomainFromEvent}
value="${o.muc_domain}"
required="required"
name="server"
class="form-control"
placeholder="${o.server_placeholder}"/>
</div>
<input type="submit" class="btn btn-primary" name="list" value="${i18n_query}"/>
</form>
`;
const form = (o) => {
const i18n_query = __('Show groupchats');
const i18n_server_address = __('Server address');
return html`
<form class="converse-form list-chatrooms"
@submit=${o.submitForm}>
<div class="form-group">
<label for="chatroom">${i18n_server_address}:</label>
<input type="text"
@change=${o.setDomainFromEvent}
value="${o.muc_domain}"
required="required"
name="server"
class="form-control"
placeholder="${o.server_placeholder}"/>
</div>
<input type="submit" class="btn btn-primary" name="list" value="${i18n_query}"/>
</form>
`;
}
const tpl_item = (o, item) => html`
<li class="room-item list-group-item">
<div class="available-chatroom d-flex flex-row">
<a class="open-room available-room w-100"
@click=${o.openRoom}
data-room-jid="${item.jid}"
data-room-name="${item.name}"
title="${i18n_open_title}"
href="#">${item.name || item.jid}</a>
<a class="right room-info icon-room-info"
@click=${o.toggleRoomInfo}
data-room-jid="${item.jid}"
title="${i18n_info_title}"
href="#"></a>
</div>
</li>
`;
const tpl_item = (o, item) => {
const i18n_info_title = __('Show more information on this groupchat');
const i18n_open_title = __('Click to open this groupchat');
return html`
<li class="room-item list-group-item">
<div class="available-chatroom d-flex flex-row">
<a class="open-room available-room w-100"
@click=${o.openRoom}
data-room-jid="${item.jid}"
data-room-name="${item.name}"
title="${i18n_open_title}"
href="#">${item.name || item.jid}</a>
<a class="right room-info icon-room-info"
@click=${o.toggleRoomInfo}
data-room-jid="${item.jid}"
title="${i18n_info_title}"
href="#"></a>
</div>
</li>
`;
}
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="list-chatrooms-modal-label">${i18n_list_chatrooms}</h5>
${modal_header_close_button}
</div>
<div class="modal-body d-flex flex-column">
<span class="modal-alert"></span>
${o.show_form ? form(o) : '' }
<ul class="available-chatrooms list-group">
${ o.loading_items ? html`<li class="list-group-item"> ${spinner()} </li>` : '' }
${ o.feedback_text ? html`<li class="list-group-item active">${ o.feedback_text }</li>` : '' }
${repeat(o.items, item => item.jid, item => tpl_item(o, item))}
</ul>
export default (o) => {
const i18n_list_chatrooms = __('Query for Groupchats');
return html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="list-chatrooms-modal-label">${i18n_list_chatrooms}</h5>
${modal_header_close_button}
</div>
<div class="modal-body d-flex flex-column">
<span class="modal-alert"></span>
${o.show_form ? form(o) : '' }
<ul class="available-chatrooms list-group">
${ o.loading_items ? html`<li class="list-group-item"> ${spinner()} </li>` : '' }
${ o.feedback_text ? html`<li class="list-group-item active">${ o.feedback_text }</li>` : '' }
${repeat(o.items, item => item.jid, item => tpl_item(o, item))}
</ul>
</div>
<div class="modal-footer">${modal_close_button}</div>
</div>
<div class="modal-footer">${modal_close_button}</div>
</div>
</div>
`;
`;
}
......@@ -2,44 +2,45 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
import tpl_spinner from './spinner.js';
const i18n_anon_login = __('Click here to log in anonymously');
const i18n_disconnected = __('Disconnected');
const i18n_login = __('Log in');
const i18n_hint_no_account = __("Don't have a chat account?");
const i18n_password = __('Password');
const i18n_trusted = __('This is a trusted device');
const i18n_xmpp_address = __("XMPP Address");
const i18n_create_account = __("Create an account");
const i18n_hint_trusted = __(
'To improve performance, we cache your data in this browser. '+
'Uncheck this box if this is a public computer or if you want your data to be deleted when you log out. '+
'It\'s important that you explicitly log out, otherwise not all cached data might be deleted. '+
'Please note, when using an untrusted device, OMEMO encryption is NOT available.')
const trust_checkbox = (o) => {
const i18n_hint_trusted = __(
'To improve performance, we cache your data in this browser. '+
'Uncheck this box if this is a public computer or if you want your data to be deleted when you log out. '+
'It\'s important that you explicitly log out, otherwise not all cached data might be deleted. '+
'Please note, when using an untrusted device, OMEMO encryption is NOT available.')
const i18n_trusted = __('This is a trusted device');
return html`
<div class="form-group form-check login-trusted">
<input id="converse-login-trusted" type="checkbox" class="form-check-input" name="trusted" ?checked=${o._converse.config.get('trusted')}>
<label for="converse-login-trusted" class="form-check-label login-trusted__desc">${i18n_trusted}</label>
<i class="fa fa-info-circle" data-toggle="popover"
data-title="Trusted device?"
data-content="${i18n_hint_trusted}"></i>
</div>
`;
}
const trust_checkbox = (o) => html`
<div class="form-group form-check login-trusted">
<input id="converse-login-trusted" type="checkbox" class="form-check-input" name="trusted" ?checked=${o._converse.config.get('trusted')}>
<label for="converse-login-trusted" class="form-check-label login-trusted__desc">${i18n_trusted}</label>
<i class="fa fa-info-circle" data-toggle="popover"
data-title="Trusted device?"
data-content="${i18n_hint_trusted}"></i>
</div>
`;
const password_input = () => html`
<div class="form-group">
<label for="converse-login-password">${i18n_password}</label>
<input id="converse-login-password" class="form-control" required="required" type="password" name="password" placeholder="${i18n_password}"/>
</div>
`;
const password_input = () => {
const i18n_password = __('Password');
return html`
<div class="form-group">
<label for="converse-login-password">${i18n_password}</label>
<input id="converse-login-password" class="form-control" required="required" type="password" name="password" placeholder="${i18n_password}"/>
</div>
`;
}
const register_link = () => html`
<fieldset class="switch-form">
<p>${i18n_hint_no_account}</p>
<p><a class="register-account toggle-register-login" href="#converse/register">${i18n_create_account}</a></p>
</fieldset>
`;
const register_link = () => {
const i18n_create_account = __("Create an account");
const i18n_hint_no_account = __("Don't have a chat account?");
return html`
<fieldset class="switch-form">
<p>${i18n_hint_no_account}</p>
<p><a class="register-account toggle-register-login" href="#converse/register">${i18n_create_account}</a></p>
</fieldset>
`;
}
const show_register_link = (o) => {
const _converse = o._converse;
......@@ -49,25 +50,33 @@ const show_register_link = (o) => {
}
const auth_fields = (o) => html`
<div class="form-group">
<label for="converse-login-jid">${i18n_xmpp_address}:</label>
<input id="converse-login-jid" class="form-control" required="required" type="text" name="jid" placeholder="${o.placeholder_username}"/>
</div>
${ (o.authentication !== o.EXTERNAL) ? password_input() : '' }
${ o.show_trust_checkbox ? trust_checkbox(o) : '' }
<fieldset class="buttons">
<input class="btn btn-primary" type="submit" value="${i18n_login}"/>
</fieldset>
${ show_register_link(o) ? register_link(o) : '' }
`;
const auth_fields = (o) => {
const i18n_login = __('Log in');
const i18n_xmpp_address = __("XMPP Address");
return html`
<div class="form-group">
<label for="converse-login-jid">${i18n_xmpp_address}:</label>
<input id="converse-login-jid" class="form-control" required="required" type="text" name="jid" placeholder="${o.placeholder_username}"/>
</div>
${ (o.authentication !== o.EXTERNAL) ? password_input() : '' }
${ o.show_trust_checkbox ? trust_checkbox(o) : '' }
<fieldset class="buttons">
<input class="btn btn-primary" type="submit" value="${i18n_login}"/>
</fieldset>
${ show_register_link(o) ? register_link(o) : '' }
`;
}
const form_fields = (o) => html`
${ (o.authentication == o.LOGIN || o.authentication == o.EXTERNAL) ? auth_fields(o) : '' }
${ o.authentication == o.ANONYMOUS ? html`<input class="btn btn-primary login-anon" type="submit" value="${i18n_anon_login}">` : '' }
${ o.authentication == o.PREBIND ? html`<p>${i18n_disconnected}</p>` : '' }
`;
const form_fields = (o) => {
const i18n_disconnected = __('Disconnected');
const i18n_anon_login = __('Click here to log in anonymously');
return html`
${ (o.authentication == o.LOGIN || o.authentication == o.EXTERNAL) ? auth_fields(o) : '' }
${ o.authentication == o.ANONYMOUS ? html`<input class="btn btn-primary login-anon" type="submit" value="${i18n_anon_login}">` : '' }
${ o.authentication == o.PREBIND ? html`<p>${i18n_disconnected}</p>` : '' }
`;
}
export default (o) => html`
......
......@@ -4,14 +4,11 @@ import dayjs from 'dayjs';
import { modal_close_button, modal_header_close_button } from "./buttons"
const i18n_message_versions = __('Message versions');
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="message-versions-modal-label">${i18n_message_versions}</h4>
<h4 class="modal-title" id="message-versions-modal-label">${__('Message versions')}</h4>
${modal_header_close_button}
</div>
<div class="modal-body">
......
......@@ -4,32 +4,6 @@ import spinner from "./spinner.js";
import { modal_header_close_button } from "./buttons"
const i18n_affiliation = __('Affiliation');
const i18n_change_affiliation = __('Change affiliation');
const i18n_change_role = __('Change role');
const i18n_moderator_tools = __('Moderator Tools');
const i18n_new_affiliation = __('New affiliation');
const i18n_new_role = __('New Role');
const i18n_no_users_with_aff = __('No users with that affiliation found.')
const i18n_no_users_with_role = __('No users with that role found.');
const i18n_reason = __('Reason');
const i18n_filter = __('Type here to filter the search results');
const i18n_role = __('Role');
const i18n_show_users = __('Show users');
const i18n_helptext_role = __(
"Roles are assigned to users to grant or deny them certain abilities in a multi-user chat. "+
"They're assigned either explicitly or implicitly as part of an affiliation. "+
"A role that's not due to an affiliation, is only valid for the duration of the user's session."
);
const i18n_helptext_affiliation = __(
"An affiliation is a long-lived entitlement which typically implies a certain role and which "+
"grants privileges and responsibilities. For example admins and owners automatically have the "+
"moderator role."
);
function getRoleHelpText (role) {
if (role === 'moderator') {
return __("Moderators are privileged users who can change the roles of other users (except those with admin or owner affiliations.");
......@@ -65,29 +39,34 @@ const affiliation_option = (o) => html`
`;
const tpl_set_role_form = (o) => html`
<form class="role-form hidden" @submit=${o.assignRole}>
<div class="form-group">
<input type="hidden" name="jid" value="${o.item.jid}"/>
<input type="hidden" name="nick" value="${o.item.nick}"/>
<div class="row">
<div class="col">
<label><strong>${i18n_new_role}:</strong></label>
<select class="custom-select select-role" name="role">
${ o.assignable_roles.map(role => html`<option value="${role}" ?selected=${role === o.item.role}>${role}</option>`) }
</select>
</div>
<div class="col">
<label><strong>${i18n_reason}:</strong></label>
<input class="form-control" type="text" name="reason"/>
const tpl_set_role_form = (o) => {
const i18n_change_role = __('Change role');
const i18n_new_role = __('New Role');
const i18n_reason = __('Reason');
return html`
<form class="role-form hidden" @submit=${o.assignRole}>
<div class="form-group">
<input type="hidden" name="jid" value="${o.item.jid}"/>
<input type="hidden" name="nick" value="${o.item.nick}"/>
<div class="row">
<div class="col">
<label><strong>${i18n_new_role}:</strong></label>
<select class="custom-select select-role" name="role">
${ o.assignable_roles.map(role => html`<option value="${role}" ?selected=${role === o.item.role}>${role}</option>`) }
</select>
</div>
<div class="col">
<label><strong>${i18n_reason}:</strong></label>
<input class="form-control" type="text" name="reason"/>
</div>
</div>
</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="${i18n_change_role}"/>
</div>
</form>
`;
<div class="form-group">
<input type="submit" class="btn btn-primary" value="${i18n_change_role}"/>
</div>
</form>
`;
}
const role_list_item = (o) => html`
......@@ -108,29 +87,34 @@ const role_list_item = (o) => html`
`;
const tpl_set_affiliation_form = (o) => html`
<form class="affiliation-form hidden" @submit=${o.assignAffiliation}>
<div class="form-group">
<input type="hidden" name="jid" value="${o.item.jid}"/>
<input type="hidden" name="nick" value="${o.item.nick}"/>
<div class="row">
<div class="col">
<label><strong>${i18n_new_affiliation}:</strong></label>
<select class="custom-select select-affiliation" name="affiliation">
${ o.assignable_affiliations.map(aff => html`<option value="${aff}" ?selected=${aff === o.item.affiliation}>${aff}</option>`) }
</select>
</div>
<div class="col">
<label><strong>${i18n_reason}:</strong></label>
<input class="form-control" type="text" name="reason"/>
const tpl_set_affiliation_form = (o) => {
const i18n_change_affiliation = __('Change affiliation');
const i18n_new_affiliation = __('New affiliation');
const i18n_reason = __('Reason');
return html`
<form class="affiliation-form hidden" @submit=${o.assignAffiliation}>
<div class="form-group">
<input type="hidden" name="jid" value="${o.item.jid}"/>
<input type="hidden" name="nick" value="${o.item.nick}"/>
<div class="row">
<div class="col">
<label><strong>${i18n_new_affiliation}:</strong></label>
<select class="custom-select select-affiliation" name="affiliation">
${ o.assignable_affiliations.map(aff => html`<option value="${aff}" ?selected=${aff === o.item.affiliation}>${aff}</option>`) }
</select>
</div>
<div class="col">
<label><strong>${i18n_reason}:</strong></label>
<input class="form-control" type="text" name="reason"/>
</div>
</div>
</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" name="change" value="${i18n_change_affiliation}"/>
</div>
</form>
`;
<div class="form-group">
<input type="submit" class="btn btn-primary" name="change" value="${i18n_change_affiliation}"/>
</div>
</form>
`;
}
const affiliation_list_item = (o) => html`
......@@ -164,6 +148,23 @@ const tpl_navigation = (o) => html`
export default (o) => {
const i18n_affiliation = __('Affiliation');
const i18n_moderator_tools = __('Moderator Tools');
const i18n_no_users_with_aff = __('No users with that affiliation found.')
const i18n_no_users_with_role = __('No users with that role found.');
const i18n_filter = __('Type here to filter the search results');
const i18n_role = __('Role');
const i18n_show_users = __('Show users');
const i18n_helptext_role = __(
"Roles are assigned to users to grant or deny them certain abilities in a multi-user chat. "+
"They're assigned either explicitly or implicitly as part of an affiliation. "+
"A role that's not due to an affiliation, is only valid for the duration of the user's session."
);
const i18n_helptext_affiliation = __(
"An affiliation is a long-lived entitlement which typically implies a certain role and which "+
"grants privileges and responsibilities. For example admins and owners automatically have the "+
"moderator role."
);
const show_both_tabs = o.queryable_roles.length && o.queryable_affiliations.length;
return html`
<div class="modal-dialog" role="document">
......
import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const i18n_heading = __('Bookmark this groupchat');
const i18n_autojoin = __('Would you like this groupchat to be automatically joined upon startup?');
const i18n_cancel = __('Cancel');
const i18n_name = __('The name for this bookmark:');
const i18n_nick = __('What should your nickname for this groupchat be?');
const i18n_submit = __('Save');
export default (o) => html`
<form class="converse-form chatroom-form" @submit=${o.onSubmit}>
<legend>${i18n_heading}</legend>
<fieldset class="form-group">
<label for="converse_muc_bookmark_name">${i18n_name}</label>
<input class="form-control" type="text" value="${o.name}" name="name" required="required" id="converse_muc_bookmark_name"/>
</fieldset>
<fieldset class="form-group">
<label for="converse_muc_bookmark_nick">${i18n_nick}</label>
<input class="form-control" type="text" name="nick" value="${o.nick || ''}" id="converse_muc_bookmark_nick"/>
</fieldset>
<fieldset class="form-group form-check">
<input class="form-check-input" id="converse_muc_bookmark_autojoin" type="checkbox" name="autojoin"/>
<label class="form-check-label" for="converse_muc_bookmark_autojoin">${i18n_autojoin}</label>
</fieldset>
<fieldset class="form-group">
<input class="btn btn-primary" type="submit" value="${i18n_submit}">
<input class="btn btn-secondary button-cancel" type="button" value="${i18n_cancel}" @click=${o.onCancel}>
</fieldset>
</form>
`;
export default (o) => {
const i18n_heading = __('Bookmark this groupchat');
const i18n_autojoin = __('Would you like this groupchat to be automatically joined upon startup?');
const i18n_cancel = __('Cancel');
const i18n_name = __('The name for this bookmark:');
const i18n_nick = __('What should your nickname for this groupchat be?');
const i18n_submit = __('Save');
return html`
<form class="converse-form chatroom-form" @submit=${o.onSubmit}>
<legend>${i18n_heading}</legend>
<fieldset class="form-group">
<label for="converse_muc_bookmark_name">${i18n_name}</label>
<input class="form-control" type="text" value="${o.name}" name="name" required="required" id="converse_muc_bookmark_name"/>
</fieldset>
<fieldset class="form-group">
<label for="converse_muc_bookmark_nick">${i18n_nick}</label>
<input class="form-control" type="text" name="nick" value="${o.nick || ''}" id="converse_muc_bookmark_nick"/>
</fieldset>
<fieldset class="form-group form-check">
<input class="form-check-input" id="converse_muc_bookmark_autojoin" type="checkbox" name="autojoin"/>
<label class="form-check-label" for="converse_muc_bookmark_autojoin">${i18n_autojoin}</label>
</fieldset>
<fieldset class="form-group">
<input class="btn btn-primary" type="submit" value="${i18n_submit}">
<input class="btn btn-secondary button-cancel" type="button" value="${i18n_cancel}" @click=${o.onCancel}>
</fieldset>
</form>
`;
}
......@@ -2,20 +2,21 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
const i18n_save = __('Save');
const i18n_cancel = __('Cancel');
export default (o) => html`
<form class="converse-form chatroom-form" autocomplete="off" @submit=${o.submitConfigForm}>
<fieldset class="form-group">
<legend>${o.title}</legend>
${ (o.title !== o.instructions) ? html`<p class="form-help">${o.instructions}</p>` : '' }
<!-- Fields are generated internally, with xForm2webForm -->
${ o.fields.map(field => unsafeHTML(field)) }
</fieldset>
<fieldset>
<input type="submit" class="btn btn-primary" value="${i18n_save}">
<input type="button" class="btn btn-secondary button-cancel" value="${i18n_cancel}" @click=${o.closeConfigForm}>
</fieldset>
</form>
`;
export default (o) => {
const i18n_save = __('Save');
const i18n_cancel = __('Cancel');
return html`
<form class="converse-form chatroom-form" autocomplete="off" @submit=${o.submitConfigForm}>
<fieldset class="form-group">
<legend>${o.title}</legend>
${ (o.title !== o.instructions) ? html`<p class="form-help">${o.instructions}</p>` : '' }
<!-- Fields are generated internally, with xForm2webForm -->
${ o.fields.map(field => unsafeHTML(field)) }
</fieldset>
<fieldset>
<input type="submit" class="btn btn-primary" value="${i18n_save}">
<input type="button" class="btn btn-secondary button-cancel" value="${i18n_cancel}" @click=${o.closeConfigForm}>
</fieldset>
</form>
`;
}
......@@ -2,47 +2,48 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
import { modal_header_close_button } from "./buttons"
const i18n_invite = __('Invite');
const i18n_invite_heading = __('Invite someone to this groupchat');
const i18n_jid_placeholder = __('user@example.org');
const i18n_error_message = __('Please enter a valid XMPP address');
const i18n_invite_label = __('XMPP Address');
const i18n_reason = __('Optional reason for the invitation');
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="add-chatroom-modal-label">${i18n_invite_heading}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
<span class="modal-alert"></span>
<div class="suggestion-box room-invite">
<form @submit=${o.submitInviteForm}>
<div class="form-group">
<label class="clearfix" for="invitee_jids">${i18n_invite_label}:</label>
${ o.invalid_invite_jid ? html`<div class="error error-feedback">${i18n_error_message}</div>` : '' }
<input class="form-control suggestion-box__input"
required="required"
name="invitee_jids"
id="invitee_jids"
placeholder="${i18n_jid_placeholder}"
type="text"/>
<span class="suggestion-box__additions visually-hidden" role="status" aria-live="assertive" aria-relevant="additions"></span>
<ul class="suggestion-box__results suggestion-box__results--below" hidden=""></ul>
</div>
<div class="form-group">
<label>${i18n_reason}:</label>
<textarea class="form-control" name="reason"></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">${i18n_invite}</button>
</div>
</form>
export default (o) => {
const i18n_invite = __('Invite');
const i18n_invite_heading = __('Invite someone to this groupchat');
const i18n_jid_placeholder = __('user@example.org');
const i18n_error_message = __('Please enter a valid XMPP address');
const i18n_invite_label = __('XMPP Address');
const i18n_reason = __('Optional reason for the invitation');
return html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="add-chatroom-modal-label">${i18n_invite_heading}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
<span class="modal-alert"></span>
<div class="suggestion-box room-invite">
<form @submit=${o.submitInviteForm}>
<div class="form-group">
<label class="clearfix" for="invitee_jids">${i18n_invite_label}:</label>
${ o.invalid_invite_jid ? html`<div class="error error-feedback">${i18n_error_message}</div>` : '' }
<input class="form-control suggestion-box__input"
required="required"
name="invitee_jids"
id="invitee_jids"
placeholder="${i18n_jid_placeholder}"
type="text"/>
<span class="suggestion-box__additions visually-hidden" role="status" aria-live="assertive" aria-relevant="additions"></span>
<ul class="suggestion-box__results suggestion-box__results--below" hidden=""></ul>
</div>
<div class="form-group">
<label>${i18n_reason}:</label>
<textarea class="form-control" name="reason"></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">${i18n_invite}</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
`;
`;
}
import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const i18n_heading = __('This groupchat requires a password');
const i18n_password = __('Password: ');
const i18n_submit = __('Submit');
export default (o) => html`
<form class="converse-form chatroom-form converse-centered-form" @submit=${o.submitPassword}>
<fieldset class="form-group">
<label>${i18n_heading}</label>
<p class="validation-message">${o.validation_message}</p>
<input class="hidden-username" type="text" autocomplete="username" value="${o.jid}"></input>
<input type="password"
name="password"
required="required"
class="form-control ${o.validation_message ? 'error': ''}"
placeholder="${i18n_password}"/>
</fieldset>
<fieldset class="form-group">
<input class="btn btn-primary" type="submit" value="${i18n_submit}"/>
</fieldset>
</form>
`;
export default (o) => {
const i18n_heading = __('This groupchat requires a password');
const i18n_password = __('Password: ');
const i18n_submit = __('Submit');
return html`
<form class="converse-form chatroom-form converse-centered-form" @submit=${o.submitPassword}>
<fieldset class="form-group">
<label>${i18n_heading}</label>
<p class="validation-message">${o.validation_message}</p>
<input class="hidden-username" type="text" autocomplete="username" value="${o.jid}"></input>
<input type="password"
name="password"
required="required"
class="form-control ${o.validation_message ? 'error': ''}"
placeholder="${i18n_password}"/>
</fieldset>
<fieldset class="form-group">
<input class="btn btn-primary" type="submit" value="${i18n_submit}"/>
</fieldset>
</form>
`;
}
......@@ -13,27 +13,28 @@ const PRETTY_CHAT_STATUS = {
'online': 'Online'
};
const i18n_occupant_hint = (occupant) => __('Click to mention %1$s in your message.', occupant.get('nick'))
const i18n_participants = __('Participants');
export default (o) => html`
<div class="occupants-header">
<i class="hide-occupants fa fa-times"></i>
<div class="occupants-header--title">
<span class="occupants-heading">${i18n_participants}</span>
export default (o) => {
const i18n_occupant_hint = (occupant) => __('Click to mention %1$s in your message.', occupant.get('nick'))
const i18n_participants = __('Participants');
return html`
<div class="occupants-header">
<i class="hide-occupants fa fa-times"></i>
<div class="occupants-header--title">
<span class="occupants-heading">${i18n_participants}</span>
</div>
</div>
</div>
<div class="dragresize dragresize-occupants-left"></div>
<ul class="occupant-list">
${ o.occupants.map(occupant => {
return tpl_occupant(
Object.assign({
'jid': '',
'hint_show': PRETTY_CHAT_STATUS[occupant.get('show')],
'hint_occupant': i18n_occupant_hint(occupant)
}, occupant.toJSON())
);
}) }
</ul>
`;
<div class="dragresize dragresize-occupants-left"></div>
<ul class="occupant-list">
${ o.occupants.map(occupant => {
return tpl_occupant(
Object.assign({
'jid': '',
'hint_show': PRETTY_CHAT_STATUS[occupant.get('show')],
'hint_occupant': i18n_occupant_hint(occupant)
}, occupant.toJSON())
);
}) }
</ul>
`;
}
......@@ -2,16 +2,10 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const i18n_moderator_hint = __('This user is a moderator.');
const i18n_participant_hint = __('This user can send messages in this groupchat.');
const i18n_visitor_hint = __('This user can NOT send messages in this groupchat.')
const i18n_owner = __('Owner');
const i18n_admin = __('Admin');
const i18n_member = __('Member');
const i18n_moderator = __('Moderator');
const i18n_visitor = __('Visitor');
const occupant_title = (o) => {
const i18n_moderator_hint = __('This user is a moderator.');
const i18n_participant_hint = __('This user can send messages in this groupchat.');
const i18n_visitor_hint = __('This user can NOT send messages in this groupchat.')
if (o.role === "moderator") {
return `${o.jid} ${i18n_moderator_hint} ${o.hint_occupant}`;
} else if (o.role === "participant") {
......@@ -24,22 +18,29 @@ const occupant_title = (o) => {
}
export default (o) => html`
<li class="occupant" id="${o.id}" title="${occupant_title(o)}">
<div class="row no-gutters">
<div class="col-auto">
<div class="occupant-status occupant-${o.show} circle" title="${o.hint_show}"></div>
</div>
<div class="col occupant-nick-badge">
<span class="occupant-nick">${o.nick || o.jid}</span>
<span class="occupant-badges">
${ (o.affiliation === "owner") ? html`<span class="badge badge-groupchat">${i18n_owner}</span>` : '' }
${ (o.affiliation === "admin") ? html`<span class="badge badge-info">${i18n_admin}</span>` : '' }
${ (o.affiliation === "member") ? html`<span class="badge badge-info">${i18n_member}</span>` : '' }
${ (o.role === "moderator") ? html`<span class="badge badge-info">${i18n_moderator}</span>` : '' }
${ (o.role === "visitor") ? html`<span class="badge badge-secondary">${i18n_visitor}</span>` : '' }
</span>
export default (o) => {
const i18n_owner = __('Owner');
const i18n_admin = __('Admin');
const i18n_member = __('Member');
const i18n_moderator = __('Moderator');
const i18n_visitor = __('Visitor');
return html`
<li class="occupant" id="${o.id}" title="${occupant_title(o)}">
<div class="row no-gutters">
<div class="col-auto">
<div class="occupant-status occupant-${o.show} circle" title="${o.hint_show}"></div>
</div>
<div class="col occupant-nick-badge">
<span class="occupant-nick">${o.nick || o.jid}</span>
<span class="occupant-badges">
${ (o.affiliation === "owner") ? html`<span class="badge badge-groupchat">${i18n_owner}</span>` : '' }
${ (o.affiliation === "admin") ? html`<span class="badge badge-info">${i18n_admin}</span>` : '' }
${ (o.affiliation === "member") ? html`<span class="badge badge-info">${i18n_member}</span>` : '' }
${ (o.role === "moderator") ? html`<span class="badge badge-info">${i18n_moderator}</span>` : '' }
${ (o.role === "visitor") ? html`<span class="badge badge-secondary">${i18n_visitor}</span>` : '' }
</span>
</div>
</div>
</div>
</li>
`;
</li>
`;
}
......@@ -2,12 +2,11 @@ import { __ } from '@converse/headless/i18n';
import { api } from "@converse/headless/converse-core";
import { html } from "lit-html";
const i18n_logout = __('Log out');
const i18n_change_status = __('Click to change your chat status');
const i18n_details = __('Show details about this chat client');
export default (o) => {
const i18n_logout = __('Log out');
const i18n_change_status = __('Click to change your chat status');
const i18n_details = __('Show details about this chat client');
const show_settings_button = api.settings.get('show_client_info') || api.settings.get('allow_adhoc_commands');
return html`
<div class="userinfo controlbox-padded">
......
......@@ -7,153 +7,164 @@ import { modal_header_close_button } from "./buttons";
const u = converse.env.utils;
const heading_profile = __('Your Profile');
const i18n_fingerprint_checkbox_label = __('Checkbox for selecting the following fingerprint');
const i18n_device_without_fingerprint = __('Device without a fingerprint');
const i18n_email = __('Email');
const i18n_fingerprint = __("This device's OMEMO fingerprint");
const i18n_fullname = __('Full Name');
const i18n_generate = __('Generate new keys and fingerprint');
const i18n_jid = __('XMPP Address (JID)');
const i18n_nickname = __('Nickname');
const i18n_other_devices = __('Other OMEMO-enabled devices');
const i18n_other_devices_label = __('Checkbox to select fingerprints of all other OMEMO devices');
const i18n_remove_devices = __('Remove checked devices and close');
const i18n_role = __('Role');
const i18n_save = __('Save and close');
const i18n_select_all = __('Select all');
const i18n_role_help = __('Use commas to separate multiple roles. Your roles are shown next to your name on your chat messages.');
const i18n_url = __('URL');
const i18n_omemo = __('OMEMO');
const i18n_profile = __('Profile');
const navigation = html`
<ul class="nav nav-pills justify-content-center">
<li role="presentation" class="nav-item">
<a class="nav-link active" id="profile-tab" href="#profile-tabpanel" aria-controls="profile-tabpanel" role="tab" data-toggle="tab">${i18n_profile}</a>
</li>
<li role="presentation" class="nav-item">
<a class="nav-link" id="omemo-tab" href="#omemo-tabpanel" aria-controls="omemo-tabpanel" role="tab" data-toggle="tab">${i18n_omemo}</a>
</li>
</ul>`;
const fingerprint = (o) => html`
<span class="fingerprint">${u.formatFingerprint(o.view.current_device.get('bundle').fingerprint)}</span>`;
const device_with_fingerprint = (o) => html`
<li class="fingerprint-removal-item list-group-item nopadding">
<label>
<input type="checkbox" value="${o.device.get('id')}"
aria-label="${i18n_fingerprint_checkbox_label}"/>
<span class="fingerprint">${u.formatFingerprint(o.device.get('bundle').fingerprint)}</span>
</label>
</li>
`;
const device_without_fingerprint = (o) => html`
<li class="fingerprint-removal-item list-group-item nopadding">
<label>
<input type="checkbox" value="${o.device.get('id')}"
aria-label="${i18n_fingerprint_checkbox_label}"/>
<span>${i18n_device_without_fingerprint}</span>
</label>
</li>
`;
const device_item = (o) => html`
${(o.device.get('bundle') && o.device.get('bundle').fingerprint) ? device_with_fingerprint(o) : device_without_fingerprint(o) }
`;
const device_with_fingerprint = (o) => {
const i18n_fingerprint_checkbox_label = __('Checkbox for selecting the following fingerprint');
return html`
<li class="fingerprint-removal-item list-group-item nopadding">
<label>
<input type="checkbox" value="${o.device.get('id')}"
aria-label="${i18n_fingerprint_checkbox_label}"/>
<span class="fingerprint">${u.formatFingerprint(o.device.get('bundle').fingerprint)}</span>
</label>
</li>
`;
}
const device_list = (o) => html`
<ul class="list-group fingerprints">
<li class="list-group-item nopadding active">
const device_without_fingerprint = (o) => {
const i18n_device_without_fingerprint = __('Device without a fingerprint');
const i18n_fingerprint_checkbox_label = __('Checkbox for selecting the following device');
return html`
<li class="fingerprint-removal-item list-group-item nopadding">
<label>
<input type="checkbox" class="select-all" title="${i18n_select_all}" aria-label="${i18n_other_devices_label}"/>
${i18n_other_devices}
<input type="checkbox" value="${o.device.get('id')}"
aria-label="${i18n_fingerprint_checkbox_label}"/>
<span>${i18n_device_without_fingerprint}</span>
</label>
</li>
${ o.view.other_devices.map(device => device_item(Object.assign({device}, o))) }
</ul>
<div class="form-group"><button type="submit" class="save-form btn btn-primary">${i18n_remove_devices}</button></div>
`;
`;
}
const omemo_page = (o) => html`
<div class="tab-pane" id="omemo-tabpanel" role="tabpanel" aria-labelledby="omemo-tab">
<form class="converse-form fingerprint-removal">
<ul class="list-group fingerprints">
<li class="list-group-item active">${i18n_fingerprint}</li>
<li class="list-group-item">
${ (o.view.current_device && o.view.current_device.get('bundle') && o.view.current_device.get('bundle').fingerprint) ? fingerprint(o) : spinner() }
</li>
</ul>
<div class="form-group">
<button type="button" class="generate-bundle btn btn-danger">${i18n_generate}</button>
</div>
${ o.view.other_devices.length ? device_list(o) : '' }
</form>
</div>`;
const device_item = (o) => html`
${(o.device.get('bundle') && o.device.get('bundle').fingerprint) ? device_with_fingerprint(o) : device_without_fingerprint(o) }
`;
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="user-profile-modal-label">${heading_profile}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
<span class="modal-alert"></span>
${_converse.pluggable.plugins['converse-omemo'].enabled(_converse) && navigation}
<div class="tab-content">
<div class="tab-pane active" id="profile-tabpanel" role="tabpanel" aria-labelledby="profile-tab">
<form class="converse-form converse-form--modal profile-form" action="#">
<div class="row">
<div class="col-auto">
<converse-image-picker image="${o.image}" width="${o.width}" height="${o.height}"></converse-image-picker>
</div>
<div class="col">
<div class="form-group">
<label class="col-form-label">${i18n_jid}:</label>
<div>${o.jid}</div>
const device_list = (o) => {
const i18n_other_devices = __('Other OMEMO-enabled devices');
const i18n_other_devices_label = __('Checkbox to select fingerprints of all other OMEMO devices');
const i18n_remove_devices = __('Remove checked devices and close');
const i18n_select_all = __('Select all');
return html`
<ul class="list-group fingerprints">
<li class="list-group-item nopadding active">
<label>
<input type="checkbox" class="select-all" title="${i18n_select_all}" aria-label="${i18n_other_devices_label}"/>
${i18n_other_devices}
</label>
</li>
${ o.view.other_devices.map(device => device_item(Object.assign({device}, o))) }
</ul>
<div class="form-group"><button type="submit" class="save-form btn btn-primary">${i18n_remove_devices}</button></div>
`;
}
const omemo_page = (o) => {
const i18n_fingerprint = __("This device's OMEMO fingerprint");
const i18n_generate = __('Generate new keys and fingerprint');
return html`
<div class="tab-pane" id="omemo-tabpanel" role="tabpanel" aria-labelledby="omemo-tab">
<form class="converse-form fingerprint-removal">
<ul class="list-group fingerprints">
<li class="list-group-item active">${i18n_fingerprint}</li>
<li class="list-group-item">
${ (o.view.current_device && o.view.current_device.get('bundle') && o.view.current_device.get('bundle').fingerprint) ? fingerprint(o) : spinner() }
</li>
</ul>
<div class="form-group">
<button type="button" class="generate-bundle btn btn-danger">${i18n_generate}</button>
</div>
${ o.view.other_devices.length ? device_list(o) : '' }
</form>
</div>`;
}
export default (o) => {
const heading_profile = __('Your Profile');
const i18n_email = __('Email');
const i18n_fullname = __('Full Name');
const i18n_jid = __('XMPP Address (JID)');
const i18n_nickname = __('Nickname');
const i18n_role = __('Role');
const i18n_save = __('Save and close');
const i18n_role_help = __('Use commas to separate multiple roles. Your roles are shown next to your name on your chat messages.');
const i18n_url = __('URL');
const i18n_omemo = __('OMEMO');
const i18n_profile = __('Profile');
const navigation = html`
<ul class="nav nav-pills justify-content-center">
<li role="presentation" class="nav-item">
<a class="nav-link active" id="profile-tab" href="#profile-tabpanel" aria-controls="profile-tabpanel" role="tab" data-toggle="tab">${i18n_profile}</a>
</li>
<li role="presentation" class="nav-item">
<a class="nav-link" id="omemo-tab" href="#omemo-tabpanel" aria-controls="omemo-tabpanel" role="tab" data-toggle="tab">${i18n_omemo}</a>
</li>
</ul>`;
return html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="user-profile-modal-label">${heading_profile}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
<span class="modal-alert"></span>
${_converse.pluggable.plugins['converse-omemo'].enabled(_converse) && navigation}
<div class="tab-content">
<div class="tab-pane active" id="profile-tabpanel" role="tabpanel" aria-labelledby="profile-tab">
<form class="converse-form converse-form--modal profile-form" action="#">
<div class="row">
<div class="col-auto">
<converse-image-picker image="${o.image}" width="${o.width}" height="${o.height}"></converse-image-picker>
</div>
<div class="col">
<div class="form-group">
<label class="col-form-label">${i18n_jid}:</label>
<div>${o.jid}</div>
</div>
</div>
</div>
<div class="form-group">
<label for="vcard-fullname" class="col-form-label">${i18n_fullname}:</label>
<input id="vcard-fullname" type="text" class="form-control" name="fn" value="${o.fullname || ''}"/>
</div>
<div class="form-group">
<label for="vcard-nickname" class="col-form-label">${i18n_nickname}:</label>
<input id="vcard-nickname" type="text" class="form-control" name="nickname" value="${o.nickname || ''}"/>
</div>
<div class="form-group">
<label for="vcard-url" class="col-form-label">${i18n_url}:</label>
<input id="vcard-url" type="url" class="form-control" name="url" value="${o.url || ''}"/>
</div>
</div>
<div class="form-group">
<label for="vcard-fullname" class="col-form-label">${i18n_fullname}:</label>
<input id="vcard-fullname" type="text" class="form-control" name="fn" value="${o.fullname || ''}"/>
</div>
<div class="form-group">
<label for="vcard-nickname" class="col-form-label">${i18n_nickname}:</label>
<input id="vcard-nickname" type="text" class="form-control" name="nickname" value="${o.nickname || ''}"/>
</div>
<div class="form-group">
<label for="vcard-url" class="col-form-label">${i18n_url}:</label>
<input id="vcard-url" type="url" class="form-control" name="url" value="${o.url || ''}"/>
</div>
<div class="form-group">
<label for="vcard-email" class="col-form-label">${i18n_email}:</label>
<input id="vcard-email" type="email" class="form-control" name="email" value="${o.email || ''}"/>
</div>
<div class="form-group">
<label for="vcard-role" class="col-form-label">${i18n_role}:</label>
<input id="vcard-role" type="text" class="form-control" name="role" value="${o.role || ''}" aria-describedby="vcard-role-help"/>
<small id="vcard-role-help" class="form-text text-muted">${i18n_role_help}</small>
</div>
<hr/>
<div class="form-group">
<button type="submit" class="save-form btn btn-primary">${i18n_save}</button>
</div>
</form>
<div class="form-group">
<label for="vcard-email" class="col-form-label">${i18n_email}:</label>
<input id="vcard-email" type="email" class="form-control" name="email" value="${o.email || ''}"/>
</div>
<div class="form-group">
<label for="vcard-role" class="col-form-label">${i18n_role}:</label>
<input id="vcard-role" type="text" class="form-control" name="role" value="${o.role || ''}" aria-describedby="vcard-role-help"/>
<small id="vcard-role-help" class="form-text text-muted">${i18n_role_help}</small>
</div>
<hr/>
<div class="form-group">
<button type="submit" class="save-form btn btn-primary">${i18n_save}</button>
</div>
</form>
</div>
${ _converse.pluggable.plugins['converse-omemo'].enabled(_converse) && omemo_page(o) }
</div>
${ _converse.pluggable.plugins['converse-omemo'].enabled(_converse) && omemo_page(o) }
</div>
</div>
</div>
</div>
`;
`;
}
......@@ -2,10 +2,6 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const i18n_cancel = __('Cancel');
const i18n_ok = __('OK');
const tpl_field = (f) => html`
<div class="form-group">
<label>
......@@ -37,8 +33,8 @@ export default (o) => html`
</div>
${ o.fields.map(f => tpl_field(f)) }
<div class="form-group">
<button type="submit" class="btn btn-primary">${i18n_ok}</button>
<input type="button" class="btn btn-secondary" data-dismiss="modal" value="${i18n_cancel}"/>
<button type="submit" class="btn btn-primary">${__('OK')}</button>
<input type="button" class="btn btn-secondary" data-dismiss="modal" value="${__('Cancel')}"/>
</div>
</form>
</div>
......
......@@ -2,20 +2,9 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const i18n_desc_rooms = __('Click to toggle the list of open groupchats');
const i18n_add_bookmark = __('Bookmark this groupchat');
const i18n_leave_room = __('Leave this groupchat');
const i18n_remove_bookmark = __('Unbookmark this groupchat');
const i18n_title = __('Show more information on this groupchat');
const i18n_open = __('Click to open this groupchat');
// Note to translators, "Open Groupchats" refers to groupchats that are open, NOT a command.
const i18n_rooms = __('Open Groupchats');
const unread_indicator = (o) => html`<span class="list-item-badge badge badge--muc msgs-indicator">${ o.room.get('num_unread') }</span>`;
const bookmark = (o) => {
const i18n_add_bookmark = __('Bookmark this groupchat');
const i18n_remove_bookmark = __('Unbookmark this groupchat');
if (o.bookmarked) {
return html`
<a class="list-item-action fa fa-bookmark remove-bookmark button-on"
......@@ -34,37 +23,42 @@ const bookmark = (o) => {
}
const room_item = (o) => html`
<div class="list-item controlbox-padded available-chatroom d-flex flex-row ${ o.currently_open(o.room) ? 'open' : '' } ${ o.room.get('num_unread_general') ? 'unread-msgs' : '' }"
data-room-jid="${o.room.get('jid')}">
const room_item = (o) => {
const i18n_leave_room = __('Leave this groupchat');
const unread_indicator = (o) => html`<span class="list-item-badge badge badge--muc msgs-indicator">${ o.room.get('num_unread') }</span>`;
return html`
<div class="list-item controlbox-padded available-chatroom d-flex flex-row ${ o.currently_open(o.room) ? 'open' : '' } ${ o.room.get('num_unread_general') ? 'unread-msgs' : '' }"
data-room-jid="${o.room.get('jid')}">
${ o.room.get('num_unread') ? unread_indicator(o) : '' }
<a class="list-item-link open-room available-room w-100"
data-room-jid="${o.room.get('jid')}"
title="${i18n_open}"
@click=${o.openRoom}>${o.room.getDisplayName()}</a>
${ o.room.get('num_unread') ? unread_indicator(o) : '' }
<a class="list-item-link open-room available-room w-100"
data-room-jid="${o.room.get('jid')}"
title="${__('Click to open this groupchat')}"
@click=${o.openRoom}>${o.room.getDisplayName()}</a>
${ o.allow_bookmarks ? bookmark(o) : '' }
${ o.allow_bookmarks ? bookmark(o) : '' }
<a class="list-item-action room-info fa fa-info-circle"
data-room-jid="${o.room.get('jid')}"
title="${i18n_title}"
@click=${o.showRoomDetailsModal}></a>
<a class="list-item-action room-info fa fa-info-circle"
data-room-jid="${o.room.get('jid')}"
title="${__('Show more information on this groupchat')}"
@click=${o.showRoomDetailsModal}></a>
<a class="list-item-action fa fa-sign-out-alt close-room"
data-room-jid="${o.room.get('jid')}"
data-room-name="${o.room.getDisplayName()}"
title="${i18n_leave_room}"
@click=${o.closeRoom}></a>
</div>
`;
<a class="list-item-action fa fa-sign-out-alt close-room"
data-room-jid="${o.room.get('jid')}"
data-room-name="${o.room.getDisplayName()}"
title="${i18n_leave_room}"
@click=${o.closeRoom}></a>
</div>`;
}
export default (o) => html`
<div class="list-container list-container--openrooms ${ o.rooms.length ? '' : 'hidden' }">
<a class="list-toggle open-rooms-toggle controlbox-padded" title="${i18n_desc_rooms}" @click=${o.toggleRoomsList}>
<span class="fa ${ (o.toggle_state === o._converse.OPENED) ? 'fa-caret-down' : 'fa-caret-right' }"></span> ${i18n_rooms}</a>
<div class="items-list rooms-list open-rooms-list ${ o.collapsed && 'collapsed' }">
${ o.rooms.map(room => room_item(Object.assign({room}, o))) }
</div>
</div>
`;
export default (o) => {
const i18n_desc_rooms = __('Click to toggle the list of open groupchats');
return html`
<div class="list-container list-container--openrooms ${ o.rooms.length ? '' : 'hidden' }">
<a class="list-toggle open-rooms-toggle controlbox-padded" title="${i18n_desc_rooms}" @click=${o.toggleRoomsList}>
<span class="fa ${ (o.toggle_state === o._converse.OPENED) ? 'fa-caret-down' : 'fa-caret-right' }"></span> ${__('Open Groupchats')}</a>
<div class="items-list rooms-list open-rooms-list ${ o.collapsed && 'collapsed' }">
${ o.rooms.map(room => room_item(Object.assign({room}, o))) }
</div>
</div>`;
}
......@@ -2,10 +2,7 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const i18n_minimized = __('Minimized')
export default (o) => html`
${o.num_minimized} ${i18n_minimized}
${o.num_minimized} ${__('Minimized')}
<span class="unread-message-count ${!o.num_unread ? 'unread-message-count-hidden' : ''}" href="#">${o.num_unread}</span>
`;
......@@ -2,14 +2,14 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const i18n_tooltip = __('Click to restore this chat');
export default (o) => html`
<div class="chat-head-${o.type} chat-head row no-gutters">
<a class="restore-chat w-100 align-self-center" title="${i18n_tooltip}">
${o.num_unread ? html`<span class="message-count badge badge-light">${o.num_unread}</span>` : '' }
${o.title}
</a>
<a class="chatbox-btn close-chatbox-button fa fa-times"></a>
</div>`;
export default (o) => {
const i18n_tooltip = __('Click to restore this chat');
return html`
<div class="chat-head-${o.type} chat-head row no-gutters">
<a class="restore-chat w-100 align-self-center" title="${i18n_tooltip}">
${o.num_unread ? html`<span class="message-count badge badge-light">${o.num_unread}</span>` : '' }
${o.title}
</a>
<a class="chatbox-btn close-chatbox-button fa fa-times"></a>
</div>`;
}
......@@ -4,27 +4,9 @@ import avatar from "./avatar.js";
import { modal_close_button, modal_header_close_button } from "./buttons"
const i18n_address = __('XMPP Address');
const i18n_email = __('Email');
const i18n_fingerprints = __('OMEMO Fingerprints');
const i18n_full_name = __('Full Name');
const i18n_nickname = __('Nickname');
const i18n_profile = __('The User\'s Profile Image');
const i18n_refresh = __('Refresh');
const i18n_role = __('Role');
const i18n_url = __('URL');
const i18n_remove_contact = __('Remove as contact');
const i18n_trusted = __('Trusted');
const i18n_untrusted = __('Untrusted');
const i18n_no_devices = __("No OMEMO-enabled devices found");
const avatar_data = {
'alt_text': i18n_profile,
'extra_classes': 'mb-3'
}
const device_fingerprint = (o) => {
const i18n_trusted = __('Trusted');
const i18n_untrusted = __('Untrusted');
if (o.device.get('bundle') && o.device.get('bundle').fingerprint) {
return html`
<li class="list-group-item">
......@@ -48,6 +30,8 @@ const device_fingerprint = (o) => {
const fingerprints = (o) => {
const i18n_fingerprints = __('OMEMO Fingerprints');
const i18n_no_devices = __("No OMEMO-enabled devices found");
const devices = o.view.devicelist.devices;
return html`
<hr/>
......@@ -61,6 +45,7 @@ const fingerprints = (o) => {
}
const remove_button = (o) => {
const i18n_remove_contact = __('Remove as contact');
return html`
<button type="button" @click="${o.removeContact}" class="btn btn-danger remove-contact">
<i class="far fa-trash-alt"></i>${i18n_remove_contact}
......@@ -69,30 +54,45 @@ const remove_button = (o) => {
}
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="user-details-modal-label">${o.display_name}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
${ o.image ? avatar(Object.assign(avatar_data, o)) : '' }
${ o.fullname ? html`<p><label>${i18n_full_name}:</label> ${o.fullname}</p>` : '' }
<p><label>${i18n_address}:</label> <a href="xmpp:${o.jid}">${o.jid}</a></p>
${ o.nickname ? html`<p><label>${i18n_nickname}:</label> ${o.nickname}</p>` : '' }
${ o.url ? html`<p><label>${i18n_url}:</label> <a target="_blank" rel="noopener" href="${o.url}">${o.url}</a></p>` : '' }
${ o.email ? html`<p><label>${i18n_email}:</label> <a href="mailto:${o.email}">${o.email}</a></p>` : '' }
${ o.role ? html`<p><label>${i18n_role}:</label> ${o.role}</p>` : '' }
export default (o) => {
const i18n_address = __('XMPP Address');
const i18n_email = __('Email');
const i18n_full_name = __('Full Name');
const i18n_nickname = __('Nickname');
const i18n_profile = __('The User\'s Profile Image');
const i18n_refresh = __('Refresh');
const i18n_role = __('Role');
const i18n_url = __('URL');
const avatar_data = {
'alt_text': i18n_profile,
'extra_classes': 'mb-3'
}
${ (o._converse.pluggable.plugins['converse-omemo'].enabled(o._converse)) ? fingerprints(o) : '' }
</div>
<div class="modal-footer">
${modal_close_button}
<button type="button" class="btn btn-info refresh-contact"><i class="fa fa-refresh"> </i>${i18n_refresh}</button>
${ (o.allow_contact_removal && o.is_roster_contact) ? remove_button(o) : '' }
return html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="user-details-modal-label">${o.display_name}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
${ o.image ? avatar(Object.assign(avatar_data, o)) : '' }
${ o.fullname ? html`<p><label>${i18n_full_name}:</label> ${o.fullname}</p>` : '' }
<p><label>${i18n_address}:</label> <a href="xmpp:${o.jid}">${o.jid}</a></p>
${ o.nickname ? html`<p><label>${i18n_nickname}:</label> ${o.nickname}</p>` : '' }
${ o.url ? html`<p><label>${i18n_url}:</label> <a target="_blank" rel="noopener" href="${o.url}">${o.url}</a></p>` : '' }
${ o.email ? html`<p><label>${i18n_email}:</label> <a href="mailto:${o.email}">${o.email}</a></p>` : '' }
${ o.role ? html`<p><label>${i18n_role}:</label> ${o.role}</p>` : '' }
${ (o._converse.pluggable.plugins['converse-omemo'].enabled(o._converse)) ? fingerprints(o) : '' }
</div>
<div class="modal-footer">
${modal_close_button}
<button type="button" class="btn btn-info refresh-contact"><i class="fa fa-refresh"> </i>${i18n_refresh}</button>
${ (o.allow_contact_removal && o.is_roster_contact) ? remove_button(o) : '' }
</div>
</div>
</div>
</div>
`;
`;
}
......@@ -7,36 +7,36 @@ import { modal_header_close_button } from "./buttons"
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
const i18n_modal_title = __('Settings');
const i18n_about = __('About');
const i18n_commands = __('Commands');
const first_subtitle = __(
'%1$s Open Source %2$s XMPP chat client brought to you by %3$s Opkode %2$s',
'<a target="_blank" rel="nofollow" href="https://conversejs.org">',
'</a>',
'<a target="_blank" rel="nofollow" href="https://opkode.com">'
);
const second_subtitle = __(
'%1$s Translate %2$s it into your own language',
'<a target="_blank" rel="nofollow" href="https://hosted.weblate.org/projects/conversejs/#languages">',
'</a>'
);
const tpl_navigation = (o) => html`
<ul class="nav nav-pills justify-content-center">
<li role="presentation" class="nav-item">
<a class="nav-link active" id="about-tab" href="#about-tabpanel" aria-controls="about-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>${i18n_about}</a>
</li>
<li role="presentation" class="nav-item">
<a class="nav-link" id="commands-tab" href="#commands-tabpanel" aria-controls="commands-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>${i18n_commands}</a>
</li>
</ul>
`;
const tpl_navigation = (o) => {
const i18n_about = __('About');
const i18n_commands = __('Commands');
return html`
<ul class="nav nav-pills justify-content-center">
<li role="presentation" class="nav-item">
<a class="nav-link active" id="about-tab" href="#about-tabpanel" aria-controls="about-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>${i18n_about}</a>
</li>
<li role="presentation" class="nav-item">
<a class="nav-link" id="commands-tab" href="#commands-tabpanel" aria-controls="commands-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>${i18n_commands}</a>
</li>
</ul>
`;
}
export default (o) => {
const i18n_modal_title = __('Settings');
const first_subtitle = __(
'%1$s Open Source %2$s XMPP chat client brought to you by %3$s Opkode %2$s',
'<a target="_blank" rel="nofollow" href="https://conversejs.org">',
'</a>',
'<a target="_blank" rel="nofollow" href="https://opkode.com">'
);
const second_subtitle = __(
'%1$s Translate %2$s it into your own language',
'<a target="_blank" rel="nofollow" href="https://hosted.weblate.org/projects/conversejs/#languages">',
'</a>'
);
const show_client_info = api.settings.get('show_client_info');
const allow_adhoc_commands = api.settings.get('allow_adhoc_commands');
const show_both_tabs = show_client_info && allow_adhoc_commands;
......
......@@ -27,7 +27,7 @@
modtools_disable_assign: ['owner', 'moderator', 'participant', 'visitor'],
modtools_disable_query: ['moderator', 'participant', 'visitor'],
enable_smacks: true,
i18n: 'en',
i18n: 'af',
// connection_options: { 'worker': '/dist/shared-connection-worker.js' },
message_archiving: 'always',
muc_domain: 'conference.chat.example.org',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment