feat: Implement sorting of peers by latest message timestamp and unread status in Nostr chat
- Introduce a computed property to sort peers based on the latest message timestamp and unread message count, enhancing the user experience by prioritizing relevant conversations. - Add methods to track and retrieve the latest message timestamp for each peer, ensuring accurate sorting. - Update the ChatComponent to utilize the new sorting logic, improving the display of peers in the chat interface. refactor: Reorganize fuzzy search and mobile detection logic in ChatComponent - Move fuzzy search implementation and mobile detection methods to improve code clarity and maintainability. - Ensure consistent functionality for searching peers by username or pubkey with typo tolerance. - Maintain mobile navigation logic for better user experience on smaller devices.
This commit is contained in:
parent
91e9756bf0
commit
b0101915c7
2 changed files with 91 additions and 23 deletions
|
|
@ -401,6 +401,62 @@ const scrollTarget = ref<HTMLElement | null>(null)
|
||||||
// Mobile detection
|
// Mobile detection
|
||||||
const isMobile = ref(false)
|
const isMobile = ref(false)
|
||||||
|
|
||||||
|
// Nostr chat composable
|
||||||
|
const {
|
||||||
|
isConnected,
|
||||||
|
messages,
|
||||||
|
connect,
|
||||||
|
disconnect,
|
||||||
|
subscribeToPeer,
|
||||||
|
subscribeToPeerForNotifications,
|
||||||
|
sendMessage: sendNostrMessage,
|
||||||
|
onMessageAdded,
|
||||||
|
markMessagesAsRead,
|
||||||
|
getUnreadCount,
|
||||||
|
getTotalUnreadCount,
|
||||||
|
getLatestMessageTimestamp
|
||||||
|
} = useNostrChat()
|
||||||
|
|
||||||
|
// Computed
|
||||||
|
const currentMessages = computed(() => {
|
||||||
|
if (!selectedPeer.value) return []
|
||||||
|
return messages.value.get(selectedPeer.value.pubkey) || []
|
||||||
|
})
|
||||||
|
|
||||||
|
// Sort peers by latest message timestamp (newest first) and unread status
|
||||||
|
const sortedPeers = computed(() => {
|
||||||
|
const sorted = [...peers.value].sort((a, b) => {
|
||||||
|
const aTimestamp = getLatestMessageTimestamp(a.pubkey)
|
||||||
|
const bTimestamp = getLatestMessageTimestamp(b.pubkey)
|
||||||
|
const aUnreadCount = getUnreadCount(a.pubkey)
|
||||||
|
const bUnreadCount = getUnreadCount(b.pubkey)
|
||||||
|
|
||||||
|
// First, sort by unread count (peers with unread messages appear first)
|
||||||
|
if (aUnreadCount > 0 && bUnreadCount === 0) return -1
|
||||||
|
if (aUnreadCount === 0 && bUnreadCount > 0) return 1
|
||||||
|
|
||||||
|
// Then, sort by latest message timestamp (newest first)
|
||||||
|
if (aTimestamp !== bTimestamp) {
|
||||||
|
return bTimestamp - aTimestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, sort alphabetically by username for peers with same timestamp
|
||||||
|
return (a.username || '').localeCompare(b.username || '')
|
||||||
|
})
|
||||||
|
|
||||||
|
// Debug logging (only in development)
|
||||||
|
if (process.env.NODE_ENV === 'development' && sorted.length > 0) {
|
||||||
|
console.log('Sorted peers:', sorted.map(p => ({
|
||||||
|
username: p.username,
|
||||||
|
pubkey: p.pubkey.slice(0, 8) + '...',
|
||||||
|
latestTimestamp: getLatestMessageTimestamp(p.pubkey),
|
||||||
|
unreadCount: getUnreadCount(p.pubkey)
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorted
|
||||||
|
})
|
||||||
|
|
||||||
// Fuzzy search for peers
|
// Fuzzy search for peers
|
||||||
// This integrates the useFuzzySearch composable to provide intelligent search functionality
|
// This integrates the useFuzzySearch composable to provide intelligent search functionality
|
||||||
// for finding peers by username or pubkey with typo tolerance and scoring
|
// for finding peers by username or pubkey with typo tolerance and scoring
|
||||||
|
|
@ -410,7 +466,7 @@ const {
|
||||||
isSearching,
|
isSearching,
|
||||||
resultCount,
|
resultCount,
|
||||||
clearSearch
|
clearSearch
|
||||||
} = useFuzzySearch(peers, {
|
} = useFuzzySearch(sortedPeers, {
|
||||||
fuseOptions: {
|
fuseOptions: {
|
||||||
keys: [
|
keys: [
|
||||||
{ name: 'username', weight: 0.7 }, // Username has higher weight for better UX
|
{ name: 'username', weight: 0.7 }, // Username has higher weight for better UX
|
||||||
|
|
@ -442,27 +498,6 @@ const goBackToPeers = () => {
|
||||||
selectedPeer.value = null
|
selectedPeer.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nostr chat composable
|
|
||||||
const {
|
|
||||||
isConnected,
|
|
||||||
messages,
|
|
||||||
connect,
|
|
||||||
disconnect,
|
|
||||||
subscribeToPeer,
|
|
||||||
subscribeToPeerForNotifications,
|
|
||||||
sendMessage: sendNostrMessage,
|
|
||||||
onMessageAdded,
|
|
||||||
markMessagesAsRead,
|
|
||||||
getUnreadCount,
|
|
||||||
getTotalUnreadCount
|
|
||||||
} = useNostrChat()
|
|
||||||
|
|
||||||
// Computed
|
|
||||||
const currentMessages = computed(() => {
|
|
||||||
if (!selectedPeer.value) return []
|
|
||||||
return messages.value.get(selectedPeer.value.pubkey) || []
|
|
||||||
})
|
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
const loadPeers = async () => {
|
const loadPeers = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,9 @@ export function useNostrChat() {
|
||||||
// Reactive unread counts
|
// Reactive unread counts
|
||||||
const unreadCounts = ref<Map<string, number>>(new Map())
|
const unreadCounts = ref<Map<string, number>>(new Map())
|
||||||
|
|
||||||
|
// Track latest message timestamp for each peer (for sorting)
|
||||||
|
const latestMessageTimestamps = ref<Map<string, number>>(new Map())
|
||||||
|
|
||||||
// Computed
|
// Computed
|
||||||
const isLoggedIn = computed(() => !!currentUser.value)
|
const isLoggedIn = computed(() => !!currentUser.value)
|
||||||
|
|
||||||
|
|
@ -97,6 +100,26 @@ export function useNostrChat() {
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get latest message timestamp for a peer
|
||||||
|
const getLatestMessageTimestamp = (peerPubkey: string): number => {
|
||||||
|
return latestMessageTimestamps.value.get(peerPubkey) || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all latest message timestamps
|
||||||
|
const getAllLatestMessageTimestamps = (): Map<string, number> => {
|
||||||
|
return new Map(latestMessageTimestamps.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update latest message timestamp for a peer
|
||||||
|
const updateLatestMessageTimestamp = (peerPubkey: string, timestamp: number): void => {
|
||||||
|
const currentLatest = latestMessageTimestamps.value.get(peerPubkey) || 0
|
||||||
|
if (timestamp > currentLatest) {
|
||||||
|
latestMessageTimestamps.value.set(peerPubkey, timestamp)
|
||||||
|
// Force reactivity
|
||||||
|
latestMessageTimestamps.value = new Map(latestMessageTimestamps.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update unread count for a peer
|
// Update unread count for a peer
|
||||||
const updateUnreadCount = (peerPubkey: string, count: number): void => {
|
const updateUnreadCount = (peerPubkey: string, count: number): void => {
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
|
|
@ -584,6 +607,9 @@ export function useNostrChat() {
|
||||||
// Force reactivity by triggering a change
|
// Force reactivity by triggering a change
|
||||||
messages.value = new Map(messages.value)
|
messages.value = new Map(messages.value)
|
||||||
|
|
||||||
|
// Update latest message timestamp for this peer (for sorting)
|
||||||
|
updateLatestMessageTimestamp(peerPubkey, message.created_at)
|
||||||
|
|
||||||
// Track unread messages (only for received messages, not sent ones)
|
// Track unread messages (only for received messages, not sent ones)
|
||||||
if (!isSentByMe) {
|
if (!isSentByMe) {
|
||||||
const unreadData = getUnreadData(peerPubkey)
|
const unreadData = getUnreadData(peerPubkey)
|
||||||
|
|
@ -748,6 +774,9 @@ export function useNostrChat() {
|
||||||
// Force reactivity by triggering a change
|
// Force reactivity by triggering a change
|
||||||
messages.value = new Map(messages.value)
|
messages.value = new Map(messages.value)
|
||||||
|
|
||||||
|
// Update latest message timestamp for this peer (for sorting)
|
||||||
|
updateLatestMessageTimestamp(peerPubkey, message.created_at)
|
||||||
|
|
||||||
// Trigger callback if set
|
// Trigger callback if set
|
||||||
if (onMessageAdded.value) {
|
if (onMessageAdded.value) {
|
||||||
onMessageAdded.value(peerPubkey)
|
onMessageAdded.value(peerPubkey)
|
||||||
|
|
@ -792,6 +821,10 @@ export function useNostrChat() {
|
||||||
getTotalUnreadCount,
|
getTotalUnreadCount,
|
||||||
clearAllUnreadCounts,
|
clearAllUnreadCounts,
|
||||||
clearProcessedMessageIds,
|
clearProcessedMessageIds,
|
||||||
debugUnreadData
|
debugUnreadData,
|
||||||
|
|
||||||
|
// Timestamp methods (for sorting)
|
||||||
|
getLatestMessageTimestamp,
|
||||||
|
getAllLatestMessageTimestamps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue