Prevent send and show toast for invalid conversations
This commit is contained in:
parent
34be0744d2
commit
3ee830ae63
5 changed files with 83 additions and 45 deletions
|
@ -311,6 +311,10 @@
|
||||||
"message": "You are no longer a member of the group.",
|
"message": "You are no longer a member of the group.",
|
||||||
"description": "Displayed when a user can't send a message because they have left the group"
|
"description": "Displayed when a user can't send a message because they have left the group"
|
||||||
},
|
},
|
||||||
|
"invalidConversation": {
|
||||||
|
"message": "This group is invalid. Please create a new group.",
|
||||||
|
"description": "Displayed when a user can't send a message because something has gone wrong in the conversation."
|
||||||
|
},
|
||||||
"scrollDown": {
|
"scrollDown": {
|
||||||
"message": "Scroll to bottom of conversation",
|
"message": "Scroll to bottom of conversation",
|
||||||
"description": "Alt text for button to take user down to bottom of conversation, shown when user scrolls up"
|
"description": "Alt text for button to take user down to bottom of conversation, shown when user scrolls up"
|
||||||
|
|
|
@ -163,6 +163,8 @@ type UpdatesResultType = {
|
||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
export const MASTER_KEY_LENGTH = 32;
|
export const MASTER_KEY_LENGTH = 32;
|
||||||
|
export const ID_V1_LENGTH = 16;
|
||||||
|
export const ID_LENGTH = 32;
|
||||||
const TEMPORAL_AUTH_REJECTED_CODE = 401;
|
const TEMPORAL_AUTH_REJECTED_CODE = 401;
|
||||||
const GROUP_ACCESS_DENIED_CODE = 403;
|
const GROUP_ACCESS_DENIED_CODE = 403;
|
||||||
const SUPPORTED_CHANGE_EPOCH = 0;
|
const SUPPORTED_CHANGE_EPOCH = 0;
|
||||||
|
|
|
@ -266,7 +266,8 @@ export class ConversationModel extends window.Backbone.Model<
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fromEncodedBinaryToArrayBuffer(groupId).byteLength === 16;
|
const buffer = fromEncodedBinaryToArrayBuffer(groupId);
|
||||||
|
return buffer.byteLength === window.Signal.Groups.ID_V1_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
isGroupV2(): boolean {
|
isGroupV2(): boolean {
|
||||||
|
@ -277,7 +278,10 @@ export class ConversationModel extends window.Backbone.Model<
|
||||||
|
|
||||||
const groupVersion = this.get('groupVersion') || 0;
|
const groupVersion = this.get('groupVersion') || 0;
|
||||||
|
|
||||||
return groupVersion === 2 && base64ToArrayBuffer(groupId).byteLength === 32;
|
return (
|
||||||
|
groupVersion === 2 &&
|
||||||
|
base64ToArrayBuffer(groupId).byteLength === window.Signal.Groups.ID_LENGTH
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
isMemberPending(conversationId: string): boolean {
|
isMemberPending(conversationId: string): boolean {
|
||||||
|
@ -822,6 +826,10 @@ export class ConversationModel extends window.Backbone.Model<
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isValid(): boolean {
|
||||||
|
return this.isPrivate() || this.isGroupV1() || this.isGroupV2();
|
||||||
|
}
|
||||||
|
|
||||||
maybeRepairGroupV2(data: {
|
maybeRepairGroupV2(data: {
|
||||||
masterKey: string;
|
masterKey: string;
|
||||||
secretParams: string;
|
secretParams: string;
|
||||||
|
|
|
@ -76,6 +76,12 @@ Whisper.LeftGroupToast = Whisper.ToastView.extend({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Whisper.InvalidConversationToast = Whisper.ToastView.extend({
|
||||||
|
render_attributes() {
|
||||||
|
return { toastMessage: window.i18n('invalidConversation') };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
Whisper.OriginalNotFoundToast = Whisper.ToastView.extend({
|
Whisper.OriginalNotFoundToast = Whisper.ToastView.extend({
|
||||||
render_attributes() {
|
render_attributes() {
|
||||||
return { toastMessage: window.i18n('originalMessageNotFound') };
|
return { toastMessage: window.i18n('originalMessageNotFound') };
|
||||||
|
@ -2897,6 +2903,10 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
this.model.set({ profileSharing: true });
|
this.model.set({ profileSharing: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.showInvalidMessageToast()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { packId, stickerId } = options;
|
const { packId, stickerId } = options;
|
||||||
this.model.sendStickerMessage(packId, stickerId);
|
this.model.sendStickerMessage(packId, stickerId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -3030,6 +3040,43 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showInvalidMessageToast(messageText?: string): boolean {
|
||||||
|
let ToastView;
|
||||||
|
|
||||||
|
if (window.reduxStore.getState().expiration.hasExpired) {
|
||||||
|
ToastView = Whisper.ExpiredToast;
|
||||||
|
}
|
||||||
|
if (!this.model.isValid()) {
|
||||||
|
ToastView = Whisper.InvalidConversationToast;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
this.model.isPrivate() &&
|
||||||
|
(window.storage.isBlocked(this.model.get('e164')) ||
|
||||||
|
window.storage.isUuidBlocked(this.model.get('uuid')))
|
||||||
|
) {
|
||||||
|
ToastView = Whisper.BlockedToast;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!this.model.isPrivate() &&
|
||||||
|
window.storage.isGroupBlocked(this.model.get('groupId'))
|
||||||
|
) {
|
||||||
|
ToastView = Whisper.BlockedGroupToast;
|
||||||
|
}
|
||||||
|
if (!this.model.isPrivate() && this.model.get('left')) {
|
||||||
|
ToastView = Whisper.LeftGroupToast;
|
||||||
|
}
|
||||||
|
if (messageText && messageText.length > MAX_MESSAGE_BODY_LENGTH) {
|
||||||
|
ToastView = Whisper.MessageBodyTooLongToast;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ToastView) {
|
||||||
|
this.showToast(ToastView);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
async sendMessage(message = '', mentions = [], options = {}) {
|
async sendMessage(message = '', mentions = [], options = {}) {
|
||||||
this.sendStart = Date.now();
|
this.sendStart = Date.now();
|
||||||
|
|
||||||
|
@ -3058,32 +3105,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
|
|
||||||
this.model.clearTypingTimers();
|
this.model.clearTypingTimers();
|
||||||
|
|
||||||
let ToastView;
|
if (this.showInvalidMessageToast(message)) {
|
||||||
if (window.reduxStore.getState().expiration.hasExpired) {
|
|
||||||
ToastView = Whisper.ExpiredToast;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
this.model.isPrivate() &&
|
|
||||||
(window.storage.isBlocked(this.model.get('e164')) ||
|
|
||||||
window.storage.isUuidBlocked(this.model.get('uuid')))
|
|
||||||
) {
|
|
||||||
ToastView = Whisper.BlockedToast;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!this.model.isPrivate() &&
|
|
||||||
window.storage.isGroupBlocked(this.model.get('groupId'))
|
|
||||||
) {
|
|
||||||
ToastView = Whisper.BlockedGroupToast;
|
|
||||||
}
|
|
||||||
if (!this.model.isPrivate() && this.model.get('left')) {
|
|
||||||
ToastView = Whisper.LeftGroupToast;
|
|
||||||
}
|
|
||||||
if (message.length > MAX_MESSAGE_BODY_LENGTH) {
|
|
||||||
ToastView = Whisper.MessageBodyTooLongToast;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ToastView) {
|
|
||||||
this.showToast(ToastView);
|
|
||||||
this.enableMessageField();
|
this.enableMessageField();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
36
ts/window.d.ts
vendored
36
ts/window.d.ts
vendored
|
@ -674,28 +674,30 @@ export type WhisperType = {
|
||||||
deliveryReceiptBatcher: BatcherType<WhatIsThis>;
|
deliveryReceiptBatcher: BatcherType<WhatIsThis>;
|
||||||
RotateSignedPreKeyListener: WhatIsThis;
|
RotateSignedPreKeyListener: WhatIsThis;
|
||||||
|
|
||||||
ExpiredToast: typeof Whisper.ToastView;
|
|
||||||
BlockedToast: typeof Whisper.ToastView;
|
|
||||||
BlockedGroupToast: typeof Whisper.ToastView;
|
BlockedGroupToast: typeof Whisper.ToastView;
|
||||||
LeftGroupToast: typeof Whisper.ToastView;
|
BlockedToast: typeof Whisper.ToastView;
|
||||||
OriginalNotFoundToast: typeof Whisper.ToastView;
|
CannotMixImageAndNonImageAttachmentsToast: typeof Whisper.ToastView;
|
||||||
OriginalNoLongerAvailableToast: typeof Whisper.ToastView;
|
DangerousFileTypeToast: typeof Whisper.ToastView;
|
||||||
|
ExpiredToast: typeof Whisper.ToastView;
|
||||||
|
FileSavedToast: typeof Whisper.ToastView;
|
||||||
|
FileSizeToast: any;
|
||||||
FoundButNotLoadedToast: typeof Whisper.ToastView;
|
FoundButNotLoadedToast: typeof Whisper.ToastView;
|
||||||
VoiceNoteLimit: typeof Whisper.ToastView;
|
InvalidConversationToast: typeof Whisper.ToastView;
|
||||||
VoiceNoteMustBeOnlyAttachmentToast: typeof Whisper.ToastView;
|
LeftGroupToast: typeof Whisper.ToastView;
|
||||||
|
MaxAttachmentsToast: typeof Whisper.ToastView;
|
||||||
|
MessageBodyTooLongToast: typeof Whisper.ToastView;
|
||||||
|
OneNonImageAtATimeToast: typeof Whisper.ToastView;
|
||||||
|
OriginalNoLongerAvailableToast: typeof Whisper.ToastView;
|
||||||
|
OriginalNotFoundToast: typeof Whisper.ToastView;
|
||||||
|
PinnedConversationsFullToast: typeof Whisper.ToastView;
|
||||||
|
ReactionFailedToast: typeof Whisper.ToastView;
|
||||||
TapToViewExpiredIncomingToast: typeof Whisper.ToastView;
|
TapToViewExpiredIncomingToast: typeof Whisper.ToastView;
|
||||||
TapToViewExpiredOutgoingToast: typeof Whisper.ToastView;
|
TapToViewExpiredOutgoingToast: typeof Whisper.ToastView;
|
||||||
FileSavedToast: typeof Whisper.ToastView;
|
|
||||||
ReactionFailedToast: typeof Whisper.ToastView;
|
|
||||||
MessageBodyTooLongToast: typeof Whisper.ToastView;
|
|
||||||
FileSizeToast: any;
|
|
||||||
UnableToLoadToast: typeof Whisper.ToastView;
|
|
||||||
DangerousFileTypeToast: typeof Whisper.ToastView;
|
|
||||||
OneNonImageAtATimeToast: typeof Whisper.ToastView;
|
|
||||||
CannotMixImageAndNonImageAttachmentsToast: typeof Whisper.ToastView;
|
|
||||||
MaxAttachmentsToast: typeof Whisper.ToastView;
|
|
||||||
TimerConflictToast: typeof Whisper.ToastView;
|
TimerConflictToast: typeof Whisper.ToastView;
|
||||||
PinnedConversationsFullToast: typeof Whisper.ToastView;
|
UnableToLoadToast: typeof Whisper.ToastView;
|
||||||
|
VoiceNoteLimit: typeof Whisper.ToastView;
|
||||||
|
VoiceNoteMustBeOnlyAttachmentToast: typeof Whisper.ToastView;
|
||||||
|
|
||||||
ConversationLoadingScreen: typeof Whisper.View;
|
ConversationLoadingScreen: typeof Whisper.View;
|
||||||
ConversationView: typeof Whisper.View;
|
ConversationView: typeof Whisper.View;
|
||||||
View: typeof Backbone.View;
|
View: typeof Backbone.View;
|
||||||
|
|
Loading…
Reference in a new issue