制作一个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-name
export 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-name
export 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"
现在的效果:
页数内容
现在我们就要为我们的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
,我们就能看到我们一共拥有多少页了。