add a getOrThrow to ConversationController when we expect this convo

pull/1387/head
Audric Ackermann 5 years ago
parent 144ae41529
commit 026a1930ed
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -1,9 +1,10 @@
import { ConversationModel } from "./models/conversations"; import { ConversationModel } from './models/conversations';
export type ConversationControllerType = { export type ConversationControllerType = {
reset: () => void; reset: () => void;
load: () => Promise<void>; load: () => Promise<void>;
get: (id: string) => ConversationModel | undefined; get: (id: string) => ConversationModel | undefined;
getOrCreateAndWait: (id: string, type: string) => Promise<ConversationModel>; getOrCreate: (id: string, type: string) => Promise<ConversationModel>; getOrThrow: (id: string) => ConversationModel;
getOrCreateAndWait: (id: string, type: string) => Promise<ConversationModel>;
} getOrCreate: (id: string, type: string) => Promise<ConversationModel>;
};

@ -64,6 +64,22 @@
return conversations.get(id); return conversations.get(id);
}, },
getOrThrow(id) {
if (!this._initialFetchComplete) {
throw new Error(
'ConversationController.get() needs complete initial fetch'
);
}
const convo = conversations.get(id);
if (convo) {
return convo;
}
throw new Error(
`Conversation ${id} does not exist on ConversationController.get()`
);
},
// Needed for some model setup which happens during the initial fetch() call below // Needed for some model setup which happens during the initial fetch() call below
getUnsafe(id) { getUnsafe(id) {
return conversations.get(id); return conversations.get(id);

@ -41,7 +41,7 @@ export interface ConversationModel
toggleVerified: () => Promise<void>; toggleVerified: () => Promise<void>;
getProfile: (id: string) => Promise<any>; getProfile: (id: string) => Promise<any>;
getProfiles: () => Promise<any>; getProfiles: () => Promise<any>;
setProfileKey: (key: string) => void; setProfileKey: (key: string) => Promise<void>;
isMe: () => boolean; isMe: () => boolean;
getRecipients: () => Array<string>; getRecipients: () => Array<string>;
getTitle: () => string; getTitle: () => string;
@ -61,12 +61,18 @@ export interface ConversationModel
isOnline: () => boolean; isOnline: () => boolean;
isModerator: (id?: string) => boolean; isModerator: (id?: string) => boolean;
lastMessage: string; lastMessage: string;
messageCollection: Backbone.Collection<MessageModel>; messageCollection: Backbone.Collection<MessageModel>;
// types to make more specific // types to make more specific
sendMessage: (body: any, attachments: any, quote: any, preview: any, groupInvitation: any, otherOptions: any) => Promise<void>; sendMessage: (
body: any,
attachments: any,
quote: any,
preview: any,
groupInvitation: any,
otherOptions: any
) => Promise<void>;
updateGroupAdmins: any; updateGroupAdmins: any;
setLokiProfile: any; setLokiProfile: any;
onSessionResetReceived: any; onSessionResetReceived: any;

@ -2607,8 +2607,6 @@
flex-grow: 0; flex-grow: 0;
} }
.module-left-pane__list { .module-left-pane__list {
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;
@ -2620,8 +2618,6 @@
outline: none; outline: none;
} }
// Third-party module: react-contextmenu // Third-party module: react-contextmenu
.react-contextmenu { .react-contextmenu {

@ -290,7 +290,7 @@ export class DevicePairingDialog extends React.Component<Props, State> {
type: 'success', type: 'success',
}); });
const { currentPubKey } = this.state; const { currentPubKey } = this.state;
if(currentPubKey) { if (currentPubKey) {
const conv = window.ConversationController.get(currentPubKey); const conv = window.ConversationController.get(currentPubKey);
if (conv) { if (conv) {
void conv.setNickname(this.state.deviceAlias); void conv.setNickname(this.state.deviceAlias);

@ -41,10 +41,7 @@ export class SearchResults extends React.Component<Props> {
const haveConversations = conversations && conversations.length; const haveConversations = conversations && conversations.length;
const haveContacts = contacts && contacts.length; const haveContacts = contacts && contacts.length;
const haveMessages = messages && messages.length; const haveMessages = messages && messages.length;
const noResults = const noResults = !haveConversations && !haveContacts && !haveMessages;
!haveConversations &&
!haveContacts &&
!haveMessages;
return ( return (
<div className="module-search-results"> <div className="module-search-results">

@ -621,6 +621,7 @@ export class Message extends React.PureComponent<Props, State> {
direction, direction,
i18n, i18n,
quote, quote,
text,
isPublic, isPublic,
convoId, convoId,
} = this.props; } = this.props;

@ -331,12 +331,13 @@ export class SessionCompositionBox extends React.Component<Props, State> {
// Send message // Send message
this.props.onMessageSending(); this.props.onMessageSending();
const extractedQuotedMessageProps = _.pick(quotedMessageProps, const extractedQuotedMessageProps = _.pick(
quotedMessageProps,
'id', 'id',
'author', 'author',
'text', 'text',
'attachments'); 'attachments'
);
try { try {
await this.props.sendMessage( await this.props.sendMessage(

@ -142,12 +142,9 @@ export class SessionConversation extends React.Component<Props, State> {
// Keyboard navigation // Keyboard navigation
this.onKeyDown = this.onKeyDown.bind(this); this.onKeyDown = this.onKeyDown.bind(this);
const conversationModel = window.ConversationController.get( const conversationModel = window.ConversationController.getOrThrow(
this.state.conversationKey this.state.conversationKey
); );
if (!conversationModel) {
throw new Error('conversation null on ConversationController.get()');
}
conversationModel.on('change', () => { conversationModel.on('change', () => {
this.setState( this.setState(
{ {
@ -214,12 +211,9 @@ export class SessionConversation extends React.Component<Props, State> {
const conversation = this.props.conversations.conversationLookup[ const conversation = this.props.conversations.conversationLookup[
conversationKey conversationKey
]; ];
const conversationModel = window.ConversationController.get( const conversationModel = window.ConversationController.getOrThrow(
conversationKey conversationKey
); );
if (!conversationModel) {
throw new Error('conversation null on ConversationController.get()');
}
const isRss = conversation.isRss; const isRss = conversation.isRss;
// TODO VINCE: OPTIMISE FOR NEW SENDING??? // TODO VINCE: OPTIMISE FOR NEW SENDING???
@ -232,7 +226,6 @@ export class SessionConversation extends React.Component<Props, State> {
const showSafetyNumber = this.state.infoViewState === 'safetyNumber'; const showSafetyNumber = this.state.infoViewState === 'safetyNumber';
const showMessageDetails = this.state.infoViewState === 'messageDetails'; const showMessageDetails = this.state.infoViewState === 'messageDetails';
return ( return (
<SessionTheme theme={this.props.theme}> <SessionTheme theme={this.props.theme}>
<div className="conversation-header">{this.renderHeader()}</div> <div className="conversation-header">{this.renderHeader()}</div>
@ -414,16 +407,13 @@ export class SessionConversation extends React.Component<Props, State> {
// in the conversation model. // in the conversation model.
// The only time we need to call getMessages() is to grab more messages on scroll. // The only time we need to call getMessages() is to grab more messages on scroll.
const { conversationKey, initialFetchComplete } = this.state; const { conversationKey, initialFetchComplete } = this.state;
const conversationModel = window.ConversationController.get( const conversationModel = window.ConversationController.getOrThrow(
conversationKey conversationKey
); );
if (initialFetchComplete) { if (initialFetchComplete) {
return; return;
} }
if (!conversationModel) {
throw new Error('conversation null on ConversationController.get()');
}
const messageSet = await window.Signal.Data.getMessagesByConversation( const messageSet = await window.Signal.Data.getMessagesByConversation(
conversationKey, conversationKey,
@ -506,10 +496,9 @@ export class SessionConversation extends React.Component<Props, State> {
public getHeaderProps() { public getHeaderProps() {
const { conversationKey } = this.state; const { conversationKey } = this.state;
const conversation = window.ConversationController.get(conversationKey); const conversation = window.ConversationController.getOrThrow(
if (!conversation) { conversationKey
throw new Error('conversation null on ConversationController.get()'); );
}
const expireTimer = conversation.get('expireTimer'); const expireTimer = conversation.get('expireTimer');
const expirationSettingName = expireTimer const expirationSettingName = expireTimer
? window.Whisper.ExpirationTimerOptions.getName(expireTimer || 0) ? window.Whisper.ExpirationTimerOptions.getName(expireTimer || 0)
@ -615,10 +604,9 @@ export class SessionConversation extends React.Component<Props, State> {
public getGroupSettingsProps() { public getGroupSettingsProps() {
const { conversationKey } = this.state; const { conversationKey } = this.state;
const conversation = window.ConversationController.get(conversationKey); const conversation = window.ConversationController.getOrThrow(
if (!conversation) { conversationKey
throw new Error('conversation null on ConversationController.get()'); );
}
const ourPK = window.textsecure.storage.user.getNumber(); const ourPK = window.textsecure.storage.user.getNumber();
const members = conversation.get('members') || []; const members = conversation.get('members') || [];
@ -730,10 +718,10 @@ export class SessionConversation extends React.Component<Props, State> {
// If you're not friends, don't mark anything as read. Otherwise // If you're not friends, don't mark anything as read. Otherwise
// this will automatically accept friend request. // this will automatically accept friend request.
const conversation = window.ConversationController.get(conversationKey); const conversation = window.ConversationController.getOrThrow(
if (!conversation) { conversationKey
throw new Error('conversation null on ConversationController.get()'); );
}
if (conversation.isBlocked()) { if (conversation.isBlocked()) {
return; return;
} }
@ -826,14 +814,12 @@ export class SessionConversation extends React.Component<Props, State> {
); );
const { conversationKey } = this.state; const { conversationKey } = this.state;
const conversationModel = window.ConversationController.get( const conversationModel = window.ConversationController.getOrThrow(
conversationKey conversationKey
); );
const multiple = selectedMessages.length > 1; const multiple = selectedMessages.length > 1;
if (!conversationModel) {
throw new Error('conversation null on ConversationController.get()');
}
const isPublic = conversationModel.isPublic(); const isPublic = conversationModel.isPublic();
// In future, we may be able to unsend private messages also // In future, we may be able to unsend private messages also
@ -1068,27 +1054,29 @@ export class SessionConversation extends React.Component<Props, State> {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~ MESSAGE QUOTE ~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~ MESSAGE QUOTE ~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private async replyToMessage(quotedMessageTimestamp ?: number) { private async replyToMessage(quotedMessageTimestamp?: number) {
if (!_.isEqual(this.state.quotedMessageTimestamp, quotedMessageTimestamp)) { if (!_.isEqual(this.state.quotedMessageTimestamp, quotedMessageTimestamp)) {
const { conversationKey } = this.state; const { conversationKey } = this.state;
const conversationModel = window.ConversationController.get( const conversationModel = window.ConversationController.getOrThrow(
conversationKey conversationKey
); );
if (!conversationModel) {
throw new Error('conversation null on ConversationController.get()');
}
const conversation = this.props.conversations.conversationLookup[ const conversation = this.props.conversations.conversationLookup[
conversationKey conversationKey
]; ];
let quotedMessageProps = null; let quotedMessageProps = null;
if (quotedMessageTimestamp) { if (quotedMessageTimestamp) {
const quotedMessageModel = conversationModel.getMessagesWithTimestamp(conversation.id, quotedMessageTimestamp); const quotedMessageModel = conversationModel.getMessagesWithTimestamp(
conversation.id,
quotedMessageTimestamp
);
if (quotedMessageModel && quotedMessageModel.length === 1) { if (quotedMessageModel && quotedMessageModel.length === 1) {
quotedMessageProps = await conversationModel.makeQuote(quotedMessageModel[0]); quotedMessageProps = await conversationModel.makeQuote(
quotedMessageModel[0]
);
} }
} }
this.setState({ quotedMessageTimestamp, quotedMessageProps }); this.setState({ quotedMessageTimestamp, quotedMessageProps });
} }
} }

@ -12,6 +12,8 @@ interface Props {
const QuotedMessageComposition = styled.div` const QuotedMessageComposition = styled.div`
width: 100%; width: 100%;
padding-inline-end: ${props => props.theme.common.margins.md};
padding-inline-start: ${props => props.theme.common.margins.md};
`; `;
const QuotedMessageCompositionReply = styled.div` const QuotedMessageCompositionReply = styled.div`

@ -710,10 +710,7 @@ export async function handleMessageEvent(event: MessageEvent): Promise<void> {
} }
// the conversation with the primary device of that source (can be the same as conversationOrigin) // the conversation with the primary device of that source (can be the same as conversationOrigin)
const conversation = window.ConversationController.get(conversationId); const conversation = window.ConversationController.getOrThrow(conversationId);
if (!conversation) {
throw new Error('conversation null on ConversationController.get()');
}
conversation.queueJob(() => { conversation.queueJob(() => {
handleMessageJob( handleMessageJob(

@ -87,7 +87,9 @@ export async function preprocessGroupMessage(
} else { } else {
// be sure to drop a message from a non admin if it tries to change group members // be sure to drop a message from a non admin if it tries to change group members
// or change the group name // or change the group name
const fromAdmin = conversation.get('groupAdmins')?.includes(primarySource); const fromAdmin = conversation
.get('groupAdmins')
?.includes(primarySource);
if (!fromAdmin) { if (!fromAdmin) {
// Make sure the message is not removing members / renaming the group // Make sure the message is not removing members / renaming the group

@ -287,7 +287,6 @@ async function handleMediumGroupChange(
return; return;
} }
// ***** Updating the group ***** // ***** Updating the group *****
const curAdmins = convo.get('groupAdmins') || []; const curAdmins = convo.get('groupAdmins') || [];

@ -381,7 +381,6 @@ async function onContactReceived(details: any) {
conversation.setProfileKey(profileKey); conversation.setProfileKey(profileKey);
} }
if (details.name && details.name.length) { if (details.name && details.name.length) {
await conversation.setLokiProfile({ displayName: details.name }); await conversation.setLokiProfile({ displayName: details.name });
} }

@ -830,7 +830,8 @@ async function updateOrCreateGroup(details: GroupInfo) {
await conversation.commit(); await conversation.commit();
const { expireTimer } = details; const { expireTimer } = details;
const isValidExpireTimer = expireTimer !== undefined && typeof expireTimer === 'number'; const isValidExpireTimer =
expireTimer !== undefined && typeof expireTimer === 'number';
if (expireTimer === undefined || typeof expireTimer !== 'number') { if (expireTimer === undefined || typeof expireTimer !== 'number') {
return; return;

@ -22,6 +22,8 @@ const common = {
margins: { margins: {
xs: '5px', xs: '5px',
sm: '10px', sm: '10px',
md: '15px',
lg: '20px',
}, },
}; };

2
ts/styled.d.ts vendored

@ -11,6 +11,8 @@ declare module 'styled-components' {
margins: { margins: {
xs: string; xs: string;
sm: string; sm: string;
md: string;
lg: string;
}; };
}; };
colors: { colors: {

2
ts/window.d.ts vendored

@ -12,7 +12,7 @@ import { LibTextsecure } from '../libtextsecure';
import { ConversationType } from '../js/modules/data'; import { ConversationType } from '../js/modules/data';
import { RecoveryPhraseUtil } from '../libloki/modules/mnemonic'; import { RecoveryPhraseUtil } from '../libloki/modules/mnemonic';
import { ConfirmationDialogParams } from '../background'; import { ConfirmationDialogParams } from '../background';
import { } from 'styled-components/cssprop'; import {} from 'styled-components/cssprop';
import { ConversationControllerType } from '../js/ConversationController'; import { ConversationControllerType } from '../js/ConversationController';
/* /*

@ -146,6 +146,7 @@
// We use || and && shortcutting because we're javascript programmers // We use || and && shortcutting because we're javascript programmers
"strict-boolean-expressions": false, "strict-boolean-expressions": false,
"no-promise-as-boolean": true, "no-promise-as-boolean": true,
"await-promise": true,
"no-suspicious-comment": false, "no-suspicious-comment": false,
"no-backbone-get-set-outside-model": false, "no-backbone-get-set-outside-model": false,
"underscore-consistent-invocation": false, "underscore-consistent-invocation": false,

Loading…
Cancel
Save