feat: add handling and setting of the expireTimer for contacts

This commit is contained in:
Audric Ackermann 2023-03-30 14:15:59 +11:00
parent 51df7d80bb
commit 796ccf0582
26 changed files with 117 additions and 157 deletions

View file

@ -281,7 +281,7 @@ export const SessionRightPanelWithDetails = () => {
const deleteConvoAction = isPublic
? () => {
deleteAllMessagesByConvoIdWithConfirmation(selectedConvoKey); // TODO this does not delete the public group and showLeaveGroupByConvoId is not only working for closed groups
deleteAllMessagesByConvoIdWithConfirmation(selectedConvoKey); // TODOLATER this does not delete the public group and showLeaveGroupByConvoId is not only working for closed groups
}
: () => {
showLeaveGroupByConvoId(selectedConvoKey);

View file

@ -98,14 +98,17 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
const onVisible = useCallback(
// tslint:disable-next-line: cyclomatic-complexity
async (inView: boolean | Object) => {
if (!selectedConversationKey) {
return;
}
// we are the most recent message
if (mostRecentMessageId === messageId && selectedConversationKey) {
if (mostRecentMessageId === messageId) {
// make sure the app is focused, because we mark message as read here
if (inView === true && isAppFocused) {
dispatch(showScrollToBottomButton(false));
getConversationController()
.get(selectedConversationKey)
?.markConversationRead(receivedAt || 0); // TODO this should be `sentAt || serverTimestamp` I believe?
?.markConversationRead(receivedAt || 0); // TODOLATER this should be `sentAt || serverTimestamp` I think
dispatch(markConversationFullyRead(selectedConversationKey));
} else if (inView === false) {
@ -117,8 +120,7 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
inView === true &&
isAppFocused &&
oldestMessageId === messageId &&
!fetchingMoreInProgress &&
selectedConversationKey
!fetchingMoreInProgress
) {
debouncedTriggerLoadMoreTop(selectedConversationKey, oldestMessageId);
}
@ -127,8 +129,7 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
inView === true &&
isAppFocused &&
youngestMessageId === messageId &&
!fetchingMoreInProgress &&
selectedConversationKey
!fetchingMoreInProgress
) {
debouncedTriggerLoadMoreBottom(selectedConversationKey, youngestMessageId);
}
@ -140,7 +141,7 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
isAppFocused
) {
if (isUnread) {
// TODO this is pretty expensive and should instead use values from the redux store
// TODOLATER this is pretty expensive and should instead use values from the redux store
const found = await Data.getMessageById(messageId);
if (found && Boolean(found.get('unread'))) {
@ -149,7 +150,7 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
// this would be part of an redesign of the sending pipeline
// mark the whole conversation as read until this point.
// this will trigger the expire timer.
if (selectedConversationKey && foundSentAt) {
if (foundSentAt) {
getConversationController()
.get(selectedConversationKey)
?.markConversationRead(foundSentAt, Date.now());

View file

@ -76,7 +76,7 @@ export const Reaction = (props: ReactionProps): ReactElement => {
const reactionRef = useRef<HTMLDivElement>(null);
const { docX, elW } = useMouse(reactionRef);
const gutterWidth = 380; // TODO make this a variable which can be shared in CSS and JS
const gutterWidth = 380; // TODOLATER make this a variable which can be shared in CSS and JS
const tooltipMidPoint = POPUP_WIDTH / 2; // px
const [tooltipPosition, setTooltipPosition] = useState<TipPosition>('center');

View file

@ -201,7 +201,7 @@ const doAppStartUp = async () => {
void getSwarmPollingInstance().start();
void loadDefaultRooms();
// TODO make this a job of the JobRunner
// TODOLATER make this a job of the JobRunner
debounce(triggerAvatarReUploadIfNeeded, 200);
/* Postpone a little bit of the polling of sogs messages to let the swarm messages come in first. */

View file

@ -193,7 +193,7 @@ Storage.onready(async () => {
await LibSessionUtil.initializeLibSessionUtilWrappers();
} catch (e) {
window.log.warn('LibSessionUtil.initializeLibSessionUtilWrappers failed with', e.message);
// TODO what should we do if this happens?
// I don't think there is anything we can do if this happens
throw e;
}
}
@ -209,7 +209,7 @@ Storage.onready(async () => {
]);
} catch (error) {
window.log.error(
'main_start.js: ConversationController failed to load:',
'main_renderer: ConversationController failed to load:',
error && error.stack ? error.stack : error
);
} finally {

View file

@ -119,12 +119,11 @@ type InMemoryConvoInfos = {
unreadCount: number;
};
// TODO decide it it makes sense to move this to a redux slice?
/**
* Some fields are not stored in the database, but are kept in memory.
* We use this map to keep track of them. The key is the conversation id.
*/
const inMemoryConvoInfos: Map<string, InMemoryConvoInfos> = new Map();
const inMemoryConvoInfos: Map<string, InMemoryConvoInfos> = new Map(); // decide it it makes sense to move this to a redux slice?
export class ConversationModel extends Backbone.Model<ConversationAttributes> {
public updateLastMessage: () => any;
@ -339,6 +338,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const foundLegacyGroup = SessionUtilUserGroups.getLegacyGroupCached(this.id);
const foundVolatileInfo = SessionUtilConvoInfoVolatile.getVolatileInfoCached(this.id);
// rely on the wrapper values rather than the DB ones if they exist in the wrapper
if (foundContact) {
if (foundContact.name) {
toRet.displayNameInProfile = foundContact.name;
@ -363,10 +363,12 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
toRet.isHidden = foundContact.hidden;
if (foundContact.priority > 0) {
toRet.isPinned = true; // TODO priority also handles sorting
toRet.isPinned = true;
}
// TODO expire timer (not in wrapper yet)
if (foundContact.expirationTimerSeconds > 0) {
toRet.expireTimer = foundContact.expirationTimerSeconds;
}
} else {
if (this.get('displayNameInProfile')) {
toRet.displayNameInProfile = this.get('displayNameInProfile');
@ -394,6 +396,10 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
if (this.get('isPinned')) {
toRet.isPinned = true;
}
if (this.get('expireTimer')) {
toRet.expireTimer = this.get('expireTimer');
}
}
if (foundLegacyGroup) {
@ -412,7 +418,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
if (foundCommunity) {
if (foundCommunity.priority > 0) {
toRet.isPinned = true; // TODO priority also handles sorting
toRet.isPinned = true;
}
}
@ -887,7 +893,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
*/
public async addIncomingApprovalMessage(timestamp: number, source: string) {
await this.addSingleIncomingMessage({
sent_at: timestamp, // TODO: maybe add timestamp to messageRequestResponse? confirm it doesn't exist first
sent_at: timestamp,
source,
messageRequestResponse: {
isApproved: 1,
@ -1210,7 +1216,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
messageAttributes: Omit<MessageAttributesOptionals, 'conversationId' | 'type' | 'direction'>
) {
// if there's a message by the other user, they've replied to us which we consider an accepted convo
if (!this.didApproveMe() && this.isPrivate()) {
if (this.isPrivate()) {
await this.setDidApproveMe(true);
}
@ -2177,7 +2183,7 @@ export async function commitConversationAndRefreshWrapper(id: string) {
return;
}
// write to DB
// TODO remove duplicates between db and wrapper (except nickname&name as we need them for search)
// TODOLATER remove duplicates between db and wrapper (except nickname&name as we need them for search, or move search to wrapper too)
// TODO when deleting a contact from the ConversationController, we still need to keep it in the wrapper but mark it as hidden (and we might need to add an hidden convo model field for it)
const savedDetails = await Data.saveConversation(convo.attributes);

View file

@ -53,7 +53,7 @@ export interface ConversationAttributes {
type: ConversationTypeEnum.PRIVATE | ConversationTypeEnum.GROUPV3 | ConversationTypeEnum.GROUP;
// 0 means inactive (undefined and null too but we try to get rid of them and only have 0 = inactive)
active_at: number;
active_at: number; // this field is the one used to sort conversations in the left pane from most recent
lastMessageStatus: LastMessageStatusType;
/**
@ -64,10 +64,10 @@ export interface ConversationAttributes {
*/
lastMessage: string | null;
avatarImageId?: number; // SOGS ONLY: avatar imageID is currently used only for sogs. It's the fileID of the image uploaded and set as the sogs avatar
avatarImageId?: number; // avatar imageID is currently used only for sogs. It's the fileID of the image uploaded and set as the sogs avatar (not only sogs I think, but our profile too?)
left: boolean; // GROUPS ONLY: if we left the group (communities are removed right away so it not relevant to communities)
isKickedFromGroup: boolean; // GROUPS ONLY: if we got kicked from the group (communities just stop polling and a message sent get rejected, so not relevant to communities)
left: boolean; // LEGACY GROUPS ONLY: if we left the group (communities are removed right away so it not relevant to communities) // TODOLATER to remove after legacy closed group are dropped
isKickedFromGroup: boolean; // LEGACY GROUPS ONLY: if we got kicked from the group (communities just stop polling and a message sent get rejected, so not relevant to communities) // TODOLATER to remove after legacy closed group are dropped
avatarInProfile?: string; // this is the avatar path locally once downloaded and stored in the application attachments folder
@ -75,9 +75,9 @@ export interface ConversationAttributes {
conversationIdOrigin?: string; // Blinded message requests ONLY: The community from which this conversation originated from
// TODO those two items are only used for legacy closed groups and will be removed when we get rid of the legacy closed groups support
lastJoinedTimestamp: number; // ClosedGroup: last time we were added to this group // TODO to remove after legacy closed group are dropped
zombies: Array<string>; // only used for closed groups. Zombies are users which left but not yet removed by the admin // TODO to remove after legacy closed group are dropped
// TODOLATER those two items are only used for legacy closed groups and will be removed when we get rid of the legacy closed groups support
lastJoinedTimestamp: number; // ClosedGroup: last time we were added to this group // TODOLATER to remove after legacy closed group are dropped
zombies: Array<string>; // only used for closed groups. Zombies are users which left but not yet removed by the admin // TODOLATER to remove after legacy closed group are dropped
// ===========================================================================
// All of the items below are duplicated one way or the other with libsession.

View file

@ -1218,6 +1218,7 @@ function insertContactIntoContactWrapper(
const dbBlocked = blockedNumbers.includes(contact.id);
const hidden = contact.hidden || false;
const isPinned = contact.isPinned;
const expirationTimerSeconds = contact.expireTimer || 0;
const wrapperContact = getContactInfoFromDBValues({
id: contact.id,
@ -1230,6 +1231,7 @@ function insertContactIntoContactWrapper(
dbProfileUrl: contact.avatarPointer || undefined,
isPinned,
hidden,
expirationTimerSeconds,
});
try {
@ -1254,6 +1256,7 @@ function insertContactIntoContactWrapper(
dbProfileUrl: undefined,
isPinned: false,
hidden,
expirationTimerSeconds: 0,
})
);
} catch (e) {
@ -1770,9 +1773,7 @@ function updateToSessionSchemaVersion30(currentVersion: number, db: BetterSqlite
data: convoVolatileDump,
});
// TODO we've just created the initial dumps. We have to add an initial SyncJob to the database so it is run on the next app start/
// or find another way of adding one on the next start (store an another item in the DB and check for it on app start?)
// or just start a conf sync job on app start
// we've just created the initial dumps. A ConfSyncJob is run when the app starts after 20 seconds
} catch (e) {
console.error(`failed to create initial wrapper: `, e.stack);
// if we get an exception here, most likely no users are logged in yet. We can just continue the transaction and the wrappers will be created when a user creates a new account.

View file

@ -504,7 +504,7 @@ function fetchConvoMemoryDetails(convoId: string): SaveConversationReturn {
const unreadCount = getUnreadCountByConversation(convoId);
const lastReadTimestampMessageSentTimestamp = getLastMessageReadInConversation(convoId);
// TODO it would be nice to be able to remove the lastMessage and lastMessageStatus from the conversation table, and just return it when saving the conversation
// TODOLATER it would be nice to be able to remove the lastMessage and lastMessageStatus from the conversation table, and just return it when saving the conversation
// and saving it in memory only.
// But we'd need to update a bunch of things as we do some logic before setting the lastUpdate text and status mostly in `getMessagePropStatus` and `getNotificationText()`
// const lastMessages = getLastMessagesByConversation(convoId, 1) as Array:Record<string, any>>;
@ -557,7 +557,7 @@ export function getIdentityKeys(db: BetterSqlite3.Database) {
const ed25519PrivateKeyUintArray = parsedIdentityKey?.value?.ed25519KeyPair?.privateKey;
// TODO migrate the ed25519KeyPair for all the users already logged in to a base64 representation
// TODOLATER migrate the ed25519KeyPair for all the users already logged in to a base64 representation
const privateEd25519 = new Uint8Array(Object.values(ed25519PrivateKeyUintArray));
if (!privateEd25519 || isEmpty(privateEd25519)) {
@ -1404,11 +1404,11 @@ function getFirstUnreadMessageWithMention(
}
const likeMatch = `%@${ourPkInThatConversation}%`;
// TODO make this use the fts search table rather than this one?
// TODOLATER make this use the fts search table rather than this one?
const rows = assertGlobalInstanceOrInstance(instance)
.prepare(
`
SELECT id, json FROM ${MESSAGES_TABLE} WHERE
SELECT id FROM ${MESSAGES_TABLE} WHERE
conversationId = $conversationId AND
unread = $unread AND
body LIKE $likeMatch

View file

@ -366,7 +366,7 @@ async function handleLegacyGroupUpdate(latestEnvelopeTimestamp: number) {
legacyGroupConvo.get('active_at') < latestEnvelopeTimestamp
? legacyGroupConvo.get('active_at')
: latestEnvelopeTimestamp,
weWereJustAdded: false, // TODO to remove
weWereJustAdded: false, // TODOLATER to remove
};
await ClosedGroup.updateOrCreateClosedGroup(groupDetails);
@ -473,10 +473,9 @@ async function applyConvoVolatileUpdateFromWrapper(
async function handleConvoInfoVolatileUpdate(
result: IncomingConfResult
): Promise<IncomingConfResult> {
// TODO do we want to enforce this?
// if (!result.needsDump) {
// return result;
// }
if (!result.needsDump) {
return result;
}
const types = SessionUtilConvoInfoVolatile.getConvoInfoVolatileTypes();
for (let typeIndex = 0; typeIndex < types.length; typeIndex++) {
@ -619,7 +618,6 @@ async function processMergingResults(results: Map<ConfigWrapperObjectTypes, Inco
async function handleConfigMessagesViaLibSession(
configMessages: Array<IncomingMessage<SignalService.ISharedConfigMessage>>
) {
// TODO: Remove this once `useSharedUtilForUserConfig` is permanent
if (!window.sessionFeatureFlags.useSharedUtilForUserConfig) {
return;
}
@ -769,11 +767,9 @@ const handleClosedGroupsFromConfigLegacy = async (
publicKey: c.publicKey,
});
try {
// TODO we should not drop the envelope from cache as long as we are still handling a new closed group from that same envelope
// check the removeFromCache inside handleNewClosedGroup()
await handleNewClosedGroup(envelope, groupUpdate);
} catch (e) {
window?.log?.warn('failed to handle a new closed group from configuration message');
window?.log?.warn('failed to handle a new closed group from configuration message');
}
})
);

View file

@ -118,7 +118,7 @@ export async function sogsV3FetchPreviewAndSaveIt(roomInfos: OpenGroupV2RoomWith
return;
}
existingImageId = convo.get('avatarImageId');
if (existingImageId !== imageIdNumber && imageIdNumber) {
if (existingImageId !== imageIdNumber && isFinite(imageIdNumber)) {
// we have to trigger an update
// write the file to the disk (automatically encrypted),

View file

@ -13,7 +13,7 @@ export const ERROR_CODE_NO_CONNECT = 'ENETUNREACH: No network connection.';
// tslint:disable: max-func-body-length
// TODO we should merge those two functions together as they are almost exactly the same
// TODOLATER we should merge those two functions together as they are almost exactly the same
const forceNetworkDeletion = async (): Promise<Array<string> | null> => {
const sodium = await getSodiumRenderer();
const userX25519PublicKey = UserUtils.getOurPubKeyStrFromCache();

View file

@ -15,6 +15,8 @@ import { SessionUtilContact } from '../utils/libsession/libsession_utils_contact
import { SessionUtilConvoInfoVolatile } from '../utils/libsession/libsession_utils_convo_info_volatile';
import { SessionUtilUserGroups } from '../utils/libsession/libsession_utils_user_groups';
import { ConfigurationDumpSync } from '../utils/job_runners/jobs/ConfigurationSyncDumpJob';
import { LibSessionUtil } from '../utils/libsession/libsession_utils';
import { assertUnreachable } from '../../types/sqlSharedTypes';
let instance: ConversationController | null;
@ -251,11 +253,7 @@ export class ConversationController {
// await conversation.setIsApproved(false, false);
await conversation.commit(); // this updates the wrappers content to reflect the hidden state
// The note to self cannot be removed from the wrapper I suppose, as it must always be there
// TODO I think we want to mark the contacts as hidden instead of removing them, so maybe keep the volatile info too?
// if (!isUsFromCache(conversation.id)) {
// await SessionUtilConvoInfoVolatile.remove1o1(conversation.id);
// }
// We don't remove entries from the contacts wrapper, so better keep corresponding convo volatile info for now (it will be pruned if needed)
// TODO the call above won't mark the conversation as hidden in the wrapper, it will just stop being updated (which is a bad thing)
}
@ -308,40 +306,49 @@ export class ConversationController {
this.conversations.add(convoModels);
const start = Date.now();
// TODO make this a switch so we take care of all wrappers and have compilation errors if we forgot to add one.
// also keep in mind that the convo volatile one need to run for each convo so it must be outside of a `else`
const numberOfVariants = LibSessionUtil.requiredUserVariants.length;
for (let index = 0; index < convoModels.length; index++) {
const convo = convoModels[index];
if (SessionUtilContact.isContactToStoreInContactsWrapper(convo)) {
await SessionUtilContact.refreshMappedValue(convo.id, true);
} else if (SessionUtilUserGroups.isUserGroupToStoreInWrapper(convo)) {
await SessionUtilUserGroups.refreshCachedUserGroup(convo.id, true);
}
// we actually want to run the convo volatile check and fetch even if one of the cases above is already true
if (SessionUtilConvoInfoVolatile.isConvoToStoreInWrapper(convo)) {
await SessionUtilConvoInfoVolatile.refreshConvoVolatileCached(
convo.id,
Boolean(convo.isClosedGroup() && convo.id.startsWith('05')),
true
);
for (let wrapperIndex = 0; wrapperIndex < numberOfVariants; wrapperIndex++) {
const variant = LibSessionUtil.requiredUserVariants[wrapperIndex];
await convo.refreshInMemoryDetails();
switch (variant) {
case 'UserConfig':
break;
case 'ContactsConfig':
if (SessionUtilContact.isContactToStoreInContactsWrapper(convo)) {
await SessionUtilContact.refreshMappedValue(convo.id, true);
}
break;
case 'UserGroupsConfig':
if (SessionUtilUserGroups.isUserGroupToStoreInWrapper(convo)) {
await SessionUtilUserGroups.refreshCachedUserGroup(convo.id, true);
}
break;
case 'ConvoInfoVolatileConfig':
if (SessionUtilConvoInfoVolatile.isConvoToStoreInWrapper(convo)) {
await SessionUtilConvoInfoVolatile.refreshConvoVolatileCached(
convo.id,
Boolean(convo.isClosedGroup() && convo.id.startsWith('05')),
true
);
await convo.refreshInMemoryDetails();
}
break;
default:
assertUnreachable(
variant,
`ConversationController: load() unhandled case "${variant}"`
);
}
}
}
window.log.info(`refreshAllWrappersMappedValues took ${Date.now() - start}ms`);
this._initialFetchComplete = true;
// TODO do we really need to do this?
// this.conversations.forEach((conversation: ConversationModel) => {
// if (
// conversation.isActive() &&
// !conversation.isHidden() &&
// !conversation.get('lastMessage')
// ) {
// conversation.updateLastMessage();
// }
// });
window?.log?.info(
`ConversationController: done with initial fetch in ${Date.now() - startLoad}ms.`
);

View file

@ -42,11 +42,11 @@ export async function initiateOpenGroupUpdate(
return false;
}
try {
const { fileId, fileUrl } = uploadedFileDetails;
const { fileId: avatarImageId, fileUrl } = uploadedFileDetails;
// this is kind of a hack just made to avoid having a specific function downloading from sogs by URL rather than fileID
const downloaded = await downloadAttachmentSogsV3(
{ id: fileId, size: null, url: fileUrl },
{ id: avatarImageId, size: null, url: fileUrl },
roomInfos
);
@ -67,11 +67,9 @@ export async function initiateOpenGroupUpdate(
isRaw: true,
contentType: MIME.IMAGE_UNKNOWN, // contentType is mostly used to generate previews and screenshot. We do not care for those in this case.
});
const avatarImageId = fileId;
await convo.setSessionProfile({
displayName: groupName || convo.get('displayNameInProfile') || 'Unknown',
avatarPath: upgraded.path,
avatarImageId,
});
} catch (e) {

View file

@ -28,7 +28,7 @@ let timeout: any;
let logger: any;
const _activeAttachmentDownloadJobs: any = {};
// TODO type those `any` properties
// TODOLATER type those `any` properties
export async function start(options: any = {}) {
({ logger } = options);

View file

@ -95,7 +95,7 @@ class ConfigurationSyncDumpJob extends PersistedJob<ConfigurationSyncDumpPersist
// so when we call needsDump(), we know for sure that we are up to date
console.time('ConfigurationSyncDumpJob insertAll');
// TODO we need to add the dump of the wrappers of other destination than ourself once we had the closed group handling of config sync job
// TODOLATER we need to add the dump of the wrappers of other destination than ourself once we had the closed group handling of config sync job
for (let index = 0; index < LibSessionUtil.requiredUserVariants.length; index++) {
const variant = LibSessionUtil.requiredUserVariants[index];

View file

@ -15,7 +15,6 @@ import { SessionUtilConvoInfoVolatile } from './libsession_utils_convo_info_vola
import { SessionUtilUserGroups } from './libsession_utils_user_groups';
import { SessionUtilUserProfile } from './libsession_utils_user_profile';
// TODO complete this list
const requiredUserVariants: Array<ConfigWrapperObjectTypes> = [
'UserConfig',
'ContactsConfig',
@ -44,8 +43,7 @@ async function initializeLibSessionUtilWrappers() {
throw new Error('edkeypair not found for current user');
}
const privateKeyEd25519 = keypair.privKeyBytes;
// let's plan a sync on start for now
// TODO is this causing any issues?
// let's plan a sync on start with some room for the app to be ready
setTimeout(() => ConfigurationSync.queueNewJobIfNeeded, 20000);
// fetch the dumps we already have from the database

View file

@ -83,6 +83,7 @@ async function insertContactFromDBIntoWrapperAndRefresh(id: string): Promise<voi
const dbBlocked = !!foundConvo.isBlocked() || false;
const hidden = foundConvo.get('hidden') || false;
const isPinned = foundConvo.get('isPinned');
const expirationTimerSeconds = foundConvo.get('expireTimer') || 0;
const wrapperContact = getContactInfoFromDBValues({
id,
@ -95,6 +96,7 @@ async function insertContactFromDBIntoWrapperAndRefresh(id: string): Promise<voi
dbProfileUrl,
isPinned,
hidden,
expirationTimerSeconds,
});
try {

View file

@ -219,7 +219,6 @@ async function refreshConvoVolatileCached(
default:
assertUnreachable(convoType, `refreshConvoVolatileCached unhandled case "${convoType}"`);
}
// TODO handle the new closed groups once we got them ready
if (refreshed && !duringAppStart) {
getConversationController()
@ -285,10 +284,10 @@ export const SessionUtilConvoInfoVolatile = {
getVolatileInfoCached,
// 1o1
// at the moment, we cannot remove a 1o1 from the conversation volatile info.
// at the moment, we cannot remove a contact from the conversation volatile info so there is nothing here
// legacy group
removeLegacyGroupFromWrapper, // a group can be removed but also just marked hidden, so only call this function when the group is completely removed // TODO
removeLegacyGroupFromWrapper, // a group can be removed but also just marked hidden, so only call this function when the group is completely removed // TODOLATER
// communities
removeCommunityFromWrapper,

View file

@ -129,7 +129,7 @@ async function insertGroupsFromDBIntoWrapperAndRefresh(convoId: string): Promise
groupAdmins: foundConvo.get('groupAdmins') || [],
expireTimer: foundConvo.get('expireTimer'),
displayNameInProfile: foundConvo.get('displayNameInProfile'),
hidden: false, // TODO we do not handle hidden yet for groups
hidden: false, // TODOLATER we do not handle hidden yet for groups
encPubkeyHex: encryptionKeyPair?.publicHex || '',
encSeckeyHex: encryptionKeyPair?.privateHex || '',
});
@ -184,7 +184,7 @@ async function refreshCachedUserGroup(convoId: string, duringAppStart = false) {
window.log.info(`refreshMappedValue: not an opengroup convoID: ${convoId}`, e);
}
// TODO handle the new closed groups once we got them ready
// TODOLATER handle the new closed groups once we got them ready
}
function getCommunityByConvoIdCached(convoId: string) {
@ -259,5 +259,5 @@ export const SessionUtilUserGroups = {
isLegacyGroupToStoreInWrapper,
getLegacyGroupCached,
getAllLegacyGroups,
removeLegacyGroupFromWrapper, // a group can be removed but also just marked hidden, so only call this function when the group is completely removed // TODO
removeLegacyGroupFromWrapper, // a group can be removed but also just marked hidden, so only call this function when the group is completely removed // TODOLATER
};

View file

@ -77,7 +77,6 @@ export const syncConfigurationIfNeeded = async () => {
export const forceSyncConfigurationNowIfNeeded = async (waitForMessageSent = false) =>
new Promise(resolve => {
// TODO this should check for feature flag and queue a ConfigurationSyncJob
const allConvos = getConversationController().getConversations();
// if we hang for more than 20sec, force resolve this promise.
setTimeout(() => {

View file

@ -379,35 +379,6 @@ describe('OpenGroupAuthentication', () => {
}
});
});
// tslint:disable-next-line: no-empty
describe('Message Decryption', () => {
it.skip('Message Decryption', () => {
// TODO: update input and expected output
});
});
describe('V4Requests', () => {
it.skip('Should bencode POST/PUT request with body successfully', () => {
// TODO: update input and expected output
// const bencoded = encodeV4Request(postDataToEncoded);
// expect(bencoded).to.be.equal(
// 'l100:{"method":"POST","endpoint":"/room/test-room/pin/123","headers":{"Content-Type":"application/json"}}2:{}e'
// );
});
it.skip('Should bencode GET request without body successfully', () => {
// TODO: change ot accept request info and expect uint8 array output
// const bencoded = encodeV4Request(getDataToEncode);
// expect(bencoded).to.be.equal('l45:{"method":"GET","endpoint":"/room/test-room"}e');
});
it.skip('Should decode bencoded response successfully', () => {
// TODO: update input and expected output
// const bencoded = decodeV4Response(responseToDecode);
// console.error({ bencoded });
});
});
});
/**

View file

@ -37,7 +37,7 @@ export const getImageDimensions = async ({
window.log.error('getImageDimensions error', toLogFormat(error));
reject(error);
});
// TODO image/jpg is hard coded, but it does not look to cause any issues
// image/jpg is hard coded here but does not look to cause any issues
const decryptedUrl = await getDecryptedMediaUrl(objectUrl, 'image/jpg', false);
image.src = decryptedUrl;
});

View file

@ -117,6 +117,7 @@ export function getContactInfoFromDBValues({
isPinned,
dbProfileUrl,
dbProfileKey,
expirationTimerSeconds,
}: {
id: string;
dbApproved: boolean;
@ -128,6 +129,7 @@ export function getContactInfoFromDBValues({
isPinned: boolean;
dbProfileUrl: string | undefined;
dbProfileKey: string | undefined;
expirationTimerSeconds: number | undefined;
}): ContactInfo {
const wrapperContact: ContactInfo = {
id,
@ -135,9 +137,17 @@ export function getContactInfoFromDBValues({
approvedMe: !!dbApprovedMe,
blocked: !!dbBlocked,
hidden: !!hidden,
priority: !!isPinned ? 1 : 0, // TODO the priority handling is not that simple
priority: !!isPinned ? 1 : 0, // TODOLATER the priority handling is not that simple
nickname: dbNickname,
name: dbName,
expirationTimerSeconds:
!!expirationTimerSeconds && isFinite(expirationTimerSeconds) && expirationTimerSeconds > 0
? expirationTimerSeconds
: 0, // TODOLATER add the expiration mode handling
expirationMode:
!!expirationTimerSeconds && isFinite(expirationTimerSeconds) && expirationTimerSeconds > 0
? 'disappearAfterSend'
: 'off',
};
if (
@ -166,7 +176,7 @@ export function getCommunityInfoFromDBValues({
}) {
const community = {
fullUrl,
priority: !!isPinned ? 1 : 0, // TODO the priority handling is not that simple
priority: !!isPinned ? 1 : 0, // TODOLATER the priority handling is not that simple
};
return community;
@ -221,7 +231,7 @@ export function getLegacyGroupInfoFromDBValues({
disappearingTimerSeconds: !expireTimer ? 0 : expireTimer,
hidden: !!hidden,
name: displayNameInProfile || '',
priority: !!isPinned ? 1 : 0, // TODO the priority handling is not that simple
priority: !!isPinned ? 1 : 0, // TODOLATER the priority handling is not that simple
members: wrappedMembers,
encPubkey: !isEmpty(encPubkeyHex) ? from_hex(encPubkeyHex) : new Uint8Array(),
encSeckey: !isEmpty(encSeckeyHex) ? from_hex(encSeckeyHex) : new Uint8Array(),
@ -235,8 +245,9 @@ export function getLegacyGroupInfoFromDBValues({
*
*/
export function assertUnreachable(_x: never, message: string): never {
console.info(`assertUnreachable: Didn't expect to get here with "${message}"`);
throw new Error("Didn't expect to get here");
const msg = `assertUnreachable: Didn't expect to get here with "${message}"`;
console.info(msg);
throw new Error(msg);
}
export function roomHasBlindEnabled(openGroup?: OpenGroupV2Room) {

View file

@ -126,7 +126,6 @@ export function getLastProfileUpdateTimestamp() {
}
export async function setLastProfileUpdateTimestamp(lastUpdateTimestamp: number) {
// TODO get rid of this once we remove the feature flag altogether
if (window.sessionFeatureFlags.useSharedUtilForUserConfig) {
return;
}

View file

@ -129,10 +129,6 @@ export const ContactsWrapperActions: ContactsWrapperActionsCalls = {
callLibSessionWorker(['ContactsConfig', 'get', pubkeyHex]) as Promise<
ReturnType<ContactsWrapperActionsCalls['get']>
>,
getOrConstruct: async (pubkeyHex: string) =>
callLibSessionWorker(['ContactsConfig', 'getOrConstruct', pubkeyHex]) as Promise<
ReturnType<ContactsWrapperActionsCalls['getOrConstruct']>
>,
getAll: async () =>
callLibSessionWorker(['ContactsConfig', 'getAll']) as Promise<
ReturnType<ContactsWrapperActionsCalls['getAll']>
@ -147,30 +143,6 @@ export const ContactsWrapperActions: ContactsWrapperActionsCalls = {
callLibSessionWorker(['ContactsConfig', 'set', contact]) as Promise<
ReturnType<ContactsWrapperActionsCalls['set']>
>,
setApproved: async (pubkeyHex: string, approved: boolean) =>
callLibSessionWorker(['ContactsConfig', 'setApproved', pubkeyHex, approved]) as Promise<
ReturnType<ContactsWrapperActionsCalls['setApproved']>
>,
setApprovedMe: async (pubkeyHex: string, approvedMe: boolean) =>
callLibSessionWorker(['ContactsConfig', 'setApprovedMe', pubkeyHex, approvedMe]) as Promise<
ReturnType<ContactsWrapperActionsCalls['setApprovedMe']>
>,
setBlocked: async (pubkeyHex: string, blocked: boolean) =>
callLibSessionWorker(['ContactsConfig', 'setBlocked', pubkeyHex, blocked]) as Promise<
ReturnType<ContactsWrapperActionsCalls['setBlocked']>
>,
setName: async (pubkeyHex: string, name: string) =>
callLibSessionWorker(['ContactsConfig', 'setName', pubkeyHex, name]) as Promise<
ReturnType<ContactsWrapperActionsCalls['setName']>
>,
setNickname: async (pubkeyHex: string, nickname: string) =>
callLibSessionWorker(['ContactsConfig', 'setNickname', pubkeyHex, nickname]) as Promise<
ReturnType<ContactsWrapperActionsCalls['setNickname']>
>,
setProfilePicture: async (pubkeyHex: string, url: string, key: Uint8Array) =>
callLibSessionWorker(['ContactsConfig', 'setProfilePicture', pubkeyHex, url, key]) as Promise<
ReturnType<ContactsWrapperActionsCalls['setProfilePicture']>
>,
};
export const UserGroupsWrapperActions: UserGroupsWrapperActionsCalls = {