From 1af40810900d0eea9be563f80be48a9d071026e2 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 29 Mar 2025 15:00:29 +0900
Subject: enhance(frontend): disable horizontal swipe for
 timeline/notifications to improve ux

---
 packages/frontend/src/components/MkNote.vue | 2 --
 1 file changed, 2 deletions(-)

(limited to 'packages/frontend/src/components/MkNote.vue')

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 07da1bd4d9..91aed351c5 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -14,8 +14,6 @@ SPDX-License-Identifier: AGPL-3.0-only
 >
 	<MkNoteSub v-if="appearNote.reply && !renoteCollapsed" :note="appearNote.reply" :class="$style.replyTo"/>
 	<div v-if="pinned" :class="$style.tip"><i class="ti ti-pin"></i> {{ i18n.ts.pinnedNote }}</div>
-	<!--<div v-if="appearNote._prId_" class="tip"><i class="ti ti-speakerphone"></i> {{ i18n.ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ i18n.ts.hideThisNote }} <i class="ti ti-x"></i></button></div>-->
-	<!--<div v-if="appearNote._featuredId_" class="tip"><i class="ti ti-bolt"></i> {{ i18n.ts.featured }}</div>-->
 	<div v-if="isRenote" :class="$style.renote">
 		<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
 		<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
-- 
cgit v1.2.3-freya


From d9012740a17ea37f45a5354551d29daf0e2f00f0 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 29 Mar 2025 20:56:59 +0900
Subject: enhance(frontend):
 アイコンのスクロール追従を無効化してパフォーマンス向上できるように
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGELOG.md                                       |   1 +
 locales/index.d.ts                                 |   4 +
 locales/ja-JP.yml                                  |   1 +
 packages/frontend/src/components/MkNote.vue        |  16 ++-
 packages/frontend/src/os.ts                        |   4 +-
 .../frontend/src/pages/settings/preferences.vue    | 122 +++++++++++--------
 packages/frontend/src/preferences/def.ts           |   3 +
 .../src/utility/autogen/settings-search-index.ts   | 134 +++++++++++----------
 8 files changed, 167 insertions(+), 118 deletions(-)

(limited to 'packages/frontend/src/components/MkNote.vue')

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ff77553206..7841db6208 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -38,6 +38,7 @@
 - Enhance: プラグインの管理が強化されました
   - インストール/アンインストール/設定の変更時にリロード不要になりました
 - Enhance: ログアウト時、ブラウザに保存されたWebクライアントのデータを全て消去するように
+- Enhance: アイコンのスクロール追従を無効化してパフォーマンス向上できるように
 - Enhance: CWの注釈テキストが入力されていない場合, Postボタンを非アクティブに
 - Enhance: CWを無効にした場合, 注釈テキストが最大入力文字数を超えていても投稿できるように
 - Enhance: テーマ設定画面のデザインを改善
diff --git a/locales/index.d.ts b/locales/index.d.ts
index d7b1c3b9b0..3dfd0e6029 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -5634,6 +5634,10 @@ export interface Locale extends ILocale {
          * 有効にすると、一部のシチュエーションでのユーザビリティが低下する場合があります。
          */
         "makeEveryTextElementsSelectable_description": string;
+        /**
+         * アイコンをスクロールに追従させる
+         */
+        "useStickyIcons": string;
         /**
          * ナビゲーションバーに副ボタンを表示
          */
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 7ab6c24d82..eb1505270c 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1409,6 +1409,7 @@ _settings:
   timelineAndNote: "タイムラインとノート"
   makeEveryTextElementsSelectable: "全てのテキスト要素を選択可能にする"
   makeEveryTextElementsSelectable_description: "有効にすると、一部のシチュエーションでのユーザビリティが低下する場合があります。"
+  useStickyIcons: "アイコンをスクロールに追従させる"
   showNavbarSubButtons: "ナビゲーションバーに副ボタンを表示"
   ifOn: "オンのとき"
   ifOff: "オフのとき"
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 91aed351c5..8840a6a8bf 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	</div>
 	<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
 		<div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div>
-		<MkAvatar :class="$style.avatar" :user="appearNote.user" :link="!mock" :preview="!mock"/>
+		<MkAvatar :class="[$style.avatar, prefer.s.useStickyIcons ? $style.useSticky : null]" :user="appearNote.user" :link="!mock" :preview="!mock"/>
 		<div :class="$style.main">
 			<MkNoteHeader :note="appearNote" :mini="true"/>
 			<MkInstanceTicker v-if="showTicker" :host="appearNote.user.host" :instance="appearNote.user.instance"/>
@@ -850,9 +850,12 @@ function emitUpdReaction(emoji: string, delta: number) {
 	margin: 0 14px 0 0;
 	width: 58px;
 	height: 58px;
-	position: sticky !important;
-	top: calc(22px + var(--MI-stickyTop, 0px));
-	left: 0;
+
+	&.useSticky {
+		position: sticky !important;
+		top: calc(22px + var(--MI-stickyTop, 0px));
+		left: 0;
+	}
 }
 
 .main {
@@ -1039,7 +1042,10 @@ function emitUpdReaction(emoji: string, delta: number) {
 		margin: 0 10px 0 0;
 		width: 46px;
 		height: 46px;
-		top: calc(14px + var(--MI-stickyTop, 0px));
+
+		&.useSticky {
+			top: calc(14px + var(--MI-stickyTop, 0px));
+		}
 	}
 }
 
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 7f4f7c5be3..63298d9407 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -13,6 +13,8 @@ import type { ComponentProps as CP } from 'vue-component-type-helpers';
 import type { Form, GetFormResultType } from '@/utility/form.js';
 import type { MenuItem } from '@/types/menu.js';
 import type { PostFormProps } from '@/types/post-form.js';
+import type MkRoleSelectDialog_TypeReferenceOnly from '@/components/MkRoleSelectDialog.vue';
+import type MkEmojiPickerDialog_TypeReferenceOnly from '@/components/MkEmojiPickerDialog.vue';
 import { misskeyApi } from '@/utility/misskey-api.js';
 import { prefer } from '@/preferences.js';
 import { i18n } from '@/i18n.js';
@@ -23,8 +25,6 @@ import MkToast from '@/components/MkToast.vue';
 import MkDialog from '@/components/MkDialog.vue';
 import MkPopupMenu from '@/components/MkPopupMenu.vue';
 import MkContextMenu from '@/components/MkContextMenu.vue';
-import type MkRoleSelectDialog_TypeReferenceOnly from '@/components/MkRoleSelectDialog.vue';
-import type MkEmojiPickerDialog_TypeReferenceOnly from '@/components/MkEmojiPickerDialog.vue';
 import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
 import { pleaseLogin } from '@/utility/please-login.js';
 import { showMovedDialog } from '@/utility/show-moved-dialog.js';
diff --git a/packages/frontend/src/pages/settings/preferences.vue b/packages/frontend/src/pages/settings/preferences.vue
index 6fe5a50e19..7e7ed21dd5 100644
--- a/packages/frontend/src/pages/settings/preferences.vue
+++ b/packages/frontend/src/pages/settings/preferences.vue
@@ -42,22 +42,6 @@ SPDX-License-Identifier: AGPL-3.0-only
 						</SearchMarker>
 
 						<div class="_gaps_s">
-							<SearchMarker :keywords="['blur']">
-								<MkPreferenceContainer k="useBlurEffect">
-									<MkSwitch v-model="useBlurEffect">
-										<template #label><SearchLabel>{{ i18n.ts.useBlurEffect }}</SearchLabel></template>
-									</MkSwitch>
-								</MkPreferenceContainer>
-							</SearchMarker>
-
-							<SearchMarker :keywords="['blur', 'modal']">
-								<MkPreferenceContainer k="useBlurEffectForModal">
-									<MkSwitch v-model="useBlurEffectForModal">
-										<template #label><SearchLabel>{{ i18n.ts.useBlurEffectForModal }}</SearchLabel></template>
-									</MkSwitch>
-								</MkPreferenceContainer>
-							</SearchMarker>
-
 							<SearchMarker :keywords="['avatar', 'icon', 'decoration', 'show']">
 								<MkPreferenceContainer k="showAvatarDecorations">
 									<MkSwitch v-model="showAvatarDecorations">
@@ -395,40 +379,6 @@ SPDX-License-Identifier: AGPL-3.0-only
 				</MkFolder>
 			</SearchMarker>
 
-			<SearchMarker :keywords="['datasaver']">
-				<MkFolder>
-					<template #label><SearchLabel>{{ i18n.ts.dataSaver }}</SearchLabel></template>
-					<template #icon><i class="ti ti-antenna-bars-3"></i></template>
-
-					<div class="_gaps_m">
-						<MkInfo>{{ i18n.ts.reloadRequiredToApplySettings }}</MkInfo>
-
-						<div class="_buttons">
-							<MkButton inline @click="enableAllDataSaver">{{ i18n.ts.enableAll }}</MkButton>
-							<MkButton inline @click="disableAllDataSaver">{{ i18n.ts.disableAll }}</MkButton>
-						</div>
-						<div class="_gaps_m">
-							<MkSwitch v-model="dataSaver.media">
-								{{ i18n.ts._dataSaver._media.title }}
-								<template #caption>{{ i18n.ts._dataSaver._media.description }}</template>
-							</MkSwitch>
-							<MkSwitch v-model="dataSaver.avatar">
-								{{ i18n.ts._dataSaver._avatar.title }}
-								<template #caption>{{ i18n.ts._dataSaver._avatar.description }}</template>
-							</MkSwitch>
-							<MkSwitch v-model="dataSaver.urlPreview">
-								{{ i18n.ts._dataSaver._urlPreview.title }}
-								<template #caption>{{ i18n.ts._dataSaver._urlPreview.description }}</template>
-							</MkSwitch>
-							<MkSwitch v-model="dataSaver.code">
-								{{ i18n.ts._dataSaver._code.title }}
-								<template #caption>{{ i18n.ts._dataSaver._code.description }}</template>
-							</MkSwitch>
-						</div>
-					</div>
-				</MkFolder>
-			</SearchMarker>
-
 			<SearchMarker :keywords="['chat', 'messaging']">
 				<MkFolder>
 					<template #label><SearchLabel>{{ i18n.ts.chat }}</SearchLabel></template>
@@ -468,6 +418,76 @@ SPDX-License-Identifier: AGPL-3.0-only
 				</MkFolder>
 			</SearchMarker>
 
+			<SearchMarker :keywords="['performance']">
+				<MkFolder>
+					<template #label><SearchLabel>{{ i18n.ts.performance }}</SearchLabel></template>
+					<template #icon><i class="ti ti-battery-vertical-eco"></i></template>
+
+					<div class="_gaps_s">
+						<SearchMarker :keywords="['blur']">
+							<MkPreferenceContainer k="useBlurEffect">
+								<MkSwitch v-model="useBlurEffect">
+									<template #label><SearchLabel>{{ i18n.ts.useBlurEffect }}</SearchLabel></template>
+									<template #caption><SearchLabel>{{ i18n.ts.turnOffToImprovePerformance }}</SearchLabel></template>
+								</MkSwitch>
+							</MkPreferenceContainer>
+						</SearchMarker>
+
+						<SearchMarker :keywords="['blur', 'modal']">
+							<MkPreferenceContainer k="useBlurEffectForModal">
+								<MkSwitch v-model="useBlurEffectForModal">
+									<template #label><SearchLabel>{{ i18n.ts.useBlurEffectForModal }}</SearchLabel></template>
+									<template #caption><SearchLabel>{{ i18n.ts.turnOffToImprovePerformance }}</SearchLabel></template>
+								</MkSwitch>
+							</MkPreferenceContainer>
+						</SearchMarker>
+
+						<SearchMarker :keywords="['sticky']">
+							<MkPreferenceContainer k="useStickyIcons">
+								<MkSwitch v-model="useStickyIcons">
+									<template #label><SearchLabel>{{ i18n.ts._settings.useStickyIcons }}</SearchLabel></template>
+									<template #caption><SearchLabel>{{ i18n.ts.turnOffToImprovePerformance }}</SearchLabel></template>
+								</MkSwitch>
+							</MkPreferenceContainer>
+						</SearchMarker>
+					</div>
+				</MkFolder>
+			</SearchMarker>
+
+			<SearchMarker :keywords="['datasaver']">
+				<MkFolder>
+					<template #label><SearchLabel>{{ i18n.ts.dataSaver }}</SearchLabel></template>
+					<template #icon><i class="ti ti-antenna-bars-3"></i></template>
+
+					<div class="_gaps_m">
+						<MkInfo>{{ i18n.ts.reloadRequiredToApplySettings }}</MkInfo>
+
+						<div class="_buttons">
+							<MkButton inline @click="enableAllDataSaver">{{ i18n.ts.enableAll }}</MkButton>
+							<MkButton inline @click="disableAllDataSaver">{{ i18n.ts.disableAll }}</MkButton>
+						</div>
+						<div class="_gaps_m">
+							<MkSwitch v-model="dataSaver.media">
+								{{ i18n.ts._dataSaver._media.title }}
+								<template #caption>{{ i18n.ts._dataSaver._media.description }}</template>
+							</MkSwitch>
+							<MkSwitch v-model="dataSaver.avatar">
+								{{ i18n.ts._dataSaver._avatar.title }}
+								<template #caption>{{ i18n.ts._dataSaver._avatar.description }}</template>
+							</MkSwitch>
+							<MkSwitch v-model="dataSaver.urlPreview">
+								{{ i18n.ts._dataSaver._urlPreview.title }}
+								<template #caption>{{ i18n.ts._dataSaver._urlPreview.description }}</template>
+							</MkSwitch>
+							<MkSwitch v-model="dataSaver.code">
+								{{ i18n.ts._dataSaver._code.title }}
+								<template #caption>{{ i18n.ts._dataSaver._code.description }}</template>
+							</MkSwitch>
+						</div>
+					</div>
+				</MkFolder>
+			</SearchMarker>
+
 			<SearchMarker :keywords="['other']">
 				<MkFolder>
 					<template #label><SearchLabel>{{ i18n.ts.other }}</SearchLabel></template>
@@ -650,6 +670,7 @@ const useBlurEffect = prefer.model('useBlurEffect');
 const defaultFollowWithReplies = prefer.model('defaultFollowWithReplies');
 const chatShowSenderName = prefer.model('chat.showSenderName');
 const chatSendOnEnter = prefer.model('chat.sendOnEnter');
+const useStickyIcons = prefer.model('useStickyIcons');
 
 watch(lang, () => {
 	miLocalStorage.setItem('lang', lang.value as string);
@@ -678,6 +699,7 @@ watch([
 	highlightSensitiveMedia,
 	enableSeasonalScreenEffect,
 	chatShowSenderName,
+	useStickyIcons,
 ], async () => {
 	await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
 });
diff --git a/packages/frontend/src/preferences/def.ts b/packages/frontend/src/preferences/def.ts
index 9fa4e6af35..37fa9471ee 100644
--- a/packages/frontend/src/preferences/def.ts
+++ b/packages/frontend/src/preferences/def.ts
@@ -198,6 +198,9 @@ export const PREF_DEF = {
 	useBlurEffect: {
 		default: DEFAULT_DEVICE_KIND === 'desktop',
 	},
+	useStickyIcons: {
+		default: true,
+	},
 	showFixedPostForm: {
 		default: false,
 	},
diff --git a/packages/frontend/src/utility/autogen/settings-search-index.ts b/packages/frontend/src/utility/autogen/settings-search-index.ts
index 8ec9ef99c9..9e1f41e3c7 100644
--- a/packages/frontend/src/utility/autogen/settings-search-index.ts
+++ b/packages/frontend/src/utility/autogen/settings-search-index.ts
@@ -290,51 +290,41 @@ export const searchIndexes: SearchIndexItem[] = [
 					},
 					{
 						id: 'lfI3yMX9g',
-						label: i18n.ts.useBlurEffect,
-						keywords: ['blur'],
-					},
-					{
-						id: '31Y4IcGEf',
-						label: i18n.ts.useBlurEffectForModal,
-						keywords: ['blur', 'modal'],
-					},
-					{
-						id: '78q2asrLS',
 						label: i18n.ts.showAvatarDecorations,
 						keywords: ['avatar', 'icon', 'decoration', 'show'],
 					},
 					{
-						id: 'zydOfGYip',
+						id: '31Y4IcGEf',
 						label: i18n.ts.alwaysConfirmFollow,
 						keywords: ['follow', 'confirm', 'always'],
 					},
 					{
-						id: 'wqpOC22Zm',
+						id: '78q2asrLS',
 						label: i18n.ts.highlightSensitiveMedia,
 						keywords: ['highlight', 'sensitive', 'nsfw', 'image', 'photo', 'picture', 'media', 'thumbnail'],
 					},
 					{
-						id: 'c98gbF9c6',
+						id: 'zydOfGYip',
 						label: i18n.ts.confirmWhenRevealingSensitiveMedia,
 						keywords: ['sensitive', 'nsfw', 'media', 'image', 'photo', 'picture', 'attachment', 'confirm'],
 					},
 					{
-						id: '4LxdiOMNh',
+						id: 'wqpOC22Zm',
 						label: i18n.ts.enableAdvancedMfm,
 						keywords: ['mfm', 'enable', 'show', 'advanced'],
 					},
 					{
-						id: '9gTCaLkIf',
+						id: 'c98gbF9c6',
 						label: i18n.ts.enableInfiniteScroll,
 						keywords: ['auto', 'load', 'auto', 'more', 'scroll'],
 					},
 					{
-						id: 'jmJT0twuJ',
+						id: '6ANRSOaNg',
 						label: i18n.ts.emojiStyle,
 						keywords: ['emoji', 'style', 'native', 'system', 'fluent', 'twemoji'],
 					},
 					{
-						id: 'igFN7RIUa',
+						id: 'wo0s0CaI1',
 						label: i18n.ts.pinnedList,
 						keywords: ['pinned', 'list'],
 					},
@@ -343,85 +333,85 @@ export const searchIndexes: SearchIndexItem[] = [
 				keywords: ['general'],
 			},
 			{
-				id: 'ufc2X9voy',
+				id: 'l78F2W9Ok',
 				children: [
 					{
-						id: 'd2H4E5ys6',
+						id: 'iOJ3Crlky',
 						label: i18n.ts.showFixedPostForm,
 						keywords: ['post', 'form', 'timeline'],
 					},
 					{
-						id: '1LHOhDKGW',
+						id: 'CQldliCSi',
 						label: i18n.ts.showFixedPostFormInChannel,
 						keywords: ['post', 'form', 'timeline', 'channel'],
 					},
 					{
-						id: 'DSzwvTp7i',
+						id: 'd2H4E5ys6',
 						label: i18n.ts.collapseRenotes,
 						keywords: ['renote', i18n.ts.collapseRenotesDescription],
 					},
 					{
-						id: 'jb3HUeyrx',
+						id: 'yb11lSY1G',
 						label: i18n.ts.showGapBetweenNotesInTimeline,
 						keywords: ['note', 'timeline', 'gap'],
 					},
 					{
-						id: '2LNjwv1cr',
+						id: 'fL49Zxe9i',
 						label: i18n.ts.disableStreamingTimeline,
 						keywords: ['disable', 'streaming', 'timeline'],
 					},
 					{
-						id: '7W6g8Dcqz',
+						id: 'ykifk3NHS',
 						label: i18n.ts.showNoteActionsOnlyHover,
 						keywords: ['hover', 'show', 'footer', 'action'],
 					},
 					{
-						id: 'uAOoH3LFF',
+						id: 'tLGyaQagB',
 						label: i18n.ts.showClipButtonInNoteFooter,
 						keywords: ['footer', 'action', 'clip', 'show'],
 					},
 					{
-						id: 'eCiyZLC8n',
+						id: '7W6g8Dcqz',
 						label: i18n.ts.showReactionsCount,
 						keywords: ['reaction', 'count', 'show'],
 					},
 					{
-						id: '68u9uRmFP',
+						id: 'uAOoH3LFF',
 						label: i18n.ts.confirmOnReact,
 						keywords: ['reaction', 'confirm'],
 					},
 					{
-						id: 'rHWm4sXIe',
+						id: 'eCiyZLC8n',
 						label: i18n.ts.loadRawImages,
 						keywords: ['image', 'photo', 'picture', 'media', 'thumbnail', 'quality', 'raw', 'attachment'],
 					},
 					{
-						id: '9L2XGJw7e',
+						id: '68u9uRmFP',
 						label: i18n.ts.useReactionPickerForContextMenu,
 						keywords: ['reaction', 'picker', 'contextmenu', 'open'],
 					},
 					{
-						id: 'uIMCIK7kG',
+						id: 'yxehrHZ6x',
 						label: i18n.ts.reactionsDisplaySize,
 						keywords: ['reaction', 'size', 'scale', 'display'],
 					},
 					{
-						id: 'uMckjO9bz',
+						id: 'gi8ILaE2Z',
 						label: i18n.ts.limitWidthOfReaction,
 						keywords: ['reaction', 'size', 'scale', 'display', 'width', 'limit'],
 					},
 					{
-						id: 'yeghU4qiH',
+						id: 'cEQJZ7DQG',
 						label: i18n.ts.mediaListWithOneImageAppearance,
 						keywords: ['attachment', 'image', 'photo', 'picture', 'media', 'thumbnail', 'list', 'size', 'height'],
 					},
 					{
-						id: 'yYSOPoAKE',
+						id: 'haX4QVulD',
 						label: i18n.ts.instanceTicker,
 						keywords: ['ticker', 'information', 'label', 'instance', 'server', 'host', 'federation'],
 					},
 					{
-						id: 'iOHiIu32L',
+						id: 'pneYnQekL',
 						label: i18n.ts.displayOfSensitiveMedia,
 						keywords: ['attachment', 'image', 'photo', 'picture', 'media', 'thumbnail', 'nsfw', 'sensitive', 'display', 'show', 'hide', 'visibility'],
 					},
@@ -430,25 +420,25 @@ export const searchIndexes: SearchIndexItem[] = [
 				keywords: ['timeline', 'note'],
 			},
 			{
-				id: 'eROFRMtXv',
+				id: 'eJ2jme16W',
 				children: [
 					{
-						id: 'BaQfrVO82',
+						id: 'ErMQr6LQk',
 						label: i18n.ts.keepCw,
 						keywords: ['remember', 'keep', 'note', 'cw'],
 					},
 					{
-						id: 'vFerPo2he',
+						id: 'zrJicawH9',
 						label: i18n.ts.rememberNoteVisibility,
 						keywords: ['remember', 'keep', 'note', 'visibility'],
 					},
 					{
-						id: 'dcAC0yJcH',
+						id: 'BaQfrVO82',
 						label: i18n.ts.enableQuickAddMfmFunction,
 						keywords: ['mfm', 'enable', 'show', 'advanced', 'picker', 'form', 'function', 'fn'],
 					},
 					{
-						id: 'bECeWZVMb',
+						id: 'C2WYcVM1d',
 						label: i18n.ts.defaultNoteVisibility,
 						keywords: ['default', 'note', 'visibility'],
 					},
@@ -457,20 +447,20 @@ export const searchIndexes: SearchIndexItem[] = [
 				keywords: ['post', 'form'],
 			},
 			{
-				id: 'tsSP93Cc6',
+				id: 'sQXSA6gik',
 				children: [
 					{
-						id: 'dtw8FepYL',
+						id: 'rICn8stqk',
 						label: i18n.ts.useGroupedNotifications,
 						keywords: ['group'],
 					},
 					{
-						id: 'eb0yCYJTn',
+						id: 'xFmAg2tDe',
 						label: i18n.ts.position,
 						keywords: ['position'],
 					},
 					{
-						id: '1Spt4Gpr5',
+						id: 'Ek4Cw3VPq',
 						label: i18n.ts.stackAxis,
 						keywords: ['stack', 'axis', 'direction'],
 					},
@@ -479,20 +469,15 @@ export const searchIndexes: SearchIndexItem[] = [
 				keywords: ['notification'],
 			},
 			{
-				id: 'SYmWxGOF',
-				label: i18n.ts.dataSaver,
-				keywords: ['datasaver'],
-			},
-			{
-				id: 'vPQPvmntL',
+				id: 'gDVCqZfxm',
 				children: [
 					{
-						id: 'zZxyXHk3A',
+						id: 'ei8Ix3s4S',
 						label: i18n.ts._settings._chat.showSenderName,
 						keywords: ['show', 'sender', 'name'],
 					},
 					{
-						id: 'omEy5Q3Ev',
+						id: '2E7vdIUQd',
 						label: i18n.ts._settings._chat.sendOnEnter,
 						keywords: ['send', 'enter', 'newline'],
 					},
@@ -501,50 +486,77 @@ export const searchIndexes: SearchIndexItem[] = [
 				keywords: ['chat', 'messaging'],
 			},
 			{
-				id: '5fy7VEy6i',
+				id: '96LnS1sxB',
+				children: [
+					{
+						id: '5h8vhCX1S',
+						label: i18n.ts.turnOffToImprovePerformance,
+						keywords: ['blur'],
+					},
+					{
+						id: 'Cbjosj3TG',
+						label: i18n.ts.turnOffToImprovePerformance,
+						keywords: ['blur', 'modal'],
+					},
+					{
+						id: 'BKndoHcCj',
+						label: i18n.ts.turnOffToImprovePerformance,
+						keywords: ['sticky'],
+					},
+				],
+				label: i18n.ts.performance,
+				keywords: ['performance'],
+			},
+			{
+				id: '4yCgcFElF',
+				label: i18n.ts.dataSaver,
+				keywords: ['datasaver'],
+			},
+			{
+				id: 'DILm2LlCn',
 				children: [
 					{
-						id: 'EosiWZvak',
+						id: 'Fd0rFTSry',
 						label: i18n.ts.squareAvatars,
 						keywords: ['avatar', 'icon', 'square'],
 					},
 					{
-						id: 'qY5xTzl35',
+						id: 'xNsLokqeA',
 						label: i18n.ts.seasonalScreenEffect,
 						keywords: ['effect', 'show'],
 					},
 					{
-						id: '2VSnj81vC',
+						id: 'sZcalFBE8',
 						label: i18n.ts.openImageInNewTab,
 						keywords: ['image', 'photo', 'picture', 'media', 'thumbnail', 'new', 'tab'],
 					},
 					{
-						id: 'hdQa7W2H1',
+						id: 'Eh7vTluDO',
 						label: i18n.ts.withRepliesByDefaultForNewlyFollowed,
 						keywords: ['follow', 'replies'],
 					},
 					{
-						id: 'nnj4DkjhP',
+						id: 'vTRSKf1JA',
 						label: i18n.ts.whenServerDisconnected,
 						keywords: ['server', 'disconnect', 'reconnect', 'reload', 'streaming'],
 					},
 					{
-						id: 'Eh7vTluDO',
+						id: 'zlO5cBZFH',
 						label: i18n.ts.numberOfPageCache,
 						keywords: ['cache', 'page'],
 					},
 					{
-						id: 'vTRSKf1JA',
+						id: 'huQ8nc4iD',
 						label: i18n.ts.forceShowAds,
 						keywords: ['ad', 'show'],
 					},
 					{
-						id: 'dwhQfcLGt',
+						id: 'nJWfqwQ4R',
 						label: i18n.ts.hemisphere,
 						keywords: [],
 					},
 					{
-						id: 'Ar1lj7f7U',
+						id: 'kwEEgTlwR',
 						label: i18n.ts.additionalEmojiDictionary,
 						keywords: ['emoji', 'dictionary', 'additional', 'extra'],
 					},
-- 
cgit v1.2.3-freya


From 88c743aa3386049f2b2de1afe7fb5c125e0581f1 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sun, 30 Mar 2025 11:45:41 +0900
Subject: chore(frontend): remove unused style

---
 packages/frontend/src/components/MkNote.vue | 1 -
 1 file changed, 1 deletion(-)

(limited to 'packages/frontend/src/components/MkNote.vue')

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 8840a6a8bf..66a70c9be3 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -658,7 +658,6 @@ function emitUpdReaction(emoji: string, delta: number) {
 <style lang="scss" module>
 .root {
 	position: relative;
-	transition: box-shadow 0.1s ease;
 	font-size: 1.05em;
 	overflow: clip;
 	contain: content;
-- 
cgit v1.2.3-freya


From c03f9bff0ade3b0b31a59dd6b345434048dfcff4 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sun, 30 Mar 2025 11:52:51 +0900
Subject: 🎨
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/frontend/src/components/MkNote.vue        |  2 ++
 packages/frontend/src/components/MkNotes.vue       | 26 ++++++++++++++++++--
 .../frontend/src/components/MkNotifications.vue    | 28 +++++++++++++++++++---
 3 files changed, 51 insertions(+), 5 deletions(-)

(limited to 'packages/frontend/src/components/MkNote.vue')

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 66a70c9be3..ab70a11b9b 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -723,6 +723,8 @@ function emitUpdReaction(emoji: string, delta: number) {
 }
 
 .skipRender {
+	// TODO: これが有効だとTransitionGroupでnoteを追加するときに一瞬がくっとなってしまうのをどうにかしたい
+	// Transitionが完了するのを待ってからskipRenderを付与すれば解決しそうだけどパフォーマンス的な影響が不明
 	content-visibility: auto;
 	contain-intrinsic-size: 0 150px;
 }
diff --git a/packages/frontend/src/components/MkNotes.vue b/packages/frontend/src/components/MkNotes.vue
index 8605877a93..ad4844fd1b 100644
--- a/packages/frontend/src/components/MkNotes.vue
+++ b/packages/frontend/src/components/MkNotes.vue
@@ -13,14 +13,22 @@ SPDX-License-Identifier: AGPL-3.0-only
 	</template>
 
 	<template #default="{ items: notes }">
-		<div :class="[$style.root, { [$style.noGap]: noGap, '_gaps': !noGap }]">
+		<component
+			:is="prefer.s.animation ? TransitionGroup : 'div'" :class="[$style.root, { [$style.noGap]: noGap, '_gaps': !noGap }]"
+			:enterActiveClass="$style.transition_x_enterActive"
+			:leaveActiveClass="$style.transition_x_leaveActive"
+			:enterFromClass="$style.transition_x_enterFrom"
+			:leaveToClass="$style.transition_x_leaveTo"
+			:moveClass=" $style.transition_x_move"
+			tag="div"
+		>
 			<template v-for="(note, i) in notes" :key="note.id">
 				<MkNote :class="$style.note" :note="note" :withHardMute="true"/>
 				<div v-if="note._shouldInsertAd_" :class="$style.ad">
 					<MkAd :preferForms="['horizontal', 'horizontal-big']"/>
 				</div>
 			</template>
-		</div>
+		</component>
 	</template>
 </MkPagination>
 </template>
@@ -48,6 +56,20 @@ defineExpose({
 </script>
 
 <style lang="scss" module>
+.transition_x_move,
+.transition_x_enterActive,
+.transition_x_leaveActive {
+	transition: opacity 0.3s cubic-bezier(0,.5,.5,1), transform 0.3s cubic-bezier(0,.5,.5,1) !important;
+}
+.transition_x_enterFrom,
+.transition_x_leaveTo {
+	opacity: 0;
+	transform: translateY(-50%);
+}
+.transition_x_leaveActive {
+	position: absolute;
+}
+
 .root {
 	container-type: inline-size;
 
diff --git a/packages/frontend/src/components/MkNotifications.vue b/packages/frontend/src/components/MkNotifications.vue
index a8282fec2a..99eca35eb7 100644
--- a/packages/frontend/src/components/MkNotifications.vue
+++ b/packages/frontend/src/components/MkNotifications.vue
@@ -14,19 +14,27 @@ SPDX-License-Identifier: AGPL-3.0-only
 		</template>
 
 		<template #default="{ items: notifications }">
-			<div :class="$style.notifications">
+			<component
+				:is="prefer.s.animation ? TransitionGroup : 'div'" :class="[$style.notifications]"
+				:enterActiveClass="$style.transition_x_enterActive"
+				:leaveActiveClass="$style.transition_x_leaveActive"
+				:enterFromClass="$style.transition_x_enterFrom"
+				:leaveToClass="$style.transition_x_leaveTo"
+				:moveClass=" $style.transition_x_move"
+				tag="div"
+			>
 				<template v-for="(notification, i) in notifications" :key="notification.id">
 					<MkNote v-if="['reply', 'quote', 'mention'].includes(notification.type)" :class="$style.item" :note="notification.note" :withHardMute="true"/>
 					<XNotification v-else :class="$style.item" :notification="notification" :withTime="true" :full="true"/>
 				</template>
-			</div>
+			</component>
 		</template>
 	</MkPagination>
 </MkPullToRefresh>
 </template>
 
 <script lang="ts" setup>
-import { onUnmounted, onDeactivated, onMounted, computed, useTemplateRef, onActivated } from 'vue';
+import { onUnmounted, onMounted, computed, useTemplateRef, TransitionGroup } from 'vue';
 import * as Misskey from 'misskey-js';
 import type { notificationTypes } from '@@/js/const.js';
 import MkPagination from '@/components/MkPagination.vue';
@@ -95,6 +103,20 @@ defineExpose({
 </script>
 
 <style lang="scss" module>
+.transition_x_move,
+.transition_x_enterActive,
+.transition_x_leaveActive {
+	transition: opacity 0.3s cubic-bezier(0,.5,.5,1), transform 0.3s cubic-bezier(0,.5,.5,1) !important;
+}
+.transition_x_enterFrom,
+.transition_x_leaveTo {
+	opacity: 0;
+	transform: translateY(-50%);
+}
+.transition_x_leaveActive {
+	position: absolute;
+}
+
 .notifications {
 	container-type: inline-size;
 	background: var(--MI_THEME-panel);
-- 
cgit v1.2.3-freya

