我用 Rust 做了一个跨平台护眼提醒工具 BlinkSpark

0 阅读8分钟

如果你和我一样,长时间盯着屏幕写代码、看文档、回消息,就会很容易进入一种“专注得忘了眨眼”的状态。时间一久,眼睛干涩、疲劳、注意力下降,基本是很多开发者和办公人群的共同问题。

所以我做了一个小而实用的桌面工具:BlinkSpark

它是一个基于 Rust 开发的跨平台 20-20-20 护眼提醒工具,支持 Linux、macOS 和 Windows。启动之后,它会在桌面上显示一个轻量的倒计时小窗,并在设定时间到达后通过系统通知提醒你休息一下,把视线从屏幕前挪开。

这篇文章想聊两件事:

  1. BlinkSpark 这个产品为什么值得做。
  2. 它在技术实现上,为什么是一种很适合 Rust 桌面应用的落地方式。

为什么是 BlinkSpark

市面上并不缺提醒类工具,但很多产品的问题是“要么太重,要么太吵,要么不够顺手”。

我希望 BlinkSpark 是一种更克制的产品体验:

  • 它不是一个复杂的效率平台,而是一个开箱即用的小工具。
  • 它不是把提醒做成打断,而是做成一种轻量、稳定、长期可接受的陪伴。
  • 它不是只在某一个系统可用,而是尽量保持跨平台一致体验。

BlinkSpark 目前围绕一个非常明确的场景来设计:用最小的交互成本,帮助用户实践 20-20-20 规则。

所谓 20-20-20,就是每 20 分钟,看向 20 英尺外大约 20 秒。这并不复杂,但真正难的是把它变成一个你愿意长期打开的桌面产品。


BlinkSpark 现在能做什么

当前版本已经具备一套比较完整的桌面提醒体验:

  • 跨平台支持 Linux / macOS / Windows
  • 默认 20 分钟提醒一次,也支持自定义提醒间隔
  • 支持系统通知提醒
  • 提供常驻桌面的倒计时小窗
  • 小窗可拖动,方便放在不打扰工作的区域
  • 自动记住上次窗口位置,下次启动直接恢复
  • 支持中文和英文界面/通知切换
  • 支持“仅提醒一次后退出”模式
  • Windows 下支持应用图标和打包资源嵌入

从产品层面看,这些功能看起来都不算“炫技”,但正是这些细节决定了一个工具能不能真的留下来。

一个只能弹通知、却不能提供可视化倒计时的工具,用户很容易忘记它是否还在运行。 一个窗口固定死、每次启动位置都变化的工具,也很难称得上顺手。 一个没有本地化、没有品牌图标、没有打包完整度的开源项目,也很难形成“产品感”。

而 BlinkSpark 想做的,恰恰是把这些体验补齐。


为什么用 Rust 来做这个项目

BlinkSpark 的定位虽然轻,但它本质上是一个典型的桌面应用工程题:

  • 需要跨平台
  • 需要稳定运行
  • 需要较低资源占用
  • 需要和系统通知、窗口、图标、构建流程打交道

Rust 在这里非常合适。

第一,它能很好地控制依赖和产物质量。 对于这种长期常驻的小工具,稳定性和可维护性比“快速拼出来”更重要。

第二,它很适合做跨平台抽象。 不同系统的通知实现差异很大,但我们完全可以在代码里把平台差异收敛到一个统一接口后面。

第三,它也非常适合做这种“小而完整”的产品。 CLI 参数、桌面 GUI、资源打包、平台兼容、配置持久化,这些事情放在 Rust 里组合起来,工程体验其实非常顺。


技术实现上,BlinkSpark 做了哪些选择

1. 用 clap 管理命令行参数

BlinkSpark 支持几个非常实用的启动参数:

  • --lang zh|en:切换语言
  • --interval <分钟>:自定义提醒间隔
  • --once:提醒一次后退出

这意味着它既可以作为普通桌面应用直接启动,也可以被纳入用户自己的脚本、启动项或者自动化工作流里。

对于开发者用户来说,这一点非常重要。一个能被命令行控制的桌面工具,往往更容易融入真实工作环境。

2. 用 eframe/egui 做轻量桌面窗口

BlinkSpark 的 GUI 并不复杂,但它并不是“没有界面”。 我希望它既轻量,又能给用户一个持续可见的状态反馈。

所以项目采用了 eframe/egui 来实现:

  • 固定尺寸的小窗
  • 实时刷新倒计时
  • 支持语言切换
  • 支持错误信息展示
  • 支持拖动后保存窗口位置

这类 UI 框架的优势在于,开发效率很高,同时足够适合这种桌面工具型应用。 你不需要为了一个很小的交互界面,引入过于沉重的前端栈或复杂的原生绑定。

3. 把系统通知做成平台抽象

通知是这个项目最关键的跨平台点之一。

BlinkSpark 针对不同系统分别使用了对应的通知方案:

  • Linux: notify-rust
  • macOS: mac-notification-sys
  • Windows: winrt-notification

在代码结构上,外部只调用统一的 notify(title, body) 接口,平台差异则放在 src/notifier/mod.rs 中处理。

这种设计的好处非常直接:

  • 业务层不需要关心平台细节
  • 后续新增平台行为更容易维护
  • 出错信息可以统一反馈到界面层

这也是 Rust 很适合做“工程型桌面工具”的原因之一:你可以把平台差异控制在一个很小、很干净的边界里。

4. 让窗口位置真正“记住你”

很多小工具都有一个体验问题:窗口明明能拖,但下次打开还是回到默认位置。

BlinkSpark 处理了这个细节。 项目会在窗口移动后,将位置写入本地配置文件:

  • Windows 下使用 %APPDATA%/BlinkSpark/window-position.txt
  • 非 Windows 环境下使用 XDG_CONFIG_HOME~/.config/blinkspark/window-position.txt

下次启动时再读取这个位置并恢复。

这个能力本身不复杂,但很能体现一个产品是不是在认真对待日常使用体验。对于桌面常驻工具来说,这比多做两个花哨功能更重要。

5. 默认右下角启动,更符合真实桌面习惯

在 Windows 上,BlinkSpark 会通过 windows-sys 获取屏幕尺寸,把小窗放到右下角附近启动。 这类默认策略看似很小,实际上能明显降低第一次使用的认知成本。

用户打开应用之后,不需要四处找窗口,也不用先进行额外配置,这种“开箱即用”的感受对工具类产品很关键。

6. 不只写功能,也把品牌和构建链路补齐

BlinkSpark 不只是“写完代码能跑”。

项目还补上了完整的品牌和打包细节:

  • 提供 SVG Logo 和 App Icon
  • 提供批量生成 PNG/ICO 资源的 PowerShell 脚本
  • 在 Windows 构建时通过 build.rs 自动嵌入图标资源
  • 提供中文的 Windows 构建与发布说明

这部分工作常常容易被忽略,但它会直接影响项目的观感、传播力和可发布性。

一个开源项目如果想从“代码仓库”走向“产品形态”,这些细节并不是加分项,而是必要项。


我希望 BlinkSpark 适合哪些人

BlinkSpark 很适合下面这些用户:

  • 长时间写代码的开发者
  • 经常开会、做文档、回消息的知识工作者
  • 需要一个轻量、安静、可长期运行的护眼提醒工具的人
  • 希望自己掌控工具、偏好开源项目的用户

如果你不想装一个功能庞杂的效率软件,只想要一个“打开就能用、存在感刚刚好”的桌面提醒器,BlinkSpark 会是一个很直接的选择。


对技术博客平台来说,这个项目为什么值得写

我觉得 BlinkSpark 适合发在技术博客平台,不只是因为它“是 Rust 写的”,更因为它同时具备三个特点:

  • 它是一个真实可用的产品,不只是 demo
  • 它覆盖了跨平台桌面应用里的几个典型问题
  • 它足够轻量,读者能快速理解,也能快速上手二次开发

对于喜欢 Rust 的读者,它能提供一个很具体的桌面应用实践样本。 对于喜欢做产品的开发者,它也说明了一件事:小工具不是“小项目”,把一个小需求做出产品感,本身就是一种工程能力。


现在就可以怎么用

如果你想快速体验 BlinkSpark,可以直接从仓库拉代码编译运行:

cargo build --release

常见启动方式:

blinkspark
blinkspark --lang zh
blinkspark --interval 30
blinkspark --once

项目地址:

github.com/shuyixiao-b…


结语

BlinkSpark 想解决的不是一个宏大问题,而是一个每天都会反复发生、却经常被忽视的小问题。

我很喜欢这种项目类型:需求明确、边界清晰、用户真实、技术上又能把跨平台、桌面 GUI、系统通知、配置持久化、构建打包这些点都串起来。

如果你也在做 Rust 桌面应用,或者你正在找一个真正能用起来的护眼提醒工具,欢迎看看 BlinkSpark。 也欢迎一起提 issue、提建议、继续把它打磨成一个更完整、更好用的跨平台桌面产品。