Refactor home and tag timeline pages

This commit is contained in:
silverpill 2021-12-14 00:47:33 +00:00
parent f0c8018e20
commit 112cf150ba
5 changed files with 82 additions and 85 deletions

View file

@ -0,0 +1,55 @@
<template>
<post-or-repost
v-for="post in posts"
:post="post"
:key="post.id"
@post-deleted="onPostDeleted($event)"
></post-or-repost>
<button
v-if="isPageFull()"
class="btn"
@click="loadNextPage()"
>
Show more posts
</button>
</template>
<script setup lang="ts">
/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { watch } from "vue"
import { PAGE_SIZE } from "@/api/common"
import { Post as PostObject } from "@/api/posts"
import PostOrRepost from "@/components/PostOrRepost.vue"
const props = defineProps<{
posts: PostObject[],
}>()
const emit = defineEmits<{(event: "load-next-page", maxId: string): void}>()
const initialPostCount: number | null = null
watch(() => props.posts.length, (postCount) => {
if (initialPostCount === null) {
initialPostCount = postCount
}
})
function onPostDeleted(postId: string) {
const posts = props.posts
const postIndex = posts.findIndex((post) => post.id === postId)
posts.splice(postIndex, 1)
}
function isPageFull(): boolean {
return initialPostCount === null ? false : initialPostCount >= PAGE_SIZE
}
function loadNextPage() {
let maxId
if (props.posts.length > 0) {
maxId = props.posts[props.posts.length - 1].id
}
emit("load-next-page", maxId)
}
</script>

View file

@ -37,4 +37,8 @@ function onPostDeleted(postId: string) {
.action { .action {
@include post-action; @include post-action;
} }
.post {
margin-bottom: $block-outer-padding;
}
</style> </style>

View file

@ -2,12 +2,12 @@ import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"
import AboutPage from "@/views/About.vue" import AboutPage from "@/views/About.vue"
import AboutPublicPage from "@/views/AboutPublic.vue" import AboutPublicPage from "@/views/AboutPublic.vue"
import HomeTimeline from "@/views/HomeTimeline.vue"
import LandingPage from "../views/LandingPage.vue" import LandingPage from "../views/LandingPage.vue"
import NotificationList from "../views/NotificationList.vue" import NotificationList from "../views/NotificationList.vue"
import ProfileDirectory from "../views/ProfileDirectory.vue" import ProfileDirectory from "../views/ProfileDirectory.vue"
import ProfileView from "@/views/Profile.vue" import ProfileView from "@/views/Profile.vue"
import ProfileForm from "@/views/ProfileForm.vue" import ProfileForm from "@/views/ProfileForm.vue"
import PostList from "@/views/PostList.vue"
import PostDetail from "@/views/PostDetail.vue" import PostDetail from "@/views/PostDetail.vue"
import PostOverlay from "@/views/PostOverlay.vue" import PostOverlay from "@/views/PostOverlay.vue"
import TagTimeline from "@/views/TagTimeline.vue" import TagTimeline from "@/views/TagTimeline.vue"
@ -53,7 +53,7 @@ const routes: Array<RouteRecordRaw> = [
{ {
path: "/home", path: "/home",
name: "home", name: "home",
component: PostList, component: HomeTimeline,
meta: { onlyAuthenticated: true }, meta: { onlyAuthenticated: true },
}, },
{ {

View file

@ -2,19 +2,7 @@
<div id="main"> <div id="main">
<div class="content posts"> <div class="content posts">
<post-editor @post-created="insertPost"></post-editor> <post-editor @post-created="insertPost"></post-editor>
<post-or-repost <post-list :posts="posts" @load-next-page="loadNextPage"></post-list>
v-for="post in posts"
:post="post"
:key="post.id"
@post-deleted="onPostDeleted($event)"
></post-or-repost>
<button
v-if="isPageFull()"
class="btn"
@click="loadNextPage()"
>
Show more posts
</button>
</div> </div>
<sidebar></sidebar> <sidebar></sidebar>
</div> </div>
@ -23,23 +11,22 @@
<script lang="ts"> <script lang="ts">
import { Options, Vue, setup } from "vue-class-component" import { Options, Vue, setup } from "vue-class-component"
import { PAGE_SIZE } from "@/api/common"
import { Post, getHomeTimeline } from "@/api/posts" import { Post, getHomeTimeline } from "@/api/posts"
import Avatar from "@/components/Avatar.vue" import Avatar from "@/components/Avatar.vue"
import PostOrRepost from "@/components/PostOrRepost.vue"
import PostEditor from "@/components/PostEditor.vue" import PostEditor from "@/components/PostEditor.vue"
import PostList from "@/components/PostList.vue"
import Sidebar from "@/components/Sidebar.vue" import Sidebar from "@/components/Sidebar.vue"
import { useCurrentUser } from "@/store/user" import { useCurrentUser } from "@/store/user"
@Options({ @Options({
components: { components: {
Avatar, Avatar,
PostOrRepost,
PostEditor, PostEditor,
PostList,
Sidebar, Sidebar,
}, },
}) })
export default class PostList extends Vue { export default class HomeTimeline extends Vue {
private store = setup(() => { private store = setup(() => {
const { ensureAuthToken } = useCurrentUser() const { ensureAuthToken } = useCurrentUser()
@ -57,28 +44,13 @@ export default class PostList extends Vue {
this.posts = [post, ...this.posts] this.posts = [post, ...this.posts]
} }
onPostDeleted(postId: string) { async loadNextPage(maxId: string) {
const postIndex = this.posts.findIndex((post) => post.id === postId)
this.posts.splice(postIndex, 1)
}
isPageFull(): boolean {
return this.posts.length >= PAGE_SIZE
}
async loadNextPage() {
if (this.posts.length > 0) {
const authToken = this.store.ensureAuthToken() const authToken = this.store.ensureAuthToken()
const posts = await getHomeTimeline( const posts = await getHomeTimeline(authToken, maxId)
authToken,
this.posts[this.posts.length - 1].id,
)
this.posts.push(...posts) this.posts.push(...posts)
} }
}
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -87,8 +59,4 @@ export default class PostList extends Vue {
.post-form { .post-form {
margin-bottom: $block-outer-padding * 2; margin-bottom: $block-outer-padding * 2;
} }
:deep(.post) {
margin-bottom: $block-outer-padding;
}
</style> </style>

View file

@ -1,19 +1,10 @@
<template> <template>
<div id="main"> <div id="main">
<div class="content posts"> <div class="content posts">
<post-or-repost <post-list
v-for="post in posts" :posts="posts"
:post="post" @load-next-page="loadNextPage"
:key="post.id" ></post-list>
@post-deleted="onPostDeleted($event)"
></post-or-repost>
<button
v-if="isPageFull()"
class="btn"
@click="loadNextPage()"
>
Show more posts
</button>
</div> </div>
<sidebar></sidebar> <sidebar></sidebar>
</div> </div>
@ -24,12 +15,10 @@
import { ref, onMounted } from "vue" import { ref, onMounted } from "vue"
import { useRoute } from "vue-router" import { useRoute } from "vue-router"
import { PAGE_SIZE } from "@/api/common"
import { Post, getTagTimeline } from "@/api/posts" import { Post, getTagTimeline } from "@/api/posts"
import PostOrRepost from "@/components/PostOrRepost.vue" import PostList from "@/components/PostList.vue"
import Sidebar from "@/components/Sidebar.vue" import Sidebar from "@/components/Sidebar.vue"
import { useCurrentUser } from "@/store/user" import { useCurrentUser } from "@/store/user"
import { formatDate } from "@/utils/format"
const route = useRoute() const route = useRoute()
const posts = ref<Post[]>([]) const posts = ref<Post[]>([])
@ -42,32 +31,13 @@ onMounted(async () => {
) )
}) })
function onPostDeleted(postId: string) { async function loadNextPage(maxId: string) {
const postIndex = posts.value.findIndex((post) => post.id === postId)
posts.value.splice(postIndex, 1)
}
function isPageFull(): boolean {
return posts.value.length >= PAGE_SIZE
}
async function loadNextPage() {
if (posts.value.length > 0) {
const { authToken } = useCurrentUser() const { authToken } = useCurrentUser()
const newPosts = await getTagTimeline( const newPosts = await getTagTimeline(
authToken.value, authToken.value,
route.params.tagName, route.params.tagName,
posts.value[posts.value.length - 1].id, maxId,
) )
posts.value.push(...newPosts) posts.value.push(...newPosts)
}
} }
</script> </script>
<style scoped lang="scss">
@import "../styles/layout";
:deep(.post) {
margin-bottom: $block-outer-padding;
}
</style>