forked from Mirrors/elk
feat: following (#22)
This commit is contained in:
parent
f97920d9d2
commit
9aa7243d43
4 changed files with 46 additions and 5 deletions
|
@ -1,9 +1,26 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Account } from 'masto'
|
import type { Account } from 'masto'
|
||||||
|
|
||||||
defineProps<{
|
const { account, following } = defineProps<{
|
||||||
account: Account
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -11,8 +28,8 @@ defineProps<{
|
||||||
<AccountInfo :account="account" p3 />
|
<AccountInfo :account="account" p3 />
|
||||||
<div h-full p5>
|
<div h-full p5>
|
||||||
<!-- TODO is following logic and actions -->
|
<!-- 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-if="isFollowing === true" color-purple hover:color-gray hover:cursor-pointer i-ri:user-unfollow-fill @click="unfollow" />
|
||||||
<div v-else color-gray hover:color-purple hover:cursor-pointer i-ri:user-follow-fill />
|
<div v-else-if="isFollowing === false" color-gray hover:color-purple hover:cursor-pointer i-ri:user-follow-fill @click="follow" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -4,16 +4,30 @@ import type { Account, Paginator } from 'masto'
|
||||||
const { paginator } = defineProps<{
|
const { paginator } = defineProps<{
|
||||||
paginator: Paginator<any, Account[]>
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CommonPaginator
|
<CommonPaginator
|
||||||
:paginator="paginator"
|
:paginator="paginator"
|
||||||
border="t border"
|
border="t border"
|
||||||
|
@items="onNewItems"
|
||||||
>
|
>
|
||||||
<template #default="{ item }">
|
<template #default="{ item }">
|
||||||
<AccountCard
|
<AccountCard
|
||||||
:account="item"
|
:account="item"
|
||||||
|
:following="metadataMap[item.id]?.following"
|
||||||
border="b border" py-1
|
border="b border" py-1
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { Ref } from 'vue'
|
||||||
import type { Paginator } from 'masto'
|
import type { Paginator } from 'masto'
|
||||||
|
|
||||||
const { paginator, keyProp = 'id' } = defineProps<{
|
const { paginator, keyProp = 'id' } = defineProps<{
|
||||||
|
@ -6,7 +7,13 @@ const { paginator, keyProp = 'id' } = defineProps<{
|
||||||
keyProp?: string
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import type { PaginatorState } from '~/types'
|
||||||
export function usePaginator<T>(paginator: Paginator<any, T[]>) {
|
export function usePaginator<T>(paginator: Paginator<any, T[]>) {
|
||||||
const state = ref<PaginatorState>('idle')
|
const state = ref<PaginatorState>('idle')
|
||||||
const items = ref<T[]>([])
|
const items = ref<T[]>([])
|
||||||
|
const newItems = ref<T[]>([])
|
||||||
|
|
||||||
const endAnchor = ref<HTMLDivElement>()
|
const endAnchor = ref<HTMLDivElement>()
|
||||||
const bound = reactive(useElementBounding(endAnchor))
|
const bound = reactive(useElementBounding(endAnchor))
|
||||||
|
@ -19,7 +20,8 @@ export function usePaginator<T>(paginator: Paginator<any, T[]>) {
|
||||||
const result = await paginator.next()
|
const result = await paginator.next()
|
||||||
|
|
||||||
if (result.value?.length) {
|
if (result.value?.length) {
|
||||||
items.value.push(...result.value)
|
newItems.value = result.value
|
||||||
|
items.value.push(...newItems.value)
|
||||||
state.value = 'idle'
|
state.value = 'idle'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -50,6 +52,7 @@ export function usePaginator<T>(paginator: Paginator<any, T[]>) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items,
|
items,
|
||||||
|
newItems,
|
||||||
state,
|
state,
|
||||||
error,
|
error,
|
||||||
endAnchor,
|
endAnchor,
|
||||||
|
|
Loading…
Reference in a new issue