Apply reactions optimistically
This commit is contained in:
parent
18abe93022
commit
03eaa9eb3e
6 changed files with 54 additions and 33 deletions
|
@ -61,11 +61,11 @@
|
||||||
reaction.get('targetAuthorUuid'),
|
reaction.get('targetAuthorUuid'),
|
||||||
reaction.get('targetTimestamp')
|
reaction.get('targetTimestamp')
|
||||||
);
|
);
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// awaiting is safe since `onReaction` is never called from inside the queue
|
// awaiting is safe since `onReaction` is never called from inside the queue
|
||||||
await targetConversation.queueJob(async () => {
|
return await targetConversation.queueJob(async () => {
|
||||||
window.log.info(
|
window.log.info(
|
||||||
'Handling reaction for',
|
'Handling reaction for',
|
||||||
reaction.get('targetTimestamp')
|
reaction.get('targetTimestamp')
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
oldReaction.forEach(r => this.remove(r));
|
oldReaction.forEach(r => this.remove(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = MessageController.register(
|
const message = MessageController.register(
|
||||||
|
@ -120,15 +120,18 @@
|
||||||
targetMessage
|
targetMessage
|
||||||
);
|
);
|
||||||
|
|
||||||
await message.handleReaction(reaction);
|
const oldReaction = await message.handleReaction(reaction);
|
||||||
|
|
||||||
this.remove(reaction);
|
this.remove(reaction);
|
||||||
|
|
||||||
|
return oldReaction;
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
window.log.error(
|
window.log.error(
|
||||||
'Reactions.onReaction error:',
|
'Reactions.onReaction error:',
|
||||||
error && error.stack ? error.stack : error
|
error && error.stack ? error.stack : error
|
||||||
);
|
);
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}))();
|
}))();
|
||||||
|
|
21
ts/model-types.d.ts
vendored
21
ts/model-types.d.ts
vendored
|
@ -109,15 +109,6 @@ export type MessageAttributesType = {
|
||||||
quote?: QuotedMessageType;
|
quote?: QuotedMessageType;
|
||||||
reactions?: Array<{
|
reactions?: Array<{
|
||||||
emoji: string;
|
emoji: string;
|
||||||
from: {
|
|
||||||
id: string;
|
|
||||||
color?: string;
|
|
||||||
avatarPath?: string;
|
|
||||||
name?: string;
|
|
||||||
profileName?: string;
|
|
||||||
isMe?: boolean;
|
|
||||||
phoneNumber?: string;
|
|
||||||
};
|
|
||||||
fromId: string;
|
fromId: string;
|
||||||
targetAuthorUuid: string;
|
targetAuthorUuid: string;
|
||||||
targetTimestamp: number;
|
targetTimestamp: number;
|
||||||
|
@ -348,3 +339,15 @@ export declare class ConversationModelCollectionType extends Backbone.Collection
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare class MessageModelCollectionType extends Backbone.Collection<MessageModel> {}
|
export declare class MessageModelCollectionType extends Backbone.Collection<MessageModel> {}
|
||||||
|
|
||||||
|
export type ReactionAttributesType = {
|
||||||
|
emoji: string;
|
||||||
|
remove?: boolean;
|
||||||
|
targetAuthorUuid: string;
|
||||||
|
targetTimestamp: number;
|
||||||
|
fromId?: string;
|
||||||
|
timestamp: number;
|
||||||
|
fromSync?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export declare class ReactionModelType extends Backbone.Model<ReactionAttributesType> {}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
MessageModelCollectionType,
|
MessageModelCollectionType,
|
||||||
WhatIsThis,
|
WhatIsThis,
|
||||||
MessageAttributesType,
|
MessageAttributesType,
|
||||||
|
ReactionModelType,
|
||||||
ConversationAttributesType,
|
ConversationAttributesType,
|
||||||
VerificationOptions,
|
VerificationOptions,
|
||||||
} from '../model-types.d';
|
} from '../model-types.d';
|
||||||
|
@ -3067,6 +3068,11 @@ export class ConversationModel extends window.Backbone
|
||||||
fromSync: true,
|
fromSync: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Apply reaction optimistically
|
||||||
|
const oldReaction = await window.Whisper.Reactions.onReaction(
|
||||||
|
reactionModel
|
||||||
|
);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const destination = this.getSendTarget()!;
|
const destination = this.getSendTarget()!;
|
||||||
const recipients = this.getRecipients();
|
const recipients = this.getRecipients();
|
||||||
|
@ -3176,9 +3182,23 @@ export class ConversationModel extends window.Backbone
|
||||||
throw new Error('No successful delivery for reaction');
|
throw new Error('No successful delivery for reaction');
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Whisper.Reactions.onReaction(reactionModel);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
}).catch(() => {
|
||||||
|
let reverseReaction: ReactionModelType;
|
||||||
|
if (oldReaction) {
|
||||||
|
// Either restore old reaction
|
||||||
|
reverseReaction = window.Whisper.Reactions.add({
|
||||||
|
...oldReaction,
|
||||||
|
fromId: window.ConversationController.getOurConversationId(),
|
||||||
|
timestamp,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Or remove a new one on failure
|
||||||
|
reverseReaction = reactionModel.clone();
|
||||||
|
reverseReaction.set('remove', !reverseReaction.get('remove'));
|
||||||
|
}
|
||||||
|
|
||||||
|
window.Whisper.Reactions.onReaction(reverseReaction);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
CustomError,
|
CustomError,
|
||||||
MessageAttributesType,
|
MessageAttributesType,
|
||||||
RetryOptions,
|
RetryOptions,
|
||||||
|
ReactionAttributesType,
|
||||||
ShallowChallengeError,
|
ShallowChallengeError,
|
||||||
QuotedMessageType,
|
QuotedMessageType,
|
||||||
WhatIsThis,
|
WhatIsThis,
|
||||||
|
@ -4084,9 +4085,9 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
async handleReaction(
|
async handleReaction(
|
||||||
reaction: typeof window.WhatIsThis,
|
reaction: typeof window.WhatIsThis,
|
||||||
shouldPersist = true
|
shouldPersist = true
|
||||||
): Promise<void> {
|
): Promise<ReactionAttributesType | undefined> {
|
||||||
if (this.get('deletedForEveryone')) {
|
if (this.get('deletedForEveryone')) {
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We allow you to react to messages with outgoing errors only if it has sent
|
// We allow you to react to messages with outgoing errors only if it has sent
|
||||||
|
@ -4095,7 +4096,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
this.hasErrors() &&
|
this.hasErrors() &&
|
||||||
(this.isIncoming() || this.getMessagePropStatus() !== 'partial-sent')
|
(this.isIncoming() || this.getMessagePropStatus() !== 'partial-sent')
|
||||||
) {
|
) {
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const reactions = this.get('reactions') || [];
|
const reactions = this.get('reactions') || [];
|
||||||
|
@ -4108,6 +4109,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
|
|
||||||
let reactionToRemove: Partial<ReactionType> | undefined;
|
let reactionToRemove: Partial<ReactionType> | undefined;
|
||||||
|
|
||||||
|
let oldReaction: ReactionAttributesType | undefined;
|
||||||
if (reaction.get('remove')) {
|
if (reaction.get('remove')) {
|
||||||
window.log.info('Removing reaction for message', messageId);
|
window.log.info('Removing reaction for message', messageId);
|
||||||
const newReactions = reactions.filter(
|
const newReactions = reactions.filter(
|
||||||
|
@ -4137,9 +4139,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
newReactions.push(reaction.toJSON());
|
newReactions.push(reaction.toJSON());
|
||||||
this.set({ reactions: newReactions });
|
this.set({ reactions: newReactions });
|
||||||
|
|
||||||
const oldReaction = reactions.find(
|
oldReaction = reactions.find(re => re.fromId === reaction.get('fromId'));
|
||||||
re => re.fromId === reaction.get('fromId')
|
|
||||||
);
|
|
||||||
if (oldReaction) {
|
if (oldReaction) {
|
||||||
reactionToRemove = {
|
reactionToRemove = {
|
||||||
emoji: oldReaction.emoji,
|
emoji: oldReaction.emoji,
|
||||||
|
@ -4177,6 +4177,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
Message: window.Whisper.Message,
|
Message: window.Whisper.Message,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return oldReaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleDeleteForEveryone(
|
async handleDeleteForEveryone(
|
||||||
|
|
|
@ -179,15 +179,6 @@ export type MessageType = {
|
||||||
reactions?: Array<{
|
reactions?: Array<{
|
||||||
emoji: string;
|
emoji: string;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
from: {
|
|
||||||
id: string;
|
|
||||||
color?: string;
|
|
||||||
avatarPath?: string;
|
|
||||||
name?: string;
|
|
||||||
profileName?: string;
|
|
||||||
isMe?: boolean;
|
|
||||||
phoneNumber?: string;
|
|
||||||
};
|
|
||||||
}>;
|
}>;
|
||||||
deletedForEveryone?: boolean;
|
deletedForEveryone?: boolean;
|
||||||
|
|
||||||
|
|
8
ts/window.d.ts
vendored
8
ts/window.d.ts
vendored
|
@ -16,6 +16,8 @@ import {
|
||||||
ConversationModelCollectionType,
|
ConversationModelCollectionType,
|
||||||
MessageModelCollectionType,
|
MessageModelCollectionType,
|
||||||
MessageAttributesType,
|
MessageAttributesType,
|
||||||
|
ReactionAttributesType,
|
||||||
|
ReactionModelType,
|
||||||
} from './model-types.d';
|
} from './model-types.d';
|
||||||
import { ContactRecordIdentityState, TextSecureType } from './textsecure.d';
|
import { ContactRecordIdentityState, TextSecureType } from './textsecure.d';
|
||||||
import {
|
import {
|
||||||
|
@ -724,9 +726,9 @@ export type WhisperType = {
|
||||||
};
|
};
|
||||||
|
|
||||||
Reactions: {
|
Reactions: {
|
||||||
forMessage: (message: unknown) => Array<WhatIsThis>;
|
forMessage: (message: unknown) => Array<ReactionModelType>;
|
||||||
add: (reaction: unknown) => WhatIsThis;
|
add: (reaction: ReactionAttributesType) => ReactionModelType;
|
||||||
onReaction: (reactionModel: unknown) => unknown;
|
onReaction: (reactionModel: ReactionModelType) => ReactionAttributesType;
|
||||||
};
|
};
|
||||||
|
|
||||||
Deletes: {
|
Deletes: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue