|
|
|
/**
|
|
|
|
* @prettier
|
|
|
|
*/
|
|
|
|
import { Attachment } from './Attachment';
|
Index messages with attachments using a boolean
When indexing message attachment metadata using numeric indexes such as:
```javascript
{
conversationId: '+12223334455',
received_at: 123,
attachments: […],
numAttachments: 2,
},
{
conversationId: '+12223334455',
received_at: 456,
attachments: [],
numAttachments: 0,
}
{
conversationId: '+12223334455',
received_at: 789,
attachments: [],
numAttachments: 1,
}
```
It creates an index as follows:
```
[conversationId, received_at, numAttachments]
['+12223334455', 123, 2]
['+12223334455', 456, 0]
['+12223334455', 789, 1]
```
This means a query such as…
```
lowerBound: ['+12223334455', 0, 1 ]
upperBound: ['+12223334455', Number.MAX_VALUE, Number.MAX_VALUE]
```
…will return all three original entries because they span the `received_at`
from `0` through `Number.MAX_VALUE`. One workaround is to index booleans using
`1 | undefined` where `1` is included in the index and `undefined` is not, but
that way we lose the ability to query for the `false` value. Instead, we flip
adjust the index to `[conversationId, hasAttachments, received_at]` and can
then query messages with attachments using
```
[conversationId, 1 /* hasAttachments */, 0 /* received_at */]
[conversationId, 1 /* hasAttachments */, Number.MAX_VALUE /* received_at */]
```
7 years ago
|
|
|
import { IndexableBoolean } from './IndexedDB';
|
|
|
|
|
|
|
|
export type Message = IncomingMessage | OutgoingMessage | VerifiedChangeMessage;
|
|
|
|
|
|
|
|
export type IncomingMessage = Readonly<
|
|
|
|
{
|
|
|
|
type: 'incoming';
|
|
|
|
// Required
|
|
|
|
attachments: Array<Attachment>;
|
|
|
|
id: string;
|
|
|
|
received_at: number;
|
|
|
|
|
|
|
|
// Optional
|
|
|
|
body?: string;
|
|
|
|
decrypted_at?: number;
|
|
|
|
errors?: Array<any>;
|
|
|
|
flags?: number;
|
|
|
|
source?: string;
|
|
|
|
sourceDevice?: number;
|
|
|
|
} & SharedMessageProperties &
|
|
|
|
Message4 &
|
|
|
|
ExpirationTimerUpdate
|
|
|
|
>;
|
|
|
|
|
|
|
|
export type OutgoingMessage = Readonly<
|
|
|
|
{
|
|
|
|
type: 'outgoing';
|
|
|
|
|
|
|
|
// Required
|
|
|
|
attachments: Array<Attachment>;
|
|
|
|
delivered: number;
|
|
|
|
delivered_to: Array<string>;
|
|
|
|
destination: string; // PhoneNumber
|
|
|
|
expirationStartTimestamp: number;
|
|
|
|
id: string;
|
|
|
|
received_at: number;
|
|
|
|
sent: boolean;
|
|
|
|
sent_to: Array<string>; // Array<PhoneNumber>
|
|
|
|
|
|
|
|
// Optional
|
|
|
|
body?: string;
|
|
|
|
expires_at?: number;
|
|
|
|
expireTimer?: number;
|
|
|
|
recipients?: Array<string>; // Array<PhoneNumber>
|
|
|
|
synced: boolean;
|
|
|
|
} & SharedMessageProperties &
|
|
|
|
Message4 &
|
|
|
|
ExpirationTimerUpdate
|
|
|
|
>;
|
|
|
|
|
|
|
|
export type VerifiedChangeMessage = Readonly<
|
|
|
|
{
|
|
|
|
type: 'verified-change';
|
|
|
|
} & SharedMessageProperties &
|
|
|
|
Message4 &
|
|
|
|
ExpirationTimerUpdate
|
|
|
|
>;
|
|
|
|
|
|
|
|
type SharedMessageProperties = Readonly<{
|
|
|
|
conversationId: string;
|
|
|
|
sent_at: number;
|
|
|
|
timestamp: number;
|
|
|
|
}>;
|
|
|
|
|
|
|
|
type ExpirationTimerUpdate = Partial<
|
|
|
|
Readonly<{
|
|
|
|
expirationTimerUpdate: Readonly<{
|
|
|
|
expireTimer: number;
|
|
|
|
fromSync: boolean;
|
|
|
|
source: string; // PhoneNumber
|
|
|
|
}>;
|
|
|
|
}>
|
|
|
|
>;
|
|
|
|
|
|
|
|
type Message4 = Partial<
|
|
|
|
Readonly<{
|
|
|
|
hasAttachments: IndexableBoolean;
|
|
|
|
hasVisualMediaAttachments: IndexableBoolean;
|
|
|
|
hasFileAttachments: IndexableBoolean;
|
|
|
|
}>
|
|
|
|
>;
|