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._typingTimers = new Set()
|
||||
this._guildPresenceSummary = new Map()
|
||||
this._guildPresencePrefsTimer = null
|
||||
this._searchFetchedAt = 0
|
||||
}
|
||||
|
||||
async ready () {
|
||||
@@ -366,7 +368,12 @@ class PearcordPlatform extends EventEmitter {
|
||||
userId: snap.user.id
|
||||
})
|
||||
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({
|
||||
storagePath: this.storagePath,
|
||||
userId: snap.user.id
|
||||
@@ -458,7 +465,12 @@ class PearcordPlatform extends EventEmitter {
|
||||
userId: user.id
|
||||
})
|
||||
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({
|
||||
storagePath: this.storagePath,
|
||||
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 () {
|
||||
const q = this._searchQuery
|
||||
if (!q || !this.guild?.guild?.id) return []
|
||||
@@ -1061,8 +1084,11 @@ class PearcordPlatform extends EventEmitter {
|
||||
mesh: out.mesh,
|
||||
meshHitCount: out.meshHitCount || 0,
|
||||
localHitCount: out.localHitCount || 0,
|
||||
scope: 'forum'
|
||||
scope: 'forum',
|
||||
fetchedAt: Date.now(),
|
||||
refreshing: false
|
||||
}
|
||||
this._searchFetchedAt = this._lastSearchMeshMeta.fetchedAt
|
||||
return out.hits
|
||||
}
|
||||
if (this._searchScope === 'guild') {
|
||||
@@ -1073,8 +1099,12 @@ class PearcordPlatform extends EventEmitter {
|
||||
this._lastSearchMeshMeta = {
|
||||
mesh: out.mesh,
|
||||
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 []
|
||||
@@ -4834,12 +4864,42 @@ class PearcordPlatform extends EventEmitter {
|
||||
if (onlineish.has(p.status)) online += 1
|
||||
}
|
||||
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 () {
|
||||
const out = {}
|
||||
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) {
|
||||
this._updateGuildPresenceSummary(this.guild.guild.id)
|
||||
|
||||
Reference in New Issue
Block a user