CorrectRoad's Blog
905 words
5 minutes
Logseq Plugins 开发实战系列:3.制作一个toolbar仪表盘
2022-02-27

制作一个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或者yarnpnpm的优点大家使用之后一定会感觉到。使用方法和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.provideUIlogseq.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.tsxdashboard.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,我们就能看到我们一共拥有多少页了。

Logseq Plugins 开发实战系列:3.制作一个toolbar仪表盘
https://correctroadh.github.io/posts/plugins-3/
Author
CorrectRoad
Published at
2022-02-27