enhance(backend): フォロー・フォロワー関連の通知の受信設定の強化 (#13468)

* enhance(backend): 通知の受信設定に「フォロー中またはフォロワー」を追加

* fix(backend): 通知の受信設定で「相互フォロー」が正しく動作しない問題を修正

* Update CHANGELOG.md
This commit is contained in:
zyoshoka 2024-02-28 09:49:34 +09:00 committed by GitHub
parent f906ad6ca7
commit 0d47877db1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 62 additions and 43 deletions

View File

@ -16,6 +16,7 @@
### General
- Enhance: サーバーごとにモデレーションノートを残せるように
- Enhance: コンディショナルロールの条件に「マニュアルロールへのアサイン」を追加
- Enhance: 通知の受信設定に「フォロー中またはフォロワー」を追加
### Client
- Enhance: ノート作成画面のファイル添付メニューの区切り線の位置を調整
@ -33,6 +34,7 @@
- 必須パラメータを`id`または`name`のいずれかのみに
- `id`の代わりに`name`で絵文字を指定可能に(`id`・`name`両指定時は従来通り`name`を変更する挙動)
- `category`および`licence`が指定なしの時勝手にnullに上書きされる挙動を修正
- Fix: 通知の受信設定で「相互フォロー」が正しく動作しない問題を修正
## 2024.2.0

4
locales/index.d.ts vendored
View File

@ -4656,6 +4656,10 @@ export interface Locale extends ILocale {
*
*/
"mutualFollow": string;
/**
*
*/
"followingOrFollower": string;
/**
*
*/

View File

@ -1160,6 +1160,7 @@ showRenotes: "リノートを表示"
edited: "編集済み"
notificationRecieveConfig: "通知の受信設定"
mutualFollow: "相互フォロー"
followingOrFollower: "フォロー中またはフォロワー"
fileAttachedOnly: "ファイル付きのみ"
showRepliesToOthersInTimeline: "TLに他の人への返信を含める"
hideRepliesToOthersInTimeline: "TLに他の人への返信を含めない"

View File

@ -122,6 +122,14 @@ export class NotificationService implements OnApplicationShutdown {
return null;
}
} else if (recieveConfig?.type === 'mutualFollow') {
const [isFollowing, isFollower] = await Promise.all([
this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId)),
this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId)),
]);
if (!(isFollowing && isFollower)) {
return null;
}
} else if (recieveConfig?.type === 'followingOrFollower') {
const [isFollowing, isFollower] = await Promise.all([
this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId)),
this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId)),

View File

@ -249,6 +249,8 @@ export class MiUserProfile {
type: 'follower';
} | {
type: 'mutualFollow';
} | {
type: 'followingOrFollower';
} | {
type: 'list';
userListId: MiUserList['id'];

View File

@ -13,7 +13,7 @@ export const notificationRecieveConfig = {
type: {
type: 'string',
nullable: false,
enum: ['all', 'following', 'follower', 'mutualFollow', 'never'],
enum: ['all', 'following', 'follower', 'mutualFollow', 'followingOrFollower', 'never'],
},
},
required: ['type'],

View File

@ -10,6 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<option value="following">{{ i18n.ts.following }}</option>
<option value="follower">{{ i18n.ts.followers }}</option>
<option value="mutualFollow">{{ i18n.ts.mutualFollow }}</option>
<option value="followingOrFollower">{{ i18n.ts.followingOrFollower }}</option>
<option value="list">{{ i18n.ts.userList }}</option>
<option value="never">{{ i18n.ts.none }}</option>
</MkSelect>

View File

@ -16,6 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
$i.notificationRecieveConfig[type]?.type === 'following' ? i18n.ts.following :
$i.notificationRecieveConfig[type]?.type === 'follower' ? i18n.ts.followers :
$i.notificationRecieveConfig[type]?.type === 'mutualFollow' ? i18n.ts.mutualFollow :
$i.notificationRecieveConfig[type]?.type === 'followingOrFollower' ? i18n.ts.followingOrFollower :
$i.notificationRecieveConfig[type]?.type === 'list' ? i18n.ts.userList :
i18n.ts.all
}}

View File

@ -3700,7 +3700,7 @@ export type components = {
notificationRecieveConfig: {
note?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3709,7 +3709,7 @@ export type components = {
}]>;
follow?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3718,7 +3718,7 @@ export type components = {
}]>;
mention?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3727,7 +3727,7 @@ export type components = {
}]>;
reply?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3736,7 +3736,7 @@ export type components = {
}]>;
renote?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3745,7 +3745,7 @@ export type components = {
}]>;
quote?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3754,7 +3754,7 @@ export type components = {
}]>;
reaction?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3763,7 +3763,7 @@ export type components = {
}]>;
pollEnded?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3772,7 +3772,7 @@ export type components = {
}]>;
receiveFollowRequest?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3781,7 +3781,7 @@ export type components = {
}]>;
followRequestAccepted?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3790,7 +3790,7 @@ export type components = {
}]>;
roleAssigned?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3799,7 +3799,7 @@ export type components = {
}]>;
achievementEarned?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3808,7 +3808,7 @@ export type components = {
}]>;
app?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -3817,7 +3817,7 @@ export type components = {
}]>;
test?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8436,7 +8436,7 @@ export type operations = {
notificationRecieveConfig: {
note?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8445,7 +8445,7 @@ export type operations = {
}]>;
follow?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8454,7 +8454,7 @@ export type operations = {
}]>;
mention?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8463,7 +8463,7 @@ export type operations = {
}]>;
reply?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8472,7 +8472,7 @@ export type operations = {
}]>;
renote?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8481,7 +8481,7 @@ export type operations = {
}]>;
quote?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8490,7 +8490,7 @@ export type operations = {
}]>;
reaction?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8499,7 +8499,7 @@ export type operations = {
}]>;
pollEnded?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8508,7 +8508,7 @@ export type operations = {
}]>;
receiveFollowRequest?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8517,7 +8517,7 @@ export type operations = {
}]>;
followRequestAccepted?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8526,7 +8526,7 @@ export type operations = {
}]>;
roleAssigned?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8535,7 +8535,7 @@ export type operations = {
}]>;
achievementEarned?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8544,7 +8544,7 @@ export type operations = {
}]>;
app?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -8553,7 +8553,7 @@ export type operations = {
}]>;
test?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18787,7 +18787,7 @@ export type operations = {
notificationRecieveConfig?: {
note?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18796,7 +18796,7 @@ export type operations = {
}]>;
follow?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18805,7 +18805,7 @@ export type operations = {
}]>;
mention?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18814,7 +18814,7 @@ export type operations = {
}]>;
reply?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18823,7 +18823,7 @@ export type operations = {
}]>;
renote?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18832,7 +18832,7 @@ export type operations = {
}]>;
quote?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18841,7 +18841,7 @@ export type operations = {
}]>;
reaction?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18850,7 +18850,7 @@ export type operations = {
}]>;
pollEnded?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18859,7 +18859,7 @@ export type operations = {
}]>;
receiveFollowRequest?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18868,7 +18868,7 @@ export type operations = {
}]>;
followRequestAccepted?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18877,7 +18877,7 @@ export type operations = {
}]>;
roleAssigned?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18886,7 +18886,7 @@ export type operations = {
}]>;
achievementEarned?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18895,7 +18895,7 @@ export type operations = {
}]>;
app?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';
@ -18904,7 +18904,7 @@ export type operations = {
}]>;
test?: OneOf<[{
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'never';
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
}, {
/** @enum {string} */
type: 'list';