working on messages sync
This commit is contained in:
parent
be4a3e928c
commit
1c288a9b47
1 changed files with 52 additions and 22 deletions
74
xmpp.view.ts
74
xmpp.view.ts
|
|
@ -7,21 +7,22 @@
|
|||
status: string
|
||||
}
|
||||
|
||||
type Xmpp_message = {
|
||||
id: string
|
||||
from: string
|
||||
to: string
|
||||
body: string
|
||||
time: number
|
||||
nick?: string // sender nick for MUC groupchat messages
|
||||
media_uri?: string
|
||||
media_mime?: string
|
||||
media_name?: string
|
||||
media_kind?: Media_type
|
||||
media_size?: number
|
||||
media_hash?: string
|
||||
media_hash_algo?: string
|
||||
}
|
||||
type Xmpp_message = {
|
||||
id: string
|
||||
from: string
|
||||
to: string
|
||||
body: string
|
||||
time: number
|
||||
nick?: string // sender nick for MUC groupchat messages
|
||||
mam_id?: string // archive result id for MAM pagination
|
||||
media_uri?: string
|
||||
media_mime?: string
|
||||
media_name?: string
|
||||
media_kind?: Media_type
|
||||
media_size?: number
|
||||
media_hash?: string
|
||||
media_hash_algo?: string
|
||||
}
|
||||
|
||||
type Xmpp_room = {
|
||||
jid: string
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
body: string
|
||||
time: number
|
||||
nick?: string
|
||||
mam_id?: string
|
||||
media_uri?: string
|
||||
media_mime?: string
|
||||
media_name?: string
|
||||
|
|
@ -317,6 +319,7 @@ private _getBody(el: Element): string | null {
|
|||
// XEP-0313 for MUC: query sent TO the room, no "with" filter, optional end-timestamp to avoid duplicating join-history
|
||||
request_mam_room(room_jid: string, max = 50, before_id?: string, before_time?: number): void {
|
||||
if (!this._ws) return
|
||||
room_jid = room_jid.split('/')[0]
|
||||
const qid = this._id()
|
||||
const id = this._id()
|
||||
this._mam_iqs.set(id, room_jid)
|
||||
|
|
@ -341,6 +344,7 @@ private _getBody(el: Element): string | null {
|
|||
// XEP-0313: request last `max` messages with a given peer; pass `before_id` for pagination
|
||||
request_mam(with_jid: string, max = 50, before_id?: string): void {
|
||||
if (!this._ws) return
|
||||
with_jid = with_jid.split('/')[0]
|
||||
const qid = this._id()
|
||||
const id = this._id()
|
||||
this._mam_iqs.set(id, with_jid)
|
||||
|
|
@ -662,11 +666,14 @@ private _handle_message(el: Element) {
|
|||
const from = slash >= 0 ? from_full.slice(0, slash) : from_full
|
||||
// Only groupchat carries a meaningful nick after the slash; for 1:1 the resource is just a device id.
|
||||
const nick = type === 'groupchat' && slash >= 0 ? from_full.slice(slash + 1) : undefined
|
||||
const stanza_id = msg.getAttribute('id') || result.getAttribute('id') || this._id()
|
||||
const mam_id = result.getAttribute('id') || stanza_id
|
||||
this.on_mam_message?.({
|
||||
id: result.getAttribute('id') || this._id(),
|
||||
id: stanza_id,
|
||||
from,
|
||||
to: (msg.getAttribute('to') || '').split('/')[0],
|
||||
body, time,
|
||||
mam_id,
|
||||
...(nick !== undefined ? { nick } : {}),
|
||||
...(media || {}),
|
||||
})
|
||||
|
|
@ -705,6 +712,7 @@ private _handle_message(el: Element) {
|
|||
private _rec = new Map<string, { recorder: MediaRecorder; chunks: Blob[]; stream: MediaStream }>()
|
||||
private _history_loaded = new Set<string>()
|
||||
private _mam_oldest = new Map<string, string>() // jid → oldest MAM result id
|
||||
private _mam_oldest_time = new Map<string, number>() // jid → oldest MAM result time
|
||||
private _loading_more = new Set<string>()
|
||||
private _fin_count = new Map<string, number>()
|
||||
private _scroll_setup = new Set<string>() // scroll listener installed
|
||||
|
|
@ -1281,9 +1289,12 @@ private _handle_message(el: Element) {
|
|||
const bare = this.my_jid().split('/')[0]
|
||||
const peer = msg.from === bare ? msg.to : msg.from
|
||||
if (peer) {
|
||||
const cur = this._mam_oldest.get(peer)
|
||||
const cur_time = cur ? (this._msg_by_id.get(cur)?.time ?? Infinity) : Infinity
|
||||
if (msg.time < cur_time) this._mam_oldest.set(peer, msg.id)
|
||||
const oldest_id = msg.mam_id || msg.id
|
||||
const cur_time = this._mam_oldest_time.get(peer) ?? Infinity
|
||||
if (msg.time < cur_time) {
|
||||
this._mam_oldest.set(peer, oldest_id)
|
||||
this._mam_oldest_time.set(peer, msg.time)
|
||||
}
|
||||
}
|
||||
// MAM-on-delivery: server may wrap live messages in <result>; notify if recent
|
||||
if (Date.now() - msg.time < 30_000 && msg.from !== bare) {
|
||||
|
|
@ -1471,6 +1482,8 @@ private _handle_message(el: Element) {
|
|||
this._scroll_setup.delete(jid)
|
||||
this._oldest_time.delete(jid)
|
||||
this._mam_oldest.delete(jid)
|
||||
this._mam_oldest_time.delete(jid)
|
||||
this._history_loaded.delete(jid)
|
||||
this._fin_count.delete(jid)
|
||||
this.messages_ver(this.messages_ver() + 1)
|
||||
this.$.$mol_state_arg.value('chat', null)
|
||||
|
|
@ -1852,7 +1865,13 @@ private _handle_message(el: Element) {
|
|||
|
||||
private _load_more_history(jid: string) {
|
||||
if (this._loading_more.has(jid) || !this._conn) return
|
||||
const oldest_id = this._mam_oldest.get(jid)
|
||||
let oldest_id = this._mam_oldest.get(jid)
|
||||
if (!oldest_id) {
|
||||
const oldest_msg = this._msgs
|
||||
.filter(m => m.from === jid || m.to === jid || (m.from === this.my_jid().split('/')[0] && m.to === jid) || (m.from === jid && m.to === this.my_jid().split('/')[0]))
|
||||
.sort((a, b) => a.time - b.time)[0]
|
||||
if (oldest_msg?.mam_id) oldest_id = oldest_msg.mam_id
|
||||
}
|
||||
this._loading_more.add(jid)
|
||||
if (this._rooms.has(jid)) {
|
||||
// cursor available after first MAM batch; otherwise use timestamp to avoid duplicating join-history
|
||||
|
|
@ -1937,6 +1956,7 @@ private _handle_message(el: Element) {
|
|||
...(msg.media_size !== undefined ? { media_size: msg.media_size } : {}),
|
||||
...(msg.media_hash !== undefined ? { media_hash: msg.media_hash } : {}),
|
||||
...(msg.media_hash_algo !== undefined ? { media_hash_algo: msg.media_hash_algo } : {}),
|
||||
...(msg.mam_id !== undefined ? { mam_id: msg.mam_id } : {}),
|
||||
}
|
||||
await Messages.put(doc, [account, msg.id])
|
||||
} catch (e) { console.warn('[xmpp] persist failed', e) }
|
||||
|
|
@ -1953,7 +1973,7 @@ private _handle_message(el: Element) {
|
|||
this._loading_persisted = true
|
||||
try {
|
||||
for (const doc of docs) {
|
||||
this._add_message({
|
||||
const msg: Xmpp_message = {
|
||||
id: doc.id, from: doc.from, to: doc.to,
|
||||
body: doc.body, time: doc.time,
|
||||
...(doc.nick !== undefined ? { nick: doc.nick } : {}),
|
||||
|
|
@ -1964,7 +1984,17 @@ private _handle_message(el: Element) {
|
|||
...(doc.media_size !== undefined ? { media_size: doc.media_size } : {}),
|
||||
...(doc.media_hash !== undefined ? { media_hash: doc.media_hash } : {}),
|
||||
...(doc.media_hash_algo !== undefined ? { media_hash_algo: doc.media_hash_algo } : {}),
|
||||
})
|
||||
...(doc.mam_id !== undefined ? { mam_id: doc.mam_id } : {}),
|
||||
}
|
||||
this._add_message(msg)
|
||||
if (msg.mam_id) {
|
||||
const peer = this._peer_of(msg, account)
|
||||
const cur_time = this._mam_oldest_time.get(peer) ?? Infinity
|
||||
if (msg.time < cur_time) {
|
||||
this._mam_oldest.set(peer, msg.mam_id)
|
||||
this._mam_oldest_time.set(peer, msg.time)
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this._loading_persisted = false
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue