JC Brand 2 месяцев назад
Родитель
Сommit
bb271eab43

+ 1 - 1
README.md

@@ -65,7 +65,7 @@ In embedded mode, Converse can be embedded into an element in the DOM.
 -   Chat statuses (online, busy, away, offline)
 -   Anonymous logins, see the [anonymous login demo](https://conversejs.org/demo/anonymous.html)
 -   URL Previews (requires server support, for example [mod_ogp](https://modules.prosody.im/mod_ogp.html)
--   Translated into over 30 languages
+-   Translated into over 40 languages
 
 ### Supported XMPP Extensions
 

+ 1 - 1
index.html

@@ -170,7 +170,7 @@
                             <li>Message Styling (<a href="https://xmpp.org/extensions/xep-0384.html" target="_blank" rel="noopener">XEP 393</a>)</li>
                             <li>Anonymous logins, see the <a href="/demo/anonymous.html" target="_blank" rel="noopener">anonymous login demo</a></li>
                             <li>Message corrections, retractions and moderation</li>
-                            <li>Translated into over 30 languages</li>
+                            <li>Translated into over 40 languages</li>
                         </ul>
                     </div>
                 </div>

+ 0 - 2
src/plugins/muc-views/tests/mentions.js

@@ -453,9 +453,7 @@ describe("A sent groupchat message", function () {
             action.style.opacity = 1;
             action.click();
 
-                    debugger;
             await u.waitUntil(() => textarea.value === 'hello @z3r0 @gibson @mr.robot, how are you?');
-                    return
             expect(view.model.messages.at(0).get('correcting')).toBe(true);
             expect(view.querySelectorAll('.chat-msg').length).toBe(1);
             await u.waitUntil(() => u.hasClass('correcting', view.querySelector('.chat-msg')), 500);

+ 3 - 2
src/plugins/rosterview/modals/add-contact.js

@@ -1,10 +1,11 @@
 import { Strophe } from "strophe.js";
-import { _converse, api, log, u } from "@converse/headless";
-import "shared/autocomplete/index.js";
+import { _converse, api, log } from "@converse/headless";
 import BaseModal from "plugins/modal/modal.js";
 import tplAddContactModal from "./templates/add-contact.js";
 import { __ } from "i18n";
 
+import './styles/add-contact.scss';
+
 export default class AddContactModal extends BaseModal {
     initialize() {
         super.initialize();

+ 8 - 0
src/plugins/rosterview/modals/styles/add-contact.scss

@@ -0,0 +1,8 @@
+.conversejs {
+    converse-add-contact-modal {
+        .modal-body {
+            // Necessary for the auto-complete dropdown to show and to not cause a scrollbar in the modal.
+            overflow-y: visible !important;
+        }
+    }
+}

+ 10 - 7
src/plugins/rosterview/modals/templates/add-contact.js

@@ -1,7 +1,8 @@
-import { __ } from "i18n";
+import { html } from "lit";
 import { api } from "@converse/headless";
+import { __ } from "i18n";
 import { getGroupsAutoCompleteList, getJIDsAutoCompleteList, getNamesAutoCompleteList } from "../../utils.js";
-import { html } from "lit";
+import "shared/autocomplete/index.js";
 import { FILTER_STARTSWITH, FILTER_CONTAINS } from "shared/autocomplete/utils";
 
 /**
@@ -26,18 +27,20 @@ export default (el) => {
                     ? html`<converse-autocomplete
                           .getAutoCompleteList=${getNamesAutoCompleteList}
                           position="below"
-                          filter=${FILTER_CONTAINS}
+                          min_chars="2"
+                          filter="${FILTER_CONTAINS}"
                           ?required=${true}
                           value="${el.model.get("jid") || ""}"
                           placeholder="${i18n_contact_placeholder}"
                           name="jid"
                       ></converse-autocomplete>`
                     : html`<converse-autocomplete
-                          .list=${getJIDsAutoCompleteList()}
-                          .data=${(text, input) => `${input.slice(0, input.indexOf("@"))}@${text}`}
+                          .list="${getJIDsAutoCompleteList()}"
+                          .data="${(text, input) => `${input.slice(0, input.indexOf("@"))}@${text}`}"
                           position="below"
-                          filter=${FILTER_STARTSWITH}
-                          ?required=${!api.settings.get("xhr_user_search_url")}
+                          min_chars="2"
+                          filter="${FILTER_STARTSWITH}"
+                          ?required="${!api.settings.get("xhr_user_search_url")}"
                           value="${el.model.get("jid") || ""}"
                           placeholder="${i18n_contact_placeholder}"
                           name="jid"

+ 1 - 1
src/plugins/rosterview/tests/add-contact-modal.js

@@ -63,7 +63,7 @@ describe("The 'Add Contact' widget", function () {
                 {"jid": "marty@mcfly.net", "fullname": "Marty McFly"},
                 {"jid": "doc@brown.com", "fullname": "Doc Brown"}
             ];
-            return { json };
+            return Promise.resolve({ json });
         });
 
         await mock.openControlBox(_converse);

+ 2 - 2
src/plugins/rosterview/utils.js

@@ -17,7 +17,7 @@ const { STATUS_WEIGHTS } = constants;
 export async function removeContact(contact, unauthorize = false) {
     if (!api.settings.get('allow_contact_removal')) return;
 
-    const result = await api.confirm(__('Are you sure you want to remove this contact?'));
+    const result = await api.confirm(__('Confirm'), __('Are you sure you want to remove this contact?'));
     if (!result) return false;
 
     const chat = await api.chats.get(contact.get('jid'));
@@ -317,7 +317,7 @@ export async function getNamesAutoCompleteList(query) {
         return [];
     }
 
-    const json = response.json();
+    const json = await response.json();
     if (!Array.isArray(json)) {
         log.error(`Invalid JSON returned"`);
         return [];

+ 9 - 9
src/shared/autocomplete/component.js

@@ -130,15 +130,15 @@ export default class AutoCompleteComponent extends CustomElement {
 
     firstUpdated() {
         this.auto_complete = new AutoComplete(/** @type HTMLElement */ (this.firstElementChild), {
-            "ac_triggers": this.triggers.split(" "),
-            "auto_first": this.auto_first,
-            "filter": this.filter == "contains" ? FILTER_CONTAINS : FILTER_STARTSWITH,
-            "include_triggers": [],
-            "list": this.list ?? ((q) => this.getAutoCompleteList(q)),
-            "data": this.data,
-            "match_current_word": true,
-            "max_items": this.max_items,
-            "min_chars": this.min_chars,
+            ac_triggers: this.triggers.split(" "),
+            auto_first: this.auto_first,
+            filter: this.filter == "contains" ? FILTER_CONTAINS : FILTER_STARTSWITH,
+            include_triggers: [],
+            list: this.list ?? (/** @param {string} q */(q) => this.getAutoCompleteList(q)),
+            data: this.data,
+            match_current_word: true,
+            max_items: this.max_items,
+            min_chars: this.min_chars,
         });
         this.auto_complete.on("suggestion-box-selectcomplete", () => (this.auto_completing = false));
     }

+ 1 - 1
src/shared/autocomplete/styles/_autocomplete.scss

@@ -62,7 +62,7 @@
                 padding: 1em;
                 position: relative;
                 text-overflow: ellipsis;
-
+                white-space: pre;
                 &:hover {
                     mark {
                         background-color: unset;