* Add an option for timeline replies. Credit to Emilis (puffaboo) * update db on request
This commit is contained in:
parent
c0ef868ad2
commit
3ff89fa7ec
|
@ -141,6 +141,8 @@ flagAsBot: "Botとして設定"
|
||||||
flagAsBotDescription: "このアカウントがプログラムによって運用される場合は、このフラグをオンにします。オンにすると、反応の連鎖を防ぐためのフラグとして他の開発者に役立ったり、Misskeyのシステム上での扱いがBotに合ったものになります。"
|
flagAsBotDescription: "このアカウントがプログラムによって運用される場合は、このフラグをオンにします。オンにすると、反応の連鎖を防ぐためのフラグとして他の開発者に役立ったり、Misskeyのシステム上での扱いがBotに合ったものになります。"
|
||||||
flagAsCat: "Catとして設定"
|
flagAsCat: "Catとして設定"
|
||||||
flagAsCatDescription: "このアカウントが猫であることを示す場合は、このフラグをオンにします。"
|
flagAsCatDescription: "このアカウントが猫であることを示す場合は、このフラグをオンにします。"
|
||||||
|
flagShowTimelineReplies: "タイムラインにノートへの返信を表示する"
|
||||||
|
flagShowTimelineRepliesDescription: "オンにすると、タイムラインにユーザーのノート以外にもそのユーザーの他のノートへの返信を表示します。"
|
||||||
autoAcceptFollowed: "フォロー中ユーザーからのフォロリクを自動承認"
|
autoAcceptFollowed: "フォロー中ユーザーからのフォロリクを自動承認"
|
||||||
addAccount: "アカウントを追加"
|
addAccount: "アカウントを追加"
|
||||||
loginFailed: "ログインに失敗しました"
|
loginFailed: "ログインに失敗しました"
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
class addShowTLReplies1629833361000 {
|
||||||
|
constructor() {
|
||||||
|
this.name = 'addShowTLReplies1629833361000';
|
||||||
|
}
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "showTimelineReplies" boolean NOT NULL DEFAULT false`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user"."showTimelineReplies" IS 'Whether to show users replying to other users in the timeline.'`);
|
||||||
|
}
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "showTimelineReplies"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.addShowTLReplies1629833361000 = addShowTLReplies1629833361000;
|
|
@ -225,6 +225,12 @@ export class User {
|
||||||
})
|
})
|
||||||
public followersUri: string | null;
|
public followersUri: string | null;
|
||||||
|
|
||||||
|
@Column('boolean', {
|
||||||
|
default: false,
|
||||||
|
comment: 'Whether to show users replying to other users in the timeline'
|
||||||
|
})
|
||||||
|
public showTimelineReplies: boolean;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('char', {
|
@Column('char', {
|
||||||
length: 16, nullable: true, unique: true,
|
length: 16, nullable: true, unique: true,
|
||||||
|
|
|
@ -220,6 +220,7 @@ export class UserRepository extends Repository<User> {
|
||||||
isModerator: user.isModerator || falsy,
|
isModerator: user.isModerator || falsy,
|
||||||
isBot: user.isBot || falsy,
|
isBot: user.isBot || falsy,
|
||||||
isCat: user.isCat || falsy,
|
isCat: user.isCat || falsy,
|
||||||
|
showTimelineReplies: user.showTimelineReplies || falsy,
|
||||||
instance: user.host ? Instances.findOne({ host: user.host }).then(instance => instance ? {
|
instance: user.host ? Instances.findOne({ host: user.host }).then(instance => instance ? {
|
||||||
name: instance.name,
|
name: instance.name,
|
||||||
softwareName: instance.softwareName,
|
softwareName: instance.softwareName,
|
||||||
|
|
|
@ -164,6 +164,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
|
||||||
tags,
|
tags,
|
||||||
isBot,
|
isBot,
|
||||||
isCat: (person as any).isCat === true,
|
isCat: (person as any).isCat === true,
|
||||||
|
showTimelineReplies: false,
|
||||||
})) as IRemoteUser;
|
})) as IRemoteUser;
|
||||||
|
|
||||||
await transactionalEntityManager.save(new UserProfile({
|
await transactionalEntityManager.save(new UserProfile({
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { User } from '@/models/entities/user';
|
import { User } from '@/models/entities/user';
|
||||||
import { Brackets, SelectQueryBuilder } from 'typeorm';
|
import { Brackets, SelectQueryBuilder } from 'typeorm';
|
||||||
|
|
||||||
export function generateRepliesQuery(q: SelectQueryBuilder<any>, me?: { id: User['id'] } | null) {
|
export function generateRepliesQuery(q: SelectQueryBuilder<any>, me?: Pick<User, 'id' | 'showTimelineReplies'> | null) {
|
||||||
if (me == null) {
|
if (me == null) {
|
||||||
q.andWhere(new Brackets(qb => { qb
|
q.andWhere(new Brackets(qb => { qb
|
||||||
.where(`note.replyId IS NULL`) // 返信ではない
|
.where(`note.replyId IS NULL`) // 返信ではない
|
||||||
|
@ -10,7 +10,7 @@ export function generateRepliesQuery(q: SelectQueryBuilder<any>, me?: { id: User
|
||||||
.andWhere('note.replyUserId = note.userId');
|
.andWhere('note.replyUserId = note.userId');
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
} else {
|
} else if(!me.showTimelineReplies) {
|
||||||
q.andWhere(new Brackets(qb => { qb
|
q.andWhere(new Brackets(qb => { qb
|
||||||
.where(`note.replyId IS NULL`) // 返信ではない
|
.where(`note.replyId IS NULL`) // 返信ではない
|
||||||
.orWhere('note.replyUserId = :meId', { meId: me.id }) // 返信だけど自分のノートへの返信
|
.orWhere('note.replyUserId = :meId', { meId: me.id }) // 返信だけど自分のノートへの返信
|
||||||
|
|
|
@ -96,6 +96,10 @@ export const meta = {
|
||||||
validator: $.optional.bool,
|
validator: $.optional.bool,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showTimelineReplies: {
|
||||||
|
validator: $.optional.bool,
|
||||||
|
},
|
||||||
|
|
||||||
injectFeaturedNote: {
|
injectFeaturedNote: {
|
||||||
validator: $.optional.bool,
|
validator: $.optional.bool,
|
||||||
},
|
},
|
||||||
|
@ -197,6 +201,7 @@ export default define(meta, async (ps, _user, token) => {
|
||||||
if (typeof ps.hideOnlineStatus === 'boolean') updates.hideOnlineStatus = ps.hideOnlineStatus;
|
if (typeof ps.hideOnlineStatus === 'boolean') updates.hideOnlineStatus = ps.hideOnlineStatus;
|
||||||
if (typeof ps.publicReactions === 'boolean') profileUpdates.publicReactions = ps.publicReactions;
|
if (typeof ps.publicReactions === 'boolean') profileUpdates.publicReactions = ps.publicReactions;
|
||||||
if (typeof ps.isBot === 'boolean') updates.isBot = ps.isBot;
|
if (typeof ps.isBot === 'boolean') updates.isBot = ps.isBot;
|
||||||
|
if (typeof ps.showTimelineReplies === 'boolean') updates.showTimelineReplies = ps.showTimelineReplies;
|
||||||
if (typeof ps.carefulBot === 'boolean') profileUpdates.carefulBot = ps.carefulBot;
|
if (typeof ps.carefulBot === 'boolean') profileUpdates.carefulBot = ps.carefulBot;
|
||||||
if (typeof ps.autoAcceptFollowed === 'boolean') profileUpdates.autoAcceptFollowed = ps.autoAcceptFollowed;
|
if (typeof ps.autoAcceptFollowed === 'boolean') profileUpdates.autoAcceptFollowed = ps.autoAcceptFollowed;
|
||||||
if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle;
|
if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle;
|
||||||
|
|
|
@ -43,7 +43,7 @@ export default class extends Channel {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
if (note.reply) {
|
if (note.reply && !this.user!.showTimelineReplies) {
|
||||||
const reply = note.reply;
|
const reply = note.reply;
|
||||||
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
||||||
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
|
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
|
||||||
|
|
|
@ -54,7 +54,7 @@ export default class extends Channel {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
if (note.reply) {
|
if (note.reply && !this.user!.showTimelineReplies) {
|
||||||
const reply = note.reply;
|
const reply = note.reply;
|
||||||
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
||||||
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
|
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
|
||||||
|
|
|
@ -62,7 +62,7 @@ export default class extends Channel {
|
||||||
if (isInstanceMuted(note, new Set<string>(this.userProfile?.mutedInstances ?? []))) return;
|
if (isInstanceMuted(note, new Set<string>(this.userProfile?.mutedInstances ?? []))) return;
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
if (note.reply) {
|
if (note.reply && !this.user!.showTimelineReplies) {
|
||||||
const reply = note.reply;
|
const reply = note.reply;
|
||||||
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
||||||
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
|
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
|
||||||
|
|
|
@ -43,7 +43,7 @@ export default class extends Channel {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
if (note.reply) {
|
if (note.reply && !this.user!.showTimelineReplies) {
|
||||||
const reply = note.reply;
|
const reply = note.reply;
|
||||||
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
||||||
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
|
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
</FormSlot>
|
</FormSlot>
|
||||||
|
|
||||||
<FormSwitch v-model="profile.isCat" class="_formBlock">{{ i18n.ts.flagAsCat }}<template #caption>{{ i18n.ts.flagAsCatDescription }}</template></FormSwitch>
|
<FormSwitch v-model="profile.isCat" class="_formBlock">{{ i18n.ts.flagAsCat }}<template #caption>{{ i18n.ts.flagAsCatDescription }}</template></FormSwitch>
|
||||||
|
<FormSwitch v-model="profile.showTimelineReplies" class="_formBlock">{{ i18n.ts.flagShowTimelineReplies }}<template #caption>{{ i18n.ts.flagShowTimelineRepliesDescription }}</template></FormSwitch>
|
||||||
<FormSwitch v-model="profile.isBot" class="_formBlock">{{ i18n.ts.flagAsBot }}<template #caption>{{ i18n.ts.flagAsBotDescription }}</template></FormSwitch>
|
<FormSwitch v-model="profile.isBot" class="_formBlock">{{ i18n.ts.flagAsBot }}<template #caption>{{ i18n.ts.flagAsBotDescription }}</template></FormSwitch>
|
||||||
|
|
||||||
<FormSwitch v-model="profile.alwaysMarkNsfw" class="_formBlock">{{ i18n.ts.alwaysMarkSensitive }}</FormSwitch>
|
<FormSwitch v-model="profile.alwaysMarkNsfw" class="_formBlock">{{ i18n.ts.alwaysMarkSensitive }}</FormSwitch>
|
||||||
|
@ -68,6 +68,7 @@ const profile = reactive({
|
||||||
lang: $i.lang,
|
lang: $i.lang,
|
||||||
isBot: $i.isBot,
|
isBot: $i.isBot,
|
||||||
isCat: $i.isCat,
|
isCat: $i.isCat,
|
||||||
|
showTimelineReplies: $i.showTimelineReplies,
|
||||||
alwaysMarkNsfw: $i.alwaysMarkNsfw,
|
alwaysMarkNsfw: $i.alwaysMarkNsfw,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@ function save() {
|
||||||
lang: profile.lang || null,
|
lang: profile.lang || null,
|
||||||
isBot: !!profile.isBot,
|
isBot: !!profile.isBot,
|
||||||
isCat: !!profile.isCat,
|
isCat: !!profile.isCat,
|
||||||
|
showTimelineReplies: !!profile.showTimelineReplies,
|
||||||
alwaysMarkNsfw: !!profile.alwaysMarkNsfw,
|
alwaysMarkNsfw: !!profile.alwaysMarkNsfw,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue