Honor preferContactAvatars field on AccountRecord
This commit is contained in:
parent
f5eb17e0d1
commit
68a458ec4a
|
@ -133,6 +133,7 @@ message AccountRecord {
|
|||
optional PhoneNumberSharingMode phoneNumberSharingMode = 12;
|
||||
optional bool notDiscoverableByPhoneNumber = 13;
|
||||
repeated PinnedConversation pinnedConversations = 14;
|
||||
optional bool preferContactAvatars = 15;
|
||||
optional uint32 universalExpireTimer = 17;
|
||||
optional bool primarySendsSms = 18;
|
||||
optional string e164 = 19;
|
||||
|
|
|
@ -20,6 +20,7 @@ import { UUID, isValidUuid } from './types/UUID';
|
|||
import { Address } from './types/Address';
|
||||
import { QualifiedAddress } from './types/QualifiedAddress';
|
||||
import * as log from './logging/log';
|
||||
import { sleep } from './util/sleep';
|
||||
|
||||
const MAX_MESSAGE_BODY_LENGTH = 64 * 1024;
|
||||
|
||||
|
@ -784,6 +785,36 @@ export class ConversationController {
|
|||
return this._initialPromise;
|
||||
}
|
||||
|
||||
// A number of things outside conversation.attributes affect conversation re-rendering.
|
||||
// If it's scoped to a given conversation, it's easy to trigger('change'). There are
|
||||
// important values in storage and the storage service which change rendering pretty
|
||||
// radically, so this function is necessary to force regeneration of props.
|
||||
async forceRerender(): Promise<void> {
|
||||
let count = 0;
|
||||
const conversations = this._conversations.models.slice();
|
||||
log.info(
|
||||
`forceRerender: Starting to loop through ${conversations.length} conversations`
|
||||
);
|
||||
|
||||
for (let i = 0, max = conversations.length; i < max; i += 1) {
|
||||
const conversation = conversations[i];
|
||||
|
||||
if (conversation.cachedProps) {
|
||||
conversation.oldCachedProps = conversation.cachedProps;
|
||||
conversation.cachedProps = null;
|
||||
|
||||
conversation.trigger('props-change', conversation, false);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
if (count % 10 === 0) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await sleep(300);
|
||||
}
|
||||
}
|
||||
log.info(`forceRerender: Updated ${count} conversations`);
|
||||
}
|
||||
|
||||
onConvoOpenStart(conversationId: string): void {
|
||||
this._conversationOpenStart.set(conversationId, Date.now());
|
||||
}
|
||||
|
|
|
@ -684,8 +684,10 @@ export async function startApp(): Promise<void> {
|
|||
}
|
||||
|
||||
if (
|
||||
window.isBeforeVersion(lastVersion, 'v1.36.0-beta.1') &&
|
||||
window.isAfterVersion(lastVersion, 'v1.35.0-beta.1')
|
||||
(window.isBeforeVersion(lastVersion, 'v1.36.0-beta.1') &&
|
||||
window.isAfterVersion(lastVersion, 'v1.35.0-beta.1')) ||
|
||||
// 5.30 introduced understanding of new storage service AccountRecord fields
|
||||
window.isBeforeVersion(lastVersion, 'v5.30.0-alpha')
|
||||
) {
|
||||
await window.Signal.Services.eraseAllStorageServiceState();
|
||||
}
|
||||
|
|
|
@ -4896,7 +4896,10 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
private getAvatarPath(): undefined | string {
|
||||
const avatar = isMe(this.attributes)
|
||||
const shouldShowProfileAvatar =
|
||||
isMe(this.attributes) ||
|
||||
window.storage.get('preferContactAvatars') === false;
|
||||
const avatar = shouldShowProfileAvatar
|
||||
? this.get('profileAvatar') || this.get('avatar')
|
||||
: this.get('avatar') || this.get('profileAvatar');
|
||||
return avatar?.path || undefined;
|
||||
|
|
|
@ -182,6 +182,11 @@ export async function toAccountRecord(
|
|||
);
|
||||
accountRecord.linkPreviews = Boolean(window.Events.getLinkPreviewSetting());
|
||||
|
||||
const preferContactAvatars = window.storage.get('preferContactAvatars');
|
||||
if (preferContactAvatars !== undefined) {
|
||||
accountRecord.preferContactAvatars = Boolean(preferContactAvatars);
|
||||
}
|
||||
|
||||
const primarySendsSms = window.storage.get('primarySendsSms');
|
||||
if (primarySendsSms !== undefined) {
|
||||
accountRecord.primarySendsSms = Boolean(primarySendsSms);
|
||||
|
@ -855,6 +860,7 @@ export async function mergeAccountRecord(
|
|||
readReceipts,
|
||||
sealedSenderIndicators,
|
||||
typingIndicators,
|
||||
preferContactAvatars,
|
||||
primarySendsSms,
|
||||
universalExpireTimer,
|
||||
e164: accountE164,
|
||||
|
@ -878,6 +884,15 @@ export async function mergeAccountRecord(
|
|||
window.storage.put('linkPreviews', linkPreviews);
|
||||
}
|
||||
|
||||
if (typeof preferContactAvatars === 'boolean') {
|
||||
const previous = window.storage.get('preferContactAvatars');
|
||||
window.storage.put('preferContactAvatars', preferContactAvatars);
|
||||
|
||||
if (Boolean(previous) !== Boolean(preferContactAvatars)) {
|
||||
window.ConversationController.forceRerender();
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof primarySendsSms === 'boolean') {
|
||||
window.storage.put('primarySendsSms', primarySendsSms);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
import { areArraysMatchingSets } from '../../util/areArraysMatchingSets';
|
||||
|
||||
describe('areArraysMatchingSets', () => {
|
||||
it('returns true if arrays are both empty', () => {
|
||||
const left: Array<string> = [];
|
||||
const right: Array<string> = [];
|
||||
|
||||
assert.isTrue(areArraysMatchingSets(left, right));
|
||||
});
|
||||
|
||||
it('returns true if arrays are equal', () => {
|
||||
const left = [1, 2, 3];
|
||||
const right = [1, 2, 3];
|
||||
|
||||
assert.isTrue(areArraysMatchingSets(left, right));
|
||||
});
|
||||
|
||||
it('returns true if arrays are equal but out of order', () => {
|
||||
const left = [1, 2, 3];
|
||||
const right = [3, 1, 2];
|
||||
|
||||
assert.isTrue(areArraysMatchingSets(left, right));
|
||||
});
|
||||
|
||||
it('returns true if arrays are equal but one has duplicates', () => {
|
||||
const left = [1, 2, 3, 1];
|
||||
const right = [1, 2, 3];
|
||||
|
||||
assert.isTrue(areArraysMatchingSets(left, right));
|
||||
});
|
||||
|
||||
it('returns false if first array has missing elements', () => {
|
||||
const left = [1, 2];
|
||||
const right = [1, 2, 3];
|
||||
|
||||
assert.isFalse(areArraysMatchingSets(left, right));
|
||||
});
|
||||
|
||||
it('returns false if second array has missing elements', () => {
|
||||
const left = [1, 2, 3];
|
||||
const right = [1, 2];
|
||||
|
||||
assert.isFalse(areArraysMatchingSets(left, right));
|
||||
});
|
||||
|
||||
it('returns false if second array is empty', () => {
|
||||
const left = [1, 2, 3];
|
||||
const right: Array<number> = [];
|
||||
|
||||
assert.isFalse(areArraysMatchingSets(left, right));
|
||||
});
|
||||
});
|
|
@ -105,6 +105,7 @@ import {
|
|||
GroupSyncEvent,
|
||||
} from './messageReceiverEvents';
|
||||
import * as log from '../logging/log';
|
||||
import { areArraysMatchingSets } from '../util/areArraysMatchingSets';
|
||||
|
||||
const GROUPV1_ID_LENGTH = 16;
|
||||
const GROUPV2_ID_LENGTH = 32;
|
||||
|
@ -2629,19 +2630,32 @@ export default class MessageReceiver
|
|||
envelope: ProcessedEnvelope,
|
||||
blocked: Proto.SyncMessage.IBlocked
|
||||
): Promise<void> {
|
||||
let changed = false;
|
||||
|
||||
if (blocked.numbers) {
|
||||
const previous = this.storage.get('blocked', []);
|
||||
log.info('handleBlocked: Blocking these numbers:', blocked.numbers);
|
||||
await this.storage.put('blocked', blocked.numbers);
|
||||
|
||||
if (!areArraysMatchingSets(previous, blocked.numbers)) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (blocked.uuids) {
|
||||
const previous = this.storage.get('blocked-uuids', []);
|
||||
const uuids = blocked.uuids.map((uuid, index) => {
|
||||
return normalizeUuid(uuid, `handleBlocked.uuids.${index}`);
|
||||
});
|
||||
log.info('handleBlocked: Blocking these uuids:', uuids);
|
||||
await this.storage.put('blocked-uuids', uuids);
|
||||
|
||||
if (!areArraysMatchingSets(previous, uuids)) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (blocked.groupIds) {
|
||||
const previous = this.storage.get('blocked-groups', []);
|
||||
const groupV1Ids: Array<string> = [];
|
||||
const groupIds: Array<string> = [];
|
||||
|
||||
|
@ -2661,10 +2675,21 @@ export default class MessageReceiver
|
|||
'v1:',
|
||||
groupV1Ids.map(groupId => `group(${groupId})`)
|
||||
);
|
||||
await this.storage.put('blocked-groups', [...groupIds, ...groupV1Ids]);
|
||||
|
||||
const ids = [...groupIds, ...groupV1Ids];
|
||||
await this.storage.put('blocked-groups', ids);
|
||||
|
||||
if (!areArraysMatchingSets(previous, ids)) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.removeFromCache(envelope);
|
||||
|
||||
if (changed) {
|
||||
log.info('handleBlocked: Block list changed, forcing re-render.');
|
||||
window.ConversationController.forceRerender();
|
||||
}
|
||||
}
|
||||
|
||||
private isBlocked(number: string): boolean {
|
||||
|
|
|
@ -94,6 +94,7 @@ export type StorageAccessType = {
|
|||
phoneNumberSharingMode: PhoneNumberSharingMode;
|
||||
phoneNumberDiscoverability: PhoneNumberDiscoverability;
|
||||
pinnedConversationIds: Array<string>;
|
||||
preferContactAvatars: boolean;
|
||||
primarySendsSms: boolean;
|
||||
// Unlike `number_id` (which also includes device id) this field is only
|
||||
// updated whenever we receive a new storage manifest
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2020-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
export function areArraysMatchingSets<T>(
|
||||
left: Array<T>,
|
||||
right: Array<T>
|
||||
): boolean {
|
||||
const leftSet = new Set(left);
|
||||
const rightSet = new Set(right);
|
||||
|
||||
for (const item of leftSet) {
|
||||
if (!rightSet.has(item)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of rightSet) {
|
||||
if (!leftSet.has(item)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
Loading…
Reference in New Issue