Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/headless/plugins/bookmarks/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import converse from '../../shared/api/public.js';
const { Strophe } = converse.env;

class Bookmark extends Model {
get idAttribute () {
get idAttribute() {
return 'jid';
}

getDisplayName () {
return Strophe.xmlunescape(this.get('name')) || this.get('jid');
getDisplayName() {
return this.get('name') && Strophe.xmlunescape(this.get('name')) || this.get('jid');
}
}

Expand Down
12 changes: 7 additions & 5 deletions src/headless/plugins/disco/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,10 @@ export default {
* @method api.disco.info
* @param {string} jid The Jabber ID of the entity to query
* @param {string} [node] A specific node identifier associated with the JID
* @param {import('./types').DiscoInfoOptions} [options]
* @returns {promise} Promise which resolves once we have a result from the server.
*/
info(jid, node) {
info(jid, node, options) {
const attrs = { xmlns: Strophe.NS.DISCO_INFO };
if (node) {
attrs.node = node;
Expand All @@ -164,7 +165,7 @@ export default {
'to': jid,
'type': 'get',
}).c('query', attrs);
return api.sendIQ(info);
return api.sendIQ(info, options?.timeout);
},

/**
Expand Down Expand Up @@ -381,11 +382,12 @@ export default {
* disco entity by refetching them from the server
* @method api.disco.refresh
* @param {string} jid The JID of the entity whose features are refreshed.
* @param {import('./types').DiscoInfoOptions} [options]
* @returns {Promise} A promise which resolves once the features have been refreshed
* @example
* await api.disco.refresh('[email protected]');
*/
async refresh(jid) {
async refresh(jid, options) {
if (!jid) throw new TypeError('api.disco.refresh: You need to provide an entity JID');

await api.waitUntil('discoInitialized');
Expand All @@ -400,10 +402,10 @@ export default {
if (!entity.waitUntilItemsFetched.isPending) {
entity.waitUntilItemsFetched = getOpenPromise();
}
entity.queryInfo();
entity.queryInfo(options);
} else {
// Create it if it doesn't exist
entity = await api.disco.entities.create({ jid }, { ignore_cache: true });
entity = await api.disco.entities.create({ jid }, { ignore_cache: true, timeout: options.timeout });
}
return entity.waitUntilItemsFetched;
},
Expand Down
12 changes: 9 additions & 3 deletions src/headless/plugins/disco/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,12 @@ class DiscoEntity extends Model {
api.trigger('discoExtensionFieldDiscovered', field);
}

/**
* @param {import('./types').FetchEntityFeaturesOptions} options
*/
async fetchFeatures(options) {
if (options.ignore_cache) {
await this.queryInfo();
await this.queryInfo(options);
} else {
const store_id = this.features.browserStorage.name;

Expand Down Expand Up @@ -144,10 +147,13 @@ class DiscoEntity extends Model {
}
}

async queryInfo() {
/**
* @param {import('./types').DiscoInfoOptions} [options]
*/
async queryInfo(options) {
let stanza;
try {
stanza = await api.disco.info(this.get('jid'), null);
stanza = await api.disco.info(this.get('jid'), null, options);
} catch (iq) {
if (u.isElement(iq)) {
const e = await parseErrorStanza(iq);
Expand Down
8 changes: 8 additions & 0 deletions src/headless/plugins/disco/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type DiscoInfoOptions = {
timeout?: number;
}

export type FetchEntityFeaturesOptions = {
timeout?: number;
ignore_cache?: boolean;
}
14 changes: 10 additions & 4 deletions src/headless/plugins/muc/muc.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import MUCSession from './session';

const { u, stx } = converse.env;

const DISCO_INFO_TIMEOUT_ON_JOIN = 5000;

/**
* Represents a groupchat conversation.
*/
Expand Down Expand Up @@ -192,7 +194,9 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
// Set this early, so we don't rejoin in onHiddenChange
this.session.save('connection_status', ROOMSTATUS.CONNECTING);

const is_new = (await this.refreshDiscoInfo()) instanceof ItemNotFoundError;
const result = await this.refreshDiscoInfo({ timeout: DISCO_INFO_TIMEOUT_ON_JOIN });
const is_new = result instanceof ItemNotFoundError;

nick = await this.getAndPersistNickname(nick);
if (!nick) {
safeSave(this.session, { 'connection_status': ROOMSTATUS.NICKNAME_REQUIRED });
Expand Down Expand Up @@ -1254,10 +1258,11 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
* Refresh the disco identity, features and fields for this {@link MUC}.
* *features* are stored on the features {@link Model} attribute on this {@link MUC}.
* *fields* are stored on the config {@link Model} attribute on this {@link MUC}.
* @param {import('@converse/headless/plugins/disco/types').DiscoInfoOptions} [options]
* @returns {Promise}
*/
async refreshDiscoInfo() {
const result = await api.disco.refresh(this.get('jid'));
async refreshDiscoInfo(options) {
const result = await api.disco.refresh(this.get('jid'), options);
if (result instanceof StanzaError) {
return result;
}
Expand Down Expand Up @@ -1738,7 +1743,8 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
<iq to="${this.get('jid')}" type="get" xmlns="jabber:client">
<query xmlns="${Strophe.NS.DISCO_INFO}" node="x-roomuser-item"/>
</iq>`;
const result = await api.sendIQ(stanza, null, false);

const result = await api.sendIQ(stanza, DISCO_INFO_TIMEOUT_ON_JOIN, false);
if (u.isErrorObject(result)) {
throw result;
}
Expand Down
1 change: 1 addition & 0 deletions src/headless/shared/api/send.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default {
send(stanza) {
const { api } = _converse;
if (!api.connection.connected()) {
// TODO: queue unsent messages and send once we're connected again
log.warn("Not sending stanza because we're not connected!");
log.warn(Strophe.serialize(stanza));
return;
Expand Down
6 changes: 4 additions & 2 deletions src/headless/types/plugins/disco/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,10 @@ declare namespace _default {
* @method api.disco.info
* @param {string} jid The Jabber ID of the entity to query
* @param {string} [node] A specific node identifier associated with the JID
* @param {import('./types').DiscoInfoOptions} [options]
* @returns {promise} Promise which resolves once we have a result from the server.
*/
export function info(jid: string, node?: string): Promise<any>;
export function info(jid: string, node?: string, options?: import("./types").DiscoInfoOptions): Promise<any>;
/**
* Query for items associated with an XMPP entity
*
Expand Down Expand Up @@ -190,11 +191,12 @@ declare namespace _default {
* disco entity by refetching them from the server
* @method api.disco.refresh
* @param {string} jid The JID of the entity whose features are refreshed.
* @param {import('./types').DiscoInfoOptions} [options]
* @returns {Promise} A promise which resolves once the features have been refreshed
* @example
* await api.disco.refresh('[email protected]');
*/
export function refresh(jid: string): Promise<any>;
export function refresh(jid: string, options?: import("./types").DiscoInfoOptions): Promise<any>;
/**
* Return all the features associated with a disco entity
*
Expand Down
10 changes: 8 additions & 2 deletions src/headless/types/plugins/disco/entity.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ declare class DiscoEntity extends Model {
getFeature(feature: string): Promise<this>;
onFeatureAdded(feature: any): void;
onFieldAdded(field: any): void;
fetchFeatures(options: any): Promise<void>;
queryInfo(): Promise<void>;
/**
* @param {import('./types').FetchEntityFeaturesOptions} options
*/
fetchFeatures(options: import("./types").FetchEntityFeaturesOptions): Promise<void>;
/**
* @param {import('./types').DiscoInfoOptions} [options]
*/
queryInfo(options?: import("./types").DiscoInfoOptions): Promise<void>;
/**
* @param {Element} stanza
*/
Expand Down
8 changes: 8 additions & 0 deletions src/headless/types/plugins/disco/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type DiscoInfoOptions = {
timeout?: number;
};
export type FetchEntityFeaturesOptions = {
timeout?: number;
ignore_cache?: boolean;
};
//# sourceMappingURL=types.d.ts.map
3 changes: 2 additions & 1 deletion src/headless/types/plugins/muc/muc.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,10 @@ declare class MUC extends MUC_base {
* Refresh the disco identity, features and fields for this {@link MUC}.
* *features* are stored on the features {@link Model} attribute on this {@link MUC}.
* *fields* are stored on the config {@link Model} attribute on this {@link MUC}.
* @param {import('@converse/headless/plugins/disco/types').DiscoInfoOptions} [options]
* @returns {Promise}
*/
refreshDiscoInfo(): Promise<any>;
refreshDiscoInfo(options?: import("@converse/headless/plugins/disco/types").DiscoInfoOptions): Promise<any>;
/**
* Fetch the *extended* MUC info from the server and cache it locally
* https://xmpp.org/extensions/xep-0045.html#disco-roominfo
Expand Down
20 changes: 14 additions & 6 deletions src/shared/avatar/avatar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ import { html } from 'lit';
import { until } from 'lit/directives/until.js';
import { api } from '@converse/headless';
import { __ } from 'i18n';
import { CustomElement } from 'shared/components/element.js';
import { ObservableElement } from 'shared/components/observable.js';
import tplAvatar from './templates/avatar.js';

import './avatar.scss';

export default class Avatar extends CustomElement {
export default class Avatar extends ObservableElement {
/**
* @typedef {import('shared/components/types').ObservableProperty} ObservableProperty
*/
static get properties() {
return {
...super.properties,
model: { type: Object },
pickerdata: { type: Object },
name: { type: String },
Expand All @@ -26,6 +30,7 @@ export default class Avatar extends CustomElement {
this.width = 36;
this.height = 36;
this.name = '';
this.observable = /** @type {ObservableProperty} */ ("once");
}

render() {
Expand Down Expand Up @@ -57,14 +62,17 @@ export default class Avatar extends CustomElement {
height: ${this.height}px;
font: ${this.width / 2}px Arial;
line-height: ${this.height}px;`;
const style = this.isVisible ? until(this.model.getAvatarStyle(css), default_bg_css + css) : default_bg_css + css;

const author_style = this.model.getAvatarStyle(css);
return html`<div class="avatar-initials" style="${until(author_style, default_bg_css + css)}"
aria-label="${this.name}">
${this.getInitials(this.name)}
return html`<div class="avatar-initials" style="${style}" aria-label="${this.name}">
${this.getInitials(this.name)}
</div>`;
}

onVisibilityChanged() {
this.requestUpdate();
}

/**
* @param {string} name
* @returns {string}
Expand Down
15 changes: 12 additions & 3 deletions src/types/shared/avatar/avatar.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export default class Avatar extends CustomElement {
export default class Avatar extends ObservableElement {
/**
* @typedef {import('shared/components/types').ObservableProperty} ObservableProperty
*/
static get properties(): {
model: {
type: ObjectConstructor;
Expand All @@ -18,18 +21,24 @@ export default class Avatar extends CustomElement {
nonce: {
type: StringConstructor;
};
observable: {
type: StringConstructor;
};
intersectionRatio: {
type: NumberConstructor;
};
};
model: any;
pickerdata: any;
width: number;
height: number;
name: string;
render(): import("lit-html").TemplateResult<1> | "";
onVisibilityChanged(): void;
/**
* @param {string} name
* @returns {string}
*/
getInitials(name: string): string;
}
import { CustomElement } from 'shared/components/element.js';
import { ObservableElement } from 'shared/components/observable.js';
//# sourceMappingURL=avatar.d.ts.map
Loading