feat: following (#22)
parent
f97920d9d2
commit
9aa7243d43
|
@ -1,9 +1,26 @@
|
|||
<script setup lang="ts">
|
||||
import type { Account } from 'masto'
|
||||
|
||||
defineProps<{
|
||||
const { account, following } = defineProps<{
|
||||
account: Account
|
||||
following?: boolean
|
||||
}>()
|
||||
|
||||
const masto = await useMasto()
|
||||
|
||||
let isFollowing = $ref<boolean | undefined>(following)
|
||||
watch($$(following), () => {
|
||||
isFollowing = following
|
||||
})
|
||||
|
||||
function unfollow() {
|
||||
masto.accounts.unfollow(account.id)
|
||||
isFollowing = false
|
||||
}
|
||||
function follow() {
|
||||
masto.accounts.follow(account.id)
|
||||
isFollowing = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -11,8 +28,8 @@ defineProps<{
|
|||
<AccountInfo :account="account" p3 />
|
||||
<div h-full p5>
|
||||
<!-- TODO is following logic and actions -->
|
||||
<div v-if="false" color-purple hover:color-gray hover:cursor-pointer i-ri:user-unfollow-fill />
|
||||
<div v-else color-gray hover:color-purple hover:cursor-pointer i-ri:user-follow-fill />
|
||||
<div v-if="isFollowing === true" color-purple hover:color-gray hover:cursor-pointer i-ri:user-unfollow-fill @click="unfollow" />
|
||||
<div v-else-if="isFollowing === false" color-gray hover:color-purple hover:cursor-pointer i-ri:user-follow-fill @click="follow" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -4,16 +4,30 @@ import type { Account, Paginator } from 'masto'
|
|||
const { paginator } = defineProps<{
|
||||
paginator: Paginator<any, Account[]>
|
||||
}>()
|
||||
|
||||
const masto = await useMasto()
|
||||
|
||||
const metadataMap = $ref<{ [key: string]: { following?: boolean } }>({})
|
||||
async function onNewItems(items: Account[]) {
|
||||
for (const item of items)
|
||||
metadataMap[item.id] = { following: undefined }
|
||||
|
||||
const relationships = await masto.accounts.fetchRelationships(items.map(item => item.id))
|
||||
for (const rel of relationships)
|
||||
metadataMap[rel.id].following = rel.following
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CommonPaginator
|
||||
:paginator="paginator"
|
||||
border="t border"
|
||||
@items="onNewItems"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<AccountCard
|
||||
:account="item"
|
||||
:following="metadataMap[item.id]?.following"
|
||||
border="b border" py-1
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import type { Ref } from 'vue'
|
||||
import type { Paginator } from 'masto'
|
||||
|
||||
const { paginator, keyProp = 'id' } = defineProps<{
|
||||
|
@ -6,7 +7,13 @@ const { paginator, keyProp = 'id' } = defineProps<{
|
|||
keyProp?: string
|
||||
}>()
|
||||
|
||||
const { items, state, endAnchor, error } = usePaginator(paginator)
|
||||
const emit = defineEmits(['items'])
|
||||
|
||||
const { items, newItems, state, endAnchor, error } = usePaginator(paginator)
|
||||
|
||||
watch(newItems, () => {
|
||||
emit('items', newItems.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -4,6 +4,7 @@ import type { PaginatorState } from '~/types'
|
|||
export function usePaginator<T>(paginator: Paginator<any, T[]>) {
|
||||
const state = ref<PaginatorState>('idle')
|
||||
const items = ref<T[]>([])
|
||||
const newItems = ref<T[]>([])
|
||||
|
||||
const endAnchor = ref<HTMLDivElement>()
|
||||
const bound = reactive(useElementBounding(endAnchor))
|
||||
|
@ -19,7 +20,8 @@ export function usePaginator<T>(paginator: Paginator<any, T[]>) {
|
|||
const result = await paginator.next()
|
||||
|
||||
if (result.value?.length) {
|
||||
items.value.push(...result.value)
|
||||
newItems.value = result.value
|
||||
items.value.push(...newItems.value)
|
||||
state.value = 'idle'
|
||||
}
|
||||
else {
|
||||
|
@ -50,6 +52,7 @@ export function usePaginator<T>(paginator: Paginator<any, T[]>) {
|
|||
|
||||
return {
|
||||
items,
|
||||
newItems,
|
||||
state,
|
||||
error,
|
||||
endAnchor,
|
||||
|
|
Loading…
Reference in New Issue