diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst
index eacff43af5..6a7a2b4950 100644
--- a/docs/source/configuration.rst
+++ b/docs/source/configuration.rst
@@ -1718,6 +1718,29 @@ providers_link
The hyperlink on the registration form which points to a directory of public
XMPP servers.
+registration_providers
+----------------------
+
+* Default: ``[]``
+
+An optional array of XMPP provider domains to suggest via autocomplete when the user enters the
+provider on the registration form.
+
+For example:
+
+.. code-block:: javascript
+
+ converse.initialize({
+ registration_providers: [
+ 'conversejs.org',
+ 'jabber.org',
+ 'xmpp.jp',
+ 'trashserver.net',
+ ]
+ });
+
+Suggestions are shown via the ```` component and filtered by prefix.
+
.. _`assets_path`:
assets_path
diff --git a/src/plugins/chatview/index.js b/src/plugins/chatview/index.js
index a9fa389d0d..5cc74822c9 100644
--- a/src/plugins/chatview/index.js
+++ b/src/plugins/chatview/index.js
@@ -54,7 +54,8 @@ converse.plugins.add('converse-chatview', {
'call': false,
'clear': true,
'emoji': true,
- 'spoiler': false
+ 'spoiler': false,
+ 'location': true
}
});
diff --git a/src/plugins/chatview/templates/message-form.js b/src/plugins/chatview/templates/message-form.js
index b5bbcfe41b..cca4624daa 100644
--- a/src/plugins/chatview/templates/message-form.js
+++ b/src/plugins/chatview/templates/message-form.js
@@ -15,6 +15,7 @@ export default (el) => {
const show_emoji_button = api.settings.get("visible_toolbar_buttons").emoji;
const show_send_button = api.settings.get("show_send_button");
const show_spoiler_button = api.settings.get("visible_toolbar_buttons").spoiler;
+ const show_location_button = api.settings.get("visible_toolbar_buttons").location;
const show_toolbar = api.settings.get("show_toolbar");
return html`
${i18n_providers}
${i18n_providers_link}.
diff --git a/src/plugins/rosterview/modals/templates/add-contact.js b/src/plugins/rosterview/modals/templates/add-contact.js
index 6ff57f8e7d..ff4511c5d7 100644
--- a/src/plugins/rosterview/modals/templates/add-contact.js
+++ b/src/plugins/rosterview/modals/templates/add-contact.js
@@ -35,12 +35,13 @@ export default (el) => {
name="jid"
>`
: html` `${input.slice(0, input.indexOf('@'))}@${text}`}
position="below"
- min_chars="2"
+ min_chars="1"
filter="startswith"
- ?required="${!api.settings.get('xhr_user_search_url')}"
+ triggers="@"
+ ?required=${!api.settings.get('xhr_user_search_url')}
value="${el.state.get('jid') || ''}"
placeholder="${i18n_contact_placeholder}"
name="jid"
diff --git a/src/plugins/rosterview/utils.js b/src/plugins/rosterview/utils.js
index fa2f192a50..91dd96f36f 100644
--- a/src/plugins/rosterview/utils.js
+++ b/src/plugins/rosterview/utils.js
@@ -340,11 +340,14 @@ export function getGroupsAutoCompleteList() {
export function getJIDsAutoCompleteList() {
const roster = /** @type {RosterContacts} */ (_converse.state.roster);
+ const from_roster = roster.map((item) => Strophe.getDomainFromJid(item.get('jid')));
+ const from_settings = api.settings.get('registration_providers') || [];
return [
...new Set([
- ...roster.map((item) => Strophe.getDomainFromJid(item.get('jid'))),
+ ...from_roster,
_converse.session.get('domain'),
- ]),
+ ...from_settings,
+ ].filter(Boolean)),
];
}
diff --git a/src/shared/chat/toolbar.js b/src/shared/chat/toolbar.js
index cca72707d8..ee67d307c1 100644
--- a/src/shared/chat/toolbar.js
+++ b/src/shared/chat/toolbar.js
@@ -24,6 +24,7 @@ export class ChatToolbar extends CustomElement {
show_emoji_button: { type: Boolean },
show_send_button: { type: Boolean },
show_spoiler_button: { type: Boolean },
+ show_location_button: { type: Boolean },
}
}
@@ -34,6 +35,7 @@ export class ChatToolbar extends CustomElement {
this.hidden_occupants = false;
this.show_send_button = false;
this.show_spoiler_button = false;
+ this.show_location_button = false;
this.show_call_button = false;
this.show_emoji_button = false;
}
@@ -83,6 +85,19 @@ export class ChatToolbar extends CustomElement {
buttons.push(this.getSpoilerButton());
}
+ if (this.show_location_button) {
+ const color = this.is_groupchat ? '--muc-color' : '--chat-color';
+ const i18n_insert_location = __('Insert current location');
+ buttons.push(html`
+ `
+ );
+ }
+
const domain = _converse.session.get('domain');
const http_upload_promise = api.disco.supports(Strophe.NS.HTTPUPLOAD, domain);
buttons.push(html`${until(http_upload_promise.then(is_supported => this.getHTTPUploadButton(!!is_supported)),'')}`);
@@ -198,6 +213,30 @@ export class ChatToolbar extends CustomElement {
model: this.model
});
}
+
+ /** @param {MouseEvent} ev */
+ insertLocation (ev) {
+ ev?.preventDefault?.();
+ ev?.stopPropagation?.();
+ const i18n_error = __('Unable to get current location');
+ if (!('geolocation' in navigator)) {
+ api.toast.show('geo-not-supported', { type: 'warning', body: i18n_error });
+ return;
+ }
+ navigator.geolocation.getCurrentPosition(
+ (pos) => {
+ const { latitude, longitude } = pos.coords;
+ const lat = latitude.toFixed(6);
+ const lon = longitude.toFixed(6);
+ const geo = `geo:${lat},${lon}`;
+ const draft = (this.model.get('draft') || '').trim();
+ const sep = draft ? ' ' : '';
+ this.model.set('draft', `${draft}${sep}${geo}`);
+ },
+ () => api.toast.show('geo-error', { type: 'danger', body: i18n_error }),
+ { enableHighAccuracy: true, timeout: 8000, maximumAge: 60000 }
+ );
+ }
}
api.elements.define('converse-chat-toolbar', ChatToolbar);
diff --git a/src/shared/texture/templates/audio.js b/src/shared/texture/templates/audio.js
index bb29a791aa..5b65ffbcf8 100644
--- a/src/shared/texture/templates/audio.js
+++ b/src/shared/texture/templates/audio.js
@@ -10,7 +10,8 @@ import "../styles/audio.scss";
*/
export default (url, hide_url, title) => {
const { hostname } = u.getURL(url);
- return html`
+ const label = title || (hostname ? `Audio from ${hostname}` : 'Audio');
+ return html`
${title || !hide_url
? html`
${title ? html`${title}` : ""}
@@ -19,6 +20,6 @@ export default (url, hide_url, title) => {
: html`${hostname}`}
`
: ""}
-
+
`;
};
diff --git a/src/types/shared/chat/toolbar.d.ts b/src/types/shared/chat/toolbar.d.ts
index ce6dc0e893..ea9a57ee77 100644
--- a/src/types/shared/chat/toolbar.d.ts
+++ b/src/types/shared/chat/toolbar.d.ts
@@ -24,6 +24,9 @@ export class ChatToolbar extends CustomElement {
show_spoiler_button: {
type: BooleanConstructor;
};
+ show_location_button: {
+ type: BooleanConstructor;
+ };
};
model: any;
is_groupchat: any;
@@ -43,6 +46,8 @@ export class ChatToolbar extends CustomElement {
getSpoilerButton(): import("lit-html").TemplateResult<1>;
/** @param {MouseEvent} ev */
toggleFileUpload(ev: MouseEvent): void;
+ /** @param {MouseEvent} ev */
+ insertLocation(ev: MouseEvent): void;
/** @param {InputEvent} ev */
onFileSelection(ev: InputEvent): void;
/** @param {MouseEvent} ev */