- 桌面应用
【免费下载链接】Lunar
Intelligent adaptive brightness for your external monitors
导读
本文以 Lunar 开源仓库中的 ReleaseNotes/4.0.4.md 为核心,深入剖析 Lunar 4.0.4 的关键修复:在免费更新期仍然有效的情况下,错误弹出 "Your period of free updates has expired"(免费更新期已过期)提示。文章将结合仓库中 Sparkle 更新器、Paddle 许可模块与 appcast 发布配置的实现细节,说明该问题在 Lunar 许可与更新体系中的位置、4.0.4 的修复内容,以及用户如何通过更新界面验证和获取该修复。读完本文,你将掌握 Lunar 的版本更新校验机制、更新控制项与发布通道的运作方式。
一、4.0.4 修复内容速览
ReleaseNotes/4.0.4.md 全文只有一条 Fixes 记录:
Stop showingYour period of free updates has expiredwhen the period of updates is still valid
即:当免费更新期仍然有效时,不再显示"免费更新期已过期"的提示。该条目同样收录于 CHANGELOG.md(# 4.0.4段落),并在 Releases/appcast.xml 的 4.0.4 发布条目中给出了补充说明:
I'm really sorry if you have been seing theYour period of free updates has expiredscreen. This should be fixed now in 4.0.4 and the next update shouldn't show that screen anymore.
从表述看,这是一次面向付费用户的误报修复:Lunar 4 采用"购买后含一定时长的免费更新期"模式,应用需要校验当前许可证的更新期是否仍在有效期内,而 4.0.4 之前存在校验逻辑缺陷,导致更新期有效的用户也看到了过期提示。
二、问题背景:Lunar 4 的许可与免费更新模型
理解这条修复,需要先了解 Lunar 4 的许可体系。当前仓库的快照中保留了完整的 Paddle(商业许可/支付 SDK)集成代码:
- Lunar/AppDelegate.swift 中
import Paddle,并在 Lunar/AppDelegate.swift 中通过producct?.activationEmail、producct?.activationID将 Paddle 激活信息关联到 Sentry 用户上下文,用于诊断反馈; - Lunar/Views/ProViews.swift 中的
LicenseView持有PADProduct(@State var product: PADProduct?),读取trialDaysRemaining、lunarProActive、lunarProOnTrial等状态,实时显示许可证状态徽标(trial/active/inactive)以及剩余试用天数。
从源码结构可以推断,"Your period of free updates has expired" 这类提示来自 Paddle 的产品校验结果:当 Paddle 判定许可证绑定的免费更新期已结束而用户尚未续费时,会弹出付费引导界面;而 4.0.4 修复的正是有效期内也被误判为过期的分支。
这条修复并非孤立事件。在其后的版本中,更新期提示逻辑被持续打磨:
- ReleaseNotes/4.6.5.md 中记录"Make the paid updates message clearer when the free updates period expires"(让免费更新期真正到期时的付费提示更清晰),与 4.0.4 形成"误报修正 → 真实到期提示优化"的完整演进;
- 更早的 4.0.2 版本在 Releases/appcast.xml 中同样记录了一条 "Fix valid updates checking logic",说明 4.0.x 系列一直在集中修复更新有效性校验逻辑。
三、更新检查链路:Sparkle 在 AppDelegate 中的实现
Lunar 的版本更新功能由 Sparkle 框架承载,相关代码集中在 Lunar/AppDelegate.swift:
- AppDelegate.swift 惰性初始化
SPUUpdater实例,并在 AppDelegate.swift 中调用updater.start()启动更新器,同时将automaticallyDownloadsUpdates绑定到Defaults[.silentUpdate](静默更新开关); - AppDelegate.swift 提供
checkForUpdates(_:)动作,直接调用updater.checkForUpdates()触发手动检查,该动作同时挂在菜单栏与主界面(见 Main.storyboard); - AppDelegate.swift 将"自动下载更新"和"自动检查更新"两个开关分别映射到
updater.automaticallyDownloadsUpdates与updater.automaticallyChecksForUpdates。
这条链路决定了用户获取 4.0.4 的方式:既有 Sparkle 周期性自动检查,也有用户手动触发。误报的过期提示正是出现在这套更新流程与 Paddle 许可校验交汇处——Sparkle 从 appcast 拉取到新版本后,Paddle 需确认用户是否有资格免费升级,校验逻辑出错即导致误报。
四、用户侧的更新控制项与校验周期
更新行为的所有用户可调项集中在 Lunar/Views/ProViews.swift 的VersionView中,并被 Lunar/SwiftUIViews/QuickActionsMenuView.swift 嵌入到菜单栏快捷界面:
| 控制项 | 作用 | 源码位置 |
|---|---|---|
| Check for updates | 手动触发updater.checkForUpdates() | ProViews.swift |
| Auto update | 绑定Defaults[.checkForUpdate],控制自动检查 | ProViews.swift |
| Daily / Weekly / Monthly | 通过UpdateCheckInterval枚举设置检查周期 | ProViews.swift |
| Update to beta builds | 切换Defaults[.updateChannel]到 beta 通道 | ProViews.swift |
| Install updates silently in the background | 绑定Defaults[.silentUpdate] | ProViews.swift |
其中 UpdateCheckInterval 枚举定义了四个周期对应的秒数,作为默认值存储:
enum UpdateCheckInterval: Int { case daily = 86400 // 每天 case everyThreeDays = 259_200 // 每三天(界面未直接暴露,但定义存在) case weekly = 604_800 // 每周 case monthly = 2_592_000 // 每月 }对 4.0.4 的修复而言,用户侧的验证方式非常简单:保持 Auto update 开启或手动点击 Check for updates,等待 Sparkle 拉取 Releases/appcast.xml 中 4.0.4 条目后完成升级;升级后若仍在免费更新期内,不应再看到过期提示界面。
五、发布与分发证据:appcast.xml 中的 4.0.4 条目
Releases/appcast.xml 完整记录了 4.0.4 的发布元数据,是 Sparkle 更新器识别与下载该版本的唯一依据:
- 版本标识:
sparkle:shortVersionString="4.0.4"、sparkle:version="4.0.4",两者一致; - 发布时间:
pubDate为Sat, 29 May 2021 20:19:12 +0300; - 系统要求:
sparkle:minimumSystemVersion="10.15",与 ReleaseNotes/4.0.3.md 中"最低要求 macOS 10.15"的调整保持一致; - 最低可自动升级版本:
sparkle:minimumAutoupdateVersion="4.0.0",即只有已处于 4.0.0 及以上的安装实例才会走自动升级路径; - 安装类型:
sparkle:installationType="package",4.0.x 系列通过安装包形式分发; - 完整包与增量包:
enclosure指向完整安装包(约 19.8 MB),并提供了自 4.0.0 / 4.0.1 / 4.0.2 / 4.0.3 四个历史版本的sparkle:deltas增量更新包,用户可从任何 4.0.x 小版本平滑升到 4.0.4; - 签名:
sparkle:edSignature/sparkle:dsaSignature提供 EdDSA 与 DSA 双重签名校验,保证更新包来源可信。
其中minimumAutoupdateVersion="4.0.0"与增量包配置值得注意:这意味着 4.0.4 的修复能够通过增量补丁快速送达,用户无需重新下载完整安装包,这正是"the next update shouldn't show that screen anymore"能迅速生效的分发前提。
六、验证与升级建议
针对仍在 4.0.x 且可能遭遇过误报的用户,建议按以下步骤操作:
- 打开 Lunar 菜单栏界面,进入 Version 区域(对应 QuickActionsMenuView.swift 中的版本入口);
- 点击Check for updates,Sparkle 将读取 appcast 并提示 4.0.4 可用;
- 确认系统版本不低于 macOS 10.15(4.0.3 起的最低要求);
- 升级完成后在设置中确认 Auto update 状态与检查周期(Daily / Weekly / Monthly),并核验许可证状态徽标是否仍为
active(见 LicenseView)。
若升级后仍在有效期内却再次看到过期提示,可结合诊断信息中的许可证与更新日志进行反馈——AppDelegate.swift 会将激活邮箱(在用户同意时)、激活 ID 与自适应模式等信息写入 Sentry 上下文,便于开发者定位许可校验分支。
结语:从一条 Fix 看 Lunar 的更新与许可体系
一条看似简单的发布说明,实际牵动 Paddle 许可校验(ProViews.swift)、Sparkle 更新调度(AppDelegate.swift)、用户侧更新控制项(VersionView)与发布分发配置(appcast.xml)四层链路。4.0.4 的修复标志着 Lunar 4 在"付费引导"与"真实过期判断"之间终于划清了边界,也为后续 4.6.5 的到期提示优化与 5.6.0 的"无限免费更新"策略调整奠定了逻辑基础。对开发者而言,这份发布说明连同其后的 ReleaseNotes/4.0.5.md 等系列文档,是观察一个商业软件如何在不打扰付费用户的前提下打磨许可体验的完整样本。
- 桌面应用
【免费下载链接】Lunar
Intelligent adaptive brightness for your external monitors
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考