如何监听思源关闭操作

目的:实现在思源关闭前执行某些代码

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    25714 引用 • 106403 回帖 • 1 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    9854 引用 • 44797 回帖 • 80 关注

相关帖子

被采纳的回答
  • 没太懂,日程不是你自己实现的插件吗?什么时候触发编辑,你自己不是可控的吗?

    还是你的日程在文档中编辑的?建议描述下你的日程是什么?怎样操作的?

    触发频繁,我没试过通过插件开发的方式监听,但我看官方源码大概率是 ws-main 里有很多情况被触发,你通过 data 参数里的 transactions 应该可以判断为更新操作的。

    另外,通过源码可知,这个事件就是官方 ws 的 onmessage 的回调,所以,通过 onmessage 监听也应该是一样的。

    比如:

    siyuan.ws.ws.addEventListener('message', (e) => { const msg = JSON.parse(e.data); if(msg.cmd === "transactions") { // 这里获取更新后的数据 console.log(msg); } });

    可参考 https://github.com/siyuan-note/siyuan/issues/13313#issuecomment-2515402535


    如果非要关闭时生成一次的话,下面这个代码可以满足需求,该代码会拦截思源退出事件,当退出时,先执行回调代码,当完成后再继续退出。

    但注意,该代码仅支持 electron 客户端,由于浏览器和手机端不好拦截暂不支持。

    如果有兴趣研究,可以参考源码 https://github.com/siyuan-note/siyuan/blob/5129ad926a21176a352cf5f630e0651011bf9c83/app/src/dialog/processSystem.ts#L287

    Demo 代码如下(仅支持 electron 客户端):

    // 调用示例,当callback返回true时退出 listenExit(async () => { console.log('waiting'); await sleep(30000); return true; }); // 监听思源退出事件,退出前执行callback,当callback返回true时退出(仅支持electron客户端) // see https://github.com/siyuan-note/siyuan/blob/5129ad926a21176a352cf5f630e0651011bf9c83/app/src/dialog/processSystem.ts#L287 function listenExit(callback) { if(!navigator.userAgent.includes('Electron')) return; // 内核是否已退出 let isKernelExited = false; // 监听内核退出 const originalFetch = window.fetch; window.fetch = async function (url, ...args) { try { if(url.endsWith('/api/system/exit')) { for(;;) { if(await callback()) { isKernelExited = true; break; } await sleep(200); } } const response = await originalFetch(url, ...args); return response; } catch (error) { throw error; } }; // 监听客户端退出 // 保存原始方法 const ipcRenderer = require('electron').ipcRenderer; const originalSend = ipcRenderer.send; // 重写 ipcRenderer.send 方法 ipcRenderer.send = async function (...args) { if(args[0] === 'siyuan-quit'){ for(;;) { if(isKernelExited) { await sleep(400); break; } await sleep(200); } originalSend.apply(ipcRenderer, args); } else { originalSend.apply(ipcRenderer, args); } }; } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }

    虽然这个方法可行,但还是推荐之前的建议,即缩小生成时间间隔和监听日程修改事件。

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 即使监听到,也无法保证代码执行完就退出了,如果执行速度很快可以。长时间执行估计只能调用思源外的命令执行了。

    建议说说实际需求和场景,说不定是 XY 问题。

    1 回复
  • stevehfut via Android

    感谢回复,场景:我开发日程同步插件时,想实现自动生成 ics 文件,考虑到手机日历订阅日历的同步时间最小为 15 分钟,故设定为 15 分钟同步一次,但代码在前端运行,若添加了日程,还没等到 15 分钟就关闭了思源,会导致无法生成新的 ics 文件,故想监听思源关闭事件,在关闭之前生成一次(就像思源关闭时同步一样)

    在此之前也想过监听相关文件的读写或指定数据库的写入(因为 ics 文件是靠数据库的值生成的),但没有实现。

    本人尝试开发思源 插件刚三个左右还算小白,若大佬有什么其他方式可以实现此需求,不胜感激!

    1 回复
  • 我之前理解有误,去网上了解了下,生成 ics 和手机端同步是相互独立的。

    既然这样,我觉得生成 ics 文件的过程可以适当的小些,比如 1 分钟,然后如果检测到日历没变化就不用生成,也不会太占用资源。

    当然最好的方式,是监听日历修改事件,日历修改后就生成文件,不修改不生成,这样就不用担心关闭问题了。

    1 回复
  • stevehfut via Android

    感谢再次回复!

    确实,监听日程数据变化是最好的方式,但我的日程数据是通过数据库获取的,但目前我不知道如何监听数据库编辑事件(我看了思源的 api 文档,觉得最有可能是通过监听 ws–main 来实现,但我没有成功,ws–main 事件的返回值我不太懂,且 ws–main 触发的频率太高了,估计一秒一次,编辑数据时,触发更快)

    不知大佬有什么好的监听数据库编辑事件的方法

    若无法监听,缩短检测日程数据变化时间,可能是目前最好的解决办法了

    1 回复
  • 没太懂,日程不是你自己实现的插件吗?什么时候触发编辑,你自己不是可控的吗?

    还是你的日程在文档中编辑的?建议描述下你的日程是什么?怎样操作的?

    触发频繁,我没试过通过插件开发的方式监听,但我看官方源码大概率是 ws-main 里有很多情况被触发,你通过 data 参数里的 transactions 应该可以判断为更新操作的。

    另外,通过源码可知,这个事件就是官方 ws 的 onmessage 的回调,所以,通过 onmessage 监听也应该是一样的。

    比如:

    siyuan.ws.ws.addEventListener('message', (e) => { const msg = JSON.parse(e.data); if(msg.cmd === "transactions") { // 这里获取更新后的数据 console.log(msg); } });

    可参考 https://github.com/siyuan-note/siyuan/issues/13313#issuecomment-2515402535


    如果非要关闭时生成一次的话,下面这个代码可以满足需求,该代码会拦截思源退出事件,当退出时,先执行回调代码,当完成后再继续退出。

    但注意,该代码仅支持 electron 客户端,由于浏览器和手机端不好拦截暂不支持。

    如果有兴趣研究,可以参考源码 https://github.com/siyuan-note/siyuan/blob/5129ad926a21176a352cf5f630e0651011bf9c83/app/src/dialog/processSystem.ts#L287

    Demo 代码如下(仅支持 electron 客户端):

    // 调用示例,当callback返回true时退出 listenExit(async () => { console.log('waiting'); await sleep(30000); return true; }); // 监听思源退出事件,退出前执行callback,当callback返回true时退出(仅支持electron客户端) // see https://github.com/siyuan-note/siyuan/blob/5129ad926a21176a352cf5f630e0651011bf9c83/app/src/dialog/processSystem.ts#L287 function listenExit(callback) { if(!navigator.userAgent.includes('Electron')) return; // 内核是否已退出 let isKernelExited = false; // 监听内核退出 const originalFetch = window.fetch; window.fetch = async function (url, ...args) { try { if(url.endsWith('/api/system/exit')) { for(;;) { if(await callback()) { isKernelExited = true; break; } await sleep(200); } } const response = await originalFetch(url, ...args); return response; } catch (error) { throw error; } }; // 监听客户端退出 // 保存原始方法 const ipcRenderer = require('electron').ipcRenderer; const originalSend = ipcRenderer.send; // 重写 ipcRenderer.send 方法 ipcRenderer.send = async function (...args) { if(args[0] === 'siyuan-quit'){ for(;;) { if(isKernelExited) { await sleep(400); break; } await sleep(200); } originalSend.apply(ipcRenderer, args); } else { originalSend.apply(ipcRenderer, args); } }; } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }

    虽然这个方法可行,但还是推荐之前的建议,即缩小生成时间间隔和监听日程修改事件。

    1 回复
  • stevehfut via Android

    感谢大佬,这么细致耐心认真的回复,万分感谢!

    日程是在思源数据库中编辑的

    (主键为日程标题,开始时间为日程的持续时间,备注是日程的具体内容)

    当时想着更好地融合思源,故没有弄单独的 ui 界面。

    根据您的提示,我再尝试监听编辑数据库事件,若达不到预期效果,则采用缩短间隔的方法。

    再次感谢您的回复!

    1 回复
  • wilsons 1 评论

    哦哦,明白了。

    不过,通过 transcations 判断,范围还是有点大,它包括所有更新,包括普通块等。

    如果数据库单元格更新的话,再判断下 updateAttrViewCell 就更精确了,建议循环下判断,防止可能有批量更新的情况

    image.png

    当然也可以通过 dom 监听方式,比如,监听 .av__cell 内容的变化,不过有了上面的方法,不推荐这种方法,只是提供一种思路。

    嗯,感谢提供多种思路,我有时间再测一测,改一改。再次感谢回复
    stevehfut
请输入回帖内容 ...
stevehfut
望天空云卷云舒,看庭前花开花落 淮南

推荐标签 标签

  • Access
    1 引用 • 3 回帖 • 1 关注
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    200 引用 • 543 回帖 • 2 关注
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    268 引用 • 666 回帖
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖 • 1 关注
  • V2Ray
    1 引用 • 15 回帖
  • 工具

    子曰:“工欲善其事,必先利其器。”

    298 引用 • 763 回帖 • 1 关注
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    186 引用 • 1020 回帖
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 83 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    20 引用 • 23 回帖 • 739 关注
  • 职场

    找到自己的位置,萌新烦恼少。

    127 引用 • 1708 回帖
  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 14 关注
  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    734 引用 • 1281 回帖 • 1 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 466 关注
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    107 引用 • 127 回帖 • 338 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    76 引用 • 258 回帖 • 626 关注
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    178 引用 • 3866 回帖 • 1 关注
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    108 引用 • 295 回帖 • 1 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 183 关注
  • 浅吟主题

    Jeffrey Chen 制作的思源笔记主题,项目仓库:https://github.com/TCOTC/Whisper

    1 引用 • 28 回帖 • 2 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    25714 引用 • 106403 回帖 • 1 关注
  • 叶归
    9 引用 • 41 回帖 • 21 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    229 引用 • 1432 回帖
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    239 引用 • 224 回帖 • 1 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 29 关注
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 1 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖 • 1 关注