4

在electron中监听系统剪贴板变化

 3 years ago
source link: https://segmentfault.com/a/1190000040554103
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

因为要完成剪贴板历史记录功能,经过查阅electron剪贴板文档。没有发现有剪贴板变化的钩子事件,于是决定自己实现一个。

electron 中有读取剪贴板内容API,可以借助此API封装监听定时器方法。具体逻辑如下:

使用定时器不断判断内容是否相同,如不相同。执行剪贴板改变回调

编写一剪贴板观察者类,实例化时传入监听的消息/图片变化回调、由于频繁获取剪贴板内容可能会带来性能负担,所以还需要支持传入自定义监听间隔时间。

返回的实例应该支持暂停和继续监听的方法。

编写剪贴板观察者类

首先定义构造函数参数的接口

import { clipboard, NativeImage } from 'electron';

interface Options {
  //  定时器获取内容判断的间隔
  duration?: number;
  //  文本变化回调
  textChange?: (text: string, beforeText: string) => void;
  //  图片变化回调
  imageChange?: (image: NativeImage, beforeImage: NativeImage) => void;
}

接着定义类,编写构造器中处理传参的逻辑与暴露的api

class ClipboardObserver {
  //  定时器
  timer: NodeJS.Timeout;
  //  变化前的文本(用于对比新获取的剪贴板文本)
  beforeText: string;
  //  变化去的图片(用于对比新获取的剪贴板图片)
  beforeImage: NativeImage;

  duration = 500;
  textChange: (text: string, beforeText: string) => void;
  imageChange: (image: NativeImage, beforeImage: NativeImage) => void;

  constructor(options: Options) {
    //  获取传入配置并保存到属性中
    const { duration, textChange, imageChange } = options;

    this.duration = duration;
    this.textChange = textChange;
    this.imageChange = imageChange;

    //  判断传入回调,默认开始执行定时器
    if (this.textChange || this.imageChange) {
      this.start();
    }
  }

  /**
   * 开始
   */
  start(): void {
    //  记录剪贴板目前的内容
    this.setClipboardDefaultValue();
    //  设置定时器
    this.setTimer();
  }

  /**
   * 暂停
   */
  stop(): void {
    //  清除定时器
    this.setTimer();
  }
}

clearTimer负责调用clearInterval来清除定时器,setClipboardDefaultValue负责设置实例中记录上一次变化的内容。

class ClipboardObserver {
  ...

  /**
   * 清除定时器
   */
  clearTimer(): void {
    clearInterval(this.timer);
  }

  /**
   * 设置剪贴板默认内容
   */
  setClipboardDefaultValue(): void {
    if (this.textChange) {
      //  electron剪贴板读取文本方法
      this.beforeText = clipboard.readText();
    }
    if (this.imageChange) {
      //  electron剪贴板读取图片方法
      this.beforeImage = clipboard.readImage();
    }
  }
}

setTimer 负责比较核心的逻辑,设置定时器,并在每一轮定时器回调中判断内容是否存在变化。如内容变化,执行内容变化回调。

class ClipboardObserver {
  ...

  /**
   * 设置定时器
   */
  setTimer(): void {
    //  设置定时器
    this.timer = setInterval(() => {
      if (this.textChange) {
        const text = clipboard.readText();
        //  判断内容是否与上次读取的内容不同
        if (this.isDiffText(this.beforeText, text)) {
          //  执行变化回调
          this.textChange(text, this.beforeText);
          //  记录此次内容
          this.beforeText = text;
        }
      }

      if (this.imageChange) {
        const image = clipboard.readImage();
        //  判断内容是否与上次读取的内容不同
        if (this.isDiffImage(this.beforeImage, image)) {
          //  执行变化回调
          this.imageChange(image, this.beforeImage);
          //  记录此次内容
          this.beforeImage = image;
        }
      }
    }, this.duration);
  }

  /**
   * 判断内容是否不一致
   * @param beforeText
   * @param afterText
   * @returns
   */
  isDiffText(beforeText: string, afterText: string): boolean {
    return afterText && beforeText !== afterText;
  }

  /**
   * 判断图片是否不一致
   * @param beforeImage
   * @param afterImage
   * @returns
   */
  isDiffImage(beforeImage: NativeImage, afterImage: NativeImage): boolean {
    return afterImage && !afterImage.isEmpty() && beforeImage.toDataURL() !== afterImage.toDataURL();
  }
}

至此,剪贴板观察者类的逻辑已经完成了。我们在代码中可以这样食用

const clipboardObserver = new ClipboardObserver({
  textChange: (text: string, beforeText: string) => {
    //  处理文本变化的逻辑
  },
  imageChange: (image: Electron.NativeImage, beforeText: Electron.NativeImage) => {
    //  处理图片变化的逻辑
  }
});

//  也可以暂停
clipboardObserver.stop();

//  也可以再开始
clipboardObserver.start();

项目已开源到 electron-clipboard-observer 中。可以将代码拷到项目中使用

也可以在项目中安装依赖 electron-clipboard-observer 安装后在项目内可直接引用使用。

npm install electron-clipboard-observer

或者

yarn add electron-clipboard-observer
import ClipboardObserver from "electron-clipboard-observer"

const clipboardObserver = new ClipboardObserver({
    textChange() {},
    imageChange() {}
})

代码仓库

npm


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK