兰 亭 墨 苑
期货 · 量化 · AI · 终身学习
首页
归档
编辑文章
标题 *
URL 别名 *
内容 *
(支持 Markdown 格式)
我们来详细解释一下这段代码。 这是一段为 **JSBox** 应用编写的 **剪贴板历史管理器** 脚本。JSBox 是一个在 iOS 上运行 JavaScript 代码的强大工具,可以通过脚本实现各种自动化功能。 ### 核心功能概览 这个脚本的核心目标是: 1. **自动记录**:在后台静默监控系统剪贴板,每当有新的内容被复制时,自动保存下来。 2. **持久化存储**:将剪贴板历史记录安全地存储在 iOS 的钥匙串(Keychain)中,即使关闭脚本或重启手机,数据也不会丢失。 3. **管理与交互**:提供一个用户界面,让你可以浏览、搜索、复制、置顶、编辑和删除历史记录。 --- ### 代码分段详解 我们将代码分成几个逻辑部分来理解。 #### 1. 全局设置 (Settings) ```javascript const KC_KEY = "CLIPBOARD_HISTORY"; // 在钥匙串中存储数据用的“钥匙” // Settings const MAX_ITEMS = 200; // 最多保存200条历史记录 const POLL_INTERVAL = 1.5; // 每1.5秒检查一次剪贴板 const MIN_TEXT_LEN = 1; // 文本长度至少为1才记录 const IGNORE_SAME_CONSEC = true; // 如果连续复制同样的内容,则忽略 ``` 这部分定义了脚本的基本行为: * `KC_KEY`: 一个唯一的字符串,用作在钥匙串中存取数据的标识符。 * `MAX_ITEMS`: 为了防止历史记录无限增长占用过多空间,这里限制最多只保存200条。当超过时,最旧的记录会被删除。 * `POLL_INTERVAL`: 轮询间隔,即脚本每隔多久检查一次剪贴板有没有新内容。1.5秒是一个比较均衡的设置。 * `MIN_TEXT_LEN`: 太短的内容(比如一个空格)通常没有意义,所以不记录。 * `IGNORE_SAME_CONSEC`: 这是一个优化。如果你反复按 `Cmd+C` 复制同一个东西,脚本只会记录一次。 #### 2. 数据存储与管理函数 (Utilities) 这部分函数负责处理数据的读取、保存和清理,它们都与钥匙串(`$keychain`)交互。 * `loadHistory()`: 从钥匙串中读取历史记录。它使用 `JSON.parse` 将存储的字符串转换回 JavaScript 数组。如果读取失败或没有数据,返回一个空数组。 * `saveHistory(list)`: 将历史记录数组(`list`)保存到钥匙串。在保存前,它会确保记录不超过 `MAX_ITEMS` 的限制,并使用 `JSON.stringify` 将数组转换为字符串。 * `clearAll()`: 清空所有历史记录,通过从钥匙串中移除对应的 `KC_KEY` 实现。 #### 3. 核心数据操作函数 这部分函数是业务逻辑的核心,负责增、删、改、查历史记录。 * `normalizeText(t)`: 一个辅助函数,用于“标准化”文本。它会统一换行符(`\r\n` -> `\n`)并去除首尾的空格,这样可以确保比较文本时的一致性。 * `upsertItem(list, text, opts)`: 这是最核心的函数之一,实现了 **"Update or Insert"(更新或插入)** 的逻辑。 * 如果 `text` 在历史记录中 **已存在**,它会更新这条记录的时间戳,并将其移动到列表顶部(如果记录被置顶,则移动到所有置顶项的顶部)。 * 如果 `text` 是 **新内容**,它会创建一个新的记录对象(包含文本、当前时间戳、是否置顶),并将其插入到列表顶部(同样,置顶项优先)。 * 这个函数保证了最新使用或复制的内容总是在最前面,非常符合使用习惯。 * `pinToggle(list, index, filtered)`: 切换指定记录的 **置顶** 状态。它会修改记录的 `pinned` 属性,然后对整个列表重新排序,确保所有置顶项都在非置顶项之前,最后保存。 * `deleteItem(list, index, filtered)`: 删除指定的记录。 #### 4. UI 界面与状态管理 这部分代码负责构建用户界面并处理界面的数据更新。 * `state`: 一个全局状态对象,存储了当前所有的历史记录 (`list`)、经过搜索过滤后的记录 (`filtered`)、搜索关键词 (`q`) 等。UI 的显示完全依赖于这个 `state` 对象。 * `filterList()`: 根据搜索框中的关键词 (`state.q`) 过滤历史记录。它支持多个关键词搜索,并会对搜索结果进行排序,让匹配度更高的结果排在前面。 * `reloadListView()`: 刷新列表视图。它会先调用 `filterList()` 获取最新的显示数据,然后将数据格式化(比如处理标题、副标题、时间戳、置顶标记 `📌`),最后更新到界面上的列表(`$("list")`)中。 * `copyItem(index)`: 当用户点击列表中的某一项时触发。它会将该项的文本复制到系统剪贴板,并调用 `upsertItem` 将其更新到列表顶部。 * `editSheet(index)`: 当用户选择编辑某一项时,弹出一个新的页面,其中包含一个文本框,允许用户修改内容并保存。 #### 5. 剪贴板自动监控 (Polling) * `startPolling()`: 启动一个定时器 (`$timer.schedule`),按照前面设定的 `POLL_INTERVAL` 间隔,周期性地执行一个任务。 * **定时器任务**:检查当前剪贴板的内容,如果内容是新的(与上次复制的不同,也与列表顶部的不同),就调用 `upsertItem` 将其添加到历史记录中,并刷新界面。 * `stopPolling()`: 停止定时器。这很重要,当脚本界面关闭时,需要调用它来停止后台检查,以节省系统资源。 #### 6. 主界面定义 (`$ui.render`) 这是脚本的入口,定义了整个应用的界面布局和事件处理。 * **`views` 数组**: * **Toolbar (工具栏)**: 位于顶部的视图,包含了“导入”、“导出”、“清空”三个按钮和一个“搜索框”。 * **导入**: 手动将当前剪贴板的内容添加到历史记录。 * **导出**: 将所有历史记录格式化成纯文本,并弹出系统分享菜单。 * **清空**: 弹出确认框,防止误操作,确认后清空所有历史。 * **搜索框**: 输入文字时会实时调用 `reloadListView` 筛选列表。 * **List (列表)**: 显示剪贴板历史的主体部分。 * `template`: 定义了列表中每一行的样式(一个标题标签和一个副标题标签)。 * `actions`: 定义了列表项 **左滑** 时出现的按钮(“置顶/取消”和“删除”)。 * `events`: 定义了列表的交互事件。 * `didSelect`: **单击** 列表项,触发 `copyItem` 复制内容。 * `didLongPress`: **长按** 列表项,弹出一个菜单,提供复制、置顶、编辑、删除、分享等更多操作。 * **`events` 对象**: * `appeared`: 当脚本界面 **出现** 时触发。在这里,它会加载历史记录,并启动 `startPolling` 开始监控剪贴板。 * `disappeared`: 当脚本界面 **消失**(比如切换到其他应用或关闭)时触发。在这里,它会调用 `stopPolling` 停止监控,节省电量。 ### 总结 总而言之,这是一个设计精良、功能完备的剪贴板历史管理工具。它利用 JSBox 提供的原生 UI 和系统能力(`$clipboard`, `$keychain`, `$timer`),实现了自动记录、安全存储、高效管理和友好交互等一系列功能。代码结构清晰,通过 `state` 对象管理状态,通过函数分离不同职责,是一个很好的 JSBox 脚本范例。
配图 (可多选)
选择新图片文件或拖拽到此处
标签
更新文章
删除文章