chore: formatting

This commit is contained in:
Kainoa Kanter 2023-04-07 22:46:10 -07:00
parent a624aeebe3
commit 437a6e29a5
21 changed files with 119 additions and 76 deletions

View file

@ -1,16 +1,22 @@
export class addRenoteMuting1665091090561 { export class addRenoteMuting1665091090561 {
constructor() { constructor() {
this.name = 'addRenoteMuting1665091090561'; this.name = "addRenoteMuting1665091090561";
} }
async up(queryRunner) { async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "renote_muting" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "muteeId" character varying(32) NOT NULL, "muterId" character varying(32) NOT NULL, CONSTRAINT "PK_renoteMuting_id" PRIMARY KEY ("id"))`); await queryRunner.query(
await queryRunner.query(`CREATE INDEX "IDX_renote_muting_createdAt" ON "muting" ("createdAt") `); `CREATE TABLE "renote_muting" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "muteeId" character varying(32) NOT NULL, "muterId" character varying(32) NOT NULL, CONSTRAINT "PK_renoteMuting_id" PRIMARY KEY ("id"))`,
await queryRunner.query(`CREATE INDEX "IDX_renote_muting_muteeId" ON "muting" ("muteeId") `); );
await queryRunner.query(`CREATE INDEX "IDX_renote_muting_muterId" ON "muting" ("muterId") `); await queryRunner.query(
`CREATE INDEX "IDX_renote_muting_createdAt" ON "muting" ("createdAt") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_renote_muting_muteeId" ON "muting" ("muteeId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_renote_muting_muterId" ON "muting" ("muterId") `,
);
} }
async down(queryRunner) { async down(queryRunner) {}
}
} }

View file

@ -1,4 +1,11 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from "typeorm"; import {
PrimaryColumn,
Entity,
Index,
JoinColumn,
Column,
ManyToOne,
} from "typeorm";
import { id } from "../id.js"; import { id } from "../id.js";
import { User } from "./user.js"; import { User } from "./user.js";

View file

@ -10,7 +10,8 @@ export const RenoteMutingRepository = db.getRepository(RenoteMuting).extend({
src: RenoteMuting["id"] | RenoteMuting, src: RenoteMuting["id"] | RenoteMuting,
me?: { id: User["id"] } | null | undefined, me?: { id: User["id"] } | null | undefined,
): Promise<Packed<"RenoteMuting">> { ): Promise<Packed<"RenoteMuting">> {
const muting = typeof src === "object" ? src : await this.findOneByOrFail({ id: src }); const muting =
typeof src === "object" ? src : await this.findOneByOrFail({ id: src });
return await awaitAll({ return await awaitAll({
id: muting.id, id: muting.id,
@ -22,10 +23,7 @@ export const RenoteMutingRepository = db.getRepository(RenoteMuting).extend({
}); });
}, },
packMany( packMany(mutings: any[], me: { id: User["id"] }) {
mutings: any[], return Promise.all(mutings.map((x) => this.pack(x, me)));
me: { id: User["id"] },
) {
return Promise.all(mutings.map(x => this.pack(x, me)));
}, },
}); });

View file

@ -3,23 +3,27 @@ export const packedRenoteMutingSchema = {
properties: { properties: {
id: { id: {
type: "string", type: "string",
optional: false, nullable: false, optional: false,
nullable: false,
format: "id", format: "id",
example: "xxxxxxxxxx", example: "xxxxxxxxxx",
}, },
createdAt: { createdAt: {
type: "string", type: "string",
optional: false, nullable: false, optional: false,
nullable: false,
format: "date-time", format: "date-time",
}, },
muteeId: { muteeId: {
type: "string", type: "string",
optional: false, nullable: false, optional: false,
nullable: false,
format: "id", format: "id",
}, },
mutee: { mutee: {
type: "object", type: "object",
optional: false, nullable: false, optional: false,
nullable: false,
ref: "UserDetailed", ref: "UserDetailed",
}, },
}, },

View file

@ -337,7 +337,8 @@ export const packedUserDetailedNotMeOnlySchema = {
}, },
isRenoteMuted: { isRenoteMuted: {
type: "boolean", type: "boolean",
nullable: false, optional: true, nullable: false,
optional: true,
}, },
//#endregion //#endregion
}, },

View file

@ -2,21 +2,27 @@ import { Brackets, SelectQueryBuilder } from "typeorm";
import { User } from "@/models/entities/user.js"; import { User } from "@/models/entities/user.js";
import { RenoteMutings } from "@/models/index.js"; import { RenoteMutings } from "@/models/index.js";
export function generateMutedUserRenotesQueryForNotes(q: SelectQueryBuilder<any>, me: { id: User["id"] }): void { export function generateMutedUserRenotesQueryForNotes(
q: SelectQueryBuilder<any>,
me: { id: User["id"] },
): void {
const mutingQuery = RenoteMutings.createQueryBuilder("renote_muting") const mutingQuery = RenoteMutings.createQueryBuilder("renote_muting")
.select("renote_muting.muteeId") .select("renote_muting.muteeId")
.where("renote_muting.muterId = :muterId", { muterId: me.id }); .where("renote_muting.muterId = :muterId", { muterId: me.id });
q.andWhere(new Brackets(qb => { q.andWhere(
qb new Brackets((qb) => {
.where(new Brackets(qb => { qb.where(
qb.where("note.renoteId IS NOT NULL"); new Brackets((qb) => {
qb.andWhere("note.text IS NULL"); qb.where("note.renoteId IS NOT NULL");
qb.andWhere(`note.userId NOT IN (${ mutingQuery.getQuery() })`); qb.andWhere("note.text IS NULL");
})) qb.andWhere(`note.userId NOT IN (${mutingQuery.getQuery()})`);
.orWhere("note.renoteId IS NULL") }),
.orWhere("note.text IS NOT NULL"); )
})); .orWhere("note.renoteId IS NULL")
.orWhere("note.text IS NOT NULL");
}),
);
q.setParameters(mutingQuery.getParameters()); q.setParameters(mutingQuery.getParameters());
} }

View file

@ -51,8 +51,9 @@ export default define(meta, paramDef, async (ps, user) => {
} }
// Get mutee // Get mutee
const mutee = await getUser(ps.userId).catch(e => { const mutee = await getUser(ps.userId).catch((e) => {
if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff") throw new ApiError(meta.errors.noSuchUser); if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff")
throw new ApiError(meta.errors.noSuchUser);
throw e; throw e;
}); });

View file

@ -49,8 +49,9 @@ export default define(meta, paramDef, async (ps, user) => {
} }
// Get mutee // Get mutee
const mutee = await getUser(ps.userId).catch(e => { const mutee = await getUser(ps.userId).catch((e) => {
if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff") throw new ApiError(meta.errors.noSuchUser); if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff")
throw new ApiError(meta.errors.noSuchUser);
throw e; throw e;
}); });

View file

@ -11,10 +11,12 @@ export const meta = {
res: { res: {
type: "array", type: "array",
optional: false, nullable: false, optional: false,
nullable: false,
items: { items: {
type: "object", type: "object",
optional: false, nullable: false, optional: false,
nullable: false,
ref: "RenoteMuting", ref: "RenoteMuting",
}, },
}, },
@ -32,12 +34,13 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, me) => { export default define(meta, paramDef, async (ps, me) => {
const query = makePaginationQuery(RenoteMutings.createQueryBuilder("muting"), ps.sinceId, ps.untilId) const query = makePaginationQuery(
.andWhere("muting.muterId = :meId", { meId: me.id }); RenoteMutings.createQueryBuilder("muting"),
ps.sinceId,
ps.untilId,
).andWhere("muting.muterId = :meId", { meId: me.id });
const mutings = await query const mutings = await query.take(ps.limit).getMany();
.take(ps.limit)
.getMany();
return await RenoteMutings.packMany(mutings, me); return await RenoteMutings.packMany(mutings, me);
}); });

View file

@ -59,7 +59,8 @@ export const meta = {
}, },
isRenoteMuted: { isRenoteMuted: {
type: "boolean", type: "boolean",
optional: false, nullable: false, optional: false,
nullable: false,
}, },
}, },
}, },
@ -113,7 +114,8 @@ export const meta = {
}, },
isRenoteMuted: { isRenoteMuted: {
type: "boolean", type: "boolean",
optional: false, nullable: false, optional: false,
nullable: false,
}, },
}, },
}, },

View file

@ -34,7 +34,8 @@ export default class extends Channel {
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.blocking)) return; if (isUserRelated(note, this.blocking)) return;
if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; if (note.renote && !note.text && isUserRelated(note, this.renoteMuting))
return;
this.connection.cacheNote(note); this.connection.cacheNote(note);

View file

@ -36,7 +36,8 @@ export default class extends Channel {
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.blocking)) return; if (isUserRelated(note, this.blocking)) return;
if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; if (note.renote && !note.text && isUserRelated(note, this.renoteMuting))
return;
this.connection.cacheNote(note); this.connection.cacheNote(note);

View file

@ -56,7 +56,8 @@ export default class extends Channel {
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.blocking)) return; if (isUserRelated(note, this.blocking)) return;
if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; if (note.renote && !note.text && isUserRelated(note, this.renoteMuting))
return;
// 流れてきたNoteがミュートすべきNoteだったら無視する // 流れてきたNoteがミュートすべきNoteだったら無視する
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある) // TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)

View file

@ -36,8 +36,9 @@ export default class extends Channel {
if (isUserRelated(note, this.muting)) return; if (isUserRelated(note, this.muting)) return;
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.blocking)) return; if (isUserRelated(note, this.blocking)) return;
if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; if (note.renote && !note.text && isUserRelated(note, this.renoteMuting))
return;
this.connection.cacheNote(note); this.connection.cacheNote(note);

View file

@ -54,7 +54,8 @@ export default class extends Channel {
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.blocking)) return; if (isUserRelated(note, this.blocking)) return;
if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; if (note.renote && !note.text && isUserRelated(note, this.renoteMuting))
return;
// 流れてきたNoteがミュートすべきNoteだったら無視する // 流れてきたNoteがミュートすべきNoteだったら無視する
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある) // TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)

View file

@ -71,7 +71,8 @@ export default class extends Channel {
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.blocking)) return; if (isUserRelated(note, this.blocking)) return;
if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; if (note.renote && !note.text && isUserRelated(note, this.renoteMuting))
return;
// 流れてきたNoteがミュートすべきNoteだったら無視する // 流れてきたNoteがミュートすべきNoteだったら無視する
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある) // TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)

View file

@ -48,7 +48,8 @@ export default class extends Channel {
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.blocking)) return; if (isUserRelated(note, this.blocking)) return;
if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; if (note.renote && !note.text && isUserRelated(note, this.renoteMuting))
return;
// 流れてきたNoteがミュートすべきNoteだったら無視する // 流れてきたNoteがミュートすべきNoteだったら無視する
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある) // TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)

View file

@ -56,7 +56,8 @@ export default class extends Channel {
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.blocking)) return; if (isUserRelated(note, this.blocking)) return;
if (note.renote && !note.text && isUserRelated(note, this.renoteMuting)) return; if (note.renote && !note.text && isUserRelated(note, this.renoteMuting))
return;
this.send("note", note); this.send("note", note);
} }

View file

@ -765,9 +765,9 @@ export type Endpoints = {
"mute/create": { req: TODO; res: TODO }; "mute/create": { req: TODO; res: TODO };
"mute/delete": { req: { userId: User["id"] }; res: null }; "mute/delete": { req: { userId: User["id"] }; res: null };
"mute/list": { req: TODO; res: TODO }; "mute/list": { req: TODO; res: TODO };
"renote-mute/create": { req: TODO; res: TODO; }; "renote-mute/create": { req: TODO; res: TODO };
"renote-mute/delete": { req: { userId: User['id'] }; res: null; }; "renote-mute/delete": { req: { userId: User["id"] }; res: null };
"renote-mute/list": { req: TODO; res: TODO; }; "renote-mute/list": { req: TODO; res: TODO };
// my // my
"my/apps": { req: TODO; res: TODO }; "my/apps": { req: TODO; res: TODO };

View file

@ -7,36 +7,39 @@
<FormSuspense :p="init"> <FormSuspense :p="init">
<FormTextarea v-model="hiddenTags" class="_formBlock"> <FormTextarea v-model="hiddenTags" class="_formBlock">
<span>{{ i18n.ts.hiddenTags }}</span> <span>{{ i18n.ts.hiddenTags }}</span>
<template #caption>{{ i18n.ts.hiddenTagsDescription }}</template> <template #caption>{{
i18n.ts.hiddenTagsDescription
}}</template>
</FormTextarea> </FormTextarea>
<FormButton primary class="_formBlock" @click="save"><i <FormButton primary class="_formBlock" @click="save"
class="ph-floppy-disk-back ph-bold ph-lg"></i> ><i class="ph-floppy-disk-back ph-bold ph-lg"></i>
{{ i18n.ts.save }}</FormButton> {{ i18n.ts.save }}</FormButton
>
</FormSuspense> </FormSuspense>
</MkSpacer> </MkSpacer>
</MkStickyContainer> </MkStickyContainer>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { } from 'vue'; import {} from "vue";
import FormButton from '@/components/MkButton.vue'; import FormButton from "@/components/MkButton.vue";
import FormTextarea from '@/components/form/textarea.vue'; import FormTextarea from "@/components/form/textarea.vue";
import FormSuspense from '@/components/form/suspense.vue'; import FormSuspense from "@/components/form/suspense.vue";
import * as os from '@/os'; import * as os from "@/os";
import { fetchInstance } from '@/instance'; import { fetchInstance } from "@/instance";
import { i18n } from '@/i18n'; import { i18n } from "@/i18n";
import { definePageMetadata } from '@/scripts/page-metadata'; import { definePageMetadata } from "@/scripts/page-metadata";
let hiddenTags: string = $ref(''); let hiddenTags: string = $ref("");
async function init() { async function init() {
const meta = await os.api('admin/meta'); const meta = await os.api("admin/meta");
hiddenTags = meta.hiddenTags.join("\n"); hiddenTags = meta.hiddenTags.join("\n");
} }
function save() { function save() {
os.apiWithDialog('admin/update-meta', { os.apiWithDialog("admin/update-meta", {
hiddenTags: hiddenTags.split("\n").map((h: string) => h.trim()) || [], hiddenTags: hiddenTags.split("\n").map((h: string) => h.trim()) || [],
}).then(() => { }).then(() => {
fetchInstance(); fetchInstance();
@ -49,6 +52,6 @@ const headerTabs = $computed(() => []);
definePageMetadata({ definePageMetadata({
title: i18n.ts.hiddenTags, title: i18n.ts.hiddenTags,
icon: 'ph-hash ph-bold ph-lg', icon: "ph-hash ph-bold ph-lg",
}); });
</script> </script>

View file

@ -118,9 +118,12 @@ export function getUserMenu(user, router: Router = mainRouter) {
} }
async function toggleRenoteMute(): Promise<void> { async function toggleRenoteMute(): Promise<void> {
os.apiWithDialog(user.isRenoteMuted ? "renote-mute/delete" : "renote-mute/create", { os.apiWithDialog(
userId: user.id, user.isRenoteMuted ? "renote-mute/delete" : "renote-mute/create",
}).then(() => { {
userId: user.id,
},
).then(() => {
user.isRenoteMuted = !user.isRenoteMuted; user.isRenoteMuted = !user.isRenoteMuted;
}); });
} }