Skip to content

Commit

Permalink
feat(indexeddb): integrate indexeddb with textile messages
Browse files Browse the repository at this point in the history
* if nothing stored, fetch every message and store
* if stored, combine indexed messages with new messages from textile
  • Loading branch information
josephmcg committed Jan 5, 2022
1 parent 3ae22b4 commit 35d6577
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 42 deletions.
35 changes: 22 additions & 13 deletions libraries/Textile/MailboxManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,26 @@ export class MailboxManager {
* @param lastInbound timestamp of last received message
* @returns an array of messages
*/
async getConversation(
friendIdentifier: string,
query: ConversationQuery,
lastInbound?: number,
): Promise<Message[]> {
async getConversation({
friendIdentifier,
query,
lastInbound,
}: {
friendIdentifier: string
query: ConversationQuery
lastInbound?: number
}): Promise<Message[]> {
const thread = await this.textile.users.getThread('hubmail')
const threadID = ThreadID.fromString(thread.id)

let inboxQuery = Query.where('from').eq(friendIdentifier).orderByIDDesc()

// if messages are stored in indexeddb, only fetch new messages from textile
if (lastInbound) {
inboxQuery = Query.where('from')
.eq(friendIdentifier)
.and(PropCommonEnum.MOD)
.ge(lastInbound) // this will always return every message. textile timestamp has more digits, so it will always be larger
.ge(lastInbound)
.orderByIDDesc()
}

Expand Down Expand Up @@ -122,11 +128,16 @@ export class MailboxManager {
sentboxQuery.and(PropCommonEnum.CREATED_AT).lt(lastMessageTime)
}

const encryptedSentbox = await this.textile.client.find<MessageFromThread>(
threadID,
MailboxSubscriptionType.sentbox,
sentboxQuery,
)
let encryptedSentbox: MessageFromThread[] = []

// only fetch sent messages if indexeddb is empty. after that, sending/editing action will add to indexeddb
if (lastInbound === undefined) {
encryptedSentbox = await this.textile.client.find<MessageFromThread>(
threadID,
MailboxSubscriptionType.sentbox,
sentboxQuery,
)
}

const messages = [...encryptedInbox, ...encryptedSentbox].sort(
(a, b) => a.created_at - b.created_at,
Expand All @@ -140,8 +151,6 @@ export class MailboxManager {
(r) => r.status === PropCommonEnum.FULFILLED,
) as PromiseFulfilledResult<Message>[]

debugger

return filtered.map((r) => r.value)
}

Expand Down
62 changes: 33 additions & 29 deletions store/textile/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,38 +65,42 @@ export default {

const query = { limit: Config.chat.defaultMessageLimit, skip: 0 }

const conversation = await db.conversations
.get(address)
.then((convo) => {
// if nothing indexed, fetch entire conversation
if (!convo) {
return $MailboxManager.getConversation(friend.textilePubkey, query)
}

const dbinfo = convo[address]
console.log('db', dbinfo)

// todo - return db and partial fetch combined
// return convo[address]
return $MailboxManager.getConversation(
friend.textilePubkey,
query,
lastInbound,
)
let conversation: Message[] = []

let dbMessages = await db.conversations.get(address).then((convo) => {
return convo?.[address] ?? []
})

// if nothing stored in indexeddb, fetch entire conversation
if (!dbMessages.length) {
conversation = await $MailboxManager.getConversation({
friendIdentifier: friend.textilePubkey,
query,
})
//
.then((convo) => {
console.log('fetched', convo)
// @ts-ignore
const dbData: DexieMessage = {
[address]: convo,
key: address,
}
console.log('stored in db')
db.conversations.put(dbData)
return convo
}
// otherwise, combine new textile messages with stored messages
else {
const textileMessages = await $MailboxManager.getConversation({
friendIdentifier: friend.textilePubkey,
query,
lastInbound: lastInbound * 1000000, // textile has a more specific unix timestamp, matching theirs
})

// use textileMessages as primary source. this way, old versions of edited messages (with the same id) will not be used
const ids = new Set(textileMessages.map((d) => d.id))
conversation = [
...textileMessages,
...dbMessages.filter((d) => !ids.has(d.id)),
]
}

// @ts-ignore - store latest data in indexeddb
const dbData: DexieMessage = {
[address]: conversation,
key: address,
}
db.conversations.put(dbData)

commit('setConversation', {
address: friend.address,
messages: conversation,
Expand Down

0 comments on commit 35d6577

Please sign in to comment.