mirror of https://github.com/halo-dev/halo
feat: add support for saving post by shortcut keys (#4510)
#### What type of PR is this? /area editor /area console #### What this PR does / why we need it: 1. mac: 在编辑器中添加command+s保存文章 2. windows: 在编辑器中添加ctrl+s保存文章 #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/4340 #### Does this PR introduce a user-facing change? ```release-note Console 端支持通过快捷键保存文章 ```pull/4533/head
parent
1892dce64b
commit
178c0704c8
|
@ -1,4 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { isMac } from "@/utils/device";
|
||||||
import { VButton } from "@halo-dev/components";
|
import { VButton } from "@halo-dev/components";
|
||||||
import { useMagicKeys } from "@vueuse/core";
|
import { useMagicKeys } from "@vueuse/core";
|
||||||
import { computed, useAttrs, watchEffect } from "vue";
|
import { computed, useAttrs, watchEffect } from "vue";
|
||||||
|
@ -19,8 +20,6 @@ const emit = defineEmits<{
|
||||||
(event: "submit"): void;
|
(event: "submit"): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
|
|
||||||
|
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs();
|
||||||
|
|
||||||
const buttonText = computed(() => {
|
const buttonText = computed(() => {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { isMac } from "@/utils/device";
|
||||||
|
import { useEventListener } from "@vueuse/core";
|
||||||
|
import { useDebounceFn } from "@vueuse/shared";
|
||||||
|
import { nextTick } from "vue";
|
||||||
|
|
||||||
|
export function useSaveKeybinding(fn: () => void) {
|
||||||
|
const debouncedFn = useDebounceFn(() => {
|
||||||
|
fn();
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
useEventListener(window, "keydown", (e: KeyboardEvent) => {
|
||||||
|
if (isMac ? e.metaKey : e.ctrlKey) {
|
||||||
|
if (e.key === "s") {
|
||||||
|
e.preventDefault();
|
||||||
|
nextTick(() => {
|
||||||
|
debouncedFn();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ import {
|
||||||
useOverlayScrollbars,
|
useOverlayScrollbars,
|
||||||
type UseOverlayScrollbarsParams,
|
type UseOverlayScrollbarsParams,
|
||||||
} from "overlayscrollbars-vue";
|
} from "overlayscrollbars-vue";
|
||||||
|
import { isMac } from "@/utils/device";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -70,8 +71,6 @@ const handleLogout = () => {
|
||||||
// Global Search
|
// Global Search
|
||||||
const globalSearchVisible = ref(false);
|
const globalSearchVisible = ref(false);
|
||||||
|
|
||||||
const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
|
|
||||||
|
|
||||||
const handleGlobalSearchKeybinding = (e: KeyboardEvent) => {
|
const handleGlobalSearchKeybinding = (e: KeyboardEvent) => {
|
||||||
const { key, ctrlKey, metaKey } = e;
|
const { key, ctrlKey, metaKey } = e;
|
||||||
if (key === "k" && ((ctrlKey && !isMac) || metaKey)) {
|
if (key === "k" && ((ctrlKey && !isMac) || metaKey)) {
|
||||||
|
|
|
@ -38,6 +38,7 @@ import { contentAnnotations } from "@/constants/annotations";
|
||||||
import { usePageUpdateMutate } from "./composables/use-page-update-mutate";
|
import { usePageUpdateMutate } from "./composables/use-page-update-mutate";
|
||||||
import { useAutoSaveContent } from "@/composables/use-auto-save-content";
|
import { useAutoSaveContent } from "@/composables/use-auto-save-content";
|
||||||
import { useContentSnapshot } from "@/composables/use-content-snapshot";
|
import { useContentSnapshot } from "@/composables/use-content-snapshot";
|
||||||
|
import { useSaveKeybinding } from "@/composables/use-save-keybinding";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -365,6 +366,8 @@ const handlePreview = async () => {
|
||||||
previewModal.value = true;
|
previewModal.value = true;
|
||||||
previewPending.value = false;
|
previewPending.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useSaveKeybinding(handleSave);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -38,6 +38,7 @@ import { usePostUpdateMutate } from "./composables/use-post-update-mutate";
|
||||||
import { contentAnnotations } from "@/constants/annotations";
|
import { contentAnnotations } from "@/constants/annotations";
|
||||||
import { useAutoSaveContent } from "@/composables/use-auto-save-content";
|
import { useAutoSaveContent } from "@/composables/use-auto-save-content";
|
||||||
import { useContentSnapshot } from "@/composables/use-content-snapshot";
|
import { useContentSnapshot } from "@/composables/use-content-snapshot";
|
||||||
|
import { useSaveKeybinding } from "@/composables/use-save-keybinding";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -381,6 +382,8 @@ const handlePreview = async () => {
|
||||||
previewModal.value = true;
|
previewModal.value = true;
|
||||||
previewPending.value = false;
|
previewPending.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useSaveKeybinding(handleSave);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
|
Loading…
Reference in New Issue