@maccesar/titools 2.0.7 → 2.2.0

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 (132) hide show
  1. package/{AGENTS-TEMPLATE.md → AGENTS-VERCEL-RESEARCH.md} +16 -18
  2. package/README.md +250 -168
  3. package/agents/{ti-researcher.md → ti-pro.md} +10 -10
  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/lib/commands/install.js +0 -188
  126. package/skills/alloy-expert/references/anti-patterns.md +0 -133
  127. package/skills/alloy-expert/references/testing.md +0 -872
  128. package/skills/ti-guides/references/alloy-cli-advanced.md +0 -84
  129. package/skills/ti-guides/references/alloy-data-mastery.md +0 -29
  130. package/skills/ti-guides/references/alloy-widgets-and-themes.md +0 -19
  131. /package/skills/{alloy-expert → ti-expert}/assets/ControllerAutoCleanup.js +0 -0
  132. /package/skills/{alloy-expert → ti-expert}/references/contracts.md +0 -0
@@ -1,44 +1,17 @@
1
1
  # Orientation
2
2
 
3
- ## Table of Contents
4
-
5
- - [Orientation](#orientation)
6
- - [Table of Contents](#table-of-contents)
7
- - [1. Overview](#1-overview)
8
- - [2. Orientation Modes](#2-orientation-modes)
9
- - [Supported Orientations](#supported-orientations)
10
- - [3. Locking Orientation](#3-locking-orientation)
11
- - [Lock to Specific Orientation](#lock-to-specific-orientation)
12
- - [Android Orientation Values](#android-orientation-values)
13
- - [Runtime Orientation Lock (iOS)](#runtime-orientation-lock-ios)
14
- - [4. Handling Orientation Changes](#4-handling-orientation-changes)
15
- - [Detect Orientation Change](#detect-orientation-change)
16
- - [Window Orientation Events](#window-orientation-events)
17
- - [5. Adapting UI to Orientation](#5-adapting-ui-to-orientation)
18
- - [Responsive Layout Example](#responsive-layout-example)
19
- - [Orientation-Specific Components](#orientation-specific-components)
20
- - [6. Platform Differences](#6-platform-differences)
21
- - [iOS Orientation](#ios-orientation)
22
- - [Android Orientation](#android-orientation)
23
- - [7. Checking Current Orientation](#7-checking-current-orientation)
24
- - [8. Disabling Orientation Change](#8-disabling-orientation-change)
25
- - [Disable All Rotation](#disable-all-rotation)
26
- - [Disable Rotation for Specific Window (iOS)](#disable-rotation-for-specific-window-ios)
27
- - [9. Orientation Lock During Specific Operation](#9-orientation-lock-during-specific-operation)
28
- - [Temporarily Lock Orientation](#temporarily-lock-orientation)
29
- - [10. Best Practices](#10-best-practices)
30
- - [11. Common Issues](#11-common-issues)
31
- - [Orientation Not Changing](#orientation-not-changing)
32
- - [UI Doesn't Adapt](#ui-doesnt-adapt)
33
- - [Upside-Down Orientation](#upside-down-orientation)
34
-
35
- ---
36
-
37
3
  ## 1. Overview
38
4
 
39
5
  Orientation refers to whether the app displays in portrait or landscape mode, and how to handle orientation changes.
40
6
 
41
- ## 2. Orientation Modes
7
+ ## 2. Design Principles
8
+
9
+ - **Don't mix orientations on iPhone/iPod** — Pick either portrait or landscape for your entire app; switching between them mid-flow creates a jarring user experience.
10
+ - **Don't support portrait-upside-down on iPhone** — If a user receives a phone call while the device is upside-down, the call UI appears upside-down, which is disorienting and risky.
11
+ - **iPad should support all orientations** — Apple's HIG expects iPad apps to work in every orientation. Users frequently rotate their iPads.
12
+ - **These principles apply equally to Android** — While Android is more permissive, the same UX considerations hold. Consistency within your app matters.
13
+
14
+ ## 3. Orientation Modes
42
15
 
43
16
  ### Supported Orientations
44
17
 
@@ -52,7 +25,7 @@ Orientation refers to whether the app displays in portrait or landscape mode, an
52
25
  | `Ti.UI.FACE_DOWN` | Device face down (flat on table) |
53
26
  | `Ti.UI.AUTO` | Let system decide |
54
27
 
55
- ## 3. Locking Orientation
28
+ ## 4. Locking Orientation
56
29
 
57
30
  ### Lock to Specific Orientation
58
31
 
@@ -70,7 +43,14 @@ Orientation refers to whether the app displays in portrait or landscape mode, an
70
43
  </dict>
71
44
  </plist>
72
45
  </ios>
46
+ ```
73
47
 
48
+ **iOS plist iPhone vs iPad keys**: You can specify different supported orientations for iPhone and iPad using device-specific keys:
49
+ - `UISupportedInterfaceOrientations~iphone` — iPhone-specific orientations (default: portrait only)
50
+ - `UISupportedInterfaceOrientations~ipad` — iPad-specific orientations (default: all four orientations)
51
+ - `UISupportedInterfaceOrientations` (without suffix) — applies to both if device-specific keys are absent
52
+
53
+ ```xml
74
54
  <android>
75
55
  <manifest>
76
56
  <activity>
@@ -104,6 +84,8 @@ Orientation refers to whether the app displays in portrait or landscape mode, an
104
84
  - `nosensor` - Ignores accelerometer (orientation changes only)
105
85
  - `user` - User's preference
106
86
 
87
+ > **Warning — Android set-vs-get value mismatch**: On Android, the orientation values you SET don't match those you GET. You can set 4 values (portrait upright, landscape right, portrait upside-down, landscape left) but only get 2 values back (portrait or landscape). Also, "portrait" and "landscape" meaning varies between phones and tablets based on sensor orientation — on most phones portrait is the default, but on some tablets landscape is the default sensor position.
88
+
107
89
  ### Runtime Orientation Lock (iOS)
108
90
 
109
91
  ```javascript
@@ -114,7 +96,7 @@ Ti.UI.iPhone.setStatusBarStyle(Ti.UI.iPhone.StatusBar.DEFAULT);
114
96
  // Use tiapp.xml configuration for consistent behavior
115
97
  ```
116
98
 
117
- ## 4. Handling Orientation Changes
99
+ ## 5. Handling Orientation Changes
118
100
 
119
101
  ### Detect Orientation Change
120
102
 
@@ -128,8 +110,14 @@ Ti.Gesture.addEventListener('orientationchange', (e) => {
128
110
  e.orientation === Ti.UI.LANDSCAPE_RIGHT) {
129
111
  adjustForLandscape();
130
112
  }
113
+
114
+ // Ti.Gesture helper methods — convenience booleans
115
+ Ti.API.info(`Is portrait: ${e.source.isPortrait()}`);
116
+ Ti.API.info(`Is landscape: ${e.source.isLandscape()}`);
131
117
  });
132
118
  ```
119
+
120
+ > **Anti-pattern warning**: Do NOT use `orientationchange` event listeners to force an orientation. This causes: (1) the wrong orientation showing briefly before the forced one kicks in, (2) potential memory leaks from repeated listener firing, and (3) improper technique. Use `tiapp.xml` or window `orientationModes` instead.
133
121
  ...
134
122
  ### Window Orientation Events
135
123
 
@@ -145,7 +133,7 @@ win.addEventListener('orientationchange', (e) => {
145
133
  });
146
134
  ```
147
135
 
148
- ## 5. Adapting UI to Orientation
136
+ ## 6. Adapting UI to Orientation
149
137
 
150
138
  ### Responsive Layout Example
151
139
 
@@ -211,7 +199,7 @@ function switchLayout() {
211
199
  Ti.Gesture.addEventListener('orientationchange', switchLayout);
212
200
  ```
213
201
 
214
- ## 6. Platform Differences
202
+ ## 7. Platform Differences
215
203
 
216
204
  ### iOS Orientation
217
205
 
@@ -227,7 +215,7 @@ Ti.Gesture.addEventListener('orientationchange', switchLayout);
227
215
  - More granular control (sensor, user, nosensor)
228
216
  - May ignore upside-down depending on device
229
217
 
230
- ## 7. Checking Current Orientation
218
+ ## 8. Checking Current Orientation
231
219
 
232
220
  ```javascript
233
221
  // Get current orientation
@@ -244,7 +232,7 @@ const isLandscape = (currentOrientation === Ti.UI.LANDSCAPE_LEFT ||
244
232
  currentOrientation === Ti.UI.LANDSCAPE_RIGHT);
245
233
  ```
246
234
 
247
- ## 8. Disabling Orientation Change
235
+ ## 9. Disabling Orientation Change
248
236
 
249
237
  ### Disable All Rotation
250
238
 
@@ -253,7 +241,7 @@ const isLandscape = (currentOrientation === Ti.UI.LANDSCAPE_LEFT ||
253
241
  <ios>
254
242
  <plist>
255
243
  <dict>
256
- <key>UISupportedInterfaceOorientations</key>
244
+ <key>UISupportedInterfaceOrientations</key>
257
245
  <array>
258
246
  <string>UIInterfaceOrientationPortrait</string>
259
247
  </array>
@@ -281,45 +269,43 @@ const win = Ti.UI.createWindow({
281
269
 
282
270
  **Note**: Window-level orientation control is limited; app-level configuration is preferred.
283
271
 
284
- ## 9. Orientation Lock During Specific Operation
272
+ ## 10. Orientation Lock Limitations
285
273
 
286
- ### Temporarily Lock Orientation
274
+ **Important:** Runtime orientation locking is NOT reliably supported across platforms.
287
275
 
288
- ```javascript
289
- let originalOrientation = null;
290
-
291
- function lockOrientation() {
292
- // Save current orientation
293
- originalOrientation = Ti.Gesture.orientation;
276
+ - **iOS**: Orientation is controlled exclusively via `tiapp.xml` plist keys and window-level `orientationModes`. There is no API to lock/unlock orientation at runtime.
277
+ - **Android**: Use `android:screenOrientation` in `tiapp.xml` manifest. Changing orientation programmatically at runtime is not supported through Titanium APIs.
294
278
 
295
- // Force portrait
296
- if (Ti.Platform.osname === 'iphone' || Ti.Platform.osname === 'ipad') {
297
- // iOS doesn't support runtime orientation lock
298
- // This is controlled at app level
299
- Ti.API.warn('iOS orientation must be locked in tiapp.xml');
300
- }
301
- }
279
+ If you need a specific orientation for a particular screen (e.g., landscape for video playback), create a dedicated window with the desired `orientationModes` set at creation time:
302
280
 
303
- function unlockOrientation() {
304
- // Would restore orientation
305
- // Not fully supported on all platforms
306
- }
281
+ ```javascript
282
+ // Landscape-only video window
283
+ const videoWin = Ti.UI.createWindow({
284
+ orientationModes: [Ti.UI.LANDSCAPE_LEFT, Ti.UI.LANDSCAPE_RIGHT]
285
+ });
307
286
 
308
- // Use case: During video playback
309
287
  const videoPlayer = Ti.Media.createVideoPlayer({
310
288
  url: 'video.mp4'
311
289
  });
312
290
 
313
- videoPlayer.addEventListener('playbackstart', () => {
314
- lockOrientation();
315
- });
316
-
317
- videoPlayer.addEventListener('playbackcomplete', () => {
318
- unlockOrientation();
319
- });
291
+ videoWin.add(videoPlayer);
292
+ videoWin.open();
320
293
  ```
321
294
 
322
- ## 10. Best Practices
295
+ ## 11. Modal Window Constraints (iOS)
296
+
297
+ > **Note**: Modal windows should not support orientations unsupported by the parent window. This can cause bad visual/redraw behavior after the modal is dismissed. Additionally, setting `orientationModes` on non-modal windows inside a `NavigationWindow` or `TabGroup` is bad practice — only the root window's orientation settings are respected.
298
+
299
+ ## 12. Splash Screen Configuration
300
+
301
+ Splash screens need orientation-specific image variants:
302
+
303
+ - **Android**: Uses `default.png` (lowercase `d`) placed in `Resources/android/images/`.
304
+ - **iOS**: Uses `Default.png` (uppercase `D`) with orientation variants like `Default-Landscape.png` and `Default-Portrait.png` for iPad and Universal apps.
305
+
306
+ See the `icons-and-splash-screens.md` reference for full details on naming conventions and required sizes.
307
+
308
+ ## 13. Best Practices
323
309
 
324
310
  1. **Test on multiple devices** - Orientation behavior varies
325
311
  2. **Test rotation scenarios** - How does your UI adapt?
@@ -330,7 +316,7 @@ videoPlayer.addEventListener('playbackcomplete', () => {
330
316
  7. **Handle edge cases** - What happens during phone calls?
331
317
  8. **Consider tablets** - Default orientation may differ
332
318
 
333
- ## 11. Common Issues
319
+ ## 14. Common Issues
334
320
 
335
321
  ### Orientation Not Changing
336
322
 
@@ -1,53 +1,5 @@
1
1
  # Android UI Components and Conventions
2
2
 
3
- ## Table of Contents
4
-
5
- - [Android UI Components and Conventions](#android-ui-components-and-conventions)
6
- - [Table of Contents](#table-of-contents)
7
- - [1. Action Bar](#1-action-bar)
8
- - [Overview](#overview)
9
- - [Enabling Action Bar](#enabling-action-bar)
10
- - [Creating Action Bar (Programmatic)](#creating-action-bar-programmatic)
11
- - [Action Bar with App Icon](#action-bar-with-app-icon)
12
- - [Action View (Custom Layout)](#action-view-custom-layout)
13
- - [2. Android Themes](#2-android-themes)
14
- - [Overview](#overview-1)
15
- - [Titanium Material Themes (SDK 10.0.0+)](#titanium-material-themes-sdk-1000)
16
- - [Material 3 Themes (SDK 12.0.0+)](#material-3-themes-sdk-1200)
17
- - [Applying Themes](#applying-themes)
18
- - [Custom Theme](#custom-theme)
19
- - [Color Palette Attributes](#color-palette-attributes)
20
- - [Hiding Action Bar](#hiding-action-bar)
21
- - [Theme Requirements](#theme-requirements)
22
- - [3. Options Menu](#3-options-menu)
23
- - [Legacy Options Menu](#legacy-options-menu)
24
- - [Context Menu (Long Press)](#context-menu-long-press)
25
- - [4. Status Bar Notifications](#4-status-bar-notifications)
26
- - [Notifications](#notifications)
27
- - [Notification Channels (Android 8.0+)](#notification-channels-android-80)
28
- - [Clearing Notifications](#clearing-notifications)
29
- - [5. Progress Bars](#5-progress-bars)
30
- - [Horizontal Progress Bar](#horizontal-progress-bar)
31
- - [Spinner (Indeterminate Progress)](#spinner-indeterminate-progress)
32
- - [6. Tab Groups and Tabs](#6-tab-groups-and-tabs)
33
- - [Native Android Tabs](#native-android-tabs)
34
- - [Tab Badges](#tab-badges)
35
- - [7. Hardware Back Button Handling](#7-hardware-back-button-handling)
36
- - [Handling Back Button](#handling-back-button)
37
- - [Exit Confirmation Dialog](#exit-confirmation-dialog)
38
- - [8. Notification Drawer](#8-notification-drawer)
39
- - [Display Notification](#display-notification)
40
- - [9. Android UI Conventions](#9-android-ui-conventions)
41
- - [Back Button Behavior](#back-button-behavior)
42
- - [Up/Down Navigation](#updown-navigation)
43
- - [App Shortcuts](#app-shortcuts)
44
- - [10. Material Design Components](#10-material-design-components)
45
- - [Using AppCompat v7](#using-appcompat-v7)
46
- - [Material Design Components](#material-design-components)
47
- - [Best Practices](#best-practices)
48
-
49
- ---
50
-
51
3
  ## 1. Action Bar
52
4
 
53
5
  ### Overview
@@ -130,8 +82,35 @@ activity.onPrepareOptionsMenu = (e) => {
130
82
  const menu = e.menu;
131
83
  // Modify items based on state
132
84
  };
85
+
86
+ // Force menu recreation (useful when menu items need to change dynamically)
87
+ activity.invalidateOptionsMenu();
133
88
  ```
134
89
 
90
+ ### Action Bar Properties
91
+
92
+ ```javascript
93
+ const activity = Ti.Android.currentActivity;
94
+ const actionBar = activity.actionBar;
95
+
96
+ // Show the "up" affordance arrow next to the home icon
97
+ actionBar.displayHomeAsUp = true;
98
+
99
+ // Customize icon and logo
100
+ actionBar.icon = '/images/actionbar_icon.png';
101
+ actionBar.logo = '/images/actionbar_logo.png';
102
+
103
+ // Handle home icon/logo clicks
104
+ actionBar.onHomeIconItemSelected = () => {
105
+ // Navigate up or open navigation drawer
106
+ win.close();
107
+ };
108
+ ```
109
+
110
+ ### Refreshing the Options Menu
111
+
112
+ Call `activity.invalidateOptionsMenu()` to force `onCreateOptionsMenu` to be called again. This is useful when menu items need to change dynamically (e.g., when the user switches tabs or a state change requires different menu options).
113
+
135
114
  ### Action Bar with App Icon
136
115
 
137
116
  ```javascript
@@ -311,6 +290,8 @@ win.addEventListener('open', () => {
311
290
 
312
291
  ### Theme Requirements
313
292
 
293
+ > **Warning:** SDK 10.0.0+ requires material-based themes. Using non-material themes will cause a runtime error. Do NOT name your custom theme file `theme.xml` — this will overwrite Titanium's built-in theme file. Use descriptive names like `mytheme.xml`.
294
+
314
295
  - SDK 10.0.0+ requires material-based themes (runtime error otherwise)
315
296
  - Place custom themes in `platform/android/res/values/`
316
297
  - Do NOT name file `theme.xml` (overwrites Titanium's)
@@ -623,6 +604,91 @@ Android 7.1+ app shortcuts:
623
604
 
624
605
  These can be accessed via Hyperloop or custom modules.
625
606
 
607
+ ## 11. Toast Notifications
608
+
609
+ Toast notifications display brief messages at the bottom of the screen that automatically disappear.
610
+
611
+ ```javascript
612
+ const toast = Ti.UI.createNotification({
613
+ message: 'Item saved successfully',
614
+ duration: Ti.UI.NOTIFICATION_DURATION_LONG
615
+ });
616
+ toast.show();
617
+ ```
618
+
619
+ ### Positioning
620
+
621
+ Use `offsetX` and `offsetY` to reposition the toast from its default location:
622
+
623
+ ```javascript
624
+ const toast = Ti.UI.createNotification({
625
+ message: 'Custom position',
626
+ duration: Ti.UI.NOTIFICATION_DURATION_SHORT,
627
+ offsetX: 0,
628
+ offsetY: 100
629
+ });
630
+ toast.show();
631
+ ```
632
+
633
+ **Duration options:**
634
+ - `Ti.UI.NOTIFICATION_DURATION_SHORT` — Short display time
635
+ - `Ti.UI.NOTIFICATION_DURATION_LONG` — Longer display time
636
+
637
+ ## 12. HTML Labels and Linkification
638
+
639
+ ### HTML Content in Labels
640
+
641
+ Use the `html` property on Labels to render inline HTML content:
642
+
643
+ ```javascript
644
+ const label = Ti.UI.createLabel({
645
+ html: '<b>Bold</b> and <i>italic</i> text',
646
+ autoLink: Ti.UI.AUTOLINK_ALL
647
+ });
648
+ ```
649
+
650
+ ### Auto-Link Constants
651
+
652
+ The `autoLink` property automatically detects and linkifies content:
653
+
654
+ | Constant | Description |
655
+ | -------------------------------- | ----------------------------- |
656
+ | `Ti.UI.AUTOLINK_ALL` | Linkify all detected patterns |
657
+ | `Ti.UI.AUTOLINK_EMAIL_ADDRESSES` | Linkify email addresses |
658
+ | `Ti.UI.AUTOLINK_MAP_ADDRESSES` | Linkify street addresses |
659
+ | `Ti.UI.AUTOLINK_PHONE_NUMBERS` | Linkify phone numbers |
660
+ | `Ti.UI.AUTOLINK_URLS` | Linkify web URLs |
661
+
662
+ You can combine multiple constants using bitwise OR:
663
+
664
+ ```javascript
665
+ const label = Ti.UI.createLabel({
666
+ text: 'Call 555-1234 or visit example.com',
667
+ autoLink: Ti.UI.AUTOLINK_PHONE_NUMBERS | Ti.UI.AUTOLINK_URLS
668
+ });
669
+ ```
670
+
671
+ ## 13. Nine-Patch Images
672
+
673
+ Nine-patch images (`.9.png`) define stretchable regions that adapt to different screen sizes and content.
674
+
675
+ ### Key Points
676
+
677
+ - Files use the `.9.png` extension
678
+ - Only work as `backgroundImage` (not as regular images)
679
+ - Define stretchable regions so the image scales without distortion
680
+ - Reference **without** the `.9` in code — Android resolves it automatically
681
+ - Create with the Android SDK's `draw9patch` tool
682
+
683
+ ```javascript
684
+ const button = Ti.UI.createButton({
685
+ title: 'Submit',
686
+ backgroundImage: '/images/button_bg.png', // actual file: button_bg.9.png
687
+ width: Ti.UI.SIZE,
688
+ height: Ti.UI.SIZE
689
+ });
690
+ ```
691
+
626
692
  ## Best Practices
627
693
 
628
694
  1. **Follow Material Design guidelines** for modern Android apps
@@ -1,43 +1,5 @@
1
1
  # iOS UI Components and Conventions
2
2
 
3
- ## Table of Contents
4
-
5
- - [iOS UI Components and Conventions](#ios-ui-components-and-conventions)
6
- - [Table of Contents](#table-of-contents)
7
- - [1. Overview](#1-overview)
8
- - [2. iPad-Only UI Components](#2-ipad-only-ui-components)
9
- - [Popover](#popover)
10
- - [Popover Events](#popover-events)
11
- - [SplitWindow](#splitwindow)
12
- - [SplitWindow in Portrait](#splitwindow-in-portrait)
13
- - [3. Badges](#3-badges)
14
- - [App Icon Badge](#app-icon-badge)
15
- - [Tab Badge](#tab-badge)
16
- - [Accessing Preferences in App](#accessing-preferences-in-app)
17
- - [Dynamic Quick Actions](#dynamic-quick-actions)
18
- - [Handling Quick Actions](#handling-quick-actions)
19
- - [Peek and Pop](#peek-and-pop)
20
- - [Enabling Peek and Pop](#enabling-peek-and-pop)
21
- - [Preview Action Styles](#preview-action-styles)
22
- - [6. Navigation Bar (iOS)](#6-navigation-bar-ios)
23
- - [NavigationWindow](#navigationwindow)
24
- - [Toolbar](#toolbar)
25
- - [System Buttons](#system-buttons)
26
- - [7. Tab Bar](#7-tab-bar)
27
- - [Creating Tab Bar](#creating-tab-bar)
28
- - [Tab Bar Customization (iOS)](#tab-bar-customization-ios)
29
- - [8. Activity Indicator](#8-activity-indicator)
30
- - [iOS-Specific Location](#ios-specific-location)
31
- - [9. Platform Best Practices](#9-platform-best-practices)
32
- - [Follow iOS Human Interface Guidelines](#follow-ios-human-interface-guidelines)
33
- - [iOS-Specific Patterns](#ios-specific-patterns)
34
- - [10. Common Issues](#10-common-issues)
35
- - [Settings Not Appearing](#settings-not-appearing)
36
- - [3D Touch Not Working](#3d-touch-not-working)
37
- - [SplitWindow Issues](#splitwindow-issues)
38
-
39
- ---
40
-
41
3
  ## 1. Overview
42
4
 
43
5
  iOS offers several UI components and conventions that differ from Android. This guide covers iPad-specific controls, app badges, Settings integration, 3D Touch, and iOS-specific navigation patterns.
@@ -183,14 +145,59 @@ tab1.setBadge(null);
183
145
  tab1.badge = null;
184
146
  ```
185
147
  ...
148
+ ### Settings.bundle Integration
149
+
150
+ iOS apps can expose user-configurable settings in the device's Settings app using a Settings.bundle.
151
+
152
+ **Setup**:
153
+ - Place the bundle at `platform/iphone/Settings.bundle/` (SDK 1.8+)
154
+ - The bundle contains `Root.plist`, which defines the settings UI (toggles, text fields, groups, etc.)
155
+ - Edit `Root.plist` using Xcode's Property List editor for a visual interface
156
+
157
+ **Key conventions**: Settings keys typically use the `_preference` suffix (e.g., `username_preference`, `enabled_preference`).
158
+
186
159
  ### Accessing Preferences in App
187
160
 
188
161
  ```javascript
162
+ // Read a preference set in iOS Settings app
163
+ const username = Ti.App.Properties.getString('username_preference');
164
+
189
165
  // Must match the "Key" value from Root.plist
190
166
  const name = Ti.App.Properties.getString('name_preference');
191
167
  const enabled = Ti.App.Properties.getBool('enabled_preference');
192
168
  ```
193
169
  ...
170
+ #### Static Quick Actions (via tiapp.xml)
171
+
172
+ Static shortcuts are defined in `tiapp.xml` and available immediately when the app is installed.
173
+
174
+ - **Required keys**: `UIApplicationShortcutItemTitle`, `UIApplicationShortcutItemType`
175
+ - **Optional keys**: `UIApplicationShortcutItemSubtitle`, `UIApplicationShortcutItemIconType`, `UIApplicationShortcutItemIconFile`, `UIApplicationShortcutItemUserInfo`
176
+
177
+ ```xml
178
+ <ios>
179
+ <plist>
180
+ <dict>
181
+ <key>UIApplicationShortcutItems</key>
182
+ <array>
183
+ <dict>
184
+ <key>UIApplicationShortcutItemTitle</key>
185
+ <string>New Message</string>
186
+ <key>UIApplicationShortcutItemType</key>
187
+ <string>com.app.newmessage</string>
188
+ <key>UIApplicationShortcutItemIconType</key>
189
+ <string>UIApplicationShortcutIconTypeCompose</string>
190
+ </dict>
191
+ </array>
192
+ </dict>
193
+ </plist>
194
+ </ios>
195
+ ```
196
+
197
+ Quick action titles and subtitles can be localized using `i18n/LANG/app.xml` (not `strings.xml`). Use the localized key as the value in `tiapp.xml`.
198
+
199
+ To use custom images for quick action icons, enable app thinning in `tiapp.xml` with `<use-app-thinning>true</use-app-thinning>` inside the `<ios>` element.
200
+
194
201
  #### Dynamic Quick Actions
195
202
 
196
203
  ```javascript
@@ -285,6 +292,24 @@ Ti.UI.iOS.PREVIEW_ACTION_STYLE_SELECTED // Blue background
285
292
  Ti.UI.iOS.PREVIEW_ACTION_STYLE_DESTRUCTIVE // Red background
286
293
  ```
287
294
 
295
+ #### Peek and Pop Details
296
+
297
+ - Use the `contentHeight` property on the preview context to control the peek preview height (e.g., `contentHeight: 400` as shown above).
298
+ - Use `Ti.UI.iOS.createPreviewActionGroup()` to group related preview actions into a submenu:
299
+
300
+ ```javascript
301
+ const subAction1 = Ti.UI.iOS.createPreviewAction({ title: 'Copy', style: Ti.UI.iOS.PREVIEW_ACTION_STYLE_DEFAULT });
302
+ const subAction2 = Ti.UI.iOS.createPreviewAction({ title: 'Move', style: Ti.UI.iOS.PREVIEW_ACTION_STYLE_DEFAULT });
303
+
304
+ const actionGroup = Ti.UI.iOS.createPreviewActionGroup({
305
+ title: 'Organize',
306
+ style: Ti.UI.iOS.PREVIEW_ACTION_STYLE_DEFAULT,
307
+ actions: [subAction1, subAction2]
308
+ });
309
+ ```
310
+
311
+ > **Important**: 3D Touch features (Peek and Pop, quick actions with force) can ONLY be tested on physical devices with 3D Touch hardware. The iOS Simulator does not support force touch.
312
+
288
313
  ## 6. Navigation Bar (iOS)
289
314
 
290
315
  ### NavigationWindow
@@ -1,27 +1,5 @@
1
1
  # Scrolling Views
2
2
 
3
- ## Table of Contents
4
-
5
- - [Scrolling Views](#scrolling-views)
6
- - [Table of Contents](#table-of-contents)
7
- - [1. ScrollView vs ScrollableView](#1-scrollview-vs-scrollableview)
8
- - [2. ScrollView](#2-scrollview)
9
- - [Creating a ScrollView](#creating-a-scrollview)
10
- - [ScrollView Events](#scrollview-events)
11
- - [Android ScrollView Direction](#android-scrollview-direction)
12
- - [3. ScrollableView](#3-scrollableview)
13
- - [Creating a ScrollableView](#creating-a-scrollableview)
14
- - [ScrollableView Events](#scrollableview-events)
15
- - [Image Gallery](#image-gallery)
16
- - [Onboarding Wizard](#onboarding-wizard)
17
- - [Long Form Content](#long-form-content)
18
- - [Scrollable Form](#scrollable-form)
19
- - [ScrollableView](#scrollableview)
20
- - [8. Detecting Scroll Position](#8-detecting-scroll-position)
21
- - [Best Practices](#best-practices)
22
-
23
- ---
24
-
25
3
  ## 1. ScrollView vs ScrollableView
26
4
 
27
5
  | Feature | ScrollView | ScrollableView |
@@ -56,6 +34,19 @@ scrollView.add(content);
56
34
  win.add(scrollView);
57
35
  ```
58
36
  ...
37
+ ### ScrollView Properties
38
+
39
+ | Property | Description | Platform |
40
+ | --------------------------------------------- | ------------------------------------------------------------------- | -------- |
41
+ | `contentWidth` / `contentHeight` | Size of the scrollable content area | All |
42
+ | `scrollType` | `'vertical'` or `'horizontal'` (Android only — see below) | Android |
43
+ | `showHorizontalScrollIndicator` | Show/hide horizontal scroll indicator | All |
44
+ | `showVerticalScrollIndicator` | Show/hide vertical scroll indicator | All |
45
+ | `zoomScale` / `minZoomScale` / `maxZoomScale` | Zoom level (values 0–1) | iOS |
46
+ | `horizontalBounce` / `verticalBounce` | Enable/disable bounce effect at edges | iOS |
47
+ | `canCancelEvents` | Allow ScrollView to cancel touch events in children (default: true) | iOS |
48
+ | `scrollable` | Enable/disable scrolling | All |
49
+
59
50
  ### ScrollView Events
60
51
 
61
52
  ```javascript
@@ -77,7 +68,7 @@ scrollView.addEventListener('scrollEnd', (e) => {
77
68
  ...
78
69
  ### Android ScrollView Direction
79
70
 
80
- Android ScrollView can be vertical OR horizontal, not both:
71
+ Android ScrollView can be vertical OR horizontal, not both. If you don't set `scrollType`, Android auto-detects: if width equals contentWidth it defaults to vertical; if height equals contentHeight it defaults to horizontal. If Titanium cannot determine the direction, a warning is logged to the console.
81
72
 
82
73
  ```javascript
83
74
  // Explicit horizontal scroll
@@ -1,59 +1,5 @@
1
1
  # TableViews
2
2
 
3
- ## Table of Contents
4
-
5
- - [TableViews](#tableviews)
6
- - [Table of Contents](#table-of-contents)
7
- - [1. Overview](#1-overview)
8
- - [2. TableView vs ListView](#2-tableview-vs-listview)
9
- - [3. Creating a TableView](#3-creating-a-tableview)
10
- - [Basic TableView](#basic-tableview)
11
- - [4. Creating rows](#4-creating-rows)
12
- - [Object Literal Rows (Simple)](#object-literal-rows-simple)
13
- - [Explicit TableViewRow Objects](#explicit-tableviewrow-objects)
14
- - [Performance: setData() vs appendRow()](#performance-setdata-vs-appendrow)
15
- - [5. Row Properties](#5-row-properties)
16
- - [Built-in Row Properties](#built-in-row-properties)
17
- - [Styled Rows Example](#styled-rows-example)
18
- - [Row Indicators](#row-indicators)
19
- - [6. Custom Rows](#6-custom-rows)
20
- - [Adding Child Views](#adding-child-views)
21
- - [Performance Warning](#performance-warning)
22
- - [7. Headers and Footers](#7-headers-and-footers)
23
- - [Table-Level Headers/Footers](#table-level-headersfooters)
24
- - [Custom Header/Footer Views](#custom-headerfooter-views)
25
- - [Section Headers/Footers](#section-headersfooters)
26
- - [8. Grouped Table Style (iOS)](#8-grouped-table-style-ios)
27
- - [9. Editing Mode](#9-editing-mode)
28
- - [10. TableView Events](#10-tableview-events)
29
- - [Click Event](#click-event)
30
- - [Delete Event](#delete-event)
31
- - [Scroll Events](#scroll-events)
32
- - [11. Searching](#11-searching)
33
- - [12. Updating Table Data](#12-updating-table-data)
34
- - [Appending Rows](#appending-rows)
35
- - [Inserting Rows](#inserting-rows)
36
- - [Deleting Rows](#deleting-rows)
37
- - [Updating Specific Row](#updating-specific-row)
38
- - [13. TableView Sections](#13-tableview-sections)
39
- - [Creating Sections](#creating-sections)
40
- - [Custom Section Headers](#custom-section-headers)
41
- - [14. Performance Optimization](#14-performance-optimization)
42
- - [Use className](#use-classname)
43
- - [Avoid Too Many Rows](#avoid-too-many-rows)
44
- - [Optimize Custom Rows](#optimize-custom-rows)
45
- - [15. Common Patterns](#15-common-patterns)
46
- - [Detail View Navigation](#detail-view-navigation)
47
- - [Row Actions (Swipe to Delete)](#row-actions-swipe-to-delete)
48
- - [Refresh Control](#refresh-control)
49
- - [16. Platform Differences](#16-platform-differences)
50
- - [iOS](#ios)
51
- - [Android](#android)
52
- - [17. Migration: TableView to ListView](#17-migration-tableview-to-listview)
53
- - [Best Practices](#best-practices)
54
-
55
- ---
56
-
57
3
  ## 1. Overview
58
4
 
59
5
  TableView is a scrolling list component that displays rows of data. While ListView is the recommended modern API for most use cases, TableView remains useful for:
@@ -83,7 +29,10 @@ const table = Ti.UI.createTableView({
83
29
  width: Ti.UI.FILL,
84
30
  backgroundColor: 'white',
85
31
  rowHeight: 50,
86
- separatorColor: '#ccc'
32
+ minRowHeight: 40,
33
+ maxRowHeight: 80,
34
+ separatorColor: '#ccc',
35
+ scrollable: true // Set false to disable scrolling
87
36
  });
88
37
 
89
38
  win.add(table);
@@ -393,7 +342,8 @@ table.deleteRow(3); // Delete row at index 3
393
342
 
394
343
  // Clear all rows
395
344
  table.setData([]);
396
- // NOT: table.data = null (causes issues)
345
+ // NOT: table.data = null or undefined (causes unexpected behavior)
346
+ // Use table.setData([]) or table.data = [] to clear
397
347
  ```
398
348
 
399
349
  ### Updating Specific Row