@fudiandong/trellis-android-tv 1.0.0 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/agents/TvTouchAgent/agent.yaml +17 -0
  2. package/agents/TvTouchAgent/prompt.md +13 -0
  3. package/package.json +25 -10
  4. package/skills/code_review_tv/SKILL.md +7 -0
  5. package/skills/layout_adapt/SKILL.md +9 -0
  6. package/skills/touch_compat/SKILL.md +10 -0
  7. package/skills/trellis-before-dev/SKILL.md +34 -0
  8. package/skills/trellis-brainstorm/SKILL.md +548 -0
  9. package/skills/trellis-break-loop/SKILL.md +130 -0
  10. package/skills/trellis-check/SKILL.md +92 -0
  11. package/skills/trellis-meta/SKILL.md +73 -0
  12. package/skills/trellis-meta/references/customize-local/add-project-local-conventions.md +83 -0
  13. package/skills/trellis-meta/references/customize-local/change-agents.md +54 -0
  14. package/skills/trellis-meta/references/customize-local/change-context-loading.md +81 -0
  15. package/skills/trellis-meta/references/customize-local/change-hooks.md +57 -0
  16. package/skills/trellis-meta/references/customize-local/change-skills-or-commands.md +78 -0
  17. package/skills/trellis-meta/references/customize-local/change-spec-structure.md +83 -0
  18. package/skills/trellis-meta/references/customize-local/change-task-lifecycle.md +90 -0
  19. package/skills/trellis-meta/references/customize-local/change-workflow.md +64 -0
  20. package/skills/trellis-meta/references/customize-local/overview.md +55 -0
  21. package/skills/trellis-meta/references/local-architecture/context-injection.md +68 -0
  22. package/skills/trellis-meta/references/local-architecture/generated-files.md +80 -0
  23. package/skills/trellis-meta/references/local-architecture/overview.md +51 -0
  24. package/skills/trellis-meta/references/local-architecture/spec-system.md +102 -0
  25. package/skills/trellis-meta/references/local-architecture/task-system.md +101 -0
  26. package/skills/trellis-meta/references/local-architecture/workflow.md +75 -0
  27. package/skills/trellis-meta/references/local-architecture/workspace-memory.md +71 -0
  28. package/skills/trellis-meta/references/platform-files/agents.md +79 -0
  29. package/skills/trellis-meta/references/platform-files/hooks-and-settings.md +69 -0
  30. package/skills/trellis-meta/references/platform-files/overview.md +59 -0
  31. package/skills/trellis-meta/references/platform-files/platform-map.md +74 -0
  32. package/skills/trellis-meta/references/platform-files/skills-and-commands.md +83 -0
  33. package/skills/trellis-spec-bootstarp/SKILL.md +41 -0
  34. package/skills/trellis-spec-bootstarp/references/mcp-setup.md +90 -0
  35. package/skills/trellis-spec-bootstarp/references/repository-analysis.md +59 -0
  36. package/skills/trellis-spec-bootstarp/references/spec-task-planning.md +61 -0
  37. package/skills/trellis-spec-bootstarp/references/spec-writing.md +70 -0
  38. package/skills/trellis-update-spec/SKILL.md +356 -0
  39. package/skills/tv_focus_check/SKILL.md +10 -0
  40. package/spec/android_tv_base.md +17 -0
  41. package/spec/dpad_focus_rule.md +89 -0
  42. package/spec/guides/code-reuse-thinking-guide.md +105 -0
  43. package/spec/guides/cross-layer-thinking-guide.md +162 -0
  44. package/spec/guides/index.md +79 -0
  45. package/spec/mvvm_rule.md +100 -0
  46. package/spec/res_resource.md +111 -0
  47. package/spec/tv_touch_layout.md +31 -0
  48. package/workflow.md +10 -0
@@ -0,0 +1,89 @@
1
+ # D-pad 焦点导航规范
2
+
3
+ ## 核心原则
4
+
5
+ 所有 TV UI 必须实现**闭环焦点导航**,确保用户按任意方向键时焦点始终在可控范围内。
6
+
7
+ ## 焦点配置
8
+
9
+ ### 1. 基础配置
10
+ ```xml
11
+ <!-- 焦点控件必须设置 -->
12
+ android:focusable="true"
13
+ android:focusableInTouchMode="true"
14
+ ```
15
+
16
+ ### 2. 首次焦点
17
+ ```xml
18
+ <!-- 页面默认焦点:根布局设置 -->
19
+ android:defaultFocusHighlightEnabled="true"
20
+ ```
21
+
22
+ ## 方向导航
23
+
24
+ ### 3. nextFocusDown/Up/Left/Right
25
+ ```xml
26
+ <!-- 明确指定各方向的下一个焦点控件 -->
27
+ android:nextFocusDown="@+id/btn_confirm"
28
+ android:nextFocusUp="@+id/btn_cancel"
29
+ android:nextFocusLeft="@+id/btn_prev"
30
+ android:nextFocusRight="@+id/btn_next"
31
+ ```
32
+
33
+ ### 4. 禁止焦点越界
34
+ ```xml
35
+ <!-- 边缘控件必须指定环绕方向 -->
36
+ <Button
37
+ android:id="@+id/btn_first"
38
+ android:nextFocusLeft="@+id/btn_last" /> <!-- 左边界环绕到最后一个 -->
39
+ ```
40
+
41
+ ## 焦点丢失处理
42
+
43
+ ### 5. ViewGroup 焦点容器
44
+ ```xml
45
+ <!-- 动态区域使用 FocusableRelativeLayout 包裹 -->
46
+ <FocusableRelativeLayout
47
+ android:focusable="true"
48
+ android:focusableInTouchMode="true">
49
+ <!-- 子控件 -->
50
+ </FocusableRelativeLayout>
51
+ ```
52
+
53
+ ### 6. 焦点状态监听
54
+ ```java
55
+ // 监听焦点变化,处理边界情况
56
+ view.setOnFocusChangeListener((v, hasFocus) -> {
57
+ if (hasFocus) {
58
+ // 焦点进入:放大/高亮效果
59
+ }
60
+ });
61
+ ```
62
+
63
+ ## 常见错误
64
+
65
+ ### ❌ 禁止
66
+ - 动态添加 View 后未设置 nextFocus 属性
67
+ - Recyclerview item 内嵌套可聚焦控件未指定导航
68
+ - 使用.requestFocus() 而不处理焦点状态
69
+
70
+ ### ✅ 正确
71
+ - 静态布局完整配置 nextFocus 四方向
72
+ - 动态区域使用 FocusChangeListener 手动处理
73
+ - 边缘控件使用 `nextFocusUp/Down/Left/Right` 形成闭环
74
+
75
+ ## 触摸兼容
76
+
77
+ ### 7. 触摸点击
78
+ ```java
79
+ // 触摸模式下支持点击
80
+ if (isInTouchMode()) {
81
+ performClick();
82
+ }
83
+ ```
84
+
85
+ ### 8. 触摸模式焦点
86
+ ```xml
87
+ <!-- 触屏设备需要 -->
88
+ android:focusableInTouchMode="true"
89
+ ```
@@ -0,0 +1,105 @@
1
+ # Code Reuse Thinking Guide
2
+
3
+ > **Purpose**: Stop and think before creating new code - does it already exist?
4
+
5
+ ---
6
+
7
+ ## The Problem
8
+
9
+ **Duplicated code is the #1 source of inconsistency bugs.**
10
+
11
+ When you copy-paste or rewrite existing logic:
12
+ - Bug fixes don't propagate
13
+ - Behavior diverges over time
14
+ - Codebase becomes harder to understand
15
+
16
+ ---
17
+
18
+ ## Before Writing New Code
19
+
20
+ ### Step 1: Search First
21
+
22
+ ```bash
23
+ # Search for similar function names
24
+ grep -r "functionName" .
25
+
26
+ # Search for similar logic
27
+ grep -r "keyword" .
28
+ ```
29
+
30
+ ### Step 2: Ask These Questions
31
+
32
+ | Question | If Yes... |
33
+ |----------|-----------|
34
+ | Does a similar function exist? | Use or extend it |
35
+ | Is this pattern used elsewhere? | Follow the existing pattern |
36
+ | Could this be a shared utility? | Create it in the right place |
37
+ | Am I copying code from another file? | **STOP** - extract to shared |
38
+
39
+ ---
40
+
41
+ ## Common Duplication Patterns
42
+
43
+ ### Pattern 1: Copy-Paste Functions
44
+
45
+ **Bad**: Copying a validation function to another file
46
+
47
+ **Good**: Extract to shared utilities, import where needed
48
+
49
+ ### Pattern 2: Similar Components
50
+
51
+ **Bad**: Creating a new component that's 80% similar to existing
52
+
53
+ **Good**: Extend existing component with props/variants
54
+
55
+ ### Pattern 3: Repeated Constants
56
+
57
+ **Bad**: Defining the same constant in multiple files
58
+
59
+ **Good**: Single source of truth, import everywhere
60
+
61
+ ---
62
+
63
+ ## When to Abstract
64
+
65
+ **Abstract when**:
66
+ - Same code appears 3+ times
67
+ - Logic is complex enough to have bugs
68
+ - Multiple people might need this
69
+
70
+ **Don't abstract when**:
71
+ - Only used once
72
+ - Trivial one-liner
73
+ - Abstraction would be more complex than duplication
74
+
75
+ ---
76
+
77
+ ## After Batch Modifications
78
+
79
+ When you've made similar changes to multiple files:
80
+
81
+ 1. **Review**: Did you catch all instances?
82
+ 2. **Search**: Run grep to find any missed
83
+ 3. **Consider**: Should this be abstracted?
84
+
85
+ ---
86
+
87
+ ## Gotcha: Asymmetric Mechanisms Producing Same Output
88
+
89
+ **Problem**: When two different mechanisms must produce the same file set (e.g., recursive directory copy for init vs. manual `files.set()` for update), structural changes (renaming, moving, adding subdirectories) only propagate through the automatic mechanism. The manual one silently drifts.
90
+
91
+ **Symptom**: Init works perfectly, but update creates files at wrong paths or misses files entirely.
92
+
93
+ **Prevention checklist**:
94
+ - [ ] When migrating directory structures, search for ALL code paths that reference the old structure
95
+ - [ ] If one path is auto-derived (glob/copy) and another is manually listed, the manual one needs updating
96
+ - [ ] Add a regression test that compares outputs from both mechanisms
97
+
98
+ ---
99
+
100
+ ## Checklist Before Commit
101
+
102
+ - [ ] Searched for existing similar code
103
+ - [ ] No copy-pasted logic that should be shared
104
+ - [ ] Constants defined in one place
105
+ - [ ] Similar patterns follow same structure
@@ -0,0 +1,162 @@
1
+ # Cross-Layer Thinking Guide
2
+
3
+ > **Purpose**: Think through data flow across layers before implementing.
4
+
5
+ ---
6
+
7
+ ## The Problem
8
+
9
+ **Most bugs happen at layer boundaries**, not within layers.
10
+
11
+ Common cross-layer bugs:
12
+ - API returns format A, frontend expects format B
13
+ - Database stores X, service transforms to Y, but loses data
14
+ - Multiple layers implement the same logic differently
15
+
16
+ ---
17
+
18
+ ## Before Implementing Cross-Layer Features
19
+
20
+ ### Step 1: Map the Data Flow
21
+
22
+ Draw out how data moves:
23
+
24
+ ```
25
+ Source → Transform → Store → Retrieve → Transform → Display
26
+ ```
27
+
28
+ For each arrow, ask:
29
+ - What format is the data in?
30
+ - What could go wrong?
31
+ - Who is responsible for validation?
32
+
33
+ ### Step 2: Identify Boundaries
34
+
35
+ | Boundary | Common Issues |
36
+ |----------|---------------|
37
+ | API ↔ Service | Type mismatches, missing fields |
38
+ | Service ↔ Database | Format conversions, null handling |
39
+ | Backend ↔ Frontend | Serialization, date formats |
40
+ | Component ↔ Component | Props shape changes |
41
+
42
+ ### Step 3: Define Contracts
43
+
44
+ For each boundary:
45
+ - What is the exact input format?
46
+ - What is the exact output format?
47
+ - What errors can occur?
48
+
49
+ ---
50
+
51
+ ## Common Cross-Layer Mistakes
52
+
53
+ ### Mistake 1: Implicit Format Assumptions
54
+
55
+ **Bad**: Assuming date format without checking
56
+
57
+ **Good**: Explicit format conversion at boundaries
58
+
59
+ ### Mistake 2: Scattered Validation
60
+
61
+ **Bad**: Validating the same thing in multiple layers
62
+
63
+ **Good**: Validate once at the entry point
64
+
65
+ ### Mistake 3: Leaky Abstractions
66
+
67
+ **Bad**: Component knows about database schema
68
+
69
+ **Good**: Each layer only knows its neighbors
70
+
71
+ ---
72
+
73
+ ## Checklist for Cross-Layer Features
74
+
75
+ Before implementation:
76
+ - [ ] Mapped the complete data flow
77
+ - [ ] Identified all layer boundaries
78
+ - [ ] Defined format at each boundary
79
+ - [ ] Decided where validation happens
80
+
81
+ After implementation:
82
+ - [ ] Tested with edge cases (null, empty, invalid)
83
+ - [ ] Verified error handling at each boundary
84
+ - [ ] Checked data survives round-trip
85
+
86
+ ---
87
+
88
+ ## Cross-Platform Template Consistency
89
+
90
+ In Trellis, command templates (e.g., `record-session.md`) exist in **multiple platforms** with identical or near-identical content. This is a cross-layer boundary.
91
+
92
+ ### Checklist: After Modifying Any Command Template
93
+
94
+ - [ ] Find all platforms with the same command: `find src/templates/*/commands/trellis/ -name "<command>.*"`
95
+ - [ ] Update all platform copies (Markdown `.md` and TOML `.toml`)
96
+ - [ ] For Gemini TOML: adapt line continuations (`\\` vs `\`) and triple-quoted strings
97
+ - [ ] Run `/trellis:check-cross-layer` to verify nothing was missed
98
+
99
+ **Real-world example**: Updated `record-session.md` in Claude to use `--mode record`, but forgot iFlow, Kilo, OpenCode, and Gemini — caught by cross-layer check.
100
+
101
+ ---
102
+
103
+ ## Generated Runtime Template Upgrade Consistency
104
+
105
+ Some generated files are both documentation and runtime input. In Trellis,
106
+ `.trellis/workflow.md` is parsed by `get_context.py`, `workflow_phase.py`,
107
+ SessionStart filters, and per-turn hooks. Template changes must be validated
108
+ against both fresh init and upgrade paths.
109
+
110
+ ### Checklist: After Modifying A Runtime-Parsed Template
111
+
112
+ - [ ] Identify every runtime parser that reads the template, not just the file
113
+ writer that installs it
114
+ - [ ] Check whether relevant syntax lives outside obvious managed regions
115
+ such as tag blocks
116
+ - [ ] Verify fresh `init` output and a versioned `update` scenario that writes
117
+ the older `.trellis/.version`
118
+ - [ ] Add an upgrade regression using an older pristine template fixture, then
119
+ assert the installed file reaches the current packaged shape
120
+ - [ ] Update the backend spec that owns the runtime contract
121
+
122
+ **Real-world example**: Codex inline mode changed workflow platform markers from
123
+ `[Codex]` / `[Kilo, Antigravity, Windsurf]` to `[codex-sub-agent]` /
124
+ `[codex-inline, Kilo, Antigravity, Windsurf]`. Fresh init was correct, but
125
+ `trellis update` only merged `[workflow-state:*]` blocks and preserved stale
126
+ markers outside those blocks. Result: upgraded projects got new hook scripts
127
+ but old workflow routing, so `get_context.py --mode phase --platform codex`
128
+ could return empty Phase 2.1 detail.
129
+
130
+ ---
131
+
132
+ ## Mode-Detection Probe Checklist
133
+
134
+ When a CLI auto-detects a mode by probing a remote resource (e.g., checking if `index.json` exists to decide marketplace vs direct download):
135
+
136
+ ### Before implementing:
137
+ - [ ] Probe runs in **ALL** code paths that use the result (interactive, `-y`, `--flag` combos)
138
+ - [ ] 404 vs transient error are distinguished — don't treat both as "not found"
139
+ - [ ] Transient errors **abort or retry**, never silently switch modes
140
+ - [ ] Shared state (caches, prefetched data) is **reset** when context changes (e.g., user switches source)
141
+ - [ ] **Shortcut paths** (e.g., `--template` skipping picker) must have the same error-handling quality as the probed path — check that downstream functions don't call catch-all wrappers
142
+
143
+ ### After implementing:
144
+ - [ ] Trace every path from probe result to the mode-decision branch — no fallthrough
145
+ - [ ] External format contracts (giget URI, raw URLs) are tested or at least documented as comments
146
+ - [ ] Metadata reads consume a complete response or use a streaming parser — never parse a fixed-size prefix as full JSON
147
+ - [ ] When reconstructing a composite identifier from parsed parts, verify **all** fields are included and in the **correct position** (e.g., `provider:repo/path#ref` not `provider:repo#ref/path`)
148
+ - [ ] Verify that **action functions** called after a shortcut don't internally use the old catch-all fetch — they must use the probe-quality variant when error distinction matters
149
+
150
+ **Real-world example**: Custom registry flow had 8 bugs across 3 review rounds: (1) probe only ran in interactive mode, (2) transient errors fell through to wrong mode, (3) giget URI had `#ref` in wrong position, (4) prefetched templates leaked across source switches, (5) `--template` shortcut bypassed probe but `downloadTemplateById` internally used catch-all `fetchTemplateIndex`, turning timeouts into "Template not found".
151
+
152
+ **Real-world example**: Agent-session update hints fetched npm `latest` metadata with `response.read(4096)` and then parsed it as complete JSON. The `@mindfoldhq/trellis` package metadata exceeded 4 KB, so the JSON was truncated, parse failed silently, and the first session injection showed no update hint. Fix: read the complete response before parsing, and add a regression where `version` is followed by an 8 KB metadata tail.
153
+
154
+ ---
155
+
156
+ ## When to Create Flow Documentation
157
+
158
+ Create detailed flow docs when:
159
+ - Feature spans 3+ layers
160
+ - Multiple teams are involved
161
+ - Data format is complex
162
+ - Feature has caused bugs before
@@ -0,0 +1,79 @@
1
+ # Thinking Guides
2
+
3
+ > **Purpose**: Expand your thinking to catch things you might not have considered.
4
+
5
+ ---
6
+
7
+ ## Why Thinking Guides?
8
+
9
+ **Most bugs and tech debt come from "didn't think of that"**, not from lack of skill:
10
+
11
+ - Didn't think about what happens at layer boundaries → cross-layer bugs
12
+ - Didn't think about code patterns repeating → duplicated code everywhere
13
+ - Didn't think about edge cases → runtime errors
14
+ - Didn't think about future maintainers → unreadable code
15
+
16
+ These guides help you **ask the right questions before coding**.
17
+
18
+ ---
19
+
20
+ ## Available Guides
21
+
22
+ | Guide | Purpose | When to Use |
23
+ |-------|---------|-------------|
24
+ | [Code Reuse Thinking Guide](./code-reuse-thinking-guide.md) | Identify patterns and reduce duplication | When you notice repeated patterns |
25
+ | [Cross-Layer Thinking Guide](./cross-layer-thinking-guide.md) | Think through data flow across layers | Features spanning multiple layers |
26
+
27
+ ---
28
+
29
+ ## Quick Reference: Thinking Triggers
30
+
31
+ ### When to Think About Cross-Layer Issues
32
+
33
+ - [ ] Feature touches 3+ layers (API, Service, Component, Database)
34
+ - [ ] Data format changes between layers
35
+ - [ ] Multiple consumers need the same data
36
+ - [ ] You're not sure where to put some logic
37
+
38
+ → Read [Cross-Layer Thinking Guide](./cross-layer-thinking-guide.md)
39
+
40
+ ### When to Think About Code Reuse
41
+
42
+ - [ ] You're writing similar code to something that exists
43
+ - [ ] You see the same pattern repeated 3+ times
44
+ - [ ] You're adding a new field to multiple places
45
+ - [ ] **You're modifying any constant or config**
46
+ - [ ] **You're creating a new utility/helper function** ← Search first!
47
+
48
+ → Read [Code Reuse Thinking Guide](./code-reuse-thinking-guide.md)
49
+
50
+ ---
51
+
52
+ ## Pre-Modification Rule (CRITICAL)
53
+
54
+ > **Before changing ANY value, ALWAYS search first!**
55
+
56
+ ```bash
57
+ # Search for the value you're about to change
58
+ grep -r "value_to_change" .
59
+ ```
60
+
61
+ This single habit prevents most "forgot to update X" bugs.
62
+
63
+ ---
64
+
65
+ ## How to Use This Directory
66
+
67
+ 1. **Before coding**: Skim the relevant thinking guide
68
+ 2. **During coding**: If something feels repetitive or complex, check the guides
69
+ 3. **After bugs**: Add new insights to the relevant guide (learn from mistakes)
70
+
71
+ ---
72
+
73
+ ## Contributing
74
+
75
+ Found a new "didn't think of that" moment? Add it to the relevant guide.
76
+
77
+ ---
78
+
79
+ **Core Principle**: 30 minutes of thinking saves 3 hours of debugging.
@@ -0,0 +1,100 @@
1
+ # MVVM 架构规范
2
+
3
+ ## 项目架构
4
+
5
+ 基于 Google Android Architecture Components,采用 **MVVM + ViewBinding** 模式。
6
+
7
+ ## 目录结构
8
+
9
+ ```
10
+ com.stb.duer.apps.xtvott
11
+ ├── ui/ # Activity/Fragment/Adapter
12
+ │ ├── main/
13
+ │ ├── player/
14
+ │ └── common/
15
+ ├── vm/ # ViewModel
16
+ ├── model/ # 数据模型
17
+ │ ├── entity/ # 数据库实体
18
+ │ └── data/ # 数据类
19
+ ├── repository/ # 数据仓库
20
+ ├── data/ # 数据层
21
+ │ ├── local/ # 本地存储
22
+ │ └── remote/ # 远程接口
23
+ └── util/ # 工具类
24
+ ```
25
+
26
+ ## ViewModel 规范
27
+
28
+ ### 1. ViewModel 创建
29
+ ```java
30
+ // 使用 ViewModelProvider
31
+ ViewModelProvider provider = new ViewModelProvider(this);
32
+ MyViewModel vm = provider.get(MyViewModel.class);
33
+ ```
34
+
35
+ ### 2. LiveData 使用
36
+ ```java
37
+ // 暴露 LiveData
38
+ private final MutableLiveData<String> statusLiveData = new MutableLiveData<>();
39
+ public LiveData<String> getStatus() {
40
+ return statusLiveData;
41
+ }
42
+ ```
43
+
44
+ ### 3. 生命周期感知
45
+ ```java
46
+ // 使用 observe 绑定到 lifecycleOwner
47
+ viewModel.getData().observe(this, data -> {
48
+ // 自动在 onDestroy 时解绑
49
+ });
50
+ ```
51
+
52
+ ## 数据绑定
53
+
54
+ ### 4. ViewBinding 使用
55
+ ```java
56
+ // Activity 中
57
+ private ActivityMainBinding binding;
58
+
59
+ @Override
60
+ protected void onCreate(Bundle savedInstanceState) {
61
+ super.onCreate(savedInstanceState);
62
+ binding = ActivityMainBinding.inflate(getLayoutInflater());
63
+ setContentView(binding.getRoot());
64
+ }
65
+ ```
66
+
67
+ ### 5. 双向绑定(少量使用)
68
+ ```xml
69
+ <!-- 仅用于简单表单 -->
70
+ android:text="@={viewModel.inputText}"
71
+ ```
72
+
73
+ ## Repository 模式
74
+
75
+ ### 6. 数据仓库封装
76
+ ```java
77
+ public class UserRepository {
78
+ private final UserApi api;
79
+ private final UserDao dao;
80
+
81
+ public LiveData<User> getUser(int id) {
82
+ // 优先使用本地缓存,支持离线
83
+ return dao.getUser(id);
84
+ }
85
+ }
86
+ ```
87
+
88
+ ## 常见错误
89
+
90
+ ### ❌ 禁止
91
+ - 在 ViewModel 中直接操作 View
92
+ - 使用 LiveData 而不 observe
93
+ - ViewModel 中使用 Context(使用 Application Context)
94
+ - 在主线程进行网络/数据库操作
95
+
96
+ ### ✅ 正确
97
+ - ViewModel 通过 LiveData 通知 View
98
+ - 使用 Executor/AsyncTask 处理异步
99
+ - 使用 Application Context 或 LiveDataScope
100
+ - 数据操作在 Repository 层统一处理
@@ -0,0 +1,111 @@
1
+ # 资源文件规范
2
+
3
+ ## AutoSize 框架适配
4
+
5
+ 项目使用 **Android AutoSize** 框架实现屏幕适配,无需编写多套 dimens 文件。
6
+
7
+ ### 1. 启用 AutoSize
8
+ ```xml
9
+ <!-- AndroidManifest.xml -->
10
+ <manifest>
11
+ <application>
12
+ <meta-data
13
+ android:name="design_width_in_dp"
14
+ android:value="1920" />
15
+ <meta-data
16
+ android:name="design_height_in_dp"
17
+ android:value="1080" />
18
+ </application>
19
+ </manifest>
20
+ ```
21
+
22
+ ### 2. 单位使用
23
+ ```xml
24
+ <!-- 优先使用 dp/sp,禁止使用 px -->
25
+ <dimen name="text_size_title">48sp</dimen>
26
+ <dimen name="margin_standard">24dp</dimen>
27
+
28
+ <!-- 禁止 -->
29
+ <!-- <dimen name="wrong_size">100px</dimen> -->
30
+ ```
31
+
32
+ ### 3. 布局约束
33
+ ```xml
34
+ <!-- 优先使用约束布局 + wrap_content/match_constraint -->
35
+ <TextView
36
+ android:layout_width="0dp"
37
+ app:layout_constraintWidth_default="wrap"
38
+ android:textSize="@dimen/text_size_title" />
39
+ ```
40
+
41
+ ## 布局文件
42
+
43
+ ### 4. 命名规范
44
+ ```
45
+ activity_xxx_tv.xml # TV Activity 布局
46
+ fragment_xxx_tv.xml # TV Fragment 布局
47
+ item_xxx.xml # 列表项布局
48
+ layout_xxx.xml # 可复用布局
49
+ ```
50
+
51
+ ### 5. TV/触屏共用
52
+ ```xml
53
+ <!-- 同一布局文件,AutoSize 自动适配 -->
54
+ <!-- 不需要 values-sw720dp 等额外适配 -->
55
+ ```
56
+
57
+ ## 字体适配
58
+
59
+ ### 6. sp 单位字体
60
+ ```xml
61
+ <!-- 所有字体使用 sp 单位,AutoSize 自动缩放 -->
62
+ <TextView
63
+ android:textSize="@dimen/text_size_body"
64
+ android:textColor="@color/text_primary" />
65
+ ```
66
+
67
+ ## 颜色资源
68
+
69
+ ### 7. 颜色定义
70
+ ```xml
71
+ <!-- res/values/colors.xml -->
72
+ <color name="primary">#FF6200EE</color>
73
+ <color name="text_primary">#FFFFFFFF</color>
74
+ <color name="text_secondary">#B3FFFFFF</color>
75
+ ```
76
+
77
+ ## 字符串资源
78
+
79
+ ### 8. 字符串规范
80
+ ```xml
81
+ <!-- 禁止硬编码字符串 -->
82
+ <!-- 错误:android:text="确定" -->
83
+ <!-- 正确 -->
84
+ android:text="@string/btn_confirm"
85
+ ```
86
+
87
+ ## Selector 选择器
88
+
89
+ ### 9. 焦点/按压状态
90
+ ```xml
91
+ <!-- 必须同时定义遥控器焦点和触屏按压状态 -->
92
+ <selector xmlns:android="http://schemas.android.com/apk/res/android">
93
+ <item android:state_focused="true" android:drawable="@drawable/bg_focused"/>
94
+ <item android:state_pressed="true" android:drawable="@drawable/bg_pressed"/>
95
+ <item android:drawable="@drawable/bg_normal"/>
96
+ </selector>
97
+ ```
98
+
99
+ ## 常见错误
100
+
101
+ ### ❌ 禁止
102
+ - 使用 px 单位
103
+ - 硬编码尺寸数值
104
+ - 硬编码字符串
105
+ - 布局中缺少 focusable 属性
106
+
107
+ ### ✅ 正确
108
+ - 使用 dp/sp 单位
109
+ - 统一管理颜色/字符串资源
110
+ - TV 控件设置 focusable="true"
111
+ - 使用 ConstraintLayout 减少嵌套
@@ -0,0 +1,31 @@
1
+ # TV+触屏双端布局规范
2
+
3
+ ## 1. 布局结构
4
+ 根布局优先ConstraintLayout,杜绝多层LinearLayout嵌套(TV渲染卡顿)
5
+
6
+ ## 2. 焦点配置
7
+ 焦点控件默认设置focusable=true,触屏环境focusableInTouchMode=true
8
+
9
+ ## 3. 控件尺寸
10
+ TV端控件偏大(最小高48dp起),触屏复用同套layout,使用 AutoSize 框架自动适配各尺寸屏幕
11
+ - 基准设计稿:1920x1080dp
12
+ - 单位:dp/sp(禁止px)
13
+
14
+ ## 4. 点击状态
15
+ selector必须同时配置state_focused(遥控器选中)、state_pressed(触屏按压)
16
+
17
+ ## 5. 布局约束
18
+ 禁止写死宽高match_parent+固定dp混用,优先wrap_content+layout_constraint约束
19
+
20
+ ## 6. 列表控件
21
+ RecyclerView统一封装TvRecyclerView,内置焦点跳转+触屏滑动兼容
22
+
23
+ ## 7. AutoSize 配置
24
+ ```xml
25
+ <meta-data
26
+ android:name="design_width_in_dp"
27
+ android:value="1920" />
28
+ <meta-data
29
+ android:name="design_height_in_dp"
30
+ android:value="1080" />
31
+ ```
package/workflow.md ADDED
@@ -0,0 +1,10 @@
1
+ # Android TV+触屏 标准化开发工作流
2
+ 1. 需求录入:解析页面功能,生成标准目录结构(Activity + Fragment + ViewModel + 布局文件)
3
+ 2. 布局编写:基于 ConstraintLayout 实现布局,默认开启焦点、触屏双适配属性
4
+ 3. 业务代码:采用 Java + AndroidX + MVVM 架构,强制继承项目基础基类,启用 ViewBinding
5
+ 4. 自动化校验:依次执行内置技能
6
+ - tv_focus_check:校验并修复 Dpad 焦点问题
7
+ - touch_compat:补全触屏兼容逻辑与交互效果
8
+ - layout_adapt:抽离硬编码尺寸,完成多分辨率适配
9
+ 5. 代码评审:code_review_tv 全量检查编码规范、架构、适配规则
10
+ 6. 最终输出:可直接编译运行的完整代码