fix: gallery posts not show & fix types

This commit is contained in:
Lhcfl 2024-04-12 00:22:49 +08:00
parent ef94ba1474
commit d8b4eb6f5e
7 changed files with 93 additions and 27 deletions

View file

@ -19,7 +19,9 @@ export const GalleryPostRepository = db.getRepository(GalleryPost).extend({
createdAt: post.createdAt.toISOString(), createdAt: post.createdAt.toISOString(),
updatedAt: post.updatedAt.toISOString(), updatedAt: post.updatedAt.toISOString(),
userId: post.userId, userId: post.userId,
user: Users.pack(post.user || post.userId, me), user: Users.pack(post.user || post.userId, me, {
detail: true,
}),
title: post.title, title: post.title,
description: post.description, description: post.description,
fileIds: post.fileIds, fileIds: post.fileIds,

View file

@ -38,7 +38,7 @@ export const packedGalleryPostSchema = {
}, },
user: { user: {
type: "object", type: "object",
ref: "UserLite", ref: "UserDetailed",
optional: false, optional: false,
nullable: false, nullable: false,
}, },
@ -79,5 +79,15 @@ export const packedGalleryPostSchema = {
optional: false, optional: false,
nullable: false, nullable: false,
}, },
isLiked: {
type: "boolean",
optional: true,
nullable: false,
},
likedCount: {
type: "number",
optional: false,
nullable: false,
},
}, },
} as const; } as const;

View file

@ -2,10 +2,24 @@
<MkA :to="`/gallery/${post.id}`" class="ttasepnz _panel"> <MkA :to="`/gallery/${post.id}`" class="ttasepnz _panel">
<div class="thumbnail"> <div class="thumbnail">
<ImgWithBlurhash <ImgWithBlurhash
v-if="post.files && post.files.length > 0"
class="img" class="img"
:src="post.files[0].thumbnailUrl" :src="post.files[0].thumbnailUrl"
:hash="post.files[0].blurhash" :hash="post.files[0].blurhash"
/> />
<div
v-else
class="_fullinfo"
>
<!-- If there is no picture
This can happen if the user deletes the image in the drive
-->
<img
src="/static-assets/badges/not-found.webp"
class="img"
:alt="i18n.ts.notFound"
/>
</div>
</div> </div>
<article> <article>
<header> <header>
@ -20,9 +34,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import ImgWithBlurhash from "@/components/MkImgWithBlurhash.vue"; import ImgWithBlurhash from "@/components/MkImgWithBlurhash.vue";
import { i18n } from "@/i18n";
import type { entities } from "firefish-js";
const props = defineProps<{ defineProps<{
post: any; post: entities.GalleryPost;
}>(); }>();
</script> </script>

View file

@ -22,7 +22,7 @@
<div class="body _block"> <div class="body _block">
<div class="title">{{ post.title }}</div> <div class="title">{{ post.title }}</div>
<div class="description"> <div class="description">
<Mfm :text="post.description" /> <Mfm :text="post.description || ''" />
</div> </div>
<div class="info"> <div class="info">
<i :class="icon('ph-clock')"></i> <i :class="icon('ph-clock')"></i>
@ -59,7 +59,7 @@
<div class="other"> <div class="other">
<button <button
v-if=" v-if="
isSignedIn && me.id === post.user.id isSignedIn && me!.id === post.user.id
" "
v-tooltip="i18n.ts.toEdit" v-tooltip="i18n.ts.toEdit"
v-click-anime v-click-anime
@ -105,7 +105,7 @@
<MkAcct :user="post.user" /> <MkAcct :user="post.user" />
</div> </div>
<MkFollowButton <MkFollowButton
v-if="!me || me.id != post.user.id" v-if="!isSignedIn || me!.id != post.user.id"
:user="post.user" :user="post.user"
:inline="true" :inline="true"
:transparent="false" :transparent="false"
@ -140,7 +140,7 @@
</MkPagination> </MkPagination>
</MkContainer> </MkContainer>
</div> </div>
<MkError v-else-if="error" @retry="fetch()" /> <MkError v-else-if="error" @retry="fetchPost()" />
<MkLoading v-else /> <MkLoading v-else />
</transition> </transition>
</div> </div>
@ -163,7 +163,8 @@ import { definePageMetadata } from "@/scripts/page-metadata";
import { shareAvailable } from "@/scripts/share-available"; import { shareAvailable } from "@/scripts/share-available";
import { defaultStore } from "@/store"; import { defaultStore } from "@/store";
import icon from "@/scripts/icon"; import icon from "@/scripts/icon";
import { isSignedIn } from "@/me"; import { isSignedIn, me } from "@/me";
import type { entities } from "firefish-js";
const router = useRouter(); const router = useRouter();
@ -171,18 +172,19 @@ const props = defineProps<{
postId: string; postId: string;
}>(); }>();
const post = ref(null); const post = ref<entities.GalleryPost | null>(null);
const error = ref(null); const error = ref(null);
const otherPostsPagination = { const otherPostsPagination = {
endpoint: "users/gallery/posts" as const, endpoint: "users/gallery/posts" as const,
limit: 6, limit: 6,
params: computed(() => ({ params: computed(() => ({
userId: post.value.user.id, userId: post.value!.user.id,
})), })),
}; };
function fetchPost() { function fetchPost() {
post.value = null; post.value = null;
error.value = null;
os.api("gallery/posts/show", { os.api("gallery/posts/show", {
postId: props.postId, postId: props.postId,
}) })
@ -196,15 +198,15 @@ function fetchPost() {
function share() { function share() {
navigator.share({ navigator.share({
title: post.value.title, title: post.value!.title,
text: post.value.description, text: post.value!.description || undefined,
url: `${url}/gallery/${post.value.id}`, url: `${url}/gallery/${post.value!.id}`,
}); });
} }
function shareWithNote() { function shareWithNote() {
os.post({ os.post({
initialText: `${post.value.title} ${url}/gallery/${post.value.id}`, initialText: `${post.value!.title} ${url}/gallery/${post.value!.id}`,
}); });
} }
@ -212,8 +214,8 @@ function like() {
os.api("gallery/posts/like", { os.api("gallery/posts/like", {
postId: props.postId, postId: props.postId,
}).then(() => { }).then(() => {
post.value.isLiked = true; post.value!.isLiked = true;
post.value.likedCount++; post.value!.likedCount++;
}); });
} }
@ -221,13 +223,13 @@ async function unlike() {
os.api("gallery/posts/unlike", { os.api("gallery/posts/unlike", {
postId: props.postId, postId: props.postId,
}).then(() => { }).then(() => {
post.value.isLiked = false; post.value!.isLiked = false;
post.value.likedCount--; post.value!.likedCount--;
}); });
} }
function edit() { function edit() {
router.push(`/gallery/${post.value.id}/edit`); router.push(`/gallery/${post.value!.id}/edit`);
} }
watch(() => props.postId, fetchPost, { immediate: true }); watch(() => props.postId, fetchPost, { immediate: true });

View file

@ -432,7 +432,12 @@ export type Endpoints = {
"gallery/posts/create": { req: TODO; res: TODO }; "gallery/posts/create": { req: TODO; res: TODO };
"gallery/posts/delete": { req: { postId: GalleryPost["id"] }; res: null }; "gallery/posts/delete": { req: { postId: GalleryPost["id"] }; res: null };
"gallery/posts/like": { req: TODO; res: TODO }; "gallery/posts/like": { req: TODO; res: TODO };
"gallery/posts/show": { req: TODO; res: TODO }; "gallery/posts/show": {
req: {
postId: GalleryPost["id"];
};
res: GalleryPost;
};
"gallery/posts/unlike": { req: TODO; res: TODO }; "gallery/posts/unlike": { req: TODO; res: TODO };
"gallery/posts/update": { req: TODO; res: TODO }; "gallery/posts/update": { req: TODO; res: TODO };
@ -474,7 +479,14 @@ export type Endpoints = {
res: NoteFavorite[]; res: NoteFavorite[];
}; };
"i/gallery/likes": { req: TODO; res: TODO }; "i/gallery/likes": { req: TODO; res: TODO };
"i/gallery/posts": { req: TODO; res: TODO }; "i/gallery/posts": {
req: {
limit?: number;
sinceId?: NoteFavorite["id"];
untilId?: NoteFavorite["id"];
};
res: GalleryPost[];
};
"i/get-word-muted-notes-count": { req: TODO; res: TODO }; "i/get-word-muted-notes-count": { req: TODO; res: TODO };
"i/import-following": { req: TODO; res: TODO }; "i/import-following": { req: TODO; res: TODO };
"i/import-user-lists": { req: TODO; res: TODO }; "i/import-user-lists": { req: TODO; res: TODO };
@ -890,7 +902,15 @@ export type Endpoints = {
}; };
res: FollowingFolloweePopulated[]; res: FollowingFolloweePopulated[];
}; };
"users/gallery/posts": { req: TODO; res: TODO }; "users/gallery/posts": {
req: {
userId: User["id"];
limit?: number;
sinceId?: NoteFavorite["id"];
untilId?: NoteFavorite["id"];
};
res: GalleryPost[];
};
"users/get-frequently-replied-users": { req: TODO; res: TODO }; "users/get-frequently-replied-users": { req: TODO; res: TODO };
"users/groups/create": { req: TODO; res: TODO }; "users/groups/create": { req: TODO; res: TODO };
"users/groups/delete": { req: { groupId: UserGroup["id"] }; res: null }; "users/groups/delete": { req: { groupId: UserGroup["id"] }; res: null };

View file

@ -136,7 +136,21 @@ export type DriveFile = {
export type DriveFolder = TODO; export type DriveFolder = TODO;
export type GalleryPost = TODO; export type GalleryPost = {
id: ID;
createdAt: DateString;
updatedAt: DateString;
title: string;
description: string | null;
userId: User["id"];
user: UserDetailed;
fileIds?: DriveFile["id"][];
files?: DriveFile[];
tags?: string[];
isSensitive: boolean;
isLiked?: boolean;
likedCount: number;
};
export type Note = { export type Note = {
id: ID; id: ID;

View file

@ -8,7 +8,9 @@ import type {
Notification, Notification,
PageEvent, PageEvent,
User, User,
UserDetailed,
UserGroup, UserGroup,
UserLite,
} from "./entities"; } from "./entities";
import type { Connection } from "./streaming"; import type { Connection } from "./streaming";
@ -26,9 +28,9 @@ export type Channels = {
mention: (payload: Note) => void; mention: (payload: Note) => void;
reply: (payload: Note) => void; reply: (payload: Note) => void;
renote: (payload: Note) => void; renote: (payload: Note) => void;
follow: (payload: User) => void; // 自分が他人をフォローしたとき follow: (payload: UserDetailed) => void; // 自分が他人をフォローしたとき
followed: (payload: User) => void; // 他人が自分をフォローしたとき followed: (payload: UserLite) => void; // 他人が自分をフォローしたとき
unfollow: (payload: User) => void; // 自分が他人をフォロー解除したとき unfollow: (payload: UserDetailed) => void; // 自分が他人をフォロー解除したとき
meUpdated: (payload: MeDetailed) => void; meUpdated: (payload: MeDetailed) => void;
pageEvent: (payload: PageEvent) => void; pageEvent: (payload: PageEvent) => void;
urlUploadFinished: (payload: { marker: string; file: DriveFile }) => void; urlUploadFinished: (payload: { marker: string; file: DriveFile }) => void;