@maccesar/titools 2.0.7 → 2.2.1

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 (133) hide show
  1. package/AGENTS-VERCEL-RESEARCH.md +172 -0
  2. package/README.md +408 -389
  3. package/agents/{ti-researcher.md → ti-pro.md} +14 -13
  4. package/bin/titools.js +16 -12
  5. package/lib/cleanup.js +95 -0
  6. package/lib/commands/agents.js +146 -70
  7. package/lib/commands/skills.js +349 -0
  8. package/lib/commands/uninstall.js +189 -154
  9. package/lib/commands/update.js +104 -21
  10. package/lib/config.js +26 -20
  11. package/lib/downloader.js +1 -1
  12. package/lib/installer.js +37 -97
  13. package/lib/platform.js +9 -5
  14. package/lib/prompts/checkboxCancel.js +264 -0
  15. package/lib/prompts/selectCancel.js +204 -0
  16. package/lib/symlink.js +19 -7
  17. package/lib/utils.js +17 -17
  18. package/package.json +10 -10
  19. package/skills/alloy-guides/SKILL.md +8 -30
  20. package/skills/alloy-guides/references/CLI_TASKS.md +14 -24
  21. package/skills/alloy-guides/references/CONCEPTS.md +5 -25
  22. package/skills/alloy-guides/references/CONTROLLERS.md +2 -19
  23. package/skills/alloy-guides/references/MODELS.md +40 -10
  24. package/skills/alloy-guides/references/PURGETSS.md +1 -11
  25. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +8 -14
  26. package/skills/alloy-guides/references/VIEWS_STYLES.md +14 -25
  27. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +2 -8
  28. package/skills/alloy-guides/references/VIEWS_XML.md +29 -40
  29. package/skills/alloy-guides/references/WIDGETS.md +1 -17
  30. package/skills/alloy-howtos/SKILL.md +1 -22
  31. package/skills/alloy-howtos/references/best_practices.md +0 -17
  32. package/skills/alloy-howtos/references/cli_reference.md +1 -23
  33. package/skills/alloy-howtos/references/config_files.md +86 -15
  34. package/skills/alloy-howtos/references/custom_tags.md +14 -13
  35. package/skills/alloy-howtos/references/debugging_troubleshooting.md +3 -22
  36. package/skills/alloy-howtos/references/samples.md +4 -14
  37. package/skills/purgetss/SKILL.md +11 -37
  38. package/skills/purgetss/references/EXAMPLES.md +106 -17
  39. package/skills/purgetss/references/animation-system.md +0 -67
  40. package/skills/purgetss/references/apply-directive.md +0 -18
  41. package/skills/purgetss/references/arbitrary-values.md +0 -25
  42. package/skills/purgetss/references/class-index.md +0 -46
  43. package/skills/purgetss/references/cli-commands.md +0 -41
  44. package/skills/purgetss/references/configurable-properties.md +0 -55
  45. package/skills/purgetss/references/custom-rules.md +0 -14
  46. package/skills/purgetss/references/customization-deep-dive.md +0 -49
  47. package/skills/purgetss/references/dynamic-component-creation.md +56 -37
  48. package/skills/purgetss/references/grid-layout.md +0 -32
  49. package/skills/purgetss/references/icon-fonts.md +0 -50
  50. package/skills/purgetss/references/installation-setup.md +61 -32
  51. package/skills/purgetss/references/migration-guide.md +127 -0
  52. package/skills/purgetss/references/opacity-modifier.md +0 -34
  53. package/skills/purgetss/references/performance-tips.md +261 -0
  54. package/skills/purgetss/references/platform-modifiers.md +0 -46
  55. package/skills/purgetss/references/smart-mappings.md +0 -12
  56. package/skills/purgetss/references/tikit-components.md +393 -0
  57. package/skills/purgetss/references/titanium-resets.md +1 -27
  58. package/skills/purgetss/references/ui-ux-design.md +467 -117
  59. package/skills/{alloy-expert → ti-expert}/SKILL.md +45 -54
  60. package/skills/ti-expert/references/alloy-builtins.md +387 -0
  61. package/skills/{alloy-expert → ti-expert}/references/alloy-structure.md +147 -40
  62. package/skills/ti-expert/references/anti-patterns.md +90 -0
  63. package/skills/ti-expert/references/cli-expert.md +109 -0
  64. package/skills/{alloy-expert → ti-expert}/references/code-conventions.md +182 -49
  65. package/skills/{alloy-expert → ti-expert}/references/controller-patterns.md +103 -93
  66. package/skills/{alloy-expert → ti-expert}/references/error-handling.md +12 -12
  67. package/skills/{alloy-expert → ti-expert}/references/examples.md +144 -85
  68. package/skills/{alloy-expert → ti-expert}/references/migration-patterns.md +38 -36
  69. package/skills/{alloy-expert → ti-expert}/references/patterns.md +8 -8
  70. package/skills/ti-expert/references/performance-listview.md +251 -0
  71. package/skills/{alloy-expert/references/performance-patterns.md → ti-expert/references/performance-optimization.md} +67 -283
  72. package/skills/{alloy-expert/references/security-patterns.md → ti-expert/references/security-device.md} +12 -295
  73. package/skills/ti-expert/references/security-fundamentals.md +284 -0
  74. package/skills/{alloy-expert → ti-expert}/references/state-management.md +10 -10
  75. package/skills/ti-expert/references/testing-e2e-ci.md +432 -0
  76. package/skills/ti-expert/references/testing-unit.md +433 -0
  77. package/skills/ti-expert/references/theming.md +394 -0
  78. package/skills/ti-guides/SKILL.md +1 -14
  79. package/skills/ti-guides/references/advanced-data-and-images.md +126 -10
  80. package/skills/ti-guides/references/app-distribution.md +48 -10
  81. package/skills/ti-guides/references/application-frameworks.md +9 -2
  82. package/skills/ti-guides/references/cli-reference.md +338 -82
  83. package/skills/ti-guides/references/coding-best-practices.md +14 -4
  84. package/skills/ti-guides/references/commonjs-advanced.md +103 -6
  85. package/skills/ti-guides/references/hello-world.md +5 -2
  86. package/skills/ti-guides/references/hyperloop-native-access.md +439 -46
  87. package/skills/ti-guides/references/javascript-primer.md +4 -3
  88. package/skills/ti-guides/references/resources.md +0 -1
  89. package/skills/ti-guides/references/style-and-conventions.md +57 -9
  90. package/skills/ti-guides/references/tiapp-config.md +48 -6
  91. package/skills/ti-howtos/SKILL.md +2 -27
  92. package/skills/ti-howtos/references/android-platform-deep-dives.md +41 -90
  93. package/skills/ti-howtos/references/automation-fastlane-appium.md +15 -14
  94. package/skills/ti-howtos/references/buffer-codec-streams.md +22 -22
  95. package/skills/ti-howtos/references/cross-platform-development.md +68 -37
  96. package/skills/ti-howtos/references/debugging-profiling.md +8 -53
  97. package/skills/ti-howtos/references/extending-titanium.md +12 -51
  98. package/skills/ti-howtos/references/google-maps-v2.md +30 -29
  99. package/skills/ti-howtos/references/ios-map-kit.md +19 -25
  100. package/skills/ti-howtos/references/ios-platform-deep-dives.md +95 -283
  101. package/skills/ti-howtos/references/local-data-sources.md +45 -37
  102. package/skills/ti-howtos/references/location-and-maps.md +47 -28
  103. package/skills/ti-howtos/references/media-apis.md +84 -27
  104. package/skills/ti-howtos/references/notification-services.md +40 -89
  105. package/skills/ti-howtos/references/remote-data-sources.md +21 -36
  106. package/skills/ti-howtos/references/tutorials.md +79 -39
  107. package/skills/ti-howtos/references/using-modules.md +4 -30
  108. package/skills/ti-howtos/references/web-content-integration.md +28 -45
  109. package/skills/ti-howtos/references/webpack-build-pipeline.md +54 -18
  110. package/skills/ti-ui/SKILL.md +1 -21
  111. package/skills/ti-ui/references/accessibility-deep-dive.md +71 -25
  112. package/skills/ti-ui/references/animation-and-matrices.md +0 -47
  113. package/skills/ti-ui/references/application-structures.md +0 -46
  114. package/skills/ti-ui/references/custom-fonts-styling.md +9 -57
  115. package/skills/ti-ui/references/event-handling.md +32 -40
  116. package/skills/ti-ui/references/gestures.md +0 -40
  117. package/skills/ti-ui/references/icons-and-splash-screens.md +21 -44
  118. package/skills/ti-ui/references/layouts-and-positioning.md +47 -39
  119. package/skills/ti-ui/references/listviews-and-performance.md +187 -73
  120. package/skills/ti-ui/references/orientation.md +57 -71
  121. package/skills/ti-ui/references/platform-ui-android.md +114 -48
  122. package/skills/ti-ui/references/platform-ui-ios.md +63 -38
  123. package/skills/ti-ui/references/scrolling-views.md +14 -23
  124. package/skills/ti-ui/references/tableviews.md +6 -56
  125. package/AGENTS-TEMPLATE.md +0 -174
  126. package/lib/commands/install.js +0 -188
  127. package/skills/alloy-expert/references/anti-patterns.md +0 -133
  128. package/skills/alloy-expert/references/testing.md +0 -872
  129. package/skills/ti-guides/references/alloy-cli-advanced.md +0 -84
  130. package/skills/ti-guides/references/alloy-data-mastery.md +0 -29
  131. package/skills/ti-guides/references/alloy-widgets-and-themes.md +0 -19
  132. /package/skills/{alloy-expert → ti-expert}/assets/ControllerAutoCleanup.js +0 -0
  133. /package/skills/{alloy-expert → ti-expert}/references/contracts.md +0 -0
@@ -0,0 +1,251 @@
1
+ # ListView & ScrollView Performance
2
+
3
+ ## Critical Rules
4
+
5
+ 1. **NEVER use `Ti.UI.SIZE` in ListView items** - Causes layout recalculation on every scroll
6
+ 2. **ALWAYS use fixed heights** - Pre-calculated heights enable fast scrolling
7
+ 3. **USE templates** - Reuse view instances instead of creating new ones
8
+
9
+ ## Optimized ListView Template
10
+
11
+ ```xml
12
+ <!-- views/user/list.xml -->
13
+ <Alloy>
14
+ <ListView id="listView">
15
+ <Templates>
16
+ <!-- FIXED HEIGHT is critical for performance -->
17
+ <ItemTemplate name="userTemplate" height="64">
18
+ <View id="rowContainer">
19
+ <ImageView bindId="avatar" id="avatarImg" />
20
+ <View id="userInfo">
21
+ <Label bindId="name" id="nameLabel" />
22
+ <Label bindId="email" id="emailLabel" />
23
+ </View>
24
+ </View>
25
+ </ItemTemplate>
26
+ </Templates>
27
+
28
+ <ListSection id="section" dataCollection="users">
29
+ <ListItem template="userTemplate" avatar:image="{avatar}" name:text="{name}" email:text="{email}" />
30
+ </ListSection>
31
+ </ListView>
32
+ </Alloy>
33
+ ```
34
+
35
+ ```tss
36
+ /* styles/user/list.tss */
37
+ "#listView": { width: Ti.UI.FILL, height: Ti.UI.FILL }
38
+ "#rowContainer": { layout: 'horizontal', height: 64, width: Ti.UI.FILL }
39
+ "#avatarImg": { left: 16, width: 48, height: 48, borderRadius: 24 }
40
+ "#userInfo": { layout: 'vertical', left: 12 }
41
+ "#nameLabel": { font: { fontSize: 16, fontWeight: 'bold' } }
42
+ "#emailLabel": { font: { fontSize: 14 }, color: '#6b7280' }
43
+ ```
44
+
45
+ **Titanium Layout Rules:**
46
+ - Use `layout: 'horizontal'`/`layout: 'vertical'` for directional layouts
47
+ - Use margins on children for spacing (NOT padding on parent)
48
+ - Use `width: Ti.UI.FILL, height: Ti.UI.FILL` for full width + height
49
+
50
+ ## Efficient Data Binding
51
+
52
+ ```javascript
53
+ // controllers/feed/list.js
54
+ function renderItems(items) {
55
+ // Pre-format data to avoid calculation in render
56
+ const listItems = items.map(item => ({
57
+ template: 'feedTemplate',
58
+ properties: {
59
+ itemId: item.id,
60
+ searchableText: `${item.title} ${item.description}`
61
+ },
62
+ title: { text: item.title },
63
+ description: { text: item.description },
64
+ timestamp: { text: formatTimestamp(item.created_at) }
65
+ }))
66
+
67
+ // Single update
68
+ $.section.items = listItems
69
+ }
70
+
71
+ // Timestamp formatter (cache results)
72
+ const timestampCache = new Map()
73
+
74
+ function formatTimestamp(timestamp) {
75
+ if (timestampCache.has(timestamp)) {
76
+ return timestampCache.get(timestamp)
77
+ }
78
+
79
+ const formatted = new Date(timestamp).toLocaleString()
80
+ timestampCache.set(timestamp, formatted)
81
+
82
+ return formatted
83
+ }
84
+ ```
85
+
86
+ ## Image Loading & Caching
87
+
88
+ ```javascript
89
+ // lib/services/imageCache.js
90
+ exports.ImageCache = {
91
+ _cache: new Map(),
92
+ _loading: new Map(),
93
+
94
+ // Get image at appropriate size for list item
95
+ getListThumbnail(url) {
96
+ const cacheKey = `thumb_${url}`
97
+
98
+ // Return cached if available
99
+ if (this._cache.has(cacheKey)) {
100
+ return this._cache.get(cacheKey)
101
+ }
102
+
103
+ // Check if already loading
104
+ if (this._loading.has(cacheKey)) {
105
+ return this._loading.get(cacheKey)
106
+ }
107
+
108
+ // Load and resize
109
+ const promise = this._loadAndResize(url, { width: 80, height: 80 })
110
+ .then(resized => {
111
+ this._cache.set(cacheKey, resized)
112
+ this._loading.delete(cacheKey)
113
+ return resized
114
+ })
115
+
116
+ this._loading.set(cacheKey, promise)
117
+
118
+ return promise
119
+ },
120
+
121
+ async _loadAndResize(url, size) {
122
+ return new Promise((resolve, reject) => {
123
+ const imageView = Ti.UI.createImageView({
124
+ image: url,
125
+ width: size.width,
126
+ height: size.height,
127
+ preventsDefaultAnimation: true
128
+ })
129
+
130
+ imageView.addEventListener('load', () => {
131
+ const blob = imageView.toImage()
132
+ const resized = blob.imageAsResized(size.width, size.height)
133
+ imageView.image = null
134
+ resolve(resized)
135
+ })
136
+
137
+ imageView.addEventListener('error', (e) => {
138
+ reject(e)
139
+ })
140
+ })
141
+ },
142
+
143
+ clear() {
144
+ this._cache.clear()
145
+ this._loading.clear()
146
+ }
147
+ }
148
+ ```
149
+
150
+ ## ScrollView Performance
151
+
152
+ ### Optimizing Large ScrollViews
153
+
154
+ ```xml
155
+ <!-- Avoid: Creating many views at once -->
156
+ <ScrollView id="scrollView" layout="vertical">
157
+ <!-- DON'T: 100+ views created immediately -->
158
+ </ScrollView>
159
+
160
+ <!-- Better: Use ListView for list-like content -->
161
+ <ListView id="listView">
162
+ <!-- Views created on-demand as user scrolls -->
163
+ </ListView>
164
+ ```
165
+
166
+ ### When You Must Use ScrollView
167
+
168
+ ```javascript
169
+ // Lazy load content sections
170
+ const sections = [
171
+ { id: 'header', height: 200 },
172
+ { id: 'featured', height: 300 },
173
+ { id: 'products', height: 400 },
174
+ { id: 'reviews', height: 500 }
175
+ ]
176
+
177
+ let loadedSections = new Set()
178
+
179
+ function init() {
180
+ // Load only visible sections initially
181
+ loadSection('header')
182
+
183
+ $.scrollView.addEventListener('scroll', onScroll)
184
+ }
185
+
186
+ function onScroll(e) {
187
+ const scrollY = e.y
188
+ const viewportHeight = $.scrollView.rect.height
189
+
190
+ sections.forEach(section => {
191
+ if (loadedSections.has(section.id)) return
192
+
193
+ // Check if section is about to be visible
194
+ const sectionTop = getSectionTop(section.id)
195
+
196
+ if (sectionTop < scrollY + viewportHeight + 100) {
197
+ loadSection(section.id)
198
+ }
199
+ })
200
+ }
201
+
202
+ function loadSection(sectionId) {
203
+ if (loadedSections.has(sectionId)) return
204
+
205
+ loadedSections.add(sectionId)
206
+
207
+ // Load content for this section
208
+ const container = $[sectionId + 'Container']
209
+ const content = createSectionContent(sectionId)
210
+ container.add(content)
211
+ }
212
+ ```
213
+
214
+ ## ScrollView Memory Management
215
+
216
+ ```javascript
217
+ // Release images when scrolled far away
218
+ function onScroll(e) {
219
+ const scrollY = e.y
220
+ const viewportHeight = $.scrollView.rect.height
221
+
222
+ // Release images more than 2 screens away
223
+ const releaseThreshold = viewportHeight * 2
224
+
225
+ imageViews.forEach((img, index) => {
226
+ const imgTop = img.rect.y
227
+ const distance = Math.abs(imgTop - scrollY)
228
+
229
+ if (distance > releaseThreshold && img.image) {
230
+ // Store URL for later reload
231
+ img._originalUrl = img.image
232
+ img.image = null
233
+ } else if (distance < viewportHeight && img._originalUrl) {
234
+ // Reload when close to viewport
235
+ img.image = img._originalUrl
236
+ delete img._originalUrl
237
+ }
238
+ })
239
+ }
240
+ ```
241
+
242
+ ## Performance Checklist (UI)
243
+
244
+ | Area | Check |
245
+ | ------------ | ---------------------------------- |
246
+ | **ListView** | Fixed heights on all templates |
247
+ | **ListView** | Using templates, not dynamic views |
248
+ | **ListView** | Image pre-sizing and caching |
249
+ | **Scroll** | Lazy loading content sections |
250
+ | **Scroll** | Release off-screen images |
251
+ | **Images** | Resized appropriately for display |
@@ -1,151 +1,10 @@
1
- # Performance Optimization Guide
2
-
3
- ## Critical Rules
4
-
5
- 1. **NEVER use `Ti.UI.SIZE` in ListView items** - Causes layout recalculation on every scroll
6
- 2. **ALWAYS use fixed heights** - Pre-calculated heights enable fast scrolling
7
- 3. **USE templates** - Reuse view instances instead of creating new ones
8
- 4. **CACHE Ti.Platform properties** - Avoid repeated bridge crossings
9
- 5. **USE applyProperties()** - Batch UI updates in a single call
10
-
11
- ## ListView Performance
12
-
13
- ### Optimized ListView Template
14
-
15
- ```xml
16
- <!-- views/user/list.xml -->
17
- <Alloy>
18
- <ListView class="wh-screen">
19
- <Templates>
20
- <!-- FIXED HEIGHT is critical for performance -->
21
- <ItemTemplate name="userTemplate" height="64">
22
- <View class="horizontal h-16 w-screen">
23
- <ImageView bindId="avatar" class="rounded-full-12 ml-4" />
24
- <View class="vertical ml-3">
25
- <Label bindId="name" class="text-base font-bold" />
26
- <Label bindId="email" class="text-sm text-gray-500" />
27
- </View>
28
- </View>
29
- </ItemTemplate>
30
- </Templates>
31
-
32
- <ListSection id="section" dataCollection="users">
33
- <ListItem template="userTemplate" avatar:image="{avatar}" name:text="{name}" email:text="{email}" />
34
- </ListSection>
35
- </ListView>
36
- </Alloy>
37
- ```
38
-
39
- **PurgeTSS Layout Rules:**
40
- - Use `horizontal`/`vertical` for layout (NOT flexbox)
41
- - Use `m-*` on children for spacing (NOT `p-*` on parent)
42
- - Use `wh-screen` for full width + height
43
-
44
- ### Efficient Data Binding
45
-
46
- ```javascript
47
- // controllers/feed/list.js
48
- function renderItems(items) {
49
- // Pre-format data to avoid calculation in render
50
- const listItems = items.map(item => ({
51
- template: 'feedTemplate',
52
- properties: {
53
- itemId: item.id,
54
- searchableText: `${item.title} ${item.description}`
55
- },
56
- title: { text: item.title },
57
- description: { text: item.description },
58
- timestamp: { text: formatTimestamp(item.created_at) }
59
- }))
60
-
61
- // Single update
62
- $.section.items = listItems
63
- }
64
-
65
- // Timestamp formatter (cache results)
66
- const timestampCache = new Map()
67
-
68
- function formatTimestamp(timestamp) {
69
- if (timestampCache.has(timestamp)) {
70
- return timestampCache.get(timestamp)
71
- }
72
-
73
- const formatted = new Date(timestamp).toLocaleString()
74
- timestampCache.set(timestamp, formatted)
75
-
76
- return formatted
77
- }
78
- ```
79
-
80
- ### Image Loading & Caching
81
-
82
- ```javascript
83
- // lib/services/imageCache.js
84
- exports.ImageCache = {
85
- _cache: new Map(),
86
- _loading: new Map(),
87
-
88
- // Get image at appropriate size for list item
89
- getListThumbnail(url) {
90
- const cacheKey = `thumb_${url}`
91
-
92
- // Return cached if available
93
- if (this._cache.has(cacheKey)) {
94
- return this._cache.get(cacheKey)
95
- }
96
-
97
- // Check if already loading
98
- if (this._loading.has(cacheKey)) {
99
- return this._loading.get(cacheKey)
100
- }
101
-
102
- // Load and resize
103
- const promise = this._loadAndResize(url, { width: 80, height: 80 })
104
- .then(resized => {
105
- this._cache.set(cacheKey, resized)
106
- this._loading.delete(cacheKey)
107
- return resized
108
- })
109
-
110
- this._loading.set(cacheKey, promise)
111
-
112
- return promise
113
- },
114
-
115
- async _loadAndResize(url, size) {
116
- return new Promise((resolve, reject) => {
117
- const imageView = Ti.UI.createImageView({
118
- image: url,
119
- width: size.width,
120
- height: size.height,
121
- preventsDefaultAnimation: true
122
- })
123
-
124
- imageView.addEventListener('load', () => {
125
- const blob = imageView.toImage()
126
- const resized = blob.imageAsResized(size.width, size.height)
127
- imageView.image = null
128
- resolve(resized)
129
- })
130
-
131
- imageView.addEventListener('error', (e) => {
132
- reject(e)
133
- })
134
- })
135
- },
136
-
137
- clear() {
138
- this._cache.clear()
139
- this._loading.clear()
140
- }
141
- }
142
- ```
1
+ # Performance Optimization: Bridge, Memory, Animation & Timing
143
2
 
144
3
  ## Bridge Optimization
145
4
 
146
5
  ### Minimize Bridge Crossings
147
6
 
148
- Every JavaScript Native call crosses a bridge. Minimize these:
7
+ Every JavaScript -> Native call crosses a bridge. Minimize these:
149
8
 
150
9
  ```javascript
151
10
  // BAD: Multiple bridge crossings
@@ -176,14 +35,19 @@ $.nameLabel.applyProperties({
176
35
  })
177
36
  ```
178
37
 
179
- ### Use PurgeTSS Classes
38
+ ### Use TSS Files Instead of Inline Attributes
180
39
 
181
40
  ```xml
182
- <!-- BAD: Inline styling = more bridge crossings -->
41
+ <!-- BAD: Inline styling = scattered and hard to maintain -->
183
42
  <Label text="Hello" width="200" height="40" color="#000" font="{fontSize:16}" />
184
43
 
185
- <!-- GOOD: Single class application -->
186
- <Label text="Hello" class="h-10 w-1/2 text-base text-black" />
44
+ <!-- GOOD: Style defined in TSS file -->
45
+ <Label id="helloLabel" text="Hello" />
46
+ ```
47
+
48
+ ```tss
49
+ /* In the corresponding .tss file */
50
+ "#helloLabel": { width: 200, height: 40, color: '#000', font: { fontSize: 16 } }
187
51
  ```
188
52
 
189
53
  ## Memory Management
@@ -242,7 +106,7 @@ function cleanup() {
242
106
  $.cleanup = cleanup
243
107
  ```
244
108
 
245
- ### Image Memory Management
109
+ ## Image Memory Management
246
110
 
247
111
  ```javascript
248
112
  // lib/services/imageManager.js
@@ -479,115 +343,6 @@ renderUsers(users)
479
343
  measure.end()
480
344
  ```
481
345
 
482
- ## Performance Checklist
483
-
484
- | Area | Check |
485
- | ------------ | ----------------------------------------- |
486
- | **ListView** | Fixed heights on all templates |
487
- | **ListView** | Using templates, not dynamic views |
488
- | **ListView** | Image pre-sizing and caching |
489
- | **Bridge** | Cached Ti.Platform properties |
490
- | **Bridge** | Using applyProperties for updates |
491
- | **Bridge** | PurgeTSS classes instead of inline styles |
492
- | **Memory** | All global listeners cleaned up |
493
- | **Memory** | Heavy objects nulled in cleanup |
494
- | **Memory** | Images resized appropriately |
495
- | **Database** | Using transactions for batch ops |
496
- | **Database** | Indexes on frequently queried columns |
497
- | **Database** | ResultSets and DB handles closed |
498
-
499
- ## ScrollView Performance
500
-
501
- ### Optimizing Large ScrollViews
502
-
503
- ```xml
504
- <!-- Avoid: Creating many views at once -->
505
- <ScrollView class="wh-screen vertical">
506
- <!-- DON'T: 100+ views created immediately -->
507
- </ScrollView>
508
-
509
- <!-- Better: Use ListView for list-like content -->
510
- <ListView class="wh-screen">
511
- <!-- Views created on-demand as user scrolls -->
512
- </ListView>
513
- ```
514
-
515
- ### When You Must Use ScrollView
516
-
517
- ```javascript
518
- // Lazy load content sections
519
- const sections = [
520
- { id: 'header', height: 200 },
521
- { id: 'featured', height: 300 },
522
- { id: 'products', height: 400 },
523
- { id: 'reviews', height: 500 }
524
- ]
525
-
526
- let loadedSections = new Set()
527
-
528
- function init() {
529
- // Load only visible sections initially
530
- loadSection('header')
531
-
532
- $.scrollView.addEventListener('scroll', onScroll)
533
- }
534
-
535
- function onScroll(e) {
536
- const scrollY = e.y
537
- const viewportHeight = $.scrollView.rect.height
538
-
539
- sections.forEach(section => {
540
- if (loadedSections.has(section.id)) return
541
-
542
- // Check if section is about to be visible
543
- const sectionTop = getSectionTop(section.id)
544
-
545
- if (sectionTop < scrollY + viewportHeight + 100) {
546
- loadSection(section.id)
547
- }
548
- })
549
- }
550
-
551
- function loadSection(sectionId) {
552
- if (loadedSections.has(sectionId)) return
553
-
554
- loadedSections.add(sectionId)
555
-
556
- // Load content for this section
557
- const container = $[sectionId + 'Container']
558
- const content = createSectionContent(sectionId)
559
- container.add(content)
560
- }
561
- ```
562
-
563
- ### ScrollView Memory Management
564
-
565
- ```javascript
566
- // Release images when scrolled far away
567
- function onScroll(e) {
568
- const scrollY = e.y
569
- const viewportHeight = $.scrollView.rect.height
570
-
571
- // Release images more than 2 screens away
572
- const releaseThreshold = viewportHeight * 2
573
-
574
- imageViews.forEach((img, index) => {
575
- const imgTop = img.rect.y
576
- const distance = Math.abs(imgTop - scrollY)
577
-
578
- if (distance > releaseThreshold && img.image) {
579
- // Store URL for later reload
580
- img._originalUrl = img.image
581
- img.image = null
582
- } else if (distance < viewportHeight && img._originalUrl) {
583
- // Reload when close to viewport
584
- img.image = img._originalUrl
585
- delete img._originalUrl
586
- }
587
- })
588
- }
589
- ```
590
-
591
346
  ## Animation Performance
592
347
 
593
348
  ### 60fps Animation Rules
@@ -610,37 +365,48 @@ const animation = Ti.UI.createAnimation({
610
365
  $.view.animate(animation)
611
366
  ```
612
367
 
613
- ### PurgeTSS Animation Component (Recommended)
614
-
615
- ```xml
616
- <!-- Define animations with state modifiers -->
617
- <Animation id="fadeIn" module="purgetss.ui" class="close:opacity-0 duration-300 open:opacity-100" />
618
- <Animation id="fadeOut" module="purgetss.ui" class="close:opacity-100 duration-300 open:opacity-0" />
619
- <Animation id="slideInRight" module="purgetss.ui" class="close:translate-x-full duration-300 open:translate-x-0" />
620
- <Animation id="scalePress" module="purgetss.ui" class="close:scale-100 duration-150 open:scale-95" />
621
- ```
368
+ ### Ti.UI.createAnimation (Recommended)
622
369
 
623
370
  ```javascript
624
- // Fade in/out
625
- $.fadeIn.open($.card)
626
- $.fadeOut.close($.card)
371
+ // Fade in
372
+ function fadeIn(view, callback) {
373
+ const animation = Ti.UI.createAnimation({
374
+ opacity: 1,
375
+ duration: 300,
376
+ curve: Ti.UI.ANIMATION_CURVE_EASE_OUT
377
+ })
378
+ if (callback) animation.addEventListener('complete', callback)
379
+ view.animate(animation)
380
+ }
627
381
 
628
- // Slide animations
629
- $.slideInRight.open($.panel)
630
- $.slideInRight.close($.panel)
382
+ // Fade out
383
+ function fadeOut(view, callback) {
384
+ const animation = Ti.UI.createAnimation({
385
+ opacity: 0,
386
+ duration: 300,
387
+ curve: Ti.UI.ANIMATION_CURVE_EASE_OUT
388
+ })
389
+ if (callback) animation.addEventListener('complete', callback)
390
+ view.animate(animation)
391
+ }
631
392
 
632
- // Scale animations (press effect)
633
- $.scalePress.open($.button) // Scale down
634
- $.scalePress.close($.button) // Scale back up
393
+ // Slide in from right
394
+ function slideInRight(view) {
395
+ view.transform = Ti.UI.createMatrix2D().translate(Ti.Platform.displayCaps.platformWidth, 0)
396
+ view.animate(Ti.UI.createAnimation({
397
+ transform: Ti.UI.createMatrix2D(),
398
+ duration: 300,
399
+ curve: Ti.UI.ANIMATION_CURVE_EASE_OUT
400
+ }))
401
+ }
635
402
 
636
403
  // Chained animations with callback
637
- $.fadeIn.open($.modal, () => {
638
- // Animation complete, trigger next animation
639
- $.slideInRight.open($.content)
404
+ fadeIn($.modal, () => {
405
+ slideInRight($.content)
640
406
  })
641
407
  ```
642
408
 
643
- ### Hardware-Accelerated Properties
409
+ ## Hardware-Accelerated Properties
644
410
 
645
411
  ```javascript
646
412
  // These properties are GPU-accelerated (fast):
@@ -672,7 +438,7 @@ const badAnimation = Ti.UI.createAnimation({
672
438
  })
673
439
  ```
674
440
 
675
- ### Animation Cleanup
441
+ ## Animation Cleanup
676
442
 
677
443
  ```javascript
678
444
  // Always remove animation listeners
@@ -734,7 +500,7 @@ exports.debounce = function debounce(fn, delay = 300) {
734
500
 
735
501
  ```javascript
736
502
  // Usage: Search input
737
- const { debounce } = require('lib/helpers/timing')
503
+ const { debounce } = require('helpers/timing')
738
504
 
739
505
  const debouncedSearch = debounce(async (query) => {
740
506
  const results = await searchService.search(query)
@@ -788,7 +554,7 @@ exports.throttle = function throttle(fn, limit = 100) {
788
554
 
789
555
  ```javascript
790
556
  // Usage: Scroll handler
791
- const { throttle } = require('lib/helpers/timing')
557
+ const { throttle } = require('helpers/timing')
792
558
 
793
559
  const throttledScroll = throttle((scrollY) => {
794
560
  updateHeaderOpacity(scrollY)
@@ -821,7 +587,7 @@ function cleanup() {
821
587
 
822
588
  ```javascript
823
589
  // Show immediate feedback while typing, but only search when done
824
- const { debounce, throttle } = require('lib/helpers/timing')
590
+ const { debounce, throttle } = require('helpers/timing')
825
591
 
826
592
  // Update UI immediately (throttled)
827
593
  const updateSuggestions = throttle((query) => {
@@ -853,3 +619,21 @@ function cleanup() {
853
619
  $.destroy()
854
620
  }
855
621
  ```
622
+
623
+ ## Performance Checklist
624
+
625
+ | Area | Check |
626
+ | ------------- | --------------------------------------- |
627
+ | **Bridge** | Cached Ti.Platform properties |
628
+ | **Bridge** | Using applyProperties for updates |
629
+ | **Bridge** | TSS styles instead of inline attributes |
630
+ | **Memory** | All global listeners cleaned up |
631
+ | **Memory** | Heavy objects nulled in cleanup |
632
+ | **Memory** | Images resized appropriately |
633
+ | **Database** | Using transactions for batch ops |
634
+ | **Database** | Indexes on frequently queried columns |
635
+ | **Database** | ResultSets and DB handles closed |
636
+ | **Animation** | Using native animations, not intervals |
637
+ | **Animation** | GPU-accelerated properties preferred |
638
+ | **Timing** | Debounce on search/input |
639
+ | **Timing** | Throttle on scroll/touch events |