Recordly 应用内公告系统指南:远程 Feed 配置、字段详解与源码级实现剖析

发布时间:2026/9/19 23:47:20
Recordly 应用内公告系统指南:远程 Feed 配置、字段详解与源码级实现剖析 Recordly 应用内公告系统指南远程 Feed 配置、字段详解与源码级实现剖析【免费下载链接】RecordlyCreate polished demo videos without editing skills. Mac/Windows/Linux项目地址: https://gitcode.com/gh_mirrors/re/RecordlyRecordly 内置了一套可在编辑器内展示可关闭公告的应用内公告系统支持弹窗popup 轮播、轻量实时通知toast与页头横幅banner三种形态其中弹窗可以承载图片或视频。本文将基于docs/announcements.md完整讲解如何通过远程 JSON Feed 或随版本捆绑两种方式发布公告逐字段拆解 Feed 结构与校验规则并结合 src/lib/announcements.ts、electron/ipc/register/announcements.ts 等源码说明其底层解析、安全约束与展示逻辑帮助你零发布成本地触达用户。公告系统的三种呈现形态Recordly 的公告可以在编辑器audience: editor或全应用audience: all中以下列方式呈现呈现形态presentation展示位置与交互是否支持媒体说明popup默认编辑器内弹窗多条公告以轮播carousel形式展示支持图片 / 视频唯一可携带媒体的形态可配置导航箭头与指示器notification非模态 toast 通知不支持纯文本一次 Feed 加载最多展示 5 条banner编辑器页头正下方的一条横幅不支持纯文本按优先级逐条展示一次只显示一条通知与横幅均为纯文本可带按钮即使 Feed 中写了media与mediaMode也会被忽略——这一点由解析器强制保证在 src/lib/announcements.ts 中isTextOnlyPresentation为真时媒体字段被置空。值得注意的是类型定义中还包含第四种export形态见 src/lib/announcements.ts 与测试 src/lib/announcements.test.ts用于导出状态流中的纯文本小贴士但它同样属于纯文本形态不渲染媒体。远程公告不发布新版本也能推送工作机制远程公告的核心思路是将公告 Feed 放在仓库根目录的 announcements.json 中修改该文件并提交到main分支即可发布无需发布新的应用版本。已发布的客户端会以「每个运行中的应用实例最多每六小时检查一次」的频率拉取原始 Feed。拉取失败是静默的绝不会阻塞应用启动。这些约束在 electron/ipc/register/announcements.ts 中有精确的源码对应默认 Feed 地址https://raw.githubusercontent.com/webadderallorg/Recordly/main/announcements.jsonDEFAULT_ANNOUNCEMENT_FEED_URL缓存 TTLANNOUNCEMENT_CACHE_TTL_MS 6 * 60 * 60 * 1000即 6 小时第 6 行请求超时ANNOUNCEMENT_FETCH_TIMEOUT_MS 5_0005 秒第 5 行体积上限MAX_ANNOUNCEMENT_FEED_BYTES 1_000_0001 MB第 7 行响应头声明的content-length与实际 UTF-8 字节数都会校验并发去重同一时刻只有一个进行中的请求pendingFetch单例成功后写入缓存供后续读取第 70-87 行安全重定向Feed 被重定向后必须仍是https:否则视为失败第 44-46 行。抓取到的原始 JSON 通过announcements:getIPC 通道交给渲染进程第 89-91 行再由渲染侧执行字段级解析与筛选。远程 Feed 完整示例仓库根目录的 announcements.json 当前为默认空模板settings.aspectRatio: 4:3无公告条目下面是从官方文档继承的完整可运行示例覆盖了弹窗、通知、横幅三种形态{ settings: { aspectRatio: 4:3 }, announcements: [ { id: recordly-1.4-release, title: A faster Recordly is here, body: Exports are faster and cursor motion is smoother. Thanks for using Recordly!, presentation: popup, audience: editor, priority: 10, mediaMode: cover, displayDurationSeconds: 15, maxImpressions: 3, controls: { close: true, dismiss: false, action: true, navigation: false, indicators: true }, startsAt: 2026-09-01T00:00:00Z, endsAt: 2026-10-01T00:00:00Z, minVersion: 1.4.0, media: { type: image, url: https://example.com/recordly-1.4-banner.jpg, alt: Recordly 1.4 feature preview }, action: { label: See what changed, url: https://github.com/webadderallorg/Recordly/releases } }, { id: recordly-maintenance-notice, title: Quick service notice, body: Cloud sharing will undergo brief maintenance tonight., presentation: notification, audience: editor, displayDurationSeconds: 10, maxImpressions: 2, startsAt: 2026-09-05T00:00:00Z, endsAt: 2026-09-06T00:00:00Z }, { id: recordly-editor-banner, title: Try the new editor, body: The redesigned timeline is now available., presentation: banner, audience: editor, maxImpressions: 3, action: { label: Open settings, section: settings } } ] }ID 的幂等性语义每次想让某条公告重新出现都必须使用一个新的稳定id。用户一旦关闭dismiss某个 ID该 ID 就会永久保持关闭状态另外maxImpressions达到上限后也不会再展示。这一语义在 src/lib/announcements.ts 的selectAnnouncements中体现筛选条件依次为「已关闭 ID 集合」「展示次数上限」「受众范围」「startsAt未到」「endsAt已过期」「minVersion高于当前版本」「maxVersion低于当前版本」最终按priority从大到小排序。远程条目与捆绑条目同 ID 时远程条目覆盖捆绑条目。合并逻辑是先将捆绑条目写入Map再用远程条目按 ID 覆盖第 314-320 行并有测试专门验证「远程公告替换同 ID 的捆绑条目」src/lib/announcements.test.ts。关闭状态与展示次数的持久化位于 src/lib/announcementState.ts关闭 ID 列表存储在dismissedAnnouncementIds设置项、最多保留 200 条MAX_DISMISSED_ANNOUNCEMENTS印象计数存储在announcementImpressionCounts设置项每次会话每个公告最多计一次由组件内的Set去重。字段参考每个配置项的含义与取值settings与公告条目的字段说明如下均继承自官方文档并结合 src/lib/announcements.ts 的解析逻辑补充边界条件settings.aspectRatio为整个弹窗轮播设定统一的width:height比例例如16:9、4:3、1:1。所有幻灯片保持同一尺寸省略时使用捆绑默认值仓库默认模板为4:3。解析器 readAspectRatio 会校验格式为\d{1,3}:\d{1,3}且宽高比数值必须落在 0.43 之间否则视为无效并回退。弹窗组件将其转换为 CSSaspect-ratio样式见 AnnouncementDialog.tsx。公告条目标签字段必填取值与默认说明id✅字符串稳定标识长度上限 100关闭后永久隐藏重新展示需换新 IDtitle✅字符串标题长度上限 160body✅字符串正文长度上限 2 000presentation—popup默认/notification/banner展示形态通知与横幅忽略媒体字段audience—all默认/editor展示受众priority—数字默认0控制轮播顺序数值大的排前面解析时被裁剪到 -100100mediaMode—banner默认/coverbanner为当前默认布局cover让媒体铺满弹窗并将文字叠放其上startsAt/endsAt—ISO 时间戳时间窗口外不展示displayDurationSeconds—整数3300弹窗自动切到下一张对通知则控制 toast 停留时长默认 10 秒maxImpressions—整数1100最多展示的应用会话数每条公告每会话最多计一次主动关闭则永久隐藏controls—对象独立控制close/dismiss/action/navigation/indicators全部默认trueminVersion/maxVersion—版本字符串包含式的应用版本上下限支持v前缀与预发布后缀比较media—对象仅弹窗可用type为image或videoURL 必须是 HTTPS 或根相对路径的捆绑资源视频可附加posterUrlaction—对象label加且仅加一个目的地HTTPSurl系统浏览器打开或编辑器section应用内打开controls细节每个控件独立可开关close、dismiss、action、navigation、indicators默认都为true。通知与横幅只使用close与action弹窗轮播使用其余控件。即使可见的关闭按钮被隐藏按Escape键或点击弹窗外区域仍然可以关闭——组件在onOpenChange中处理了dismiss被禁用时仅关闭弹窗而不永久记录关闭的逻辑AnnouncementDialog.tsx。action目的地action必须包含label且恰好一个目的地urlHTTPS 链接点击后调用window.electronAPI.openExternalUrl在系统浏览器中打开src/lib/announcementActions.tssection应用内跳转的编辑器区域支持scene、cursor、webcam、captions、settings、extensions通过派发recordly:open-editor-section自定义事件实现src/lib/announcementActions.ts。同时包含两个目的地、一个都不含、或section不在上述列表中该 action 都会被忽略parseAction 用Boolean(url) Boolean(section)排除了歧义并有测试用例覆盖src/lib/announcements.test.ts。媒体与 URL 安全规则media.type仅对弹窗有效取值为image或video。媒体 URL 只接受两类https:协议、且不含用户名/密码的绝对地址以/开头且不以//开头的根相对路径用于引用随应用捆绑的本地资源。posterUrl仅视频可用规则相同。解析逻辑见 readSafeUrl例如javascript:alert(1)、http://example.com这类不安全地址会被静默丢弃但公告本身只要id/title/body合法仍会被保留展示测试见 src/lib/announcements.test.ts。使用自定义 Feed 与完全禁用通过环境变量在启动应用前配置自定义 HTTPS Feed# 使用自定义 HTTPS 地址作为公告 Feed RECORDLY_ANNOUNCEMENTS_URLhttps://example.com/my-announcements.json recordly # 彻底禁用远程公告 RECORDLY_ANNOUNCEMENTS_URLoff recordly源码中 getAnnouncementFeedUrl 对该变量的处理是值为off不区分大小写时返回null直接禁用拉取否则优先使用配置值回退到默认仓库地址配置值同样必须是 HTTPS 且不含凭据否则同样视为禁用。随版本捆绑公告需要与某个新版本原子性地一起发布时可将公告以类型化条目写入 src/content/announcements.ts 的BUNDLED_ANNOUNCEMENT_FEED。捆绑条目使用完全相同的 schema且离线可用——无需网络即可展示。当前仓库的默认捆绑 Feed 与远程模板保持一致aspectRatio: 4:3、公告列表为空。从组件代码看渲染进程会并行读取应用版本与远程 Feed失败时回退为null把捆绑 Feed 与解析后的远程 Feed 一起交给selectAnnouncements筛选再按形态分流弹窗类交给 AnnouncementDialog.tsx、横幅交给 EditorAnnouncementBanner.tsx、通知交给 LiveAnnouncementNotifications.tsx后者使用 sonner toast默认停留 10 秒、单次最多 5 条。安全模型远程内容只当作数据处理远程 Feed 被严格当作数据而非代码对待安全边界在解析与抓取两层均有落实不渲染 HTML所有文本以纯文本形式渲染组件中使用whitespace-pre-line等样式而非dangerouslySetInnerHTMLURL 受限媒体与 action URL 必须是 HTTPS 或根相对路径见 readSafeUrl体积受限Feed 最多 50 条公告MAX_ANNOUNCEMENTS抓取体积上限 1 MB标题/正文/标签/URL 均有长度上限src/lib/announcements.ts时间受限startsAt/endsAt时间窗控制展示窗口过期公告自动失效格式错误的条目被忽略缺少id/title/body的条目、非法的section、非法的 URL 等都会被静默丢弃不会影响同 Feed 中的其他合法条目parseAnnouncementFeed。从文档到源码发布流程速览在仓库根目录编辑 announcements.json或为捆绑发布编辑 src/content/announcements.ts为每条公告分配新的稳定id按上表补齐字段确保action只有一个目的地、媒体 URL 合规提交到main分支已发布的客户端最迟 6 小时内会拉到新 Feed验证可在本地通过RECORDLY_ANNOUNCEMENTS_URL指向自己的 HTTPS 地址先行预览解析与筛选逻辑可用 src/lib/announcements.test.ts 中的用例作为行为规范参考。掌握这套机制后你可以在不发布版本的情况下用配置化方式向用户推送版本更新、维护通知与功能引导并借助audience、版本区间与优先级实现精准的定向触达。【免费下载链接】RecordlyCreate polished demo videos without editing skills. Mac/Windows/Linux项目地址: https://gitcode.com/gh_mirrors/re/Recordly创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询