|
|
@ -1,5 +1,19 @@
|
|
|
|
import Backbone from 'backbone';
|
|
|
|
import Backbone from 'backbone';
|
|
|
|
import _, { isArray, isEmpty, isNumber, isString } from 'lodash';
|
|
|
|
import {
|
|
|
|
|
|
|
|
debounce,
|
|
|
|
|
|
|
|
defaults,
|
|
|
|
|
|
|
|
filter,
|
|
|
|
|
|
|
|
includes,
|
|
|
|
|
|
|
|
isArray,
|
|
|
|
|
|
|
|
isEmpty,
|
|
|
|
|
|
|
|
isEqual,
|
|
|
|
|
|
|
|
isNumber,
|
|
|
|
|
|
|
|
isString,
|
|
|
|
|
|
|
|
map,
|
|
|
|
|
|
|
|
sortBy,
|
|
|
|
|
|
|
|
throttle,
|
|
|
|
|
|
|
|
uniq,
|
|
|
|
|
|
|
|
} from 'lodash';
|
|
|
|
import { getMessageQueue } from '../session';
|
|
|
|
import { getMessageQueue } from '../session';
|
|
|
|
import { getConversationController } from '../session/conversations';
|
|
|
|
import { getConversationController } from '../session/conversations';
|
|
|
|
import { ClosedGroupVisibleMessage } from '../session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage';
|
|
|
|
import { ClosedGroupVisibleMessage } from '../session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage';
|
|
|
@ -99,15 +113,15 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
this.initialPromise = Promise.resolve();
|
|
|
|
this.initialPromise = Promise.resolve();
|
|
|
|
autoBind(this);
|
|
|
|
autoBind(this);
|
|
|
|
|
|
|
|
|
|
|
|
this.throttledBumpTyping = _.throttle(this.bumpTyping, 300);
|
|
|
|
this.throttledBumpTyping = throttle(this.bumpTyping, 300);
|
|
|
|
this.updateLastMessage = _.throttle(this.bouncyUpdateLastMessage.bind(this), 1000, {
|
|
|
|
this.updateLastMessage = throttle(this.bouncyUpdateLastMessage.bind(this), 1000, {
|
|
|
|
trailing: true,
|
|
|
|
trailing: true,
|
|
|
|
leading: true,
|
|
|
|
leading: true,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.throttledNotify = _.debounce(this.notify, 2000, { maxWait: 2000, trailing: true });
|
|
|
|
this.throttledNotify = debounce(this.notify, 2000, { maxWait: 2000, trailing: true });
|
|
|
|
//start right away the function is called, and wait 1sec before calling it again
|
|
|
|
//start right away the function is called, and wait 1sec before calling it again
|
|
|
|
const markReadDebounced = _.debounce(this.markReadBouncy, 1000, {
|
|
|
|
const markReadDebounced = debounce(this.markReadBouncy, 1000, {
|
|
|
|
leading: true,
|
|
|
|
leading: true,
|
|
|
|
trailing: true,
|
|
|
|
trailing: true,
|
|
|
|
});
|
|
|
|
});
|
|
|
@ -240,9 +254,22 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
return groupAdmins && groupAdmins?.length > 0 ? groupAdmins : [];
|
|
|
|
return groupAdmins && groupAdmins?.length > 0 ? groupAdmins : [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Get the list of moderators in that room, or an empty array
|
|
|
|
|
|
|
|
* Only to be called for opengroup conversations.
|
|
|
|
|
|
|
|
* This makes no sense for a private chat or an closed group, as closed group admins must be stored with getGroupAdmins
|
|
|
|
|
|
|
|
* @returns the list of moderators for the conversation if the conversation is public, or []
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public getGroupModerators(): Array<string> {
|
|
|
|
|
|
|
|
const groupModerators = this.get('groupModerators') as Array<string> | undefined;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return this.isPublic() && groupModerators && groupModerators?.length > 0 ? groupModerators : [];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// tslint:disable-next-line: cyclomatic-complexity max-func-body-length
|
|
|
|
// tslint:disable-next-line: cyclomatic-complexity max-func-body-length
|
|
|
|
public getConversationModelProps(): ReduxConversationType {
|
|
|
|
public getConversationModelProps(): ReduxConversationType {
|
|
|
|
const groupAdmins = this.getGroupAdmins();
|
|
|
|
const groupAdmins = this.getGroupAdmins();
|
|
|
|
|
|
|
|
const groupModerators = this.getGroupModerators();
|
|
|
|
// tslint:disable-next-line: cyclomatic-complexity
|
|
|
|
// tslint:disable-next-line: cyclomatic-complexity
|
|
|
|
const isPublic = this.isPublic();
|
|
|
|
const isPublic = this.isPublic();
|
|
|
|
|
|
|
|
|
|
|
@ -253,6 +280,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
const isPrivate = this.isPrivate();
|
|
|
|
const isPrivate = this.isPrivate();
|
|
|
|
const isGroup = !isPrivate;
|
|
|
|
const isGroup = !isPrivate;
|
|
|
|
const weAreAdmin = this.isAdmin(ourNumber);
|
|
|
|
const weAreAdmin = this.isAdmin(ourNumber);
|
|
|
|
|
|
|
|
const weAreModerator = this.isModerator(ourNumber); // only used for sogs
|
|
|
|
const isMe = this.isMe();
|
|
|
|
const isMe = this.isMe();
|
|
|
|
const isTyping = !!this.typingTimer;
|
|
|
|
const isTyping = !!this.typingTimer;
|
|
|
|
const unreadCount = this.get('unreadCount') || undefined;
|
|
|
|
const unreadCount = this.get('unreadCount') || undefined;
|
|
|
@ -290,6 +318,10 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
toRet.weAreAdmin = true;
|
|
|
|
toRet.weAreAdmin = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (weAreModerator) {
|
|
|
|
|
|
|
|
toRet.weAreModerator = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (isMe) {
|
|
|
|
if (isMe) {
|
|
|
|
toRet.isMe = true;
|
|
|
|
toRet.isMe = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -343,21 +375,29 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
if (didApproveMe) {
|
|
|
|
if (didApproveMe) {
|
|
|
|
toRet.didApproveMe = didApproveMe;
|
|
|
|
toRet.didApproveMe = didApproveMe;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (isApproved) {
|
|
|
|
if (isApproved) {
|
|
|
|
toRet.isApproved = isApproved;
|
|
|
|
toRet.isApproved = isApproved;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (subscriberCount) {
|
|
|
|
if (subscriberCount) {
|
|
|
|
toRet.subscriberCount = subscriberCount;
|
|
|
|
toRet.subscriberCount = subscriberCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (groupAdmins && groupAdmins.length) {
|
|
|
|
if (groupAdmins && groupAdmins.length) {
|
|
|
|
toRet.groupAdmins = _.uniq(groupAdmins);
|
|
|
|
toRet.groupAdmins = uniq(groupAdmins);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (groupModerators && groupModerators.length) {
|
|
|
|
|
|
|
|
toRet.groupModerators = uniq(groupModerators);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (members && members.length) {
|
|
|
|
if (members && members.length) {
|
|
|
|
toRet.members = _.uniq(members);
|
|
|
|
toRet.members = uniq(members);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (zombies && zombies.length) {
|
|
|
|
if (zombies && zombies.length) {
|
|
|
|
toRet.zombies = _.uniq(zombies);
|
|
|
|
toRet.zombies = uniq(zombies);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (expireTimer) {
|
|
|
|
if (expireTimer) {
|
|
|
@ -384,10 +424,10 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async updateGroupAdmins(groupAdmins: Array<string>, shouldCommit: boolean) {
|
|
|
|
public async updateGroupAdmins(groupAdmins: Array<string>, shouldCommit: boolean) {
|
|
|
|
const existingAdmins = _.uniq(_.sortBy(this.getGroupAdmins()));
|
|
|
|
const existingAdmins = uniq(sortBy(this.getGroupAdmins()));
|
|
|
|
const newAdmins = _.uniq(_.sortBy(groupAdmins));
|
|
|
|
const newAdmins = uniq(sortBy(groupAdmins));
|
|
|
|
|
|
|
|
|
|
|
|
if (_.isEqual(existingAdmins, newAdmins)) {
|
|
|
|
if (isEqual(existingAdmins, newAdmins)) {
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.set({ groupAdmins });
|
|
|
|
this.set({ groupAdmins });
|
|
|
@ -397,6 +437,23 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public async updateGroupModerators(groupModerators: Array<string>, shouldCommit: boolean) {
|
|
|
|
|
|
|
|
if (!this.isPublic()) {
|
|
|
|
|
|
|
|
throw new Error('group moderators are only possible on SOGS');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const existingModerators = uniq(sortBy(this.getGroupModerators()));
|
|
|
|
|
|
|
|
const newModerators = uniq(sortBy(groupModerators));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isEqual(existingModerators, newModerators)) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
this.set({ groupModerators: newModerators });
|
|
|
|
|
|
|
|
if (shouldCommit) {
|
|
|
|
|
|
|
|
await this.commit();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async onReadMessage(message: MessageModel, readAt: number) {
|
|
|
|
public async onReadMessage(message: MessageModel, readAt: number) {
|
|
|
|
// We mark as read everything older than this message - to clean up old stuff
|
|
|
|
// We mark as read everything older than this message - to clean up old stuff
|
|
|
|
// still marked unread in the database. If the user generally doesn't read in
|
|
|
|
// still marked unread in the database. If the user generally doesn't read in
|
|
|
@ -819,7 +876,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
|
|
|
|
|
|
|
|
const messageModel = await this.addSingleOutgoingMessage({
|
|
|
|
const messageModel = await this.addSingleOutgoingMessage({
|
|
|
|
body,
|
|
|
|
body,
|
|
|
|
quote: _.isEmpty(quote) ? undefined : quote,
|
|
|
|
quote: isEmpty(quote) ? undefined : quote,
|
|
|
|
preview,
|
|
|
|
preview,
|
|
|
|
attachments,
|
|
|
|
attachments,
|
|
|
|
sent_at: networkTimestamp,
|
|
|
|
sent_at: networkTimestamp,
|
|
|
@ -905,7 +962,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
let expireTimer = providedExpireTimer;
|
|
|
|
let expireTimer = providedExpireTimer;
|
|
|
|
let source = providedSource;
|
|
|
|
let source = providedSource;
|
|
|
|
|
|
|
|
|
|
|
|
_.defaults(options, { fromSync: false });
|
|
|
|
defaults(options, { fromSync: false });
|
|
|
|
|
|
|
|
|
|
|
|
if (!expireTimer) {
|
|
|
|
if (!expireTimer) {
|
|
|
|
expireTimer = 0;
|
|
|
|
expireTimer = 0;
|
|
|
@ -1088,7 +1145,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const options = providedOptions || {};
|
|
|
|
const options = providedOptions || {};
|
|
|
|
_.defaults(options, { sendReadReceipts: true });
|
|
|
|
defaults(options, { sendReadReceipts: true });
|
|
|
|
|
|
|
|
|
|
|
|
const conversationId = this.id;
|
|
|
|
const conversationId = this.id;
|
|
|
|
Notifications.clearByConversationID(conversationId);
|
|
|
|
Notifications.clearByConversationID(conversationId);
|
|
|
@ -1125,7 +1182,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
window.inboxStore?.dispatch(conversationActions.messagesChanged(allProps));
|
|
|
|
window.inboxStore?.dispatch(conversationActions.messagesChanged(allProps));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Some messages we're marking read are local notifications with no sender
|
|
|
|
// Some messages we're marking read are local notifications with no sender
|
|
|
|
read = _.filter(read, m => Boolean(m.sender));
|
|
|
|
read = filter(read, m => Boolean(m.sender));
|
|
|
|
const realUnreadCount = await this.getUnreadCount();
|
|
|
|
const realUnreadCount = await this.getUnreadCount();
|
|
|
|
if (read.length === 0) {
|
|
|
|
if (read.length === 0) {
|
|
|
|
const cachedUnreadCountOnConvo = this.get('unreadCount');
|
|
|
|
const cachedUnreadCountOnConvo = this.get('unreadCount');
|
|
|
@ -1165,7 +1222,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
read = read.filter(item => !item.hasErrors);
|
|
|
|
read = read.filter(item => !item.hasErrors);
|
|
|
|
|
|
|
|
|
|
|
|
if (read.length && options.sendReadReceipts) {
|
|
|
|
if (read.length && options.sendReadReceipts) {
|
|
|
|
const timestamps = _.map(read, 'timestamp').filter(t => !!t) as Array<number>;
|
|
|
|
const timestamps = map(read, 'timestamp').filter(t => !!t) as Array<number>;
|
|
|
|
await this.sendReadReceiptsIfNeeded(timestamps);
|
|
|
|
await this.sendReadReceiptsIfNeeded(timestamps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1233,7 +1290,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
// if you change this behavior, double check all setSessionProfile calls (especially the one in EditProfileDialog)
|
|
|
|
// if you change this behavior, double check all setSessionProfile calls (especially the one in EditProfileDialog)
|
|
|
|
if (newProfile.avatarPath) {
|
|
|
|
if (newProfile.avatarPath) {
|
|
|
|
const originalAvatar = this.get('avatarInProfile');
|
|
|
|
const originalAvatar = this.get('avatarInProfile');
|
|
|
|
if (!_.isEqual(originalAvatar, newProfile.avatarPath)) {
|
|
|
|
if (!isEqual(originalAvatar, newProfile.avatarPath)) {
|
|
|
|
this.set({ avatarInProfile: newProfile.avatarPath });
|
|
|
|
this.set({ avatarInProfile: newProfile.avatarPath });
|
|
|
|
changes = true;
|
|
|
|
changes = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1306,6 +1363,22 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
return Array.isArray(groupAdmins) && groupAdmins.includes(pubKey);
|
|
|
|
return Array.isArray(groupAdmins) && groupAdmins.includes(pubKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Check if the provided pubkey is a moderator.
|
|
|
|
|
|
|
|
* Being a moderator only makes sense for a sogs as closed groups have their admin under the groupAdmins property
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public isModerator(pubKey?: string) {
|
|
|
|
|
|
|
|
if (!pubKey) {
|
|
|
|
|
|
|
|
throw new Error('isModerator() pubKey is falsy');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.isPublic()) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const groupModerators = this.getGroupModerators();
|
|
|
|
|
|
|
|
return Array.isArray(groupModerators) && groupModerators.includes(pubKey);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async setIsPinned(value: boolean) {
|
|
|
|
public async setIsPinned(value: boolean) {
|
|
|
|
if (value !== this.isPinned()) {
|
|
|
|
if (value !== this.isPinned()) {
|
|
|
|
this.set({
|
|
|
|
this.set({
|
|
|
@ -1363,6 +1436,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
* Saves the infos of that room directly on the conversation table.
|
|
|
|
* Saves the infos of that room directly on the conversation table.
|
|
|
|
* This does not write anything to the db if no changes are detected
|
|
|
|
* This does not write anything to the db if no changes are detected
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
// tslint:disable-next-line: cyclomatic-complexity
|
|
|
|
public async setPollInfo(infos?: {
|
|
|
|
public async setPollInfo(infos?: {
|
|
|
|
subscriberCount: number;
|
|
|
|
subscriberCount: number;
|
|
|
|
read: boolean;
|
|
|
|
read: boolean;
|
|
|
@ -1371,6 +1445,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
details: {
|
|
|
|
details: {
|
|
|
|
admins?: Array<string>;
|
|
|
|
admins?: Array<string>;
|
|
|
|
image_id?: number;
|
|
|
|
image_id?: number;
|
|
|
|
|
|
|
|
moderators?: Array<string>;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}) {
|
|
|
|
}) {
|
|
|
|
if (!infos || isEmpty(infos)) {
|
|
|
|
if (!infos || isEmpty(infos)) {
|
|
|
@ -1403,24 +1478,26 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (details.admins && isArray(details.admins)) {
|
|
|
|
if (details.admins && isArray(details.admins)) {
|
|
|
|
const roomInfos = OpenGroupData.getV2OpenGroupRoom(this.id);
|
|
|
|
const replacedWithOurRealSessionId = await this.replaceWithOurRealSessionId(details.admins);
|
|
|
|
const ourBlindedPubkeyForThisSogs =
|
|
|
|
|
|
|
|
roomInfos && roomHasBlindEnabled(roomInfos)
|
|
|
|
|
|
|
|
? await findCachedOurBlindedPubkeyOrLookItUp(
|
|
|
|
|
|
|
|
roomInfos?.serverPublicKey,
|
|
|
|
|
|
|
|
await getSodiumRenderer()
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
: UserUtils.getOurPubKeyStrFromCache();
|
|
|
|
|
|
|
|
const replacedWithOurRealSessionId = details.admins.map(m =>
|
|
|
|
|
|
|
|
m === ourBlindedPubkeyForThisSogs ? UserUtils.getOurPubKeyStrFromCache() : m
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const adminChanged = await this.updateGroupAdmins(replacedWithOurRealSessionId, false);
|
|
|
|
const adminChanged = await this.updateGroupAdmins(replacedWithOurRealSessionId, false);
|
|
|
|
if (adminChanged) {
|
|
|
|
if (adminChanged) {
|
|
|
|
hasChange = adminChanged;
|
|
|
|
hasChange = adminChanged;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (details.moderators && isArray(details.moderators)) {
|
|
|
|
|
|
|
|
const replacedWithOurRealSessionId = await this.replaceWithOurRealSessionId(
|
|
|
|
|
|
|
|
details.moderators
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
const moderatorsChanged = await this.updateGroupModerators(
|
|
|
|
|
|
|
|
replacedWithOurRealSessionId,
|
|
|
|
|
|
|
|
false
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
if (moderatorsChanged) {
|
|
|
|
|
|
|
|
hasChange = moderatorsChanged;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.isOpenGroupV2() && details.image_id && isNumber(details.image_id)) {
|
|
|
|
if (this.isOpenGroupV2() && details.image_id && isNumber(details.image_id)) {
|
|
|
|
const roomInfos = OpenGroupData.getV2OpenGroupRoom(this.id);
|
|
|
|
const roomInfos = OpenGroupData.getV2OpenGroupRoom(this.id);
|
|
|
|
if (roomInfos) {
|
|
|
|
if (roomInfos) {
|
|
|
@ -1458,7 +1535,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public hasMember(pubkey: string) {
|
|
|
|
public hasMember(pubkey: string) {
|
|
|
|
return _.includes(this.get('members'), pubkey);
|
|
|
|
return includes(this.get('members'), pubkey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// returns true if this is a closed/medium or open group
|
|
|
|
// returns true if this is a closed/medium or open group
|
|
|
|
public isGroup() {
|
|
|
|
public isGroup() {
|
|
|
@ -1836,9 +1913,22 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
.sendToPubKey(device, typingMessage)
|
|
|
|
.sendToPubKey(device, typingMessage)
|
|
|
|
.catch(window?.log?.error);
|
|
|
|
.catch(window?.log?.error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private async replaceWithOurRealSessionId(toReplace: Array<string>) {
|
|
|
|
|
|
|
|
const roomInfos = OpenGroupData.getV2OpenGroupRoom(this.id);
|
|
|
|
|
|
|
|
const sodium = await getSodiumRenderer();
|
|
|
|
|
|
|
|
const ourBlindedPubkeyForThisSogs =
|
|
|
|
|
|
|
|
roomInfos && roomHasBlindEnabled(roomInfos)
|
|
|
|
|
|
|
|
? await findCachedOurBlindedPubkeyOrLookItUp(roomInfos?.serverPublicKey, sodium)
|
|
|
|
|
|
|
|
: UserUtils.getOurPubKeyStrFromCache();
|
|
|
|
|
|
|
|
const replacedWithOurRealSessionId = toReplace.map(m =>
|
|
|
|
|
|
|
|
m === ourBlindedPubkeyForThisSogs ? UserUtils.getOurPubKeyStrFromCache() : m
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
return replacedWithOurRealSessionId;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const throttledAllConversationsDispatch = _.debounce(
|
|
|
|
const throttledAllConversationsDispatch = debounce(
|
|
|
|
() => {
|
|
|
|
() => {
|
|
|
|
if (updatesToDispatch.size === 0) {
|
|
|
|
if (updatesToDispatch.size === 0) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|