feat(platform): Phase 130 search refresh and presence prefs sync (v0.8.95)
Add refreshSearch() to re-run guild/forum mesh queries and stamp searchMeshMeta.fetchedAt for stale UI indicators. Persist guild online counts to USER_PREFS.guildPresenceCache (debounced gossip) and merge remote cache on prefs ingest so companion rail presence stays consistent across linked devices. Expose presence row timestamps on guildPresenceSummary in view(). Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -330,6 +330,8 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
this._guildTyping = new Map()
|
this._guildTyping = new Map()
|
||||||
this._typingTimers = new Set()
|
this._typingTimers = new Set()
|
||||||
this._guildPresenceSummary = new Map()
|
this._guildPresenceSummary = new Map()
|
||||||
|
this._guildPresencePrefsTimer = null
|
||||||
|
this._searchFetchedAt = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
@@ -366,7 +368,12 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
userId: snap.user.id
|
userId: snap.user.id
|
||||||
})
|
})
|
||||||
await this.userSettings.ready()
|
await this.userSettings.ready()
|
||||||
this.userSettings.on('prefs', () => this.emit('user-prefs'))
|
const sessionPrefs = await this.userSettings.getPrefs()
|
||||||
|
this._ingestGuildPresenceCacheFromPrefs(sessionPrefs)
|
||||||
|
this.userSettings.on('prefs', (prefs) => {
|
||||||
|
this._ingestGuildPresenceCacheFromPrefs(prefs)
|
||||||
|
this.emit('user-prefs')
|
||||||
|
})
|
||||||
this.profileCosmetics = new PearcordProfileCosmetics({
|
this.profileCosmetics = new PearcordProfileCosmetics({
|
||||||
storagePath: this.storagePath,
|
storagePath: this.storagePath,
|
||||||
userId: snap.user.id
|
userId: snap.user.id
|
||||||
@@ -458,7 +465,12 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
userId: user.id
|
userId: user.id
|
||||||
})
|
})
|
||||||
await this.userSettings.ready()
|
await this.userSettings.ready()
|
||||||
this.userSettings.on('prefs', () => this.emit('user-prefs'))
|
const bootPrefs = await this.userSettings.getPrefs()
|
||||||
|
this._ingestGuildPresenceCacheFromPrefs(bootPrefs)
|
||||||
|
this.userSettings.on('prefs', (prefs) => {
|
||||||
|
this._ingestGuildPresenceCacheFromPrefs(prefs)
|
||||||
|
this.emit('user-prefs')
|
||||||
|
})
|
||||||
this.profileCosmetics = new PearcordProfileCosmetics({
|
this.profileCosmetics = new PearcordProfileCosmetics({
|
||||||
storagePath: this.storagePath,
|
storagePath: this.storagePath,
|
||||||
userId: user.id
|
userId: user.id
|
||||||
@@ -1043,6 +1055,17 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async refreshSearch () {
|
||||||
|
if (!this._searchQuery || !this.guild?.guild?.id) {
|
||||||
|
return { refreshed: false, meta: this._lastSearchMeshMeta }
|
||||||
|
}
|
||||||
|
if (this._lastSearchMeshMeta) {
|
||||||
|
this._lastSearchMeshMeta = { ...this._lastSearchMeshMeta, refreshing: true }
|
||||||
|
}
|
||||||
|
await this._resolveSearchResults()
|
||||||
|
return { refreshed: true, meta: this._lastSearchMeshMeta }
|
||||||
|
}
|
||||||
|
|
||||||
async _resolveSearchResults () {
|
async _resolveSearchResults () {
|
||||||
const q = this._searchQuery
|
const q = this._searchQuery
|
||||||
if (!q || !this.guild?.guild?.id) return []
|
if (!q || !this.guild?.guild?.id) return []
|
||||||
@@ -1061,8 +1084,11 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
mesh: out.mesh,
|
mesh: out.mesh,
|
||||||
meshHitCount: out.meshHitCount || 0,
|
meshHitCount: out.meshHitCount || 0,
|
||||||
localHitCount: out.localHitCount || 0,
|
localHitCount: out.localHitCount || 0,
|
||||||
scope: 'forum'
|
scope: 'forum',
|
||||||
|
fetchedAt: Date.now(),
|
||||||
|
refreshing: false
|
||||||
}
|
}
|
||||||
|
this._searchFetchedAt = this._lastSearchMeshMeta.fetchedAt
|
||||||
return out.hits
|
return out.hits
|
||||||
}
|
}
|
||||||
if (this._searchScope === 'guild') {
|
if (this._searchScope === 'guild') {
|
||||||
@@ -1073,8 +1099,12 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
this._lastSearchMeshMeta = {
|
this._lastSearchMeshMeta = {
|
||||||
mesh: out.mesh,
|
mesh: out.mesh,
|
||||||
meshHitCount: out.meshHitCount || 0,
|
meshHitCount: out.meshHitCount || 0,
|
||||||
localHitCount: out.localHitCount || 0
|
localHitCount: out.localHitCount || 0,
|
||||||
|
scope: 'guild',
|
||||||
|
fetchedAt: Date.now(),
|
||||||
|
refreshing: false
|
||||||
}
|
}
|
||||||
|
this._searchFetchedAt = this._lastSearchMeshMeta.fetchedAt
|
||||||
return out.hits
|
return out.hits
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
@@ -4834,12 +4864,42 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
if (onlineish.has(p.status)) online += 1
|
if (onlineish.has(p.status)) online += 1
|
||||||
}
|
}
|
||||||
this._guildPresenceSummary.set(guildId, { online, at: Date.now() })
|
this._guildPresenceSummary.set(guildId, { online, at: Date.now() })
|
||||||
|
this._scheduleGuildPresencePrefsSync()
|
||||||
|
}
|
||||||
|
|
||||||
|
_ingestGuildPresenceCacheFromPrefs (prefs) {
|
||||||
|
const cache = prefs?.guildPresenceCache
|
||||||
|
if (!cache || typeof cache !== 'object') return
|
||||||
|
for (const [gid, row] of Object.entries(cache)) {
|
||||||
|
if (!gid || !row) continue
|
||||||
|
const at = Number(row.at) || 0
|
||||||
|
const prev = this._guildPresenceSummary.get(gid)
|
||||||
|
if (!prev || at >= (prev.at || 0)) {
|
||||||
|
this._guildPresenceSummary.set(gid, {
|
||||||
|
online: Math.max(0, Number(row.online) || 0),
|
||||||
|
at
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_scheduleGuildPresencePrefsSync () {
|
||||||
|
if (!this.userSettings) return
|
||||||
|
if (this._guildPresencePrefsTimer) clearTimeout(this._guildPresencePrefsTimer)
|
||||||
|
this._guildPresencePrefsTimer = setTimeout(() => {
|
||||||
|
this._guildPresencePrefsTimer = null
|
||||||
|
const cache = {}
|
||||||
|
for (const [gid, row] of this._guildPresenceSummary) {
|
||||||
|
cache[gid] = { online: row.online || 0, at: row.at || Date.now() }
|
||||||
|
}
|
||||||
|
void this.userSettings.setPrefs({ guildPresenceCache: cache }, { gossip: true }).catch(() => {})
|
||||||
|
}, 1200)
|
||||||
}
|
}
|
||||||
|
|
||||||
_guildPresenceSummaryForView () {
|
_guildPresenceSummaryForView () {
|
||||||
const out = {}
|
const out = {}
|
||||||
for (const [gid, row] of this._guildPresenceSummary) {
|
for (const [gid, row] of this._guildPresenceSummary) {
|
||||||
out[gid] = { online: row.online || 0 }
|
out[gid] = { online: row.online || 0, at: row.at || 0 }
|
||||||
}
|
}
|
||||||
if (this.guild?.guild?.id) {
|
if (this.guild?.guild?.id) {
|
||||||
this._updateGuildPresenceSummary(this.guild.guild.id)
|
this._updateGuildPresenceSummary(this.guild.guild.id)
|
||||||
|
|||||||
Reference in New Issue
Block a user