Merge remote-tracking branch 'misskey-dev/develop' into io
This commit is contained in:
		
						commit
						7abf5dcb78
					
				|  | @ -4,7 +4,10 @@ | |||
| - | ||||
| 
 | ||||
| ### Client | ||||
| -  | ||||
| - Enhance: 自分のノートの添付ファイルから直接ファイルの詳細ページに飛べるように | ||||
| - Enhance: リアクション・いいねの総数を表示するように | ||||
| - Enhance: リアクション受け入れが「いいねのみ」の場合はリアクション絵文字一覧を表示しないように | ||||
| - Fix: 一部のページ内リンクが正しく動作しない問題を修正 | ||||
| 
 | ||||
| ### Server | ||||
| - | ||||
|  |  | |||
|  | @ -9089,6 +9089,10 @@ export interface Locale extends ILocale { | |||
|          * {n}人がリアクションしました | ||||
|          */ | ||||
|         "reactedBySomeUsers": ParameterizedString<"n">; | ||||
|         /** | ||||
|          * {n}人がいいねしました | ||||
|          */ | ||||
|         "likedBySomeUsers": ParameterizedString<"n">; | ||||
|         /** | ||||
|          * {n}人がリノートしました | ||||
|          */ | ||||
|  |  | |||
|  | @ -2403,6 +2403,7 @@ _notification: | |||
|   sendTestNotification: "テスト通知を送信する" | ||||
|   notificationWillBeDisplayedLikeThis: "通知はこのように表示されます" | ||||
|   reactedBySomeUsers: "{n}人がリアクションしました" | ||||
|   likedBySomeUsers: "{n}人がいいねしました" | ||||
|   renotedBySomeUsers: "{n}人がリノートしました" | ||||
|   followedBySomeUsers: "{n}人にフォローされました" | ||||
|   flushNotification: "通知の履歴をリセットする" | ||||
|  |  | |||
|  | @ -250,7 +250,7 @@ export class DriveFileEntityService { | |||
| 			folder: opts.detail && file.folderId ? this.driveFolderEntityService.pack(file.folderId, { | ||||
| 				detail: true, | ||||
| 			}) : null, | ||||
| 			userId: opts.withUser ? file.userId : null, | ||||
| 			userId: file.userId, | ||||
| 			user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId, me) : null, | ||||
| 		}); | ||||
| 	} | ||||
|  |  | |||
|  | @ -338,6 +338,7 @@ export class NoteEntityService implements OnModuleInit { | |||
| 			visibleUserIds: note.visibility === 'specified' ? note.visibleUserIds : undefined, | ||||
| 			renoteCount: note.renoteCount, | ||||
| 			repliesCount: note.repliesCount, | ||||
| 			reactionCount: Object.values(note.reactions).reduce((a, b) => a + b, 0), | ||||
| 			reactions: this.reactionService.convertLegacyReactions(note.reactions), | ||||
| 			reactionEmojis: this.customEmojiService.populateEmojis(reactionEmojiNames, host), | ||||
| 			reactionAndUserPairCache: opts.withReactionAndUserPairCache ? note.reactionAndUserPairCache : undefined, | ||||
|  |  | |||
|  | @ -223,6 +223,10 @@ export const packedNoteSchema = { | |||
| 				}], | ||||
| 			}, | ||||
| 		}, | ||||
| 		reactionCount: { | ||||
| 			type: 'number', | ||||
| 			optional: false, nullable: false, | ||||
| 		}, | ||||
| 		renoteCount: { | ||||
| 			type: 'number', | ||||
| 			optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -72,8 +72,8 @@ | |||
| 	//#endregion
 | ||||
| 
 | ||||
| 	//#region Script
 | ||||
| 	function importAppScript() { | ||||
| 		import(`/vite/${CLIENT_ENTRY}`) | ||||
| 	async function importAppScript() { | ||||
| 		await import(`/vite/${CLIENT_ENTRY}`) | ||||
| 			.catch(async e => { | ||||
| 				console.error(e); | ||||
| 				renderError('APP_IMPORT', e); | ||||
|  |  | |||
|  | @ -97,8 +97,6 @@ function showMenu(ev: MouseEvent) { | |||
| 
 | ||||
| 	if (iAmModerator) { | ||||
| 		menu.push({ | ||||
| 			type: 'divider', | ||||
| 		}, { | ||||
| 			text: props.audio.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive, | ||||
| 			icon: props.audio.isSensitive ? 'ti ti-eye' : 'ti ti-eye-exclamation', | ||||
| 			danger: true, | ||||
|  | @ -106,6 +104,17 @@ function showMenu(ev: MouseEvent) { | |||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	if ($i?.id === props.audio.userId) { | ||||
| 		menu.push({ | ||||
| 			type: 'divider', | ||||
| 		}, { | ||||
| 			type: 'link' as const, | ||||
| 			text: i18n.ts._fileViewer.title, | ||||
| 			icon: 'ti ti-info-circle', | ||||
| 			to: `/my/drive/file/${props.audio.id}`, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	menuShowing.value = true; | ||||
| 	os.popupMenu(menu, ev.currentTarget ?? ev.target, { | ||||
| 		align: 'right', | ||||
|  |  | |||
|  | @ -125,6 +125,13 @@ function showMenu(ev: MouseEvent) { | |||
| 		action: () => { | ||||
| 			os.apiWithDialog('drive/files/update', { fileId: props.image.id, isSensitive: true }); | ||||
| 		}, | ||||
| 	}] : []), ...($i?.id === props.image.userId ? [{ | ||||
| 		type: 'divider' as const, | ||||
| 	}, { | ||||
| 		type: 'link' as const, | ||||
| 		text: i18n.ts._fileViewer.title, | ||||
| 		icon: 'ti ti-info-circle', | ||||
| 		to: `/my/drive/file/${props.image.id}`, | ||||
| 	}] : [])], ev.currentTarget ?? ev.target); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -127,8 +127,6 @@ function showMenu(ev: MouseEvent) { | |||
| 
 | ||||
| 	if (iAmModerator) { | ||||
| 		menu.push({ | ||||
| 			type: 'divider', | ||||
| 		}, { | ||||
| 			text: props.video.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive, | ||||
| 			icon: props.video.isSensitive ? 'ti ti-eye' : 'ti ti-eye-exclamation', | ||||
| 			danger: true, | ||||
|  | @ -136,6 +134,17 @@ function showMenu(ev: MouseEvent) { | |||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	if ($i?.id === props.video.userId) { | ||||
| 		menu.push({ | ||||
| 			type: 'divider', | ||||
| 		}, { | ||||
| 			type: 'link' as const, | ||||
| 			text: i18n.ts._fileViewer.title, | ||||
| 			icon: 'ti ti-info-circle', | ||||
| 			to: `/my/drive/file/${props.video.id}`, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	menuShowing.value = true; | ||||
| 	os.popupMenu(menu, ev.currentTarget ?? ev.target, { | ||||
| 		align: 'right', | ||||
|  |  | |||
|  | @ -93,7 +93,7 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 				</div> | ||||
| 				<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA> | ||||
| 			</div> | ||||
| 			<MkReactionsViewer :note="appearNote" :maxNumber="16" @mockUpdateMyReaction="emitUpdReaction"> | ||||
| 			<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" :note="appearNote" :maxNumber="16" @mockUpdateMyReaction="emitUpdReaction"> | ||||
| 				<template #more> | ||||
| 					<div :class="$style.reactionOmitted">{{ i18n.ts.more }}</div> | ||||
| 				</template> | ||||
|  | @ -101,7 +101,7 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 			<footer :class="$style.footer"> | ||||
| 				<button :class="$style.footerButton" class="_button" @click="reply()"> | ||||
| 					<i class="ti ti-arrow-back-up"></i> | ||||
| 					<p v-if="appearNote.repliesCount > 0" :class="$style.footerButtonCount">{{ appearNote.repliesCount }}</p> | ||||
| 					<p v-if="appearNote.repliesCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.repliesCount) }}</p> | ||||
| 				</button> | ||||
| 				<button | ||||
| 					v-if="canRenote" | ||||
|  | @ -111,17 +111,17 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 					@mousedown="renote()" | ||||
| 				> | ||||
| 					<i class="ti ti-repeat"></i> | ||||
| 					<p v-if="appearNote.renoteCount > 0" :class="$style.footerButtonCount">{{ appearNote.renoteCount }}</p> | ||||
| 					<p v-if="appearNote.renoteCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.renoteCount) }}</p> | ||||
| 				</button> | ||||
| 				<button v-else :class="$style.footerButton" class="_button" disabled> | ||||
| 					<i class="ti ti-ban"></i> | ||||
| 				</button> | ||||
| 				<button v-if="appearNote.myReaction == null" ref="reactButton" :class="$style.footerButton" class="_button" @mousedown="react()"> | ||||
| 					<i v-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i> | ||||
| 				<button ref="reactButton" :class="$style.footerButton" class="_button" @click="toggleReact()"> | ||||
| 					<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--eventReactionHeart);"></i> | ||||
| 					<i v-else-if="appearNote.myReaction != null" class="ti ti-minus" style="color: var(--accent);"></i> | ||||
| 					<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i> | ||||
| 					<i v-else class="ti ti-plus"></i> | ||||
| 				</button> | ||||
| 				<button v-if="appearNote.myReaction != null" ref="reactButton" :class="$style.footerButton" class="_button" @click="undoReact(appearNote)"> | ||||
| 					<i class="ti ti-minus"></i> | ||||
| 					<p v-if="appearNote.reactionCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.reactionCount) }}</p> | ||||
| 				</button> | ||||
| 				<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" :class="$style.footerButton" class="_button" @mousedown="clip()"> | ||||
| 					<i class="ti ti-paperclip"></i> | ||||
|  | @ -169,6 +169,7 @@ import { pleaseLogin } from '@/scripts/please-login.js'; | |||
| import { focusPrev, focusNext } from '@/scripts/focus.js'; | ||||
| import { checkWordMute } from '@/scripts/check-word-mute.js'; | ||||
| import { userPage } from '@/filters/user.js'; | ||||
| import number from '@/filters/number.js'; | ||||
| import * as os from '@/os.js'; | ||||
| import * as sound from '@/scripts/sound.js'; | ||||
| import { misskeyApi } from '@/scripts/misskey-api.js'; | ||||
|  | @ -406,6 +407,14 @@ function undoReact(targetNote: Misskey.entities.Note): void { | |||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function toggleReact() { | ||||
| 	if (appearNote.value.myReaction == null) { | ||||
| 		react(); | ||||
| 	} else { | ||||
| 		undoReact(appearNote.value); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function onContextmenu(ev: MouseEvent): void { | ||||
| 	if (props.mock) { | ||||
| 		return; | ||||
|  |  | |||
|  | @ -106,10 +106,10 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 					<MkTime :time="appearNote.createdAt" mode="detail" colored/> | ||||
| 				</MkA> | ||||
| 			</div> | ||||
| 			<MkReactionsViewer ref="reactionsViewer" :note="appearNote"/> | ||||
| 			<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" ref="reactionsViewer" :note="appearNote"/> | ||||
| 			<button class="_button" :class="$style.noteFooterButton" @click="reply()"> | ||||
| 				<i class="ti ti-arrow-back-up"></i> | ||||
| 				<p v-if="appearNote.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ appearNote.repliesCount }}</p> | ||||
| 				<p v-if="appearNote.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.repliesCount) }}</p> | ||||
| 			</button> | ||||
| 			<button | ||||
| 				v-if="canRenote" | ||||
|  | @ -119,17 +119,17 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 				@mousedown="renote()" | ||||
| 			> | ||||
| 				<i class="ti ti-repeat"></i> | ||||
| 				<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ appearNote.renoteCount }}</p> | ||||
| 				<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p> | ||||
| 			</button> | ||||
| 			<button v-else class="_button" :class="$style.noteFooterButton" disabled> | ||||
| 				<i class="ti ti-ban"></i> | ||||
| 			</button> | ||||
| 			<button v-if="appearNote.myReaction == null" ref="reactButton" :class="$style.noteFooterButton" class="_button" @mousedown="react()"> | ||||
| 				<i v-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i> | ||||
| 			<button ref="reactButton" :class="$style.noteFooterButton" class="_button" @click="toggleReact()"> | ||||
| 				<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--eventReactionHeart);"></i> | ||||
| 				<i v-else-if="appearNote.myReaction != null" class="ti ti-minus" style="color: var(--accent);"></i> | ||||
| 				<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i> | ||||
| 				<i v-else class="ti ti-plus"></i> | ||||
| 			</button> | ||||
| 			<button v-if="appearNote.myReaction != null" ref="reactButton" class="_button" :class="[$style.noteFooterButton, $style.reacted]" @click="undoReact(appearNote)"> | ||||
| 				<i class="ti ti-minus"></i> | ||||
| 				<p v-if="appearNote.reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.reactionCount) }}</p> | ||||
| 			</button> | ||||
| 			<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown="clip()"> | ||||
| 				<i class="ti ti-paperclip"></i> | ||||
|  | @ -209,6 +209,7 @@ import { pleaseLogin } from '@/scripts/please-login.js'; | |||
| import { checkWordMute } from '@/scripts/check-word-mute.js'; | ||||
| import { userPage } from '@/filters/user.js'; | ||||
| import { notePage } from '@/filters/note.js'; | ||||
| import number from '@/filters/number.js'; | ||||
| import * as os from '@/os.js'; | ||||
| import { misskeyApi } from '@/scripts/misskey-api.js'; | ||||
| import * as sound from '@/scripts/sound.js'; | ||||
|  | @ -402,14 +403,22 @@ function react(viaKeyboard = false): void { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| function undoReact(note): void { | ||||
| 	const oldReaction = note.myReaction; | ||||
| function undoReact(targetNote: Misskey.entities.Note): void { | ||||
| 	const oldReaction = targetNote.myReaction; | ||||
| 	if (!oldReaction) return; | ||||
| 	misskeyApi('notes/reactions/delete', { | ||||
| 		noteId: note.id, | ||||
| 		noteId: targetNote.id, | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function toggleReact() { | ||||
| 	if (appearNote.value.myReaction == null) { | ||||
| 		react(); | ||||
| 	} else { | ||||
| 		undoReact(appearNote.value); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function onContextmenu(ev: MouseEvent): void { | ||||
| 	const isLink = (el: HTMLElement): boolean => { | ||||
| 		if (el.tagName === 'A') return true; | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 	<div :class="$style.head"> | ||||
| 		<MkAvatar v-if="['pollEnded', 'note'].includes(notification.type) && notification.note" :class="$style.icon" :user="notification.note.user" link preview/> | ||||
| 		<MkAvatar v-else-if="['roleAssigned', 'achievementEarned'].includes(notification.type)" :class="$style.icon" :user="$i" link preview/> | ||||
| 		<div v-else-if="notification.type === 'reaction:grouped' && notification.note.reactionAcceptance === 'likeOnly'" :class="[$style.icon, $style.icon_reactionGroupHeart]"><i class="ti ti-heart" style="line-height: 1;"></i></div> | ||||
| 		<div v-else-if="notification.type === 'reaction:grouped'" :class="[$style.icon, $style.icon_reactionGroup]"><i class="ti ti-plus" style="line-height: 1;"></i></div> | ||||
| 		<div v-else-if="notification.type === 'renote:grouped'" :class="[$style.icon, $style.icon_renoteGroup]"><i class="ti ti-repeat" style="line-height: 1;"></i></div> | ||||
| 		<img v-else-if="notification.type === 'test'" :class="$style.icon" :src="infoImageUrl"/> | ||||
|  | @ -57,6 +58,7 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 			<span v-else-if="notification.type === 'achievementEarned'">{{ i18n.ts._notification.achievementEarned }}</span> | ||||
| 			<span v-else-if="notification.type === 'test'">{{ i18n.ts._notification.testNotification }}</span> | ||||
| 			<MkA v-else-if="notification.type === 'follow' || notification.type === 'mention' || notification.type === 'reply' || notification.type === 'renote' || notification.type === 'quote' || notification.type === 'reaction' || notification.type === 'receiveFollowRequest' || notification.type === 'followRequestAccepted'" v-user-preview="notification.user.id" :class="$style.headerName" :to="userPage(notification.user)"><MkUserName :user="notification.user"/></MkA> | ||||
| 			<span v-else-if="notification.type === 'reaction:grouped' && notification.note.reactionAcceptance === 'likeOnly'">{{ i18n.tsx._notification.likedBySomeUsers({ n: notification.reactions.length }) }}</span> | ||||
| 			<span v-else-if="notification.type === 'reaction:grouped'">{{ i18n.tsx._notification.reactedBySomeUsers({ n: notification.reactions.length }) }}</span> | ||||
| 			<span v-else-if="notification.type === 'renote:grouped'">{{ i18n.tsx._notification.renotedBySomeUsers({ n: notification.users.length }) }}</span> | ||||
| 			<span v-else-if="notification.type === 'app'">{{ notification.header }}</span> | ||||
|  | @ -201,6 +203,7 @@ const rejectFollowRequest = () => { | |||
| } | ||||
| 
 | ||||
| .icon_reactionGroup, | ||||
| .icon_reactionGroupHeart, | ||||
| .icon_renoteGroup { | ||||
| 	display: grid; | ||||
| 	align-items: center; | ||||
|  | @ -213,11 +216,15 @@ const rejectFollowRequest = () => { | |||
| } | ||||
| 
 | ||||
| .icon_reactionGroup { | ||||
| 	background: #e99a0b; | ||||
| 	background: var(--eventReaction); | ||||
| } | ||||
| 
 | ||||
| .icon_reactionGroupHeart { | ||||
| 	background: var(--eventReactionHeart); | ||||
| } | ||||
| 
 | ||||
| .icon_renoteGroup { | ||||
| 	background: #36d298; | ||||
| 	background: var(--eventRenote); | ||||
| } | ||||
| 
 | ||||
| .icon_app { | ||||
|  | @ -246,49 +253,49 @@ const rejectFollowRequest = () => { | |||
| 
 | ||||
| .t_follow, .t_followRequestAccepted, .t_receiveFollowRequest { | ||||
| 	padding: 3px; | ||||
| 	background: #36aed2; | ||||
| 	background: var(--eventFollow); | ||||
| 	pointer-events: none; | ||||
| } | ||||
| 
 | ||||
| .t_renote { | ||||
| 	padding: 3px; | ||||
| 	background: #36d298; | ||||
| 	background: var(--eventRenote); | ||||
| 	pointer-events: none; | ||||
| } | ||||
| 
 | ||||
| .t_quote { | ||||
| 	padding: 3px; | ||||
| 	background: #36d298; | ||||
| 	background: var(--eventRenote); | ||||
| 	pointer-events: none; | ||||
| } | ||||
| 
 | ||||
| .t_reply { | ||||
| 	padding: 3px; | ||||
| 	background: #007aff; | ||||
| 	background: var(--eventReply); | ||||
| 	pointer-events: none; | ||||
| } | ||||
| 
 | ||||
| .t_mention { | ||||
| 	padding: 3px; | ||||
| 	background: #88a6b7; | ||||
| 	background: var(--eventOther); | ||||
| 	pointer-events: none; | ||||
| } | ||||
| 
 | ||||
| .t_pollEnded { | ||||
| 	padding: 3px; | ||||
| 	background: #88a6b7; | ||||
| 	background: var(--eventOther); | ||||
| 	pointer-events: none; | ||||
| } | ||||
| 
 | ||||
| .t_achievementEarned { | ||||
| 	padding: 3px; | ||||
| 	background: #cb9a11; | ||||
| 	background: var(--eventAchievement); | ||||
| 	pointer-events: none; | ||||
| } | ||||
| 
 | ||||
| .t_roleAssigned { | ||||
| 	padding: 3px; | ||||
| 	background: #88a6b7; | ||||
| 	background: var(--eventOther); | ||||
| 	pointer-events: none; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -63,6 +63,7 @@ const exampleNote = reactive<Misskey.entities.Note>({ | |||
| 	reactionAcceptance: null, | ||||
| 	renoteCount: 0, | ||||
| 	repliesCount: 1, | ||||
| 	reactionCount: 0, | ||||
| 	reactions: {}, | ||||
| 	reactionEmojis: {}, | ||||
| 	fileIds: [], | ||||
|  |  | |||
|  | @ -68,6 +68,7 @@ const exampleCWNote = reactive<Misskey.entities.Note>({ | |||
| 	reactionAcceptance: null, | ||||
| 	renoteCount: 0, | ||||
| 	repliesCount: 1, | ||||
| 	reactionCount: 0, | ||||
| 	reactions: {}, | ||||
| 	reactionEmojis: {}, | ||||
| 	fileIds: [], | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ const exampleNote = reactive<Misskey.entities.Note>({ | |||
| 	reactionAcceptance: null, | ||||
| 	renoteCount: 0, | ||||
| 	repliesCount: 1, | ||||
| 	reactionCount: 0, | ||||
| 	reactions: {}, | ||||
| 	reactionEmojis: {}, | ||||
| 	fileIds: ['0000000002'], | ||||
|  |  | |||
|  | @ -373,7 +373,7 @@ export class Router extends EventEmitter<RouterEvent> implements IRouter { | |||
| 		this.currentRoute.value = res.route; | ||||
| 		this.currentKey = res.route.globalCacheKey ?? key ?? path; | ||||
| 
 | ||||
| 		if (emitChange) { | ||||
| 		if (emitChange && res.route.path !== '/:(*)') { | ||||
| 			this.emit('change', { | ||||
| 				beforePath, | ||||
| 				path, | ||||
|  | @ -408,13 +408,17 @@ export class Router extends EventEmitter<RouterEvent> implements IRouter { | |||
| 			if (cancel) return; | ||||
| 		} | ||||
| 		const res = this.navigate(path, null); | ||||
| 		this.emit('push', { | ||||
| 			beforePath, | ||||
| 			path: res._parsedRoute.fullPath, | ||||
| 			route: res.route, | ||||
| 			props: res.props, | ||||
| 			key: this.currentKey, | ||||
| 		}); | ||||
| 		if (res.route.path === '/:(*)') { | ||||
| 			location.href = path; | ||||
| 		} else { | ||||
| 			this.emit('push', { | ||||
| 				beforePath, | ||||
| 				path: res._parsedRoute.fullPath, | ||||
| 				route: res.route, | ||||
| 				props: res.props, | ||||
| 				key: this.currentKey, | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public replace(path: string, key?: string | null) { | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ export function useNoteCapture(props: { | |||
| 				const currentCount = (note.value.reactions || {})[reaction] || 0; | ||||
| 
 | ||||
| 				note.value.reactions[reaction] = currentCount + 1; | ||||
| 				note.value.reactionCount += 1; | ||||
| 
 | ||||
| 				if ($i && (body.userId === $i.id)) { | ||||
| 					note.value.myReaction = reaction; | ||||
|  | @ -49,6 +50,7 @@ export function useNoteCapture(props: { | |||
| 				const currentCount = (note.value.reactions || {})[reaction] || 0; | ||||
| 
 | ||||
| 				note.value.reactions[reaction] = Math.max(0, currentCount - 1); | ||||
| 				note.value.reactionCount = Math.max(0, note.value.reactionCount - 1); | ||||
| 				if (note.value.reactions[reaction] === 0) delete note.value.reactions[reaction]; | ||||
| 
 | ||||
| 				if ($i && (body.userId === $i.id)) { | ||||
|  |  | |||
|  | @ -22,6 +22,13 @@ | |||
| 	} | ||||
| 
 | ||||
| 	//--ad: rgb(255 169 0 / 10%); | ||||
| 	--eventFollow: #36aed2; | ||||
| 	--eventRenote: #36d298; | ||||
| 	--eventReply: #007aff; | ||||
| 	--eventReactionHeart: #dd2e44; | ||||
| 	--eventReaction: #e99a0b; | ||||
| 	--eventAchievement: #cb9a11; | ||||
| 	--eventOther: #88a6b7; | ||||
| } | ||||
| 
 | ||||
| ::selection { | ||||
|  |  | |||
|  | @ -48,6 +48,9 @@ const devConfig = { | |||
| 			}, | ||||
| 			'/url': httpUrl, | ||||
| 			'/proxy': httpUrl, | ||||
| 			'/_info_card_': httpUrl, | ||||
| 			'/bios': httpUrl, | ||||
| 			'/cli': httpUrl, | ||||
| 		}, | ||||
| 	}, | ||||
| 	build: { | ||||
|  |  | |||
|  | @ -4095,6 +4095,7 @@ export type components = { | |||
|       reactions: { | ||||
|         [key: string]: number; | ||||
|       }; | ||||
|       reactionCount: number; | ||||
|       renoteCount: number; | ||||
|       repliesCount: number; | ||||
|       uri?: string; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue