feat(platform): Phase 134 thread pin/mute and discovery diff banner (v0.8.99)
- toggleThreadPinned and setThreadNotificationMuted APIs - _wireDiscoveryEvents at init; discoveryDiffHint on listing ingest - Pass pinned/muted maps into buildThreadsPanel Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -327,6 +327,9 @@ class PearcordPlatform extends EventEmitter {
|
||||
this._threadsPanelParentFilter = null
|
||||
this._threadsPanelSort = 'activity'
|
||||
this._discoveryMeshRefreshAt = 0
|
||||
this._discoveryDiffHint = null
|
||||
this._discoveryDiffUntil = 0
|
||||
this._discoveryListingIds = new Set()
|
||||
this._readOnly = opts.readOnly === true
|
||||
this._companionMode = opts.companionMode === true || opts.readOnly === true
|
||||
this._discoveryFilter = { query: '', sort: 'newest', minMembers: 0, tag: '' }
|
||||
@@ -355,6 +358,7 @@ class PearcordPlatform extends EventEmitter {
|
||||
await this.moderation.ready()
|
||||
this.discovery = new PearcordDiscovery({ storagePath: this.storagePath })
|
||||
await this.discovery.ready()
|
||||
this._wireDiscoveryEvents()
|
||||
this.embeds = new PearcordEmbed({ storagePath: this.storagePath })
|
||||
await this.embeds.ready()
|
||||
this.botLimits = new BotRateLimits({ storagePath: this.storagePath })
|
||||
@@ -453,6 +457,7 @@ class PearcordPlatform extends EventEmitter {
|
||||
await this.moderation.ready()
|
||||
this.discovery = new PearcordDiscovery({ storagePath: this.storagePath })
|
||||
await this.discovery.ready()
|
||||
this._wireDiscoveryEvents()
|
||||
this.embeds = new PearcordEmbed({ storagePath: this.storagePath })
|
||||
await this.embeds.ready()
|
||||
this.botLimits = new BotRateLimits({ storagePath: this.storagePath })
|
||||
@@ -506,6 +511,9 @@ class PearcordPlatform extends EventEmitter {
|
||||
this._threadsPanelParentFilter = null
|
||||
this._threadsPanelSort = 'activity'
|
||||
this._discoveryMeshRefreshAt = 0
|
||||
this._discoveryDiffHint = null
|
||||
this._discoveryDiffUntil = 0
|
||||
this._discoveryListingIds = new Set()
|
||||
this.guilds = await this.listGuilds()
|
||||
void this._finishSessionStartup()
|
||||
this.emit('user', user)
|
||||
@@ -582,25 +590,38 @@ class PearcordPlatform extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
_wireDiscoveryEvents () {
|
||||
if (!this.discovery || this._discoveryWired) return
|
||||
this._discoveryWired = true
|
||||
this.discovery.on('listing', (row) => {
|
||||
this._noteDiscoveryListingDelta(row)
|
||||
this.emit('discovery')
|
||||
})
|
||||
this.discovery.on('listing-prune', ({ removed }) => {
|
||||
if (removed > 0) {
|
||||
this._discoveryDiffHint = `${removed} stale listing${removed === 1 ? '' : 's'} pruned`
|
||||
this._discoveryDiffUntil = Date.now() + 8000
|
||||
}
|
||||
this.emit('discovery')
|
||||
})
|
||||
this.discovery.on('peer', ({ type }) => {
|
||||
this.emit('discovery')
|
||||
if (type === 'join') {
|
||||
setTimeout(() => this._refreshDiscoveryAnnouncements().catch(() => {}), 600)
|
||||
}
|
||||
})
|
||||
this.discovery.on('hub-post', (p) => {
|
||||
this._ingestAnnouncementHubPost(p).catch(() => {})
|
||||
})
|
||||
}
|
||||
|
||||
async _joinDiscoveryMesh () {
|
||||
if (!this.discovery || !this.onboarded || !this.identity?.keyPair) return
|
||||
const Hyperswarm = require('hyperswarm')
|
||||
if (!this._discoverySwarm) {
|
||||
this._discoverySwarm = new Hyperswarm({ keyPair: this.identity.keyPair })
|
||||
}
|
||||
if (!this._discoveryWired) {
|
||||
this._discoveryWired = true
|
||||
this.discovery.on('listing', () => this.emit('discovery'))
|
||||
this.discovery.on('peer', ({ type }) => {
|
||||
this.emit('discovery')
|
||||
if (type === 'join') {
|
||||
setTimeout(() => this._refreshDiscoveryAnnouncements().catch(() => {}), 600)
|
||||
}
|
||||
})
|
||||
this.discovery.on('hub-post', (p) => {
|
||||
this._ingestAnnouncementHubPost(p).catch(() => {})
|
||||
})
|
||||
}
|
||||
this._wireDiscoveryEvents()
|
||||
await this.discovery.joinMesh(this._discoverySwarm)
|
||||
await this._refreshDiscoveryAnnouncements().catch(() => {})
|
||||
}
|
||||
@@ -1150,6 +1171,21 @@ class PearcordPlatform extends EventEmitter {
|
||||
return { ...this._discoveryFilter }
|
||||
}
|
||||
|
||||
_noteDiscoveryListingDelta (row) {
|
||||
if (!row?.id) {
|
||||
this._discoveryDiffHint = 'Discovery listings updated'
|
||||
this._discoveryDiffUntil = Date.now() + 8000
|
||||
return
|
||||
}
|
||||
const isNew = !this._discoveryListingIds.has(row.id)
|
||||
this._discoveryListingIds.add(row.id)
|
||||
const name = row.name || 'Server'
|
||||
this._discoveryDiffHint = isNew
|
||||
? `New public listing: ${name}`
|
||||
: `Listing updated: ${name}`
|
||||
this._discoveryDiffUntil = Date.now() + 8000
|
||||
}
|
||||
|
||||
/** Prune stale cache and re-broadcast listings on discovery mesh (Explore refresh). */
|
||||
async refreshDiscoveryListingsFromMesh () {
|
||||
if (!this.discovery) return { synced: 0, pruned: 0 }
|
||||
@@ -8138,6 +8174,28 @@ class PearcordPlatform extends EventEmitter {
|
||||
return { panelSort: this._threadsPanelSort }
|
||||
}
|
||||
|
||||
async toggleThreadPinned (threadId) {
|
||||
if (!threadId || !this.userSettings) throw new Error('threadId required')
|
||||
const prefs = await this.userSettings.getPrefs()
|
||||
const ids = new Set(prefs.pinnedThreadIds || [])
|
||||
if (ids.has(threadId)) ids.delete(threadId)
|
||||
else ids.add(threadId)
|
||||
await this.updateUserPrefs({ pinnedThreadIds: [...ids] })
|
||||
this.emit('channel')
|
||||
return { threadId, pinned: ids.has(threadId) }
|
||||
}
|
||||
|
||||
async setThreadNotificationMuted (threadId, muted = true) {
|
||||
if (!threadId || !this.notifications) throw new Error('threadId required')
|
||||
const prefs = await this.notifications.getPrefs()
|
||||
const ids = new Set(prefs.mutedChannelIds || [])
|
||||
if (muted) ids.add(threadId)
|
||||
else ids.delete(threadId)
|
||||
await this.notifications.setPrefs({ mutedChannelIds: [...ids] })
|
||||
this.emit('channel')
|
||||
return { threadId, muted: ids.has(threadId) }
|
||||
}
|
||||
|
||||
async archiveThread (threadId, archived = true) {
|
||||
if (!this.guild?.guild) throw new Error('no guild')
|
||||
const channels = await this.guild.listChannels()
|
||||
@@ -8570,6 +8628,23 @@ class PearcordPlatform extends EventEmitter {
|
||||
if (root) threadRootMessages[ch.rootMessageId] = root
|
||||
}
|
||||
}
|
||||
const userPrefsForThreads = this.userSettings
|
||||
? await this.userSettings.getPrefs()
|
||||
: { pinnedThreadIds: [] }
|
||||
const notifPrefsForThreads = this.notifications
|
||||
? await this.notifications.getPrefs()
|
||||
: { mutedChannelIds: [] }
|
||||
const pinnedThreadMap = Object.fromEntries(
|
||||
(userPrefsForThreads.pinnedThreadIds || []).map((id) => [id, true])
|
||||
)
|
||||
const mutedThreadMap = Object.fromEntries(
|
||||
(notifPrefsForThreads.mutedChannelIds || []).map((id) => [id, true])
|
||||
)
|
||||
if (publicListings?.length) {
|
||||
for (const row of publicListings) {
|
||||
if (row?.id) this._discoveryListingIds.add(row.id)
|
||||
}
|
||||
}
|
||||
const threadsPanel = this.mode === 'guild' && guild
|
||||
? buildThreadsPanel({
|
||||
channels,
|
||||
@@ -8582,7 +8657,9 @@ class PearcordPlatform extends EventEmitter {
|
||||
includeArchived: this._threadsPanelIncludeArchived,
|
||||
threadFilter: this._threadsPanelFilter,
|
||||
parentFilterChannelId: this._threadsPanelParentFilter,
|
||||
panelSort: this._threadsPanelSort
|
||||
panelSort: this._threadsPanelSort,
|
||||
pinnedThreadIds: pinnedThreadMap,
|
||||
mutedChannelIds: mutedThreadMap
|
||||
})
|
||||
: null
|
||||
const activeChannel = channels.find((c) => c.id === this.activeChannelId) || null
|
||||
@@ -9056,6 +9133,9 @@ class PearcordPlatform extends EventEmitter {
|
||||
threadsPanelFilter: this._threadsPanelFilter,
|
||||
threadsPanelSort: this._threadsPanelSort,
|
||||
discoveryMeshRefreshAt: this._discoveryMeshRefreshAt,
|
||||
discoveryDiffHint:
|
||||
this._discoveryDiffUntil > Date.now() ? this._discoveryDiffHint : null,
|
||||
discoveryDiffUntil: this._discoveryDiffUntil,
|
||||
threadsPanelParentFilter: this._threadsPanelParentFilter,
|
||||
threadTypingByParent,
|
||||
forumPosts,
|
||||
|
||||
Reference in New Issue
Block a user