@@ -32,19 +36,20 @@
{{ $props.data.excerpt }}
-
-
-
+
+
@@ -55,11 +60,11 @@
diff --git a/src/components/link/types.ts b/src/components/link/types.ts
new file mode 100644
index 0000000..bac53cf
--- /dev/null
+++ b/src/components/link/types.ts
@@ -0,0 +1,6 @@
+export interface RouterLinkTo {
+ path?: string
+ name?: string
+ params?: { [key: string]: any }
+ query?: { [key: string]: any }
+}
diff --git a/src/components/lists/postThumbList/PostThumbList.vue b/src/components/lists/postThumbList/PostThumbList.vue
index c8eaa35..9ae351d 100644
--- a/src/components/lists/postThumbList/PostThumbList.vue
+++ b/src/components/lists/postThumbList/PostThumbList.vue
@@ -7,7 +7,7 @@
:type="index % 2 ? 'normal' : 'reverse'"
>
+
no more
@@ -17,7 +17,14 @@
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index 0569143..f1ef2d9 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -8,8 +8,11 @@ import useReachElementSide from './useReachElementSide'
import { useElementRef, useElementRefs } from './useElementRef'
import useOffsetDistance from './useOffsetDistance'
import useMDCRipple from './mdc/useMDCRipple'
-import useMessage from './useMessage'
+import useMessage, { useCommonMessages } from './useMessage'
import useTypewriterEffect from './useTypewriterEffect'
+import useIntervalWatcher from './useIntervalWatcher'
+import useKeepAliveWindowScrollTop from './useKeepAliveWindowScrollTop'
+import useWindowScrollLock from './useWindowScrollLock'
export {
useState,
@@ -29,5 +32,9 @@ export {
useElementRefs,
useOffsetDistance,
useMessage,
+ useCommonMessages,
useTypewriterEffect,
+ useIntervalWatcher,
+ useKeepAliveWindowScrollTop,
+ useWindowScrollLock,
}
diff --git a/src/hooks/useIntervalWatcher.ts b/src/hooks/useIntervalWatcher.ts
new file mode 100644
index 0000000..5536e80
--- /dev/null
+++ b/src/hooks/useIntervalWatcher.ts
@@ -0,0 +1,18 @@
+import { onMounted, onUnmounted, onActivated, onDeactivated } from 'vue'
+export default function useIntervalWatcher(func: () => void, interval = 100): void {
+ let timer = NaN
+ const addWatcher = () => {
+ if (timer) return
+ timer = window.setInterval(func, interval)
+ }
+ const removeWatcher = () => {
+ if (!timer) return
+ window.clearInterval(timer)
+ timer = NaN
+ }
+
+ onMounted(() => addWatcher())
+ onActivated(() => addWatcher())
+ onUnmounted(() => removeWatcher())
+ onDeactivated(() => removeWatcher())
+}
diff --git a/src/hooks/useKeepAliveWindowScrollTop.ts b/src/hooks/useKeepAliveWindowScrollTop.ts
new file mode 100644
index 0000000..3e4807a
--- /dev/null
+++ b/src/hooks/useKeepAliveWindowScrollTop.ts
@@ -0,0 +1,27 @@
+import { onDeactivated, watch, onActivated } from 'vue'
+import { useWindowScroll } from '@vueuse/core'
+import { useState } from '@/hooks'
+
+export default function () {
+ const { scrollTop, scrollLeft } = (function () {
+ const { x, y } = useWindowScroll()
+ return { scrollTop: y, scrollLeft: x }
+ })()
+
+ const [scrollTopCache, setScrollTopCache] = useState(0)
+ const [isScrollTopSet, setIsScrollTopSet] = useState(false)
+
+ watch(scrollTop, (value) => {
+ if (!isScrollTopSet.value) return
+ setScrollTopCache(value)
+ })
+
+ onActivated(() => {
+ window.scrollTo(scrollLeft.value ?? 0, scrollTopCache.value)
+ setIsScrollTopSet(true)
+ })
+
+ onDeactivated(() => {
+ setIsScrollTopSet(false)
+ })
+}
diff --git a/src/hooks/useMessage.ts b/src/hooks/useMessage.ts
index aea6174..dd59fc5 100644
--- a/src/hooks/useMessage.ts
+++ b/src/hooks/useMessage.ts
@@ -1,16 +1,24 @@
import type { Ref } from 'vue'
-import { useInjector } from '@/hooks'
+import { useInjector, useIntl } from '@/hooks'
import { messages } from '@/store'
import type { Message, MessageOptions } from '@/store/messages'
-export default function useMessage() {
- const {
- messageList,
- addMessage,
- }: {
- messageList: Ref
- addMessage: (state: Ref, options: MessageOptions) => void
- } = useInjector(messages)
+/**
+ * deprecated
+ */
+export interface UseMessageInjecter {
+ messageList: Ref
+ addMessage: (state: Ref, options: MessageOptions) => void
+}
+
+/**
+ * @param useMessageInjecter (deprecated)
+ * @returns
+ */
+export default function useMessage(useMessageInjecter?: UseMessageInjecter) {
+ const { messageList, addMessage }: UseMessageInjecter = useMessageInjecter
+ ? useMessageInjecter
+ : useInjector(messages)
const _addMessage = (options: MessageOptions) => {
addMessage(messageList, options)
@@ -18,3 +26,13 @@ export default function useMessage() {
return _addMessage
}
+
+export const useCommonMessages = () => {
+ const intl = useIntl()
+ return {
+ javascriptErrorTitle: intl.formatMessage({
+ id: 'messages.commonMessages.javascriptErrorTitle',
+ defaultMessage: 'Opps, something when wrong!',
+ }),
+ }
+}
diff --git a/src/hooks/useWindowScrollLock.ts b/src/hooks/useWindowScrollLock.ts
new file mode 100644
index 0000000..48f2a03
--- /dev/null
+++ b/src/hooks/useWindowScrollLock.ts
@@ -0,0 +1,29 @@
+import { onUnmounted, onDeactivated } from 'vue'
+import getScrollbarWidth from '@/utils/getScrollbarWidth'
+export default function () {
+ const removeScrollLock = () => {
+ const body = document.querySelector('body')
+ // TODO: add a fake scroll bar element
+ if (body instanceof HTMLElement) {
+ body.style.overflow = 'auto'
+ body.style.width = '100%'
+ }
+ }
+ const addScrollLock = () => {
+ const body = document.querySelector('body')
+ if (body instanceof HTMLElement) {
+ body.style.overflow = 'hidden'
+ body.style.width = `calc(100% - ${String(getScrollbarWidth())}px)`
+ }
+ }
+
+ onUnmounted(() => {
+ removeScrollLock()
+ })
+
+ onDeactivated(() => {
+ removeScrollLock()
+ })
+
+ return [removeScrollLock, addScrollLock]
+}
diff --git a/src/layouts/Base.vue b/src/layouts/Base.vue
index f5f474c..2022860 100644
--- a/src/layouts/Base.vue
+++ b/src/layouts/Base.vue
@@ -36,9 +36,13 @@