diff --git a/locales/en-US.yml b/locales/en-US.yml
index 3f04adb676..333e987811 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -1298,6 +1298,7 @@ showDetailTimeWhenHover: "Hover the timestamp of the note to expand the detailed
 noteClickToOpen: "Click to open note details"
 enableFallbackReactButton: "Enable fallback reaction button"
 enableMFMCheatsheet: "Enable MFM Cheatsheet in post form"
+enableUndoClearPostForm: "Enable undo & clear button in post form"
 disableReactionsViewer: "Disable emoji reactions viewer"
 autoSpacing: "Auto Spacing"
 autoSpacingDescription: "Adding spaces between CJK and English characters"
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index 76e5e6bdab..3769107fd0 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -1305,6 +1305,7 @@ showDetailTimeWhenHover: "悬浮/长按帖文时间戳时,展开详细时间"
 noteClickToOpen: "点击展开帖文详情"
 enableFallbackReactButton: "开启Fallback回应按钮"
 enableMFMCheatsheet: "在帖文编辑框中启用MFM Cheatsheet"
+enableUndoClearPostForm: "在帖文编辑框中启用撤销/清空按钮"
 disableReactionsViewer: "禁用帖文表情回应显示"
 autoSpacing: "自动空格"
 autoSpacingDescription: "在CJK字符和英文字符中添加空格"
diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml
index 58f5535a30..a8db1d17b0 100644
--- a/locales/zh-TW.yml
+++ b/locales/zh-TW.yml
@@ -1305,6 +1305,7 @@ showDetailTimeWhenHover: "長按貼文時間戳記時展開詳細時間"
 noteClickToOpen: "點擊展開貼文詳情"
 enableFallbackReactButton: "啓用Fallback回應鍵"
 enableMFMCheatsheet: "在貼文編輯框中啓用MFM Cheatsheet"
+enableUndoClearPostForm: "在貼文編輯框中啓用撤回/清除按鈕"
 disableReactionsViewer: "禁用貼文表情回應顯示"
 autoSpacing: "自動間距"
 autoSpacingDescription: "在CJK字符和英文字符中添加間距"
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index 435372f6a2..b2d80c1000 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -87,11 +87,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<button v-if="postFormActions.length > 0" v-tooltip="i18n.ts.plugins" class="_button" :class="$style.footerButton" @click="showActions"><i class="ti ti-plug"></i></button>
 			<button v-tooltip="i18n.ts.emoji" :class="['_button', $style.footerButton]" @click="insertEmoji"><i class="ti ti-mood-happy"></i></button>
 			<button v-if="showAddMfmFunction" v-tooltip="i18n.ts.addMfmFunction" :class="['_button', $style.footerButton]" @click="insertMfmFunction"><i class="ti ti-palette"></i></button>
+			<button v-if="enableMFMCheatsheet" v-tooltip="'MFM Cheatsheet'" class="_button" :class="$style.footerButton" @click="MFMWindow"><i class="ti ti-note"></i></button>
 		</div>
 		<div :class="$style.footerRight">
 			<button v-tooltip="i18n.ts.previewNoteText" class="_button" :class="[$style.footerButton, { [$style.previewButtonActive]: showPreview }]" @click="showPreview = !showPreview"><i class="ti ti-eye"></i></button>
-			<button v-if="showTextManageButton" v-tooltip="currentHistoryIndex >= 0 ? i18n.ts.undoPostForm : i18n.ts.clearPostForm" class="_button" :class="$style.footerButton" @click="handleTextManageClick"><i :class="textManageButtonIcon"></i></button>
-			<button v-if="defaultStore.state.enableMFMCheatsheet" v-tooltip="'MFM Cheatsheet'" class="_button" :class="$style.footerButton" @click="MFMWindow"><i class="ti ti-note"></i></button>
+			<button v-if="showTextManageButton && enableUndoClearPostForm" v-tooltip="currentHistoryIndex >= 0 ? i18n.ts.undoPostForm : i18n.ts.clearPostForm" class="_button" :class="$style.footerButton" @click="handleTextManageClick"><i :class="textManageButtonIcon"></i></button>
 			<!--<button v-tooltip="i18n.ts.more" class="_button" :class="$style.footerButton" @click="showingOptions = !showingOptions"><i class="ti ti-dots"></i></button>-->
 		</div>
 	</footer>
@@ -195,6 +195,9 @@ const showingOptions = ref(false);
 const textAreaReadOnly = ref(false);
 const justEndedComposition = ref(false);
 
+const enableMFMCheatsheet = ref(defaultStore.state.enableMFMCheatsheet);
+const enableUndoClearPostForm = ref(defaultStore.state.enableUndoClearPostForm);
+
 const draftKey = computed((): string => {
 	let key = props.channel ? `channel:${props.channel.id}` : '';
 
@@ -268,6 +271,8 @@ const textManageButtonIcon = computed(() => {
   if (currentHistoryIndex.value >= 0) return 'ti ti-arrow-back-up';
   return text.value !== '' ? 'ti ti-trash' : '';
 });
+let lastSaveTime = 0;
+const SAVE_INTERVAL = 300;
 
 function clearText() {
   if (text.value !== '') {
@@ -278,9 +283,22 @@ function clearText() {
 }
 
 function saveToHistory() {
-  textHistory.value = textHistory.value.slice(0, currentHistoryIndex.value + 1);
-  textHistory.value.push(text.value);
-  currentHistoryIndex.value = textHistory.value.length - 1;
+  const now = Date.now();
+  if (
+    (now - lastSaveTime > SAVE_INTERVAL) &&
+    (textHistory.value[currentHistoryIndex.value] !== text.value) &&
+    (text.value.length > 0)
+  ) {
+    textHistory.value = textHistory.value.slice(0, currentHistoryIndex.value + 1);
+    textHistory.value.push(text.value);
+    currentHistoryIndex.value = textHistory.value.length - 1;
+    lastSaveTime = now;
+    
+    if (textHistory.value.length > 50) {
+      textHistory.value = textHistory.value.slice(-50);
+      currentHistoryIndex.value = textHistory.value.length - 1;
+    }
+  }
 }
 
 function undoTextChange() {
@@ -615,7 +633,9 @@ function clear() {
 function onKeydown(ev: KeyboardEvent) {
 	if (ev.key === 'Enter' && (ev.ctrlKey || ev.metaKey) && canPost.value) post();
 
-	if (!ev.ctrlKey && !ev.metaKey && !ev.altKey && !justEndedComposition.value && !ev.isComposing) {
+	if (enableUndoClearPostForm.value && !ev.ctrlKey && !ev.metaKey && !ev.altKey && 
+        !justEndedComposition.value && !ev.isComposing && 
+        !['Shift', 'Alt', 'Control', 'Meta', 'CapsLock', 'Tab'].includes(ev.key)) {
       saveToHistory();
     }
 	
diff --git a/packages/frontend/src/pages/settings/pari.vue b/packages/frontend/src/pages/settings/pari.vue
index 93ba5234bc..14fa18594c 100644
--- a/packages/frontend/src/pages/settings/pari.vue
+++ b/packages/frontend/src/pages/settings/pari.vue
@@ -69,6 +69,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<MkSwitch v-model="noteClickToOpen">{{ i18n.ts.noteClickToOpen }}</MkSwitch>
 			<MkSwitch v-model="enableFallbackReactButton">{{ i18n.ts.enableFallbackReactButton }}</MkSwitch>
 			<MkSwitch v-model="enableMFMCheatsheet">{{ i18n.ts.enableMFMCheatsheet }}</MkSwitch>
+			<MkSwitch v-model="enableUndoClearPostForm">{{ i18n.ts.enableUndoClearPostForm }}</MkSwitch>
 			<MkSwitch v-model="collapseNotesRepliedTo">{{ i18n.ts.collapseNotesRepliedTo }}</MkSwitch>
 			<MkSwitch v-model="disableReactionsViewer">{{ i18n.ts.disableReactionsViewer }}</MkSwitch>
 			<MkSelect v-model="autoSpacingBehaviour">
@@ -121,6 +122,7 @@ const showDetailTimeWhenHover = computed(defaultStore.makeGetterSetter('showDeta
 const noteClickToOpen = computed(defaultStore.makeGetterSetter('noteClickToOpen'));
 const enableFallbackReactButton = computed(defaultStore.makeGetterSetter('enableFallbackReactButton'));
 const enableMFMCheatsheet = computed(defaultStore.makeGetterSetter('enableMFMCheatsheet'));
+const enableUndoClearPostForm = computed(defaultStore.makeGetterSetter('enableUndoClearPostForm'));
 const autoSpacingBehaviour = computed(defaultStore.makeGetterSetter('autoSpacingBehaviour'));
 const collapseNotesRepliedTo = computed(defaultStore.makeGetterSetter('collapseNotesRepliedTo'));
 const disableReactionsViewer = computed(defaultStore.makeGetterSetter('disableReactionsViewer'));
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index 587ab43c44..b28f461b84 100644
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -536,6 +536,10 @@ export const defaultStore = markRaw(new Storage('base', {
 		where: 'device',
 		default: true,
 	},
+	enableUndoClearPostForm: {
+		where: 'device',
+		default: true,
+	},
 	autoSpacingBehaviour: {
 		where: 'device',
 		default: null as 'all' | 'special' | null,