Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
243 commits
Select commit Hold shift + click to select a range
6dea6cd
feat: Add PRD with OCR and translation features
Feb 3, 2026
ef066af
feat: US-002 - 本地 OCR 引擎 - Vision 框架
Feb 3, 2026
c7872b0
feat: US-002 - 本地 OCR 引擎 - Vision 框架
Feb 3, 2026
955dbcf
feat: US-003 - 本地翻译引擎 - Apple Translation API
Feb 3, 2026
64298c6
feat: US-003 - 本地翻译引擎 - Apple Translation API
Feb 3, 2026
9b2d0b6
feat: US-004 - 覆盖层渲染引擎 - 原位替换模式
Feb 3, 2026
120cff1
feat: US-004 - 覆盖层渲染引擎 - 原位替换模式
Feb 3, 2026
30d8e98
feat: US-005 - 覆盖层渲染引擎 - 原文下方模式
Feb 3, 2026
d610c7e
feat: US-005 - 覆盖层渲染引擎 - 原文下方模式
Feb 3, 2026
c915505
feat: US-006 - 设置面板 - 引擎选择与基础配置
Feb 3, 2026
96df2ba
feat: US-006 - 设置面板 - 引擎选择与基础配置
Feb 3, 2026
32e9565
feat: US-007 - 设置面板 - 语言配置
Feb 3, 2026
96a2461
feat: US-007 - 设置面板 - 语言配置
Feb 3, 2026
a5a34bb
feat: US-008 - 可选 OCR 引擎 - PaddleOCR 集成
Feb 3, 2026
271927b
feat: US-008 - 可选 OCR 引擎 - PaddleOCR 集成
Feb 3, 2026
7357e38
feat: US-009 - 可选翻译引擎 - MTranServer 集成
Feb 3, 2026
ac3f861
feat: US-009 - 可选翻译引擎 - MTranServer 集成
Feb 3, 2026
9281aa6
feat: US-010 - 翻译历史记录
Feb 3, 2026
28d126a
feat: US-010 - 翻译历史记录
Feb 3, 2026
9b2323e
feat: US-011 - 首次启动引导
Feb 3, 2026
e62fc6a
feat: rename project from ScreenCapture to ScreenTranslate
Feb 3, 2026
5b7e2e7
Merge pull request #2 from hubo1989/rename-to-screentranslate
hubo1989 Feb 3, 2026
2597adf
fix"edit the orgid"
Feb 3, 2026
93df057
feat: 屏幕翻译功能优化与增强
Feb 4, 2026
a07e4e2
Merge pull request #3 from hubo1989/proud-cat-239
hubo1989 Feb 4, 2026
62fd866
feat(i18n): add complete internationalization support for English and…
Feb 4, 2026
9863d3d
Merge pull request #4 from hubo1989/i18n
hubo1989 Feb 4, 2026
affcc3a
feat(ocr): integrate PaddleOCR with installation detection and multi-…
Feb 4, 2026
64bad6f
Merge pull request #5 from hubo1989/featadd-paddleocr
hubo1989 Feb 4, 2026
7903080
feat(settings): modernize settings UI with macOS 26 design
Feb 4, 2026
88079b6
Merge pull request #6 from hubo1989/refactotymodern-ui-with-macos-26
hubo1989 Feb 4, 2026
8ddff7f
feat: US-001 - 翻译按钮始终可点击
Feb 4, 2026
04cdda5
feat: US-001 - 翻译按钮始终可点击
Feb 4, 2026
03d9ea7
feat: US-002 - 点击翻译自动触发 OCR
Feb 4, 2026
22bd0fc
feat: US-011 - 修复编辑框尺寸与原框选一致
Feb 4, 2026
5a5a0de
feat: US-011 - 修复编辑框尺寸与原框选一致
Feb 4, 2026
bc99fd8
feat: US-003 - 读取翻译显示位置设置
Feb 4, 2026
7f02a6e
feat: US-003 - 读取翻译显示位置设置
Feb 4, 2026
2ff6949
feat: US-004 - 覆盖原文模式 - 内容感知填充
Feb 4, 2026
c215516
feat: US-005 - 覆盖原文模式 - 译文渲染
Feb 4, 2026
5a5ae70
feat: US-005 - 覆盖原文模式 - 译文渲染
Feb 4, 2026
5bf3676
feat: US-006 - 原文下方模式 - 译文渲染
Feb 4, 2026
7e97672
feat: US-006 - 原文下方模式 - 译文渲染
Feb 4, 2026
9a3ebce
feat: US-007 - Preview 窗口图片渲染
Feb 4, 2026
ca63c63
feat: US-007 - Preview 窗口图片渲染
Feb 4, 2026
59dd6bf
feat: US-008 - 保留底部面板作为备用
Feb 4, 2026
095430f
feat: US-008 - 保留底部面板作为备用
Feb 4, 2026
3edf825
feat: US-009 - 保存带译文的图片
Feb 4, 2026
bd5454b
feat: US-009 - 保存带译文的图片
Feb 4, 2026
e5a6ae3
feat: US-010 - 复制带译文的图片到剪贴板
Feb 5, 2026
04dca95
feat: US-010 - 复制带译文的图片到剪贴板
Feb 5, 2026
bc55891
feat: 翻译功能重构与沉浸式翻译初步实现
Feb 5, 2026
1e5a9b3
Merge pull request #7 from hubo1989/featrefactor-translate
hubo1989 Feb 5, 2026
aaf507e
feat: US-001 - 创建独立翻译入口
Feb 6, 2026
3185cca
feat: US-001 - 创建独立翻译入口
Feb 6, 2026
c0fa776
feat: US-002 - 实现区域框选捕获
Feb 6, 2026
741e16f
feat: US-003 - 定义 TextSegment 和 ScreenAnalysisResult 模型
Feb 6, 2026
08c4bbe
feat: US-004 - 实现 VLM Provider 协议
Feb 6, 2026
6358d12
feat: US-004 - 实现 VLM Provider 协议
Feb 6, 2026
13571ab
feat: US-005 - 实现 OpenAI Vision Provider
Feb 6, 2026
26f09c2
feat: US-005 - 实现 OpenAI Vision Provider
Feb 6, 2026
65e2926
feat: US-006 - 实现 Claude Vision Provider
Feb 6, 2026
52d8ec9
feat: US-006 - 实现 Claude Vision Provider
Feb 6, 2026
c2eef25
feat: US-009 - 扩展 MTransServerProvider 翻译能力
Feb 6, 2026
dc96de9
feat: US-009 - 扩展 MTransServerProvider 翻译能力
Feb 6, 2026
8156319
feat: US-010 - 创建 TranslationService 编排层
Feb 6, 2026
3a0619b
feat: US-010 - 创建 TranslationService 编排层
Feb 6, 2026
296ca28
feat: US-011 - 定义 BilingualSegment 和 OverlayStyle 模型
Feb 6, 2026
b0efc83
feat: US-012 - 实现 OverlayRenderer 双语渲染
Feb 6, 2026
cdaafbc
feat: US-012 - 实现 OverlayRenderer 双语渲染
Feb 6, 2026
b9dff34
feat: US-013 - 创建双语对照展示窗口
Feb 6, 2026
dd0d371
feat: US-013 - 创建双语对照展示窗口
Feb 6, 2026
68a72bb
feat: US-015 - 添加 VLM 和翻译配置 UI
Feb 6, 2026
300a806
feat: US-015 - 添加 VLM 和翻译配置 UI
Feb 6, 2026
098700c
feat: US-007 - 实现 Ollama Vision Provider
Feb 6, 2026
f76a570
feat: US-007 - 实现 Ollama Vision Provider
Feb 6, 2026
2540107
feat: US-008 - 创建 ScreenCoder 引擎
Feb 6, 2026
f41f45f
feat: US-008 - 创建 ScreenCoder 引擎
Feb 6, 2026
7abc78c
feat: US-014 - 实现 TranslationFlowController 主流程
Feb 6, 2026
905c9e7
feat: US-014 - 实现 TranslationFlowController 主流程
Feb 6, 2026
81b494e
feat: US-016 - 集成快捷键到 AppDelegate
Feb 6, 2026
3e5867e
feat: US-016 - 集成快捷键到 AppDelegate
Feb 6, 2026
f80bff9
feat: 完善翻译模式渲染和用户体验
Feb 9, 2026
8fb84eb
fix: 修复 CodeRabbit 指出的问题
Feb 9, 2026
8e4538a
Merge pull request #8 from hubo1989/featscreencoderkiss-translator
hubo1989 Feb 9, 2026
b65186a
feat: US-001 - 创建 WindowDetector 窗口检测服务
Feb 9, 2026
c119f8f
feat: US-001 - 创建 WindowDetector 窗口检测服务
Feb 9, 2026
bacf863
feat: US-002 - SelectionOverlayView 窗口高亮绘制
Feb 9, 2026
595d225
feat: US-002 - SelectionOverlayView 窗口高亮绘制
Feb 9, 2026
76be173
feat: US-003 - 点击与拖拽区分逻辑
Feb 9, 2026
a555a6d
feat: US-003 - 点击与拖拽区分逻辑
Feb 9, 2026
2b7f059
feat: US-004 - 性能优化与边界情况处理
Feb 9, 2026
3947ed0
feat: US-004 - 性能优化与边界情况处理
Feb 9, 2026
d3c75dc
feat: US-005 - 集成测试与验证
Feb 9, 2026
dc7578e
feat: US-005 - 集成测试与验证
Feb 9, 2026
6239dd9
fix: 修复区域截图/翻译模式崩溃问题
Feb 9, 2026
b503472
fix: 排除 CLAUDE.md 文件避免构建冲突
Feb 9, 2026
a161292
fix: 修复窗口识别功能无效的问题
Feb 9, 2026
0715af6
style: 增强窗口高亮蓝色线条的可见性
Feb 9, 2026
1c80665
fix: 增加 Claude VLM max_tokens 限制并优化截断处理
Feb 9, 2026
fdd6104
feat: 实现 Claude VLM 自动续接机制彻底解决截断问题
Feb 9, 2026
1d6c77a
fix: 改进续接机制使用解析合并而非字符串拼接
Feb 9, 2026
4b7aa05
fix: 修复 SwiftUI "Modifying state during view update" 警告
Feb 9, 2026
40535be
fix: 修复翻译结果分辨率不一致问题
Feb 10, 2026
4f611cd
fix: 改进译文可读性 - 添加背景垫和自适应颜色
Feb 10, 2026
0127eda
fix: 修复 CGColor 初始化器参数名错误
Feb 10, 2026
493e8a8
feat: 实现全新的对照布局模式
Feb 10, 2026
2bde90b
style: 菜单栏"翻译模式"改为"截图翻译"
Feb 10, 2026
d6a8074
style: 将窗口高亮边框色值改为 #46E7F0
Feb 10, 2026
bc1e2ae
Merge pull request #9 from hubo1989/featadd-before-taking-a-screensho…
hubo1989 Feb 10, 2026
2cef998
refactor: 清理预览弹窗翻译功能并优化设置界面
Feb 10, 2026
219bd40
Merge pull request #10 from hubo1989/fixui-color-an-so-on
hubo1989 Feb 10, 2026
ddf5cc0
feat: 更新应用图标和 README
Feb 10, 2026
4c37082
refactor: 移除截图历史功能,优化翻译历史界面
Feb 10, 2026
c87941c
Merge pull request #11 from hubo1989/fixremove-screen-history
hubo1989 Feb 10, 2026
e58ad62
fix: 修复 Retina 屏幕截图和翻译结果显示放大问题
Feb 10, 2026
01029d4
fix: 使 displayScaleFactor 可变,跨屏移动时保持缩放同步
Feb 10, 2026
8c72f87
Merge pull request #12 from hubo1989/fix-highresolution
hubo1989 Feb 10, 2026
454e056
chore: 发布 v1.0.1 版本
Feb 11, 2026
f727a3b
fix: 深度修复 Retina 屏幕缩放问题并发布 v1.0.2
Feb 11, 2026
eb4dd08
feat: 优化翻译显示和设置界面
Feb 12, 2026
89cbf1e
fix: address CodeRabbit review feedback
Feb 12, 2026
c5e34d1
fix: remove duplicate padding subtraction in OverlayRenderer
Feb 12, 2026
660677e
Merge pull request #13 from hubo1989/featadd-translate-menu
hubo1989 Feb 12, 2026
02b8601
feat: US-001 - Create TextSelectionService for capturing selected text
Feb 12, 2026
39dc026
feat: US-001 - Create TextSelectionService for capturing selected text
Feb 12, 2026
32fc128
feat: US-002 - Add keyboard shortcut for text selection translation
Feb 12, 2026
5f06775
feat: US-002 - Add keyboard shortcut for text selection translation
Feb 12, 2026
7df1fe2
feat: US-003 - Create TextTranslationFlow for plain text translation
Feb 12, 2026
f145a86
feat: US-003 - Create TextTranslationFlow for plain text translation
Feb 12, 2026
6a320d8
feat: US-004 - Create TextTranslationPopup window for showing transla…
Feb 12, 2026
fba5364
feat: US-004 - Create TextTranslationPopup window for showing transla…
Feb 12, 2026
84cae54
feat: US-005 - Add copy and insert buttons to translation popup
Feb 13, 2026
75be780
feat: US-005 - Add copy and insert buttons to translation popup
Feb 13, 2026
c94f218
feat: US-006 - Wire up text selection translation in AppDelegate
Feb 13, 2026
3d9d7ee
feat: US-006 - Wire up text selection translation in AppDelegate
Feb 13, 2026
d9a859e
feat: US-007 - Add translate-and-insert keyboard shortcut
Feb 13, 2026
6f17ccd
feat: US-007 - Add translate-and-insert keyboard shortcut
Feb 13, 2026
335f1cc
feat: US-008 - Add settings UI for text translation hotkeys
Feb 13, 2026
cf58fec
feat: US-008 - Add settings UI for text translation hotkeys
Feb 13, 2026
b6f2500
feat: US-009 - Handle accessibility and input monitoring permissions
Feb 13, 2026
0c68342
feat: US-009 - Handle accessibility and input monitoring permissions
Feb 13, 2026
5691777
feat: US-010 - Integration testing and edge case handling
Feb 13, 2026
79fef46
feat: US-010 - Integration testing and edge case handling
Feb 13, 2026
0871a57
fix: address CodeRabbit review feedback
Feb 13, 2026
22867c4
Merge pull request #14 from hubo1989/featadd-text-and-input-translate
hubo1989 Feb 14, 2026
6d6791e
fix: sync menu shortcuts with settings and improve translate-and-insert
hubo1989 Feb 25, 2026
8ed464d
Merge pull request #15 from hubo1989/fix/menu-shortcut-sync-and-trans…
hubo1989 Feb 25, 2026
ac008e6
docs: add architecture refactoring design plan
Feb 25, 2026
e65757f
refactor: architecture improvements and code cleanup
Feb 25, 2026
700177b
test: add unit test files for core components
Feb 25, 2026
5978f1f
feat: improve settings UI, translate-and-insert, and menu shortcuts
hubo1989 Feb 25, 2026
4293a3c
merge: PR #16 - settings UI and translate-and-insert improvements
Feb 25, 2026
20a2266
fix: translate-and-insert use correct language settings
Feb 25, 2026
1cc8dd6
fix: address CodeRabbit review feedback
Feb 25, 2026
f91ae80
refactor: address remaining CodeRabbit feedback
Feb 25, 2026
3fcba13
Merge pull request #17 from hubo1989/review
hubo1989 Feb 25, 2026
70ee62c
chore: release v1.1.0 with text translation features
Feb 25, 2026
d2361e6
Merge pull request #18 from hubo1989/review
hubo1989 Feb 25, 2026
d60e194
feat: v1.2.0 - Multi-engine translation, Sparkle auto-update, improve…
Feb 28, 2026
3001aa5
feat: add PaddleOCR as VLM provider with fast/precise modes
Feb 28, 2026
e4cae4c
fix: address code review feedback on PR #49
Feb 28, 2026
aeb3182
fix: address second round code review feedback
Feb 28, 2026
ee868a5
fix: address third round code review feedback
Feb 28, 2026
c5eb8dd
feat: add PaddleOCR as VLM provider with fast/precise modes (#49)
hubo1989 Feb 28, 2026
ef4545e
feat: add MLX-VLM inference framework support for Apple Silicon
Feb 28, 2026
dff6c28
feat: add MLX-VLM server status detection
Feb 28, 2026
5d6d5d0
fix: auto-check MLX-VLM server status on settings load
Feb 28, 2026
61cf6e3
fix: correct localization key names for error messages
Feb 28, 2026
2e1c0d1
feat: add local VL model directory support for PaddleOCR native backend
Feb 28, 2026
7a6f100
refactor: address code review nitpicks for PaddleOCR integration
Feb 28, 2026
19847d8
merge: resolve conflicts with main branch
Feb 28, 2026
dc5ff5c
feat: add local VL model directory support for PaddleOCR native backe…
hubo1989 Feb 28, 2026
a90a94e
fix: correct minimum system version from 26.0 to 14.0
Mar 2, 2026
87928b7
Merge pull request #51 from hubo1989/feat/paddleocr-vlm-provider
hubo1989 Mar 2, 2026
312634d
fix: correct MACOSX_DEPLOYMENT_TARGET from 26.0 to 14.0 in Xcode project
Mar 2, 2026
1ef0664
Merge pull request #52 from hubo1989/feat/paddleocr-vlm-provider
hubo1989 Mar 2, 2026
ffd3725
fix: restore MACOSX_DEPLOYMENT_TARGET to 26.0
Mar 2, 2026
aa6a4e2
Merge pull request #53 from hubo1989/feat/paddleocr-vlm-provider
hubo1989 Mar 2, 2026
063c4c2
chore: bump version to 1.3.1 with build number 2
Mar 2, 2026
b155485
Merge pull request #54 from hubo1989/feat/paddleocr-vlm-provider
hubo1989 Mar 2, 2026
97ebc24
fix: restore MACOSX_DEPLOYMENT_TARGET to 26.0 in release.yml
Mar 2, 2026
a6ee938
Merge pull request #55 from hubo1989/feat/paddleocr-vlm-provider
hubo1989 Mar 2, 2026
3d12b16
fix: use /health endpoint for MLX-VLM server status check
Mar 2, 2026
f26b773
Merge pull request #56 from hubo1989/feat/paddleocr-vlm-provider
hubo1989 Mar 2, 2026
5f2417e
chore: bump version to 1.3.3 with build number 3
Mar 2, 2026
84b8411
Merge pull request #57 from hubo1989/feat/paddleocr-vlm-provider
hubo1989 Mar 2, 2026
9c84915
feat: auto-increment build number in release workflow
Mar 2, 2026
b775fa6
Merge pull request #58 from hubo1989/feat/paddleocr-vlm-provider
hubo1989 Mar 2, 2026
565cf01
docs: add annotation enhancement design document
Mar 2, 2026
398a19f
Merge branch 'main' of github.com:hubo1989/ScreenTranslate
Mar 3, 2026
abd2a36
fix: improve local VLM model compatibility
Mar 4, 2026
d62c046
fix: address PR review comments
Mar 4, 2026
7d70758
docs: add exhaustive switch checklist and hotkey aliases doc
Mar 4, 2026
943c557
docs: address nitpick comments
Mar 4, 2026
af4fcd6
feat: add new annotation types (ellipse, line, mosaic, highlight, num…
Mar 4, 2026
ffbf77b
feat: add pinned window feature for screenshots
Mar 4, 2026
beb6fa7
feat: update preview UI for new annotation tools
Mar 4, 2026
d46b767
feat: add annotation rendering for export and clipboard
Mar 4, 2026
1e2b3cb
feat: update settings for multi-engine configuration
Mar 4, 2026
445f5bc
fix: improve PaddleOCR and translation provider compatibility
Mar 4, 2026
39becae
chore: update localizations for new features
Mar 4, 2026
397fd4b
chore: update Xcode project for new files
Mar 4, 2026
4773faf
Merge pull request #59 from hubo1989/hen
hubo1989 Mar 4, 2026
d0614b1
fix: address PR #60 review comments
Mar 4, 2026
94e59c1
fix: resolve code review issues in PR #60
Mar 4, 2026
fc75807
fix: address all PR review comments
Mar 4, 2026
d55b7ad
fix: address remaining PR review comments
Mar 4, 2026
fda8141
fix: convert highlight color to sRGB before extracting components
Mar 4, 2026
b510bc2
Merge pull request #60 from hubo1989/hen
hubo1989 Mar 4, 2026
44316be
fix: use CGColorSpace(name:) instead of CGColorSpaceCreateSRGB() for …
hubo1989 Mar 4, 2026
0275b73
fix: prevent duplicate text segments in VLM responses and simplify to…
hubo1989 Mar 5, 2026
dd39ff1
Merge branch 'main' of github.com:hubo1989/ScreenTranslate
Mar 5, 2026
19e8cb5
docs: update README for v1.4.1 release
Mar 5, 2026
d01be33
chore: add .omd/ to gitignore (#63)
hubo1989 Mar 5, 2026
8ddccbb
fix:config files
Mar 5, 2026
5369666
feat(i18n): add 8 new language translations (de, es, fr, it, ja, ko, …
hubo1989 Mar 5, 2026
2442544
Fix translation language pipeline regressions
Mar 18, 2026
c86aebf
fix: resolve Google Translate connection test and onboarding screen r…
hubo1989 Mar 18, 2026
d943288
Fix auto-detect language availability handling
Mar 18, 2026
4f38196
Remove trailing commas in regression tests
Mar 18, 2026
2d97371
Merge origin/main into fixlanguage_error
Mar 18, 2026
9281cfa
Remove unreachable catch in connection check
Mar 18, 2026
bd835d2
Fix translation language pipeline regressions (#66)
hubo1989 Mar 18, 2026
633fa07
Fallback to OCR for leaked VLM prompt output
Mar 18, 2026
537c337
feat: add cloud and local modes for GLM OCR
Mar 20, 2026
cace9a0
fix: address review feedback for GLM OCR modes
Mar 20, 2026
2d3676a
Merge origin/main into fixlanguage_error
Mar 20, 2026
a770e49
fix: tighten GLM OCR review follow-ups
Mar 20, 2026
eb2b6b8
fix: clear stale GLM OCR test state
Mar 20, 2026
2da1bf9
Add cloud/local mode switching for GLM OCR (#67)
hubo1989 Mar 20, 2026
1127c68
fix: use RGB probe image for local GLM OCR tests
Mar 20, 2026
e4979fd
fix: support text-only local GLM OCR payloads
Mar 20, 2026
640a03b
Merge origin/main into fixlanguage_error
Mar 20, 2026
8ca9f5f
test: harden translation pipeline regressions
Mar 20, 2026
22b3f82
fix: address translation pipeline review feedback
Mar 20, 2026
7355f8b
fix: address remaining translation review issues
Mar 23, 2026
b1813db
fix: harden prompt routing and compatible prompt ids
Mar 23, 2026
8eec53d
fix: address latest translation review feedback
Mar 23, 2026
c1a81b9
fix: remove redundant permission dialogs and fix language code handling
Mar 24, 2026
90f521a
fix: address CodeRabbit review feedback
Mar 25, 2026
cf984b0
fix: show system settings guidance after permission denial
Mar 25, 2026
d4f9aab
fix: refresh permission status after system prompt to handle grant
Mar 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agent/skills/swiftui-expert-skill
290 changes: 290 additions & 0 deletions .agents/skills/swiftui-expert-skill/SKILL.md

Large diffs are not rendered by default.

351 changes: 351 additions & 0 deletions .agents/skills/swiftui-expert-skill/references/animation-advanced.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,351 @@
# SwiftUI Advanced Animations

Transactions, phase animations (iOS 17+), keyframe animations (iOS 17+), and completion handlers (iOS 17+).

## Table of Contents
- [Transactions](#transactions)
- [Phase Animations (iOS 17+)](#phase-animations-ios-17)
- [Keyframe Animations (iOS 17+)](#keyframe-animations-ios-17)
- [Animation Completion Handlers (iOS 17+)](#animation-completion-handlers-ios-17)

---

## Transactions

The underlying mechanism for all animations in SwiftUI.

### Basic Usage

```swift
// withAnimation is shorthand for withTransaction
withAnimation(.default) { flag.toggle() }

// Equivalent explicit transaction
var transaction = Transaction(animation: .default)
withTransaction(transaction) { flag.toggle() }
```

### The .transaction Modifier

```swift
Rectangle()
.frame(width: flag ? 100 : 50, height: 50)
.transaction { t in
t.animation = .default
}
```

**Note:** This behaves like the deprecated `.animation(_:)` without value parameter - it animates on every state change.

### Animation Precedence

**Implicit animations override explicit animations** (later in view tree wins).

```swift
Button("Tap") {
withAnimation(.linear) { flag.toggle() }
}
.animation(.bouncy, value: flag) // .bouncy wins!
```

### Disabling Animations

```swift
// Prevent implicit animations from overriding
.transaction { t in
t.disablesAnimations = true
}

// Remove animation entirely
.transaction { $0.animation = nil }
```

### Custom Transaction Keys (iOS 17+)

Pass metadata through transactions.

```swift
struct ChangeSourceKey: TransactionKey {
static let defaultValue: String = "unknown"
}

extension Transaction {
var changeSource: String {
get { self[ChangeSourceKey.self] }
set { self[ChangeSourceKey.self] = newValue }
}
}

// Set source
var transaction = Transaction(animation: .default)
transaction.changeSource = "server"
withTransaction(transaction) { flag.toggle() }

// Read in view tree
.transaction { t in
if t.changeSource == "server" {
t.animation = .smooth
} else {
t.animation = .bouncy
}
}
```

---

## Phase Animations (iOS 17+)

Cycle through discrete phases automatically. Each phase change is a separate animation.

### Basic Usage

```swift
// GOOD - triggered phase animation
Button("Shake") { trigger += 1 }
.phaseAnimator(
[0.0, -10.0, 10.0, -5.0, 5.0, 0.0],
trigger: trigger
) { content, offset in
content.offset(x: offset)
}

// Infinite loop (no trigger)
Circle()
.phaseAnimator([1.0, 1.2, 1.0]) { content, scale in
content.scaleEffect(scale)
}
```

### Enum Phases (Recommended for Clarity)

```swift
// GOOD - enum phases are self-documenting
enum BouncePhase: CaseIterable {
case initial, up, down, settle

var scale: CGFloat {
switch self {
case .initial: 1.0
case .up: 1.2
case .down: 0.9
case .settle: 1.0
}
}
}

Circle()
.phaseAnimator(BouncePhase.allCases, trigger: trigger) { content, phase in
content.scaleEffect(phase.scale)
}
```

### Custom Timing Per Phase

```swift
.phaseAnimator([0, -20, 20], trigger: trigger) { content, offset in
content.offset(x: offset)
} animation: { phase in
switch phase {
case -20: .bouncy
case 20: .linear
default: .smooth
}
}
```

### Good vs Bad

```swift
// GOOD - use phaseAnimator for multi-step sequences
.phaseAnimator([0, -10, 10, 0], trigger: trigger) { content, offset in
content.offset(x: offset)
}

// BAD - manual DispatchQueue sequencing
Button("Animate") {
withAnimation(.easeOut(duration: 0.1)) { offset = -10 }
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation { offset = 10 }
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
withAnimation { offset = 0 }
}
}
```

---

## Keyframe Animations (iOS 17+)

Precise timing control with exact values at specific times.

### Basic Usage

```swift
Button("Bounce") { trigger += 1 }
.keyframeAnimator(
initialValue: AnimationValues(),
trigger: trigger
) { content, value in
content
.scaleEffect(value.scale)
.offset(y: value.verticalOffset)
} keyframes: { _ in
KeyframeTrack(\.scale) {
SpringKeyframe(1.2, duration: 0.15)
SpringKeyframe(0.9, duration: 0.1)
SpringKeyframe(1.0, duration: 0.15)
}
KeyframeTrack(\.verticalOffset) {
LinearKeyframe(-20, duration: 0.15)
LinearKeyframe(0, duration: 0.25)
}
}

struct AnimationValues {
var scale: CGFloat = 1.0
var verticalOffset: CGFloat = 0
}
```

### Keyframe Types

| Type | Behavior |
|------|----------|
| `CubicKeyframe` | Smooth interpolation |
| `LinearKeyframe` | Straight-line interpolation |
| `SpringKeyframe` | Spring physics |
| `MoveKeyframe` | Instant jump (no interpolation) |

### Multiple Synchronized Tracks

Tracks run **in parallel**, each animating one property.

```swift
// GOOD - bell shake with synchronized rotation and scale
struct BellAnimation {
var rotation: Double = 0
var scale: CGFloat = 1.0
}

Image(systemName: "bell.fill")
.keyframeAnimator(
initialValue: BellAnimation(),
trigger: trigger
) { content, value in
content
.rotationEffect(.degrees(value.rotation))
.scaleEffect(value.scale)
} keyframes: { _ in
KeyframeTrack(\.rotation) {
CubicKeyframe(15, duration: 0.1)
CubicKeyframe(-15, duration: 0.1)
CubicKeyframe(10, duration: 0.1)
CubicKeyframe(-10, duration: 0.1)
CubicKeyframe(0, duration: 0.1)
}
KeyframeTrack(\.scale) {
CubicKeyframe(1.1, duration: 0.25)
CubicKeyframe(1.0, duration: 0.25)
}
}

// BAD - manual timer-based animation
Image(systemName: "bell.fill")
.onTapGesture {
withAnimation(.easeOut(duration: 0.1)) { rotation = 15 }
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation { rotation = -15 }
}
// ... more manual timing - error prone
}
```

### KeyframeTimeline (iOS 17+)

Query animation values directly for testing or non-SwiftUI use.

```swift
let timeline = KeyframeTimeline(initialValue: AnimationValues()) {
KeyframeTrack(\.scale) {
CubicKeyframe(1.2, duration: 0.25)
CubicKeyframe(1.0, duration: 0.25)
}
}

let midpoint = timeline.value(time: 0.25)
print(midpoint.scale) // Value at 0.25 seconds
```

---

## Animation Completion Handlers (iOS 17+)

Execute code when animations finish.

### With withAnimation

```swift
// GOOD - completion with withAnimation
Button("Animate") {
withAnimation(.spring) {
isExpanded.toggle()
} completion: {
showNextStep = true
}
}
```

### With Transaction (For Reexecution)

```swift
// GOOD - completion fires on every trigger change
Circle()
.scaleEffect(bounceCount % 2 == 0 ? 1.0 : 1.2)
.transaction(value: bounceCount) { transaction in
transaction.animation = .spring
transaction.addAnimationCompletion {
message = "Bounce \(bounceCount) complete"
}
}

// BAD - completion only fires ONCE (no value parameter)
Circle()
.scaleEffect(bounceCount % 2 == 0 ? 1.0 : 1.2)
.animation(.spring, value: bounceCount)
.transaction { transaction in // No value!
transaction.addAnimationCompletion {
completionCount += 1 // Only fires once, ever
}
}
```

---

## Quick Reference

### Transactions (All iOS versions)
- `withTransaction` is the explicit form of `withAnimation`
- Implicit animations override explicit (later in view tree wins)
- Use `disablesAnimations` to prevent override
- Use `.transaction { $0.animation = nil }` to remove animation

### Custom Transaction Keys (iOS 17+)
- Pass metadata through animation system via `TransactionKey`

### Phase Animations (iOS 17+)
- Use for multi-step sequences returning to start
- Prefer enum phases for clarity
- Each phase change is a separate animation
- Use `trigger` parameter for one-shot animations

### Keyframe Animations (iOS 17+)
- Use for precise timing control
- Tracks run in parallel
- Use `KeyframeTimeline` for testing/advanced use
- Prefer over manual DispatchQueue timing

### Completion Handlers (iOS 17+)
- Use `withAnimation(.animation) { } completion: { }` for one-shot completion handlers
- Use `.transaction(value:)` for handlers that should refire on every value change
- Without `value:` parameter, completion only fires once
Loading