fix: notification
This commit is contained in:
parent
1e6002cab9
commit
6063f4d7ab
5 changed files with 49 additions and 32 deletions
|
@ -401,7 +401,7 @@ export async function execPaginationQuery(
|
|||
filter?: {
|
||||
note?: (_: ScyllaNote[]) => Promise<ScyllaNote[]>;
|
||||
reaction?: (_: ScyllaNoteReaction[]) => Promise<ScyllaNoteReaction[]>;
|
||||
notification?: (_: ScyllaNotification[]) => ScyllaNotification[];
|
||||
notification?: (_: ScyllaNotification[]) => Promise<ScyllaNotification[]>;
|
||||
},
|
||||
userId?: User["id"],
|
||||
maxPartitions = config.scylla?.sparseTimelineDays ?? 14,
|
||||
|
@ -474,7 +474,7 @@ export async function execPaginationQuery(
|
|||
const notifications = result.rows.map(parseScyllaNotification);
|
||||
(found as ScyllaNotification[]).push(
|
||||
...(filter?.notification
|
||||
? filter.notification(notifications)
|
||||
? await filter.notification(notifications)
|
||||
: notifications),
|
||||
);
|
||||
untilDate = notifications[notifications.length - 1].createdAt;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { In, Repository } from "typeorm";
|
||||
import { In } from "typeorm";
|
||||
import { Notification } from "@/models/entities/notification.js";
|
||||
import { awaitAll } from "@/prelude/await-all.js";
|
||||
import type { Packed } from "@/misc/schema.js";
|
||||
|
@ -6,7 +6,6 @@ import type { Note } from "@/models/entities/note.js";
|
|||
import type { NoteReaction } from "@/models/entities/note-reaction.js";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
import { aggregateNoteEmojis, prefetchEmojis } from "@/misc/populate-emojis.js";
|
||||
import { notificationTypes } from "@/types.js";
|
||||
import { db } from "@/db/postgre.js";
|
||||
import {
|
||||
Users,
|
||||
|
|
|
@ -14,7 +14,8 @@ import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
|||
import {
|
||||
ScyllaNotification,
|
||||
execPaginationQuery,
|
||||
filterMutedUser,
|
||||
parseScyllaNote,
|
||||
prepared,
|
||||
scyllaClient,
|
||||
} from "@/db/scylla.js";
|
||||
import {
|
||||
|
@ -23,19 +24,14 @@ import {
|
|||
UserBlockedCache,
|
||||
UserBlockingCache,
|
||||
UserMutingsCache,
|
||||
userWordMuteCache,
|
||||
} from "@/misc/cache.js";
|
||||
import type { Client } from "cassandra-driver";
|
||||
|
||||
export const meta = {
|
||||
tags: ["account", "notifications"],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
limit: {
|
||||
duration: 60000,
|
||||
max: 15,
|
||||
},
|
||||
|
||||
kind: "read:notifications",
|
||||
|
||||
res: {
|
||||
|
@ -59,6 +55,7 @@ export const paramDef = {
|
|||
untilId: { type: "string", format: "misskey:id" },
|
||||
following: { type: "boolean", default: false },
|
||||
unreadOnly: { type: "boolean", default: false },
|
||||
directOnly: { type: "boolean", default: false },
|
||||
markAsRead: { type: "boolean", default: true },
|
||||
includeTypes: {
|
||||
type: "array",
|
||||
|
@ -89,6 +86,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
}
|
||||
|
||||
if (scyllaClient) {
|
||||
const client = scyllaClient as Client;
|
||||
const [
|
||||
followingUserIds,
|
||||
mutedUserIds,
|
||||
|
@ -104,7 +102,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
]);
|
||||
const validUserIds = [user.id, ...followingUserIds];
|
||||
|
||||
const filter = (notifications: ScyllaNotification[]) => {
|
||||
const filter = async (notifications: ScyllaNotification[]) => {
|
||||
let filtered = notifications;
|
||||
if (ps.unreadOnly) {
|
||||
// FIXME: isRead is always true at the moment
|
||||
|
@ -134,6 +132,25 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
blockerIds.includes(n.notifierId))
|
||||
),
|
||||
);
|
||||
if (
|
||||
ps.directOnly &&
|
||||
ps.includeTypes?.every((t) => ["mention", "reply"].includes(t))
|
||||
) {
|
||||
filtered = filtered.filter(({ entityId }) => !!entityId);
|
||||
let notes = await client
|
||||
.execute(
|
||||
prepared.note.select.byIds,
|
||||
[filtered.map(({ entityId }) => entityId as string)],
|
||||
{ prepare: true },
|
||||
)
|
||||
.then((result) => result.rows.map(parseScyllaNote));
|
||||
notes = notes.filter((n) => n.visibility === "specified");
|
||||
const validNoteIds = notes.map(({ id }) => id);
|
||||
filtered = filtered.filter(
|
||||
({ entityId }) => entityId && validNoteIds.includes(entityId),
|
||||
);
|
||||
}
|
||||
|
||||
return filtered;
|
||||
};
|
||||
|
||||
|
@ -173,11 +190,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.andWhere("notification.notifieeId = :meId", { meId: user.id })
|
||||
.leftJoinAndSelect("notification.notifier", "notifier")
|
||||
.leftJoinAndSelect("notification.note", "note")
|
||||
.leftJoinAndSelect("note.user", "user")
|
||||
.leftJoinAndSelect("note.reply", "reply")
|
||||
.leftJoinAndSelect("note.renote", "renote")
|
||||
.leftJoinAndSelect("reply.user", "replyUser")
|
||||
.leftJoinAndSelect("renote.user", "renoteUser");
|
||||
.leftJoinAndSelect("note.renote", "renote");
|
||||
|
||||
// muted users
|
||||
query.andWhere(
|
||||
|
@ -226,6 +240,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
}
|
||||
|
||||
if (ps.directOnly) {
|
||||
query.andWhere("note.visibility = 'specified'");
|
||||
}
|
||||
|
||||
if (ps.unreadOnly) {
|
||||
query.andWhere("notification.isRead = false");
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ import { i18n } from "@/i18n";
|
|||
const props = defineProps<{
|
||||
includeTypes?: (typeof notificationTypes)[number][];
|
||||
unreadOnly?: boolean;
|
||||
directOnly?: boolean;
|
||||
}>();
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
|
@ -72,6 +73,7 @@ const pagination: Paging = {
|
|||
excludeTypes: props.includeTypes
|
||||
? undefined
|
||||
: $i.mutingNotificationTypes,
|
||||
directOnly: props.directOnly,
|
||||
unreadOnly: props.unreadOnly,
|
||||
})),
|
||||
};
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
class="notifications"
|
||||
:include-types="includeTypes"
|
||||
:unread-only="false"
|
||||
:direct-only="false"
|
||||
/>
|
||||
</swiper-slide>
|
||||
<swiper-slide>
|
||||
|
@ -37,13 +38,24 @@
|
|||
class="notifications"
|
||||
:include-types="includeTypes"
|
||||
:unread-only="true"
|
||||
:direct-only="false"
|
||||
/>
|
||||
</swiper-slide>
|
||||
<swiper-slide>
|
||||
<XNotes :pagination="mentionsPagination" />
|
||||
<XNotifications
|
||||
class="notifications"
|
||||
:include-types="['mention', 'reply']"
|
||||
:unread-only="false"
|
||||
:direct-only="false"
|
||||
/>
|
||||
</swiper-slide>
|
||||
<swiper-slide>
|
||||
<XNotes :pagination="directNotesPagination" />
|
||||
<XNotifications
|
||||
class="notifications"
|
||||
:include-types="['mention', 'reply']"
|
||||
:unread-only="false"
|
||||
:direct-only="true"
|
||||
/>
|
||||
</swiper-slide>
|
||||
</swiper>
|
||||
</MkSpacer>
|
||||
|
@ -56,7 +68,6 @@ import { Virtual } from "swiper/modules";
|
|||
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||
import { notificationTypes } from "firefish-js";
|
||||
import XNotifications from "@/components/MkNotifications.vue";
|
||||
import XNotes from "@/components/MkNotes.vue";
|
||||
import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||
|
@ -81,19 +92,6 @@ window.addEventListener("resize", () => {
|
|||
deviceKind === "smartphone" || window.innerWidth <= MOBILE_THRESHOLD;
|
||||
});
|
||||
|
||||
const mentionsPagination = {
|
||||
endpoint: "notes/mentions" as const,
|
||||
limit: 10,
|
||||
};
|
||||
|
||||
const directNotesPagination = {
|
||||
endpoint: "notes/mentions" as const,
|
||||
limit: 10,
|
||||
params: {
|
||||
visibility: "specified",
|
||||
},
|
||||
};
|
||||
|
||||
function setFilter(ev) {
|
||||
const typeItems = notificationTypes.map((t) => ({
|
||||
text: i18n.t(`_notification._types.${t}`),
|
||||
|
|
Loading…
Reference in a new issue