feat(platform): Phase 125 settings mesh, search, drafts, and folders

- Join settings mesh with per-device swarm keys and unified connection wiring
- clearGuildSearchIndex, searchGuildMessages indexOnly / localIndexOnly mesh leg
- setComposeDraft, reorderServerFolders, view composeDrafts + activeComposeDraft

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-05-22 09:11:38 -04:00
co-authored by Cursor
parent 798fc44462
commit 01c1bdb5bd
+77 -3
View File
@@ -175,6 +175,7 @@ const {
assignGuildToFolder: assignGuildToFolderState,
setFolderCollapsed: setFolderCollapsedState,
renameFolder: renameServerFolderState,
reorderFolders: reorderServerFoldersState,
FOLDER_COLORS
} = require('pearcord-server-folders')
const {
@@ -302,6 +303,7 @@ class PearcordPlatform extends EventEmitter {
this._discoverySwarm = null
this._contactsSwarm = null
this._settingsSwarm = null
this._settingsMeshWired = false
this._devicePairSwarm = null
this._discoveryWired = false
this._archivePeerHealthRefreshedAt = null
@@ -507,10 +509,39 @@ class PearcordPlatform extends EventEmitter {
async _joinSettingsMesh () {
if (!this.onboarded || !this.identity?.keyPair || !this.identity?.user) return
const Hyperswarm = require('hyperswarm')
const b4a = require('b4a')
await this.identity.ensureDeviceSwarmKeyPair()
if (!this._settingsSwarm) {
this._settingsSwarm = new Hyperswarm({ keyPair: this.identity.keyPair })
this._settingsSwarm = new Hyperswarm({
keyPair: this.identity.getDeviceSwarmKeyPair()
})
}
const meshOpts = { deviceId: this.identity.deviceId }
if (!this._settingsMeshWired) {
this._settingsMeshWired = true
const { attachSettingsMesh } = require('pearcord-notifications/mesh')
const { attachUserPrefsMesh } = require('pearcord-settings/mesh')
const { attachProfileCosmeticsMesh } = require('pearcord-profile-cosmetics/mesh')
this._settingsSwarm.on('connection', (conn) => {
const peerId = b4a.toString(conn.remotePublicKey, 'hex')
const wire = (mod, attach) => {
if (!mod) return
const ch = attach(mod, conn)
mod._channels.set(peerId, ch)
mod.emit('peer', { peerId, type: 'join' })
}
wire(this.notifications, attachSettingsMesh)
wire(this.userSettings, attachUserPrefsMesh)
wire(this.profileCosmetics, attachProfileCosmeticsMesh)
conn.on('close', () => {
for (const mod of [this.notifications, this.userSettings, this.profileCosmetics]) {
if (!mod) continue
mod._channels.delete(peerId)
mod.emit('peer', { peerId, type: 'leave' })
}
})
})
}
const meshOpts = { deviceId: this.identity.deviceId, manageListeners: false }
if (this.notifications) {
await this.notifications.joinMesh(this._settingsSwarm, meshOpts)
}
@@ -1145,6 +1176,15 @@ class PearcordPlatform extends EventEmitter {
return idx
}
clearGuildSearchIndex (guildId) {
const id = guildId || this.guild?.guild?.id
if (!id) return false
const idx = new GuildSearchIndex()
this._guildSearchIndexes.set(id, idx)
this._getSearchIndexStore().save(id, idx)
return true
}
async rebuildGuildSearchIndex (guildId) {
const idx = new GuildSearchIndex()
const channels = await this.db.find(COLLECTIONS.CHANNELS, { guildId })
@@ -1204,6 +1244,7 @@ class PearcordPlatform extends EventEmitter {
if (indexed.length) {
return indexed.map((m) => enrichMessageRow({ ...m, channelName: m.channelName }))
}
if (opts.indexOnly) return []
const channels = await this.db.find(COLLECTIONS.CHANNELS, { guildId })
const channelById = new Map(channels.map((c) => [c.id, c]))
const searchable = new Set(
@@ -1259,7 +1300,10 @@ class PearcordPlatform extends EventEmitter {
}
async searchGuildMessagesWithMesh (guildId, query, opts = {}) {
const local = await this.searchGuildMessages(guildId, query, opts)
const local = await this.searchGuildMessages(guildId, query, {
limit: opts.limit,
indexOnly: !!opts.localIndexOnly
})
if (opts.mesh === false || !this.guild?.guild) {
return { hits: local, mesh: false, meshHitCount: 0, localHitCount: local.length }
}
@@ -2355,6 +2399,31 @@ class PearcordPlatform extends EventEmitter {
return true
}
async reorderServerFolders (folderIds = []) {
const state = await this.getServerFolders()
await this._saveServerFolders(reorderServerFoldersState(state, folderIds))
return true
}
async setComposeDraft (channelId, text) {
if (!channelId) throw new Error('channelId required')
const prefs = this.userSettings ? await this.userSettings.getPrefs() : {}
const composeDrafts = { ...(prefs.composeDrafts || {}) }
const trimmed = String(text || '').slice(0, 4000)
if (!trimmed) {
delete composeDrafts[channelId]
} else {
composeDrafts[channelId] = { text: trimmed, updatedAt: now() }
}
return this.updateUserPrefs({ composeDrafts })
}
async getComposeDraftText (channelId) {
if (!channelId || !this.userSettings) return ''
const prefs = await this.userSettings.getPrefs()
return prefs.composeDrafts?.[channelId]?.text || ''
}
async markAllNotificationsRead () {
if (!this.notifications) return 0
return this.notifications.markAllRead()
@@ -8714,6 +8783,10 @@ class PearcordPlatform extends EventEmitter {
? this.getGuildSearchIndexMeta(this.guild.guild.id)
: { persisted: false, rowCount: 0, savedAt: null },
searchIncludeMesh: this._searchIncludeMesh,
composeDrafts: userPrefs?.composeDrafts || {},
activeComposeDraft: this.activeChannelId
? (userPrefs?.composeDrafts?.[this.activeChannelId]?.text || '')
: '',
companionMode: this._companionMode,
readOnly: this._readOnly,
contacts: contactsForView,
@@ -8856,6 +8929,7 @@ class PearcordPlatform extends EventEmitter {
if (this._settingsSwarm) {
await this._settingsSwarm.destroy().catch(() => {})
this._settingsSwarm = null
this._settingsMeshWired = false
}
if (this._discoverySwarm) {
await this._discoverySwarm.destroy().catch(() => {})