diff --git a/layouts/default.vue b/layouts/default.vue
index cab93ae4..cf5762b9 100644
--- a/layouts/default.vue
+++ b/layouts/default.vue
@@ -1,6 +1,33 @@
diff --git a/nuxt.config.ts b/nuxt.config.ts
index bd78352f..c2585b86 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -9,7 +9,7 @@ const generateDynamicV = () => {
}
const isDev = process.env.NODE_ENV === "development"
-const appBase = "/"
+const appBase = "/plugins/siyuan-blog/"
const staticV = generateDynamicV()
// https://nuxt.com/docs/api/configuration/nuxt-config
@@ -24,7 +24,14 @@ export default defineNuxtConfig({
},
// build modules
- modules: ["@vueuse/nuxt", "@nuxtjs/i18n", "@element-plus/nuxt", "@nuxtjs/color-mode", "@pinia/nuxt", "@nuxt/image"],
+ modules: [
+ "@vueuse/nuxt",
+ "@nuxtjs/i18n-edge",
+ "@element-plus/nuxt",
+ "@nuxtjs/color-mode",
+ "@pinia/nuxt",
+ "@nuxt/image",
+ ],
// vueuse
vueuse: {
@@ -57,6 +64,14 @@ export default defineNuxtConfig({
themes: ["dark"],
},
+ // https://nuxt.com/docs/guide/going-further/custom-routing#hash-mode-spa
+ ssr: false,
+ router: {
+ options: {
+ hashMode: true,
+ },
+ },
+
css: ["~/assets/siyuan/style.styl", "~/assets/siyuan/index.styl"],
app: {
@@ -93,11 +108,15 @@ export default defineNuxtConfig({
// 环境变量
runtimeConfig: {
- siyuanAuthToken: process.env.NUXT_SIYUAN_AUTH_TOKEN,
+ // siyuanAuthToken: process.env.NUXT_SIYUAN_AUTH_TOKEN,
+ siyuanAuthToken: "",
public: {
- defaultType: process.env.NUXT_PUBLIC_DEFAULT_TYPE,
- siyuanApiUrl: process.env.NUXT_PUBLIC_SIYUAN_API_URL,
- waitTime: process.env.NUXT_PUBLIC_WAIT_TIME,
+ // defaultType: process.env.NUXT_PUBLIC_DEFAULT_TYPE,
+ defaultType: "siyuan",
+ // siyuanApiUrl: process.env.NUXT_PUBLIC_SIYUAN_API_URL,
+ siyuanApiUrl: "",
+ // waitTime: process.env.NUXT_PUBLIC_WAIT_TIME,
+ waitTime: "0",
},
},
})
diff --git a/siyuan/iframeEvent.ts b/siyuan/iframeEvent.ts
index 48cdb4f4..718f510e 100644
--- a/siyuan/iframeEvent.ts
+++ b/siyuan/iframeEvent.ts
@@ -25,19 +25,21 @@
import { popContentIframeId } from "~/siyuan/siyuanConstants"
import { createAppLogger } from "~/common/appLogger"
+import SiyuanBlog from "~/siyuan/index"
const logger = createAppLogger("iframe-events")
let added = false
-export const adjustIframeHeight = (iframeId: string, customHeight?: number) => {
+const adjustIframeHeight = (iframeId: string, customHeight?: number) => {
const iframe = document.getElementById(iframeId) as HTMLIFrameElement
let counter = 0
let lastHeight = "0px" // 将初始高度设为 "0px"
+ const defaultHeight = 350
// 注册定时器
const interval = setInterval(() => {
// 获取id为__nuxt的元素高度
const iframeBody = iframe?.contentWindow?.document.getElementById("__nuxt") as HTMLElement
- let height = `${customHeight ?? iframeBody.scrollHeight}px`
+ let height = `${customHeight ?? iframeBody?.scrollHeight ?? defaultHeight}px`
if (height === lastHeight) {
if (!added) {
height = height + 10
@@ -65,25 +67,38 @@ export const adjustIframeHeight = (iframeId: string, customHeight?: number) => {
}
}
-// 监听 message 事件
-window.addEventListener("message", (event) => {
- const iframe = document.getElementById(popContentIframeId) as HTMLIFrameElement
+/**
+ * 注册 iframe 事件
+ */
+export const registerIframeEvent = (pluginInstance: SiyuanBlog) => {
+ // 监听 message 事件
+ window.addEventListener("message", (event) => {
+ const iframe = document.getElementById(popContentIframeId) as HTMLIFrameElement
+
+ // 判断是否是来自指定 iframe 的消息
+ if (event.source === iframe.contentWindow) {
+ const data = event.data
+ // 判断消息类型
+ if (data.type === "updateHeight") {
+ logger.info(`Try to cancel loading`)
+ pluginInstance.popView.cancelLoading()
- // 判断是否是来自指定 iframe 的消息
- if (event.source === iframe.contentWindow) {
- const data = event.data
- // 判断消息类型
- if (data.type === "updateHeight") {
- logger.info(`Received update height message from iframe`)
- const height = data.height
- // 更新 iframe 高度
- if (height) {
- iframe.height = `${height}px`
- logger.info(`Updated iframe height to ${height}px`)
+ logger.info(`Received update height message from iframe`)
+ const height = data.height
+ // 更新 iframe 高度
+ if (height) {
+ iframe.height = `${height}px`
+ logger.info(`Updated iframe height to ${height}px`)
+ } else {
+ adjustIframeHeight(popContentIframeId)
+ logger.info(`Auto adjust iframe height to ${height}px`)
+ }
} else {
- adjustIframeHeight(popContentIframeId)
- logger.info(`Auto adjust iframe height to ${height}px`)
+ logger.warn(`Unknown message type, ignore`)
}
+ } else {
+ logger.warn(`message is not from contentWindow, ignore`)
}
- }
-})
+ })
+ logger.info("iframe event registered in plugin main")
+}
diff --git a/siyuan/index.styl b/siyuan/index.styl
index bff322a3..2f942eb2 100644
--- a/siyuan/index.styl
+++ b/siyuan/index.styl
@@ -54,3 +54,53 @@
margin 0
padding 0
overflow hidden
+
+.loading-spinner {
+ width: 64px;
+ height: 64px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ border-radius: 5px;
+}
+
+.loading-spinner > div {
+ box-sizing: border-box;
+ display: block;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 20px;
+ height: 20px;
+ margin: -10px 0 0 -10px;
+ border-radius: 50%;
+ border: 2px solid #3498db;
+ border-bottom-color: transparent;
+ animation: loading-spinner-animation 0.75s 0s linear infinite;
+}
+
+.loading-spinner > div:nth-child(1) {
+ animation-delay: 0s;
+}
+
+.loading-spinner > div:nth-child(2) {
+ animation-delay: -0.6s;
+}
+
+.loading-spinner > div:nth-child(3) {
+ animation-delay: -0.4s;
+}
+
+.loading-spinner > div:nth-child(4) {
+ animation-delay: -0.2s;
+}
+
+@keyframes loading-spinner-animation {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
\ No newline at end of file
diff --git a/siyuan/index.ts b/siyuan/index.ts
index 2be7e303..4df640d8 100644
--- a/siyuan/index.ts
+++ b/siyuan/index.ts
@@ -29,10 +29,13 @@ import { isDev } from "~/common/Constants"
import "./index.styl"
import { icons } from "~/siyuan/utils/svg"
+import { registerIframeEvent } from "~/siyuan/iframeEvent"
export default class SiyuanBlog extends Plugin {
public isMobile
public logger
+ public popView: any
+
constructor(options: { app: App; id: string; name: string; i18n: IObject }) {
super(options)
@@ -44,7 +47,10 @@ export default class SiyuanBlog extends Plugin {
onload() {
// 注册图标
this.addIcons(icons.iconShare)
+ // 初始化顶部栏以及图标
initTopbar(this)
+ // 注册 iframe 事件
+ registerIframeEvent(this)
}
openSetting() {
diff --git a/siyuan/topbar.ts b/siyuan/topbar.ts
index 3b2d9fe9..7492ceb7 100644
--- a/siyuan/topbar.ts
+++ b/siyuan/topbar.ts
@@ -28,8 +28,6 @@ import { Dialog, Menu } from "siyuan"
import PageUtil from "~/siyuan/utils/pageUtil"
import { getAvailableOrigin } from "~/siyuan/utils/utils"
import { contentElement, contentHtml } from "~/siyuan/customElement"
-import { adjustIframeHeight } from "~/siyuan/iframeEvent"
-import { popContentIframeId } from "~/siyuan/siyuanConstants"
/**
* 顶栏按钮
@@ -50,8 +48,10 @@ export function initTopbar(pluginInstance: SiyuanBlog) {
topBarElement.addEventListener("click", async () => {
const sharePage =
"/plugins/siyuan-blog/#/share?id=" + PageUtil.getPageId() + "&origin=" + getAvailableOrigin() + "&isSsr=false"
- showPopView(pluginInstance, topBarElement, sharePage)
- adjustIframeHeight(popContentIframeId)
+ const popView = showPopView(pluginInstance, topBarElement, sharePage, {
+ showLoading: true,
+ })
+ pluginInstance.popView = popView
})
// topBarElement.addEventListener("click", async () => {
@@ -139,8 +139,14 @@ const showPage = (pluginInstance: SiyuanBlog, pageUrl: string, title?: string) =
* @param pluginInstance 插件实例对象
* @param boxElement 被点击的 box 元素
* @param pageUrl 当前页面的 URL
+ * @param options
*/
-const showPopView = (pluginInstance: SiyuanBlog, boxElement: HTMLElement, pageUrl: string) => {
+const showPopView = (
+ pluginInstance: SiyuanBlog,
+ boxElement: HTMLElement,
+ pageUrl: string,
+ options: { showLoading?: boolean; cancelLoading?: any } = {}
+) => {
const popContentId = "pop-content"
let popContent = document.getElementById(popContentId)
@@ -170,8 +176,28 @@ const showPopView = (pluginInstance: SiyuanBlog, boxElement: HTMLElement, pageUr
popContent.style.opacity = "0"
popContent.style.transition = "opacity 0.3s ease-in-out"
+ // 添加loading效果
+ if (options.showLoading) {
+ const loadingElement = document.createElement("div")
+ loadingElement.className = "loading-spinner"
+ for (let i = 0; i < 4; i++) {
+ const divElement = document.createElement("div")
+ loadingElement.appendChild(divElement)
+ }
+ popContent.appendChild(loadingElement)
+
+ // 定义cancelLoading函数,用于取消loading
+ const cancelLoading = () => {
+ popContent?.removeChild(loadingElement)
+ }
+
+ // 在option中添加cancelLoading函数
+ options.cancelLoading = cancelLoading
+ }
+
// 填充内容
- popContent.innerHTML = contentElement(pageUrl).innerHTML
+ const content = contentElement(pageUrl)
+ popContent.appendChild(content)
document.body.appendChild(popContent)
@@ -204,4 +230,6 @@ const showPopView = (pluginInstance: SiyuanBlog, boxElement: HTMLElement, pageUr
}
}, 300) // 等待 300ms,即过渡时间,然后再删除浮动框
}
+
+ return options
}
diff --git a/utils/innerIframeEvent.ts b/utils/innerIframeEvent.ts
index 6a509eed..05a77ce8 100644
--- a/utils/innerIframeEvent.ts
+++ b/utils/innerIframeEvent.ts
@@ -27,7 +27,7 @@ import { createAppLogger } from "~/common/appLogger"
const logger = createAppLogger("inner-iframe-event")
-export const sendMessageToParent = (type: string) => {
+export const sendMessageToParent = (type: string, height?: number) => {
const win = window.self as any
if (!win.parent.siyuan) {
logger.info(`Not in siyuan-note plugin iframe environment, ignore message sending`)
@@ -38,6 +38,6 @@ export const sendMessageToParent = (type: string) => {
const iframeWindow = window.self
// 向父窗口发送消息
- iframeWindow.parent.postMessage({ type: type }, "*")
+ iframeWindow.parent.postMessage({ type: type, height: height }, "*")
logger.info(`Sends a message to the parent window, type => ${type}`)
}