制作一个toolbar仪表盘
前言
本文为本人发布gitbook的书籍,但是因为gitbook一直没有被谷歌索引,我也没有办法提交给谷歌(无法证明所有权)。无奈只能把该本的章节逐步搬运过来,提高SEO。希望那些想学习logseq plugins 开发的同学们能直接通过搜索引擎看到此书。
原书本章地址:https://correctroad.gitbook.io/logseq-plugins-in-action/chapter-1/make-a-toolbar-dashboard
环境搭建
我们使用logseq-plugin-template-react为项目基础。
git clone https://github.com/pengx17/logseq-plugin-template-react
现在我们有了一个手脚架了。这个项目是用pnpm而不是传统的npm或者yarn,pnpm的优点大家使用之后一定会感觉到。使用方法和npm一致,把npm换成pnpm就行。
pnpm install安装依赖
项目结构
➜ logseq-plugin-template-react git:(master) tree -L 2.├── CHANGELOG.md├── index.html├── logo.svg├── package.json├── pnpm-lock.yaml├── readme.md├── release.config.js├── renovate.json├── src│ ├── App.tsx # 页面代码写这,但是组件一般新建tsx。│ ├── main.tsx # toolbar代码写这│ └── utils.ts├── tsconfig.json└── vite.config.ts
1 directory, 13 files注册toolbar
在 main.tsx 删掉原本的logseq.provideUI和logseq.provideStyle。
logseq.provideStyle(css` div[data-injected-ui=${openIconName}-${pluginId}] { display: inline-flex; align-items: center; opacity: 0.55; font-weight: 500; padding: 0 5px; position: relative; }
div[data-injected-ui=${openIconName}-${pluginId}]:hover { opacity: 0.9; } `);
logseq.provideUI({ key: openIconName, path: "#search", template: ` <a data-on-click="show" style="opacity: .6; display: inline-flex;">⚙️</a> `, })替换成:
logseq.provideStyle(css` .${openIconName} { width: 18px; height: 18px; margin: 2px 0.4em 0 0.4em; background-color: blue; border-radius: 4px; border: 1px solid #eee; } `);
logseq.App.registerUIItem("toolbar", { key: "show-plugin-open", template: ` <a data-on-click="show"> <div class="${openIconName}"></div> </a> `, });logseq.App.registerUIItem让我们向toolbar注册组件。
代码部分来源于logseq-plugin-heatmap项目。
现在我们运行pnpm install && pnpm run build。在logseq中载入,就可以在toolbar上看到我们的UIItem了。

当我们点击该蓝色图标时,就是我们的页面了。

新建页面
我们的目标是制做一个仪表盘。上面显示着logseq里的相关信息。在界面上参考logseq-plugin-heatmap

页面组件
新建dashboard.tsx和dashboard.css。
dashborad.tsx
import React from "react";import "./dashboard.css"
// eslint-disable-next-line react/display-nameexport const Dashboard = React.forwardRef<HTMLDivElement>(({}, ref) => { return( <div className="dashboard-root"> <div className="center"> <h1>logseq borad!!!</h1> </div> </div> );});dashborad.css
.dashboard-root { height: 8vh; width: 16vh; border-radius: 5%; display: flex; background-color: #e5e7eb;}
.center{ display: flex; margin: auto;}修改App.tsx
import React, { useRef } from "react";import { useAppVisible } from "./utils";import { Dashboard } from "./dashboard";
function App() { const innerRef = useRef<HTMLDivElement>(null); const visible = useAppVisible(); if (visible) { return ( <main className="fixed inset-0 flex items-center justify-center" onClick={(e) => { if (!innerRef.current?.contains(e.target as any)) { window.logseq.hideMainUI(); } }} > <Dashboard ref={innerRef} /> </main> ); } return null;}
export default App;效果:
现在点击UIItem时就有一个小窗口出现在logseq正中央(因为items-center justify-center)。当我们点击logseq任意位置,都可以关闭该窗口。

调整页面位置
如果我们想像logseq-plugin-heatmap一样,页面出现在toolbar正下面。我们就需要调整页面的位置。

修改dashboard.css
.dashboard-root { position: absolute; background-color: #e5e7eb; display: flex; width: 300px; height: 80px;}
.center{ display: flex; margin: auto;}修改dashboard.tsx
import React from "react";import "./dashboard.css"import { useWindowSize } from "react-use";
function useIconPosition() { const windowSize = useWindowSize(); return React.useMemo(() => { const right = windowSize.width - 10; const bottom = 20; return { right, bottom }; }, [windowSize]);}
// eslint-disable-next-line react/display-nameexport const Dashboard = React.forwardRef<HTMLDivElement>(({}, ref) => { const { bottom, right } = useIconPosition(); console.log(bottom, right); return( <div ref={ref} className="dashboard-root" style={{ left: right - 400, top: bottom + 20 }} > <div className="center"> <h1>logseq borad!!!</h1> </div> </div> );});其中useWindowSize是用来获取logseq的窗口位置的。而useIconPosition是我从logseq-plugin-heatmap里扒来的。
main.tsx中<main>的className修改为className="absolute inset-0"
现在的效果:
.gif)
页数内容
现在我们就要为我们的dashboard添加真正”有用”的功能了。
修改dashboard.tsx
export const Dashboard = React.forwardRef<HTMLDivElement>(({}, ref) => { const { bottom, right } = useIconPosition();
const [pageCount, setPageCount] = React.useState(0); useEffect(()=>{ window.logseq.Editor.getAllPages().then(pages=>{ setPageCount(pages.length); }) },[])
return( <div ref={ref} className="dashboard-root" style={{ left: right - 400, top: bottom + 20 }} > <div className="center"> <h1> 一共有 {pageCount} 个页面 </h1> </div> </div> );});现在当我们点成UIItem,我们就能看到我们一共拥有多少页了。
