mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-04 07:24:13 +00:00 
			
		
		
		
	enhance: 通知の履歴をリセットできるように (#13335)
* enhance: 通知の履歴をリセットできるように * Update Changelog * 通知欄も連動して更新するように * revert some changes * Update CHANGELOG.md * Remove unused part * fix
This commit is contained in:
		
							parent
							
								
									ec18991328
								
							
						
					
					
						commit
						39d6af135f
					
				
					 15 changed files with 139 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -18,6 +18,7 @@
 | 
			
		|||
- Enhance: サーバーごとにモデレーションノートを残せるように
 | 
			
		||||
- Enhance: コンディショナルロールの条件に「マニュアルロールへのアサイン」を追加
 | 
			
		||||
- Enhance: 通知の受信設定に「フォロー中またはフォロワー」を追加
 | 
			
		||||
- Enhance: 通知の履歴をリセットできるように
 | 
			
		||||
 | 
			
		||||
### Client
 | 
			
		||||
- Enhance: ノート作成画面のファイル添付メニューの区切り線の位置を調整
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								locales/index.d.ts
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								locales/index.d.ts
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -8913,6 +8913,10 @@ export interface Locale extends ILocale {
 | 
			
		|||
         * {n}人にフォローされました
 | 
			
		||||
         */
 | 
			
		||||
        "followedBySomeUsers": ParameterizedString<"n">;
 | 
			
		||||
        /**
 | 
			
		||||
         * 通知の履歴をリセットする
 | 
			
		||||
         */
 | 
			
		||||
        "flushNotification": string;
 | 
			
		||||
        "_types": {
 | 
			
		||||
            /**
 | 
			
		||||
             * すべて
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2356,6 +2356,7 @@ _notification:
 | 
			
		|||
  reactedBySomeUsers: "{n}人がリアクションしました"
 | 
			
		||||
  renotedBySomeUsers: "{n}人がリノートしました"
 | 
			
		||||
  followedBySomeUsers: "{n}人にフォローされました"
 | 
			
		||||
  flushNotification: "通知の履歴をリセットする"
 | 
			
		||||
 | 
			
		||||
  _types:
 | 
			
		||||
    all: "すべて"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,6 +69,7 @@ export interface MainEventTypes {
 | 
			
		|||
		file: Packed<'DriveFile'>;
 | 
			
		||||
	};
 | 
			
		||||
	readAllNotifications: undefined;
 | 
			
		||||
	notificationFlushed: undefined;
 | 
			
		||||
	unreadNotification: Packed<'Notification'>;
 | 
			
		||||
	unreadMention: MiNote['id'];
 | 
			
		||||
	readAllUnreadMentions: undefined;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -214,6 +214,15 @@ export class NotificationService implements OnApplicationShutdown {
 | 
			
		|||
		*/
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@bindThis
 | 
			
		||||
	public async flushAllNotifications(userId: MiUser['id']) {
 | 
			
		||||
		await Promise.all([
 | 
			
		||||
			this.redisClient.del(`notificationTimeline:${userId}`),
 | 
			
		||||
			this.redisClient.del(`latestReadNotification:${userId}`),
 | 
			
		||||
		]);
 | 
			
		||||
		this.globalEventService.publishMainStream(userId, 'notificationFlushed');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@bindThis
 | 
			
		||||
	public dispose(): void {
 | 
			
		||||
		this.#shutdownController.abort();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -293,6 +293,7 @@ import * as ep___notes_translate from './endpoints/notes/translate.js';
 | 
			
		|||
import * as ep___notes_unrenote from './endpoints/notes/unrenote.js';
 | 
			
		||||
import * as ep___notes_userListTimeline from './endpoints/notes/user-list-timeline.js';
 | 
			
		||||
import * as ep___notifications_create from './endpoints/notifications/create.js';
 | 
			
		||||
import * as ep___notifications_flush from './endpoints/notifications/flush.js';
 | 
			
		||||
import * as ep___notifications_markAllAsRead from './endpoints/notifications/mark-all-as-read.js';
 | 
			
		||||
import * as ep___notifications_testNotification from './endpoints/notifications/test-notification.js';
 | 
			
		||||
import * as ep___pagePush from './endpoints/page-push.js';
 | 
			
		||||
| 
						 | 
				
			
			@ -664,6 +665,7 @@ const $notes_translate: Provider = { provide: 'ep:notes/translate', useClass: ep
 | 
			
		|||
const $notes_unrenote: Provider = { provide: 'ep:notes/unrenote', useClass: ep___notes_unrenote.default };
 | 
			
		||||
const $notes_userListTimeline: Provider = { provide: 'ep:notes/user-list-timeline', useClass: ep___notes_userListTimeline.default };
 | 
			
		||||
const $notifications_create: Provider = { provide: 'ep:notifications/create', useClass: ep___notifications_create.default };
 | 
			
		||||
const $notifications_flush: Provider = { provide: 'ep:notifications/flush', useClass: ep___notifications_flush.default };
 | 
			
		||||
const $notifications_markAllAsRead: Provider = { provide: 'ep:notifications/mark-all-as-read', useClass: ep___notifications_markAllAsRead.default };
 | 
			
		||||
const $notifications_testNotification: Provider = { provide: 'ep:notifications/test-notification', useClass: ep___notifications_testNotification.default };
 | 
			
		||||
const $pagePush: Provider = { provide: 'ep:page-push', useClass: ep___pagePush.default };
 | 
			
		||||
| 
						 | 
				
			
			@ -1039,6 +1041,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
 | 
			
		|||
		$notes_unrenote,
 | 
			
		||||
		$notes_userListTimeline,
 | 
			
		||||
		$notifications_create,
 | 
			
		||||
		$notifications_flush,
 | 
			
		||||
		$notifications_markAllAsRead,
 | 
			
		||||
		$notifications_testNotification,
 | 
			
		||||
		$pagePush,
 | 
			
		||||
| 
						 | 
				
			
			@ -1408,7 +1411,9 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
 | 
			
		|||
		$notes_unrenote,
 | 
			
		||||
		$notes_userListTimeline,
 | 
			
		||||
		$notifications_create,
 | 
			
		||||
		$notifications_flush,
 | 
			
		||||
		$notifications_markAllAsRead,
 | 
			
		||||
		$notifications_testNotification,
 | 
			
		||||
		$pagePush,
 | 
			
		||||
		$pages_create,
 | 
			
		||||
		$pages_delete,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -293,6 +293,7 @@ import * as ep___notes_translate from './endpoints/notes/translate.js';
 | 
			
		|||
import * as ep___notes_unrenote from './endpoints/notes/unrenote.js';
 | 
			
		||||
import * as ep___notes_userListTimeline from './endpoints/notes/user-list-timeline.js';
 | 
			
		||||
import * as ep___notifications_create from './endpoints/notifications/create.js';
 | 
			
		||||
import * as ep___notifications_flush from './endpoints/notifications/flush.js';
 | 
			
		||||
import * as ep___notifications_markAllAsRead from './endpoints/notifications/mark-all-as-read.js';
 | 
			
		||||
import * as ep___notifications_testNotification from './endpoints/notifications/test-notification.js';
 | 
			
		||||
import * as ep___pagePush from './endpoints/page-push.js';
 | 
			
		||||
| 
						 | 
				
			
			@ -662,6 +663,7 @@ const eps = [
 | 
			
		|||
	['notes/unrenote', ep___notes_unrenote],
 | 
			
		||||
	['notes/user-list-timeline', ep___notes_userListTimeline],
 | 
			
		||||
	['notifications/create', ep___notifications_create],
 | 
			
		||||
	['notifications/flush', ep___notifications_flush],
 | 
			
		||||
	['notifications/mark-all-as-read', ep___notifications_markAllAsRead],
 | 
			
		||||
	['notifications/test-notification', ep___notifications_testNotification],
 | 
			
		||||
	['page-push', ep___pagePush],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { Injectable } from '@nestjs/common';
 | 
			
		||||
import { Endpoint } from '@/server/api/endpoint-base.js';
 | 
			
		||||
import { NotificationService } from '@/core/NotificationService.js';
 | 
			
		||||
 | 
			
		||||
export const meta = {
 | 
			
		||||
	tags: ['notifications', 'account'],
 | 
			
		||||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'write:notifications',
 | 
			
		||||
} as const;
 | 
			
		||||
 | 
			
		||||
export const paramDef = {
 | 
			
		||||
	type: 'object',
 | 
			
		||||
	properties: {},
 | 
			
		||||
	required: [],
 | 
			
		||||
} as const;
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
 | 
			
		||||
	constructor(
 | 
			
		||||
		private notificationService: NotificationService,
 | 
			
		||||
	) {
 | 
			
		||||
		super(meta, paramDef, async (ps, me) => {
 | 
			
		||||
			this.notificationService.flushAllNotifications(me.id);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +35,7 @@ import { notificationTypes } from '@/const.js';
 | 
			
		|||
import { infoImageUrl } from '@/instance.js';
 | 
			
		||||
import { defaultStore } from '@/store.js';
 | 
			
		||||
import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
 | 
			
		||||
import * as Misskey from 'misskey-js';
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
	excludeTypes?: typeof notificationTypes[number][];
 | 
			
		||||
| 
						 | 
				
			
			@ -75,17 +76,19 @@ function reload() {
 | 
			
		|||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let connection;
 | 
			
		||||
let connection: Misskey.ChannelConnection<Misskey.Channels['main']>;
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
	connection = useStream().useChannel('main');
 | 
			
		||||
	connection.on('notification', onNotification);
 | 
			
		||||
	connection.on('notificationFlushed', reload);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onActivated(() => {
 | 
			
		||||
	pagingComponent.value?.reload();
 | 
			
		||||
	connection = useStream().useChannel('main');
 | 
			
		||||
	connection.on('notification', onNotification);
 | 
			
		||||
	connection.on('notificationFlushed', reload);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onUnmounted(() => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	<FormSection>
 | 
			
		||||
		<div class="_gaps_m">
 | 
			
		||||
			<FormLink @click="testNotification">{{ i18n.ts._notification.sendTestNotification }}</FormLink>
 | 
			
		||||
			<FormLink @click="flushNotification">{{ i18n.ts._notification.flushNotification }}</FormLink>
 | 
			
		||||
		</div>
 | 
			
		||||
	</FormSection>
 | 
			
		||||
	<FormSection>
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +115,17 @@ function testNotification(): void {
 | 
			
		|||
	misskeyApi('notifications/test-notification');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function flushNotification() {
 | 
			
		||||
	const { canceled } = await os.confirm({
 | 
			
		||||
		type: 'warning',
 | 
			
		||||
		text: i18n.ts.resetAreYouSure,
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (canceled) return;
 | 
			
		||||
 | 
			
		||||
	os.apiWithDialog('notifications/flush');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const headerActions = computed(() => []);
 | 
			
		||||
 | 
			
		||||
const headerTabs = computed(() => []);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -530,6 +530,7 @@ export type Channels = {
 | 
			
		|||
            unreadNotification: (payload: Notification_2) => void;
 | 
			
		||||
            unreadMention: (payload: Note['id']) => void;
 | 
			
		||||
            readAllUnreadMentions: () => void;
 | 
			
		||||
            notificationFlushed: () => void;
 | 
			
		||||
            unreadSpecifiedNote: (payload: Note['id']) => void;
 | 
			
		||||
            readAllUnreadSpecifiedNotes: () => void;
 | 
			
		||||
            readAllAntennas: () => void;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3195,6 +3195,17 @@ declare module '../api.js' {
 | 
			
		|||
      credential?: string | null,
 | 
			
		||||
    ): Promise<SwitchCaseResponseType<E, P>>;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * No description provided.
 | 
			
		||||
     * 
 | 
			
		||||
     * **Credential required**: *Yes* / **Permission**: *write:notifications*
 | 
			
		||||
     */
 | 
			
		||||
    request<E extends 'notifications/flush', P extends Endpoints[E]['req']>(
 | 
			
		||||
      endpoint: E,
 | 
			
		||||
      params: P,
 | 
			
		||||
      credential?: string | null,
 | 
			
		||||
    ): Promise<SwitchCaseResponseType<E, P>>;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * No description provided.
 | 
			
		||||
     * 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -841,6 +841,7 @@ export type Endpoints = {
 | 
			
		|||
	'notes/unrenote': { req: NotesUnrenoteRequest; res: EmptyResponse };
 | 
			
		||||
	'notes/user-list-timeline': { req: NotesUserListTimelineRequest; res: NotesUserListTimelineResponse };
 | 
			
		||||
	'notifications/create': { req: NotificationsCreateRequest; res: EmptyResponse };
 | 
			
		||||
	'notifications/flush': { req: EmptyRequest; res: EmptyResponse };
 | 
			
		||||
	'notifications/mark-all-as-read': { req: EmptyRequest; res: EmptyResponse };
 | 
			
		||||
	'notifications/test-notification': { req: EmptyRequest; res: EmptyResponse };
 | 
			
		||||
	'page-push': { req: PagePushRequest; res: EmptyResponse };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2770,6 +2770,15 @@ export type paths = {
 | 
			
		|||
     */
 | 
			
		||||
    post: operations['notifications/create'];
 | 
			
		||||
  };
 | 
			
		||||
  '/notifications/flush': {
 | 
			
		||||
    /**
 | 
			
		||||
     * notifications/flush
 | 
			
		||||
     * @description No description provided.
 | 
			
		||||
     *
 | 
			
		||||
     * **Credential required**: *Yes* / **Permission**: *write:notifications*
 | 
			
		||||
     */
 | 
			
		||||
    post: operations['notifications/flush'];
 | 
			
		||||
  };
 | 
			
		||||
  '/notifications/mark-all-as-read': {
 | 
			
		||||
    /**
 | 
			
		||||
     * notifications/mark-all-as-read
 | 
			
		||||
| 
						 | 
				
			
			@ -22056,6 +22065,50 @@ export type operations = {
 | 
			
		|||
      };
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
  /**
 | 
			
		||||
   * notifications/flush
 | 
			
		||||
   * @description No description provided.
 | 
			
		||||
   *
 | 
			
		||||
   * **Credential required**: *Yes* / **Permission**: *write:notifications*
 | 
			
		||||
   */
 | 
			
		||||
  'notifications/flush': {
 | 
			
		||||
    responses: {
 | 
			
		||||
      /** @description OK (without any results) */
 | 
			
		||||
      204: {
 | 
			
		||||
        content: never;
 | 
			
		||||
      };
 | 
			
		||||
      /** @description Client error */
 | 
			
		||||
      400: {
 | 
			
		||||
        content: {
 | 
			
		||||
          'application/json': components['schemas']['Error'];
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
      /** @description Authentication error */
 | 
			
		||||
      401: {
 | 
			
		||||
        content: {
 | 
			
		||||
          'application/json': components['schemas']['Error'];
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
      /** @description Forbidden error */
 | 
			
		||||
      403: {
 | 
			
		||||
        content: {
 | 
			
		||||
          'application/json': components['schemas']['Error'];
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
      /** @description I'm Ai */
 | 
			
		||||
      418: {
 | 
			
		||||
        content: {
 | 
			
		||||
          'application/json': components['schemas']['Error'];
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
      /** @description Internal server error */
 | 
			
		||||
      500: {
 | 
			
		||||
        content: {
 | 
			
		||||
          'application/json': components['schemas']['Error'];
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
  /**
 | 
			
		||||
   * notifications/mark-all-as-read
 | 
			
		||||
   * @description No description provided.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,7 @@ export type Channels = {
 | 
			
		|||
			unreadNotification: (payload: Notification) => void;
 | 
			
		||||
			unreadMention: (payload: Note['id']) => void;
 | 
			
		||||
			readAllUnreadMentions: () => void;
 | 
			
		||||
			notificationFlushed: () => void;
 | 
			
		||||
			unreadSpecifiedNote: (payload: Note['id']) => void;
 | 
			
		||||
			readAllUnreadSpecifiedNotes: () => void;
 | 
			
		||||
			readAllAntennas: () => void;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue