fedimovies-web/src/views/NotificationList.vue
2022-05-18 18:14:47 +00:00

172 lines
5.2 KiB
Vue

<template>
<div id="main">
<div class="content">
<div
class="notification"
v-for="(notification, index) in notifications"
:key="notification.id"
>
<div class="action">
<template v-if="notification.type === 'follow'">
<img :src="require('@/assets/feather/user-plus.svg')">
<router-link :to="{ name: 'profile', params: { profileId: notification.account.id }}">
{{ getSenderName(notification) }}
</router-link>
<span>followed you</span>
</template>
<template v-else-if="notification.type === 'reply'">
<img :src="require('@/assets/forkawesome/comment-o.svg')">
<router-link :to="{ name: 'profile', params: { profileId: notification.account.id }}">
{{ getSenderName(notification) }}
</router-link>
<span>replied to your post</span>
</template>
<template v-else-if="notification.type === 'favourite'">
<img :src="require('@/assets/forkawesome/thumbs-o-up.svg')">
<router-link :to="{ name: 'profile', params: { profileId: notification.account.id }}">
{{ getSenderName(notification) }}
</router-link>
<span>liked your post</span>
</template>
<template v-else-if="notification.type === 'mention'">
<img :src="require('@/assets/forkawesome/comment-o.svg')">
<router-link :to="{ name: 'profile', params: { profileId: notification.account.id }}">
{{ getSenderName(notification) }}
</router-link>
<span>mentioned you</span>
</template>
<template v-else-if="notification.type === 'reblog'">
<img :src="require('@/assets/feather/repeat.svg')">
<router-link :to="{ name: 'profile', params: { profileId: notification.account.id }}">
{{ getSenderName(notification) }}
</router-link>
<span>reposted your post</span>
</template>
</div>
<post
v-if="notification.status"
:post="notification.status"
@post-deleted="onPostDeleted(index)"
></post>
<router-link
v-else
class="profile"
:to="{ name: 'profile', params: { profileId: notification.account.id }}"
>
<div class="floating-avatar">
<avatar :profile="notification.account"></avatar>
</div>
<div class="display-name">{{ getSenderName(notification) }}</div>
<div class="actor-address">@{{ getActorAddress(notification.account) }}</div>
<div class="timestamp">{{ formatDate(notification.created_at) }}</div>
</router-link>
</div>
<button
v-if="isPageFull()"
class="btn"
@click="loadNextPage()"
>
Show more notifications
</button>
</div>
<sidebar></sidebar>
</div>
</template>
<script setup lang="ts">
/* eslint-disable no-unused-vars */
import { ref, onMounted } from "vue"
import { PAGE_SIZE } from "@/api/common"
import { updateNotificationMarker } from "@/api/markers"
import { getNotifications } from "@/api/notifications"
import Avatar from "@/components/Avatar.vue"
import Post from "@/components/Post.vue"
import Sidebar from "@/components/Sidebar.vue"
import { useInstanceInfo } from "@/store/instance"
import { useNotifications } from "@/store/notifications"
import { useCurrentUser } from "@/store/user"
import { formatDate } from "@/utils/format"
const { ensureAuthToken } = useCurrentUser()
const { getActorAddress } = useInstanceInfo()
const { notifications } = useNotifications()
onMounted(async () => {
// Update notification timeline marker
const firstNotification = notifications.value[0]
if (firstNotification) {
await updateNotificationMarker(
ensureAuthToken(),
firstNotification.id,
)
}
})
function getSenderName(notification: Notification): string {
const sender = notification.account
return sender.display_name || sender.username
}
function onPostDeleted(notificationIndex: number) {
notifications.value.splice(notificationIndex, 1)
}
function isPageFull(): boolean {
return notifications.value.length >= PAGE_SIZE
}
async function loadNextPage() {
const maxId = notifications.value[notifications.value.length - 1].id
const newItems = await getNotifications(ensureAuthToken(), maxId)
notifications.value.push(...newItems)
}
</script>
<style scoped lang="scss">
@import "../styles/layout";
@import "../styles/mixins";
@import "../styles/theme";
.notification {
margin-bottom: $block-outer-padding;
}
.action {
@include post-action;
}
.profile {
align-items: center;
background-color: $block-background-color;
border-radius: $block-border-radius;
box-sizing: border-box;
display: flex;
gap: $block-inner-padding / 2;
padding: $block-inner-padding;
.floating-avatar {
@include floating-avatar;
}
.display-name {
color: $text-color;
font-weight: bold;
}
.actor-address {
color: $secondary-text-color;
flex-grow: 1;
}
.timestamp {
color: $secondary-text-color;
text-align: right;
white-space: nowrap;
&:hover {
color: $secondary-text-hover-color;
}
}
}
</style>