简体中文 | 繁體中文 | English | 日本語 | 한국어 | Español | Français | Deutsch | Русский | Kiswahili | Runasimi
VibeDrop 由三端组成,通过 WebSocket 在局域网内直连通信,无需互联网、无需云服务:
- Mac 桌面端(
desktop/)— 接收文字/文件、剪贴板广播、系统托盘 - 手机端(
mobile/,Android + iOS)— 发送文字/图片/视频/文件、历史时间线 - Home Vault(
scripts/)— 家庭服务器:跨设备历史合并、媒体原件仓、探针日志回收
智能发送卡「跟随光标发送」——手机说话,文字自动落到光标所在的那台电脑(通用控制场景):
| 功能 | Mac 端 | 手机端 (Android + iOS) |
|---|---|---|
| 🎯 智能发送卡「跟随光标发送」 | ✅ 上报键鼠活动(CGEventSource,零权限) |
✅ 文字/图片/文件自动发往光标所在的 Mac,1 秒跟随,可手动切换 |
| 📝 文字传输(手机 → Mac) | ✅ 接收并模拟键盘输入 | ✅ 发送后键盘与语音输入保持,连续口述零多余动作 |
| 📋 剪贴板同步(Mac → 手机) | ✅ 监听变化广播 | ✅ 原生后台服务写入剪贴板 |
| 🌍 多语言 | ✅ 跟随系统 | ✅ 11 门语言(简繁中/英/日/韩/西/法/德/俄/斯瓦希里/克丘亚),gettext 式缺译回退中文 |
| 🤝 自动发现与配对 | ✅ 展示待确认配对、已连接设备 | ✅ 扫描附近电脑、验证码配对;设备可改名并跨手机自动同步 |
| 📜 历史时间线 | ✅ 合并全设备视图 + 缩略图 | ✅ 全设备合并、筛选(来源/目标/类型/原件/时间)、搜索高亮 |
| 📈 活跃热力图 | ✅ 接收热力图 + 点格筛选 | ✅ 发送热力图 + 点格筛选 |
| 🔬 消息自我研究 | —(报告由 Home Vault 生成) | ✅ 历史页内嵌完整报告:词云/口头禅/发送趋势柱状图(scrub 查明细) |
| 📁 文件传输(双向) | ✅ 拖拽 / Finder 服务 / Finder 共享 | ✅ 传到收件箱 / 图片进相册,批量自动打包 |
| 🗄 Home Vault | 家庭服务器:跨设备历史合并 · 媒体原件仓(哈希去重 + Range 流式) · 探针日志回收 | ✅ 增量推送 + SSE 实时同步 |
| 🔒 PIN 码认证 | ✅ 随机生成,持久化到文件 | ✅ 验证码配对后自动保存 |
| 🕰 显示时区设置 | ✅ 本机/北京/美西,显示与统计口径统一 | — |
| 📡 前台保活 / 托盘 | ✅ 系统托盘 + 开机自启 | ✅ Android 通知栏常驻 |
┌────────────────────────────┐ ┌────────────────────────────┐
│ Mac 桌面端 × N (Tauri 2) │ │ 手机端 × N (Tauri 2 Mobile)│
│ ├ Axum HTTP/WS :9001 │◄────►│ ├ app.js 单文件前端 │
│ ├ enigo 键盘模拟 │ WS │ ├ lib.rs 16 个原生命令 │
│ ├ arboard 剪贴板监听 │ │ ├ Kotlin 保活/播放器/剪贴板│
│ ├ CGEventSource 活动上报 │ │ └ iOS 滚动锁(KVO) │
│ └ UDP/HTTP 发现应答 │ └──────────────┬─────────────┘
└──────────────┬─────────────┘ │
│ HTTP :8788 │
▼ ▼
┌──────────────────────────────────────────────────────────┐
│ Home Vault (家庭服务器, home-vault-receiver.py) │
│ 跨设备历史合并 · 媒体原件仓(哈希去重+Range) · SSE 广播 │
│ 设备名公告板 · 探针日志回收 · 自我研究报告(SWR) │
└──────────────────────────────────────────────────────────┘
三条通信路径,全部局域网直连、无云依赖:
- 手机 ↔ Mac:WebSocket(
:9001/ws),PIN 认证后传文字/文件/剪贴板/活动查询; - 所有端 → Home Vault:HTTP(
:8788),历史增量推送、媒体上传、报告获取; - Vault → 客户端:SSE 长连接(
/api/events),历史落盘即广播,25s 心跳保活。
- 桌面端收到
activity_query时调用CGEventSourceSecondsSinceLastEventType(零权限、零线程——读系统为屏保维护的现成账本)回答"距上次键鼠活动几秒"; - 手机每 1 秒轮询所有已连接 Mac,比较相对空闲秒数(免疫两机时钟偏差), 最新鲜者即光标所在——通用控制把键鼠事件真实送达光标所在的机器,信号与事实强耦合;
- 发送(文字/图片/文件)瞬间锁定目标;指示器可点击在自动/手动间循环。
手机端并行两路扫描:UDP 广播 + HTTP 探测(discover_desktops),发现桌面端后走
验证码配对(桌面端弹待确认卡,双方核对同一验证码),通过即保存并自动连接。
设备自定义名保存后经 Vault 公告板(/api/device-names,serverId 为键,LWW)跨手机同步。
- 文字:
type/type_enter动作,桌面端 enigo 模拟键盘落字;外出模式改走clipboard_text(只写剪贴板,配合 UU 远程等远控工具); - 文件:分块传输协议(begin/append/finish/cancel),手机端进收件箱或相册,
Mac 端拖拽/Finder 服务即发;全链路带
transferId传输单号,收发两端记录可精确归并; - 发送按钮拒抢焦点(mousedown preventDefault):键盘与语音输入会话在发送后保持, 连续口述零多余动作。
- 每端本地历史 + 推送游标(
lastPushedEntryId),只推增量(实测单条 3ms/188B); - Vault 合并全设备时间线(
/api/history/merged),客户端平时拉 2000 条轻量、 每会话一次 10000 条深拉;SSE 一到即刷; - 同名身份自动归并(重装换随机 ID 的"前世"折进本机),名字是展示层、身份靠指纹。
原件按 SHA-256 入仓(/api/media/upload,流式+去重,2GB 上限),任何设备凭哈希
在线取原件(/api/media/blob/<hash>,支持 Range 流式播放)——"本机丢≠全网丢"。
app.js 顶端安装 window.onerror 捕获 + probe() 打点,启动 6 秒/出错 1.5 秒
POST 到 Vault /api/client-log 按设备落盘。真机黑屏/白屏类问题不猜,读日志定位。
| 文件 | 行数 | 职责 |
|---|---|---|
src-tauri/src/main.rs |
~4900 | HTTP/WS 服务器、PIN 认证、enigo 键盘、arboard 剪贴板、文件收发、托盘、发现应答、活动上报 |
src/main.js |
~2600 | 桌面 UI:设备总览、配对确认、合并历史+缩略图、接收热力图、时区设置、拖拽发送 |
src/style.css |
~2000 | 桌面样式 |
static/* |
— | mobile/src/ 的逐字节镜像(改手机端后必须同步拷贝,见构建一节) |
| 文件 | 行数 | 职责 |
|---|---|---|
src/app.js |
~11500 | 全部前端逻辑:智能卡、多设备连接、历史时间线(筛选/搜索高亮/虚拟滚动)、热力图、vault 同步、媒体查看器、探针 |
src/i18n.js |
~110 | gettext 式多语言运行时:t()/回退/插值/语言检测/词典缓存 |
src/locales/*.json |
×10 | 语言包(中文原文即钥匙,新语言=加一个文件) |
src-tauri/src/lib.rs |
~1900 | 16 个原生命令:历史持久化、分块收文件、发现配对、机型识别、vault 媒体上传、路径解析;iOS 滚动锁(KVO 观察 contentOffset 渲染前归零) |
gen/android/.../MainActivity.kt |
— | 控制台转发(VibeDropConsole)+ 委托原 WebChromeClient(文件选择器等) |
gen/android/.../KeepAliveService.kt |
— | 前台保活 |
gen/android/.../VideoPlayerActivity.kt |
— | ExoPlayer(Media3)原生全屏播放器 |
gen/android/.../BackgroundClipboardSyncManager.kt |
— | 原生后台剪贴板写入 |
| 脚本 | 职责 |
|---|---|
home-vault-receiver.py (~1000 行) |
家庭服务器全部端点(见下表);launchd 常驻 |
message-self-study.py |
jieba 全套语料分析 → 自包含 HTML 报告(含发送趋势柱状图) |
vault-media-uploader.py / sync-home-vault.py |
存量媒体补传 / 历史落盘同步 |
i18n-check.py |
多语言质检门:扫 t()/data-i18n 全部钥匙,对照语言包报缺漏冗余 |
deploy-android.sh / deploy-desktop.sh / deploy-ios.sh |
三端一键构建部署 |
generate-app-icons.py / generate-tray-frames.py |
品牌资产生成 |
| 端点 | 作用 |
|---|---|
POST /api/history/append · GET /api/history/merged |
增量入库 / 合并时间线 |
GET /api/events |
SSE:落盘即广播 |
POST /api/media/upload · /lookup · GET /api/media/blob/<hash> |
媒体仓:去重入库/查询/Range 流式取 |
GET/POST /api/device-names |
设备名公告板(LWW) |
POST /api/client-log |
探针黑匣子回收 |
GET /report/self-study |
自我研究报告(SWR:秒出缓存,过期后台重算,?refresh=1 强刷) |
| Android | iOS | macOS 桌面 | |
|---|---|---|---|
| 内核 | Chromium | WKWebView | WKWebView(同 iOS!) |
content-visibility: auto |
✅ 原生虚拟化 | ❌ 黑屏 | ❌ 滚动空白 |
| 长列表方案 | content-visibility | JS 虚拟滚动 | 分片挂载 |
Intl.Segmenter 中文分词 |
❌ 切单字 | ✅ 完整词典 | ✅ |
结论:跨内核的中文分词只能服务端 jieba;content-visibility 只许用在 Android。
- 固定布局:外层 WKWebView 滚动为应用壳架构禁用(
isScrollEnabled=false只挡手势, WebKit 键盘揭示走程序化滚动,须再用 KVO 观察 contentOffset 渲染前归零; 钉的"原点"是-adjustedContentInset系统静止位,不是 (0,0));锁在每次回前台补挂; - 出包铁律:
cargo tauri ios build --export-method debugging,不能直接 Xcode Run; - 免费签名 7 天有效(自创建日起算),需自动续签流水线配合。
- 定制 WebChromeClient 必须委托原 client(onShowFileChooser 等),整体替换会弄哑文件选择器;
- console 真身看
adb logcat -d VibeDropConsole:I "*:S"; - 启动时 5 条 "Cannot redefine property" 报错是 Tauri 注入脚本双重执行的良性噪音,勿追查。
- enigo 键盘模拟跑独立线程;剪贴板 500ms 轮询 → broadcast channel → 各 WS 连接;
- 桌面端二进制内部名仍是
voicedrop(pgrep 时注意)。
gettext 流派:中文原文即钥匙,t('发送并回车') 查当前语言词典,缺译回退中文原文
(改一半也永远可发布)。带变量用占位符 t('已改名为 {name}', {name}),严禁字符串拼接。
现有 11 门语言;新增语言 = locales/<lang>.json 一个文件 + i18n.js 映射表一行。
- 质检门:
python3 scripts/i18n-check.py --strict(键覆盖/占位符完整性); - 语义验收:每门语言 30 核心词人工精读(机器保不了语义,详见
docs/i18n-规范.md); - 语言选择器中语言名用语言自称并附中英注音,任何语言包不翻译它们。
# Android(需 cargo + Android SDK 于 PATH)
./scripts/deploy-android.sh # 构建签名 APK + adb 安装启动
# macOS 桌面端
./scripts/deploy-desktop.sh # 构建 + 本地自签 + 装入 /Applications
# --skip-build --skip-icons # 复用现成产物只重装(异机编译后拷贝场景)
# iOS(必须走 Tauri 管线)
cd mobile/src-tauri && cargo tauri ios build --export-method debugging
xcrun devicectl device install app --device <UDID> gen/apple/build/arm64/VibeDrop.ipa纪律两条:
mobile/src/的 app.js / index.html / style.css / i18n.js / locales/ 改动后 必须同步拷贝到desktop/static/(桌面端 HTTP 服务的手机浏览器版);- 两个 Tauri 构建不能并发(共用本地 IPC 通道会撞),必须串行。
推 v* tag 触发 release.yml:自动构建签名 APK + macOS dmg 并发布 GitHub Release;
ci.yml 每次 push 跑构建检查与 Python 单测。
git tag -a v0.x.y -m "说明" && git push origin v0.x.y对你自己的 Home Vault 历史语料做分词词频/口头禅/高频短语/月度话题演变(TF-IDF)/发送趋势(时/天粒度柱状图,手指 scrub 查明细)分析,生成自包含 HTML 报告(全程本地,数据不外发)。
App 内直接看:历史页 →「消息自我研究」卡 → 打开完整报告(Home Vault 端点 /report/self-study,SWR 缓存秒开,过期后台重算,?refresh=1 强制重跑)。
也可手动生成:
python3 -m venv .venv && .venv/bin/pip install jieba
.venv/bin/python scripts/message-self-study.py http://<你的vault地址>:8788报告输出到 ~/Downloads/。多语言施工契约见 docs/i18n-规范.md。



