conversation composable + virtual scrolling for trees (somewhat)
This commit is contained in:
parent
218c2ca561
commit
a24d2a1bba
6 changed files with 259 additions and 168 deletions
124
src/composables/useConversation.js
Normal file
124
src/composables/useConversation.js
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
import { get } from 'lodash-es'
|
||||
import { computed, provide, ref } from 'vue'
|
||||
|
||||
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||
import { useStatusesStore } from 'src/stores/statuses.js'
|
||||
|
||||
import {
|
||||
fetchConversation as apiFetchConversation,
|
||||
fetchStatus as apiFetchStatus,
|
||||
} from 'src/api/public.js'
|
||||
|
||||
export function useConversation(statusId, expanded) {
|
||||
const getStatusObject = (id) => useStatusesStore().allStatuses.get(id)
|
||||
const getConversationId = (statusId) => {
|
||||
const status = getStatusObject(statusId)
|
||||
return get(
|
||||
status,
|
||||
'retweeted_status.statusnet_conversation_id',
|
||||
get(status, 'statusnet_conversation_id'),
|
||||
)
|
||||
}
|
||||
|
||||
const loadError = ref(null)
|
||||
const currentStatus = computed(() => getStatusObject(statusId.value))
|
||||
|
||||
const sortById = (a, b) => {
|
||||
const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id
|
||||
const idB = b.type === 'retweet' ? b.retweeted_status.id : b.id
|
||||
const seqA = Number(idA)
|
||||
const seqB = Number(idB)
|
||||
const isSeqA = !Number.isNaN(seqA)
|
||||
const isSeqB = !Number.isNaN(seqB)
|
||||
if (isSeqA && isSeqB) {
|
||||
return seqA < seqB ? -1 : 1
|
||||
} else if (isSeqA && !isSeqB) {
|
||||
return -1
|
||||
} else if (!isSeqA && isSeqB) {
|
||||
return 1
|
||||
} else {
|
||||
return idA < idB ? -1 : 1
|
||||
}
|
||||
}
|
||||
const conversationId = computed(() => getConversationId(statusId.value))
|
||||
const conversation = computed(() => {
|
||||
if (!currentStatus.value) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (!expanded.value) {
|
||||
return [currentStatus.value]
|
||||
}
|
||||
|
||||
const conversation = useStatusesStore().conversations.get(
|
||||
conversationId.value,
|
||||
)
|
||||
|
||||
return [...conversation.keys()]
|
||||
.map((k) => useStatusesStore().allStatuses.get(k))
|
||||
.filter((status) => status.type != 'repeat') // Old backend behavior?
|
||||
.toSorted(sortById)
|
||||
})
|
||||
const replies = computed(() =>
|
||||
conversation.value.reduce(
|
||||
(result, { id, in_reply_to_status_id: irid }, index) => {
|
||||
if (irid) {
|
||||
if (!result.has(irid)) {
|
||||
result.set(irid, new Set())
|
||||
}
|
||||
result.get(irid).add({
|
||||
name: `#${index}`,
|
||||
id,
|
||||
})
|
||||
}
|
||||
return result
|
||||
},
|
||||
new Map(),
|
||||
),
|
||||
)
|
||||
const getReplies = (id) => replies.value.get(id) ?? new Set()
|
||||
provide('conversation', conversation)
|
||||
provide('replies', replies)
|
||||
|
||||
const fetchConversation = async () => {
|
||||
if (currentStatus.value) {
|
||||
const {
|
||||
data: { ancestors, descendants },
|
||||
timestamp,
|
||||
} = await apiFetchConversation({
|
||||
id: statusId.value,
|
||||
credentials: useOAuthStore().token,
|
||||
})
|
||||
|
||||
useStatusesStore().addNewStatuses({ statuses: ancestors, timestamp })
|
||||
useStatusesStore().addNewStatuses({
|
||||
statuses: descendants,
|
||||
timestamp,
|
||||
})
|
||||
} else {
|
||||
try {
|
||||
loadError.value = null
|
||||
|
||||
const { data: status } = await apiFetchStatus({
|
||||
id: statusId.value,
|
||||
credentials: useOAuthStore().token,
|
||||
})
|
||||
|
||||
useStatusesStore().addNewStatuses({ statuses: [status] })
|
||||
fetchConversation()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
loadError.value = error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
currentStatus,
|
||||
conversation,
|
||||
replies,
|
||||
getReplies,
|
||||
fetchConversation,
|
||||
loadError,
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue