@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.
- package/{AGENTS-TEMPLATE.md → AGENTS-VERCEL-RESEARCH.md} +16 -18
- package/README.md +250 -168
- package/agents/{ti-researcher.md → ti-pro.md} +10 -10
- package/bin/titools.js +16 -12
- package/lib/cleanup.js +95 -0
- package/lib/commands/agents.js +146 -70
- package/lib/commands/skills.js +349 -0
- package/lib/commands/uninstall.js +189 -154
- package/lib/commands/update.js +104 -21
- package/lib/config.js +26 -20
- package/lib/downloader.js +1 -1
- package/lib/installer.js +37 -97
- package/lib/platform.js +9 -5
- package/lib/prompts/checkboxCancel.js +264 -0
- package/lib/prompts/selectCancel.js +204 -0
- package/lib/symlink.js +19 -7
- package/lib/utils.js +17 -17
- package/package.json +10 -10
- package/skills/alloy-guides/SKILL.md +8 -30
- package/skills/alloy-guides/references/CLI_TASKS.md +14 -24
- package/skills/alloy-guides/references/CONCEPTS.md +5 -25
- package/skills/alloy-guides/references/CONTROLLERS.md +2 -19
- package/skills/alloy-guides/references/MODELS.md +40 -10
- package/skills/alloy-guides/references/PURGETSS.md +1 -11
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +8 -14
- package/skills/alloy-guides/references/VIEWS_STYLES.md +14 -25
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +2 -8
- package/skills/alloy-guides/references/VIEWS_XML.md +29 -40
- package/skills/alloy-guides/references/WIDGETS.md +1 -17
- package/skills/alloy-howtos/SKILL.md +1 -22
- package/skills/alloy-howtos/references/best_practices.md +0 -17
- package/skills/alloy-howtos/references/cli_reference.md +1 -23
- package/skills/alloy-howtos/references/config_files.md +86 -15
- package/skills/alloy-howtos/references/custom_tags.md +14 -13
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +3 -22
- package/skills/alloy-howtos/references/samples.md +4 -14
- package/skills/purgetss/SKILL.md +11 -37
- package/skills/purgetss/references/EXAMPLES.md +106 -17
- package/skills/purgetss/references/animation-system.md +0 -67
- package/skills/purgetss/references/apply-directive.md +0 -18
- package/skills/purgetss/references/arbitrary-values.md +0 -25
- package/skills/purgetss/references/class-index.md +0 -46
- package/skills/purgetss/references/cli-commands.md +0 -41
- package/skills/purgetss/references/configurable-properties.md +0 -55
- package/skills/purgetss/references/custom-rules.md +0 -14
- package/skills/purgetss/references/customization-deep-dive.md +0 -49
- package/skills/purgetss/references/dynamic-component-creation.md +56 -37
- package/skills/purgetss/references/grid-layout.md +0 -32
- package/skills/purgetss/references/icon-fonts.md +0 -50
- package/skills/purgetss/references/installation-setup.md +61 -32
- package/skills/purgetss/references/migration-guide.md +127 -0
- package/skills/purgetss/references/opacity-modifier.md +0 -34
- package/skills/purgetss/references/performance-tips.md +261 -0
- package/skills/purgetss/references/platform-modifiers.md +0 -46
- package/skills/purgetss/references/smart-mappings.md +0 -12
- package/skills/purgetss/references/tikit-components.md +393 -0
- package/skills/purgetss/references/titanium-resets.md +1 -27
- package/skills/purgetss/references/ui-ux-design.md +467 -117
- package/skills/{alloy-expert → ti-expert}/SKILL.md +45 -54
- package/skills/ti-expert/references/alloy-builtins.md +387 -0
- package/skills/{alloy-expert → ti-expert}/references/alloy-structure.md +147 -40
- package/skills/ti-expert/references/anti-patterns.md +90 -0
- package/skills/ti-expert/references/cli-expert.md +109 -0
- package/skills/{alloy-expert → ti-expert}/references/code-conventions.md +182 -49
- package/skills/{alloy-expert → ti-expert}/references/controller-patterns.md +103 -93
- package/skills/{alloy-expert → ti-expert}/references/error-handling.md +12 -12
- package/skills/{alloy-expert → ti-expert}/references/examples.md +144 -85
- package/skills/{alloy-expert → ti-expert}/references/migration-patterns.md +38 -36
- package/skills/{alloy-expert → ti-expert}/references/patterns.md +8 -8
- package/skills/ti-expert/references/performance-listview.md +251 -0
- package/skills/{alloy-expert/references/performance-patterns.md → ti-expert/references/performance-optimization.md} +67 -283
- package/skills/{alloy-expert/references/security-patterns.md → ti-expert/references/security-device.md} +12 -295
- package/skills/ti-expert/references/security-fundamentals.md +284 -0
- package/skills/{alloy-expert → ti-expert}/references/state-management.md +10 -10
- package/skills/ti-expert/references/testing-e2e-ci.md +432 -0
- package/skills/ti-expert/references/testing-unit.md +433 -0
- package/skills/ti-expert/references/theming.md +394 -0
- package/skills/ti-guides/SKILL.md +1 -14
- package/skills/ti-guides/references/advanced-data-and-images.md +126 -10
- package/skills/ti-guides/references/app-distribution.md +48 -10
- package/skills/ti-guides/references/application-frameworks.md +9 -2
- package/skills/ti-guides/references/cli-reference.md +338 -82
- package/skills/ti-guides/references/coding-best-practices.md +14 -4
- package/skills/ti-guides/references/commonjs-advanced.md +103 -6
- package/skills/ti-guides/references/hello-world.md +5 -2
- package/skills/ti-guides/references/hyperloop-native-access.md +439 -46
- package/skills/ti-guides/references/javascript-primer.md +4 -3
- package/skills/ti-guides/references/resources.md +0 -1
- package/skills/ti-guides/references/style-and-conventions.md +57 -9
- package/skills/ti-guides/references/tiapp-config.md +48 -6
- package/skills/ti-howtos/SKILL.md +2 -27
- package/skills/ti-howtos/references/android-platform-deep-dives.md +41 -90
- package/skills/ti-howtos/references/automation-fastlane-appium.md +15 -14
- package/skills/ti-howtos/references/buffer-codec-streams.md +22 -22
- package/skills/ti-howtos/references/cross-platform-development.md +68 -37
- package/skills/ti-howtos/references/debugging-profiling.md +8 -53
- package/skills/ti-howtos/references/extending-titanium.md +12 -51
- package/skills/ti-howtos/references/google-maps-v2.md +30 -29
- package/skills/ti-howtos/references/ios-map-kit.md +19 -25
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +95 -283
- package/skills/ti-howtos/references/local-data-sources.md +45 -37
- package/skills/ti-howtos/references/location-and-maps.md +47 -28
- package/skills/ti-howtos/references/media-apis.md +84 -27
- package/skills/ti-howtos/references/notification-services.md +40 -89
- package/skills/ti-howtos/references/remote-data-sources.md +21 -36
- package/skills/ti-howtos/references/tutorials.md +79 -39
- package/skills/ti-howtos/references/using-modules.md +4 -30
- package/skills/ti-howtos/references/web-content-integration.md +28 -45
- package/skills/ti-howtos/references/webpack-build-pipeline.md +54 -18
- package/skills/ti-ui/SKILL.md +1 -21
- package/skills/ti-ui/references/accessibility-deep-dive.md +71 -25
- package/skills/ti-ui/references/animation-and-matrices.md +0 -47
- package/skills/ti-ui/references/application-structures.md +0 -46
- package/skills/ti-ui/references/custom-fonts-styling.md +9 -57
- package/skills/ti-ui/references/event-handling.md +32 -40
- package/skills/ti-ui/references/gestures.md +0 -40
- package/skills/ti-ui/references/icons-and-splash-screens.md +21 -44
- package/skills/ti-ui/references/layouts-and-positioning.md +47 -39
- package/skills/ti-ui/references/listviews-and-performance.md +187 -73
- package/skills/ti-ui/references/orientation.md +57 -71
- package/skills/ti-ui/references/platform-ui-android.md +114 -48
- package/skills/ti-ui/references/platform-ui-ios.md +63 -38
- package/skills/ti-ui/references/scrolling-views.md +14 -23
- package/skills/ti-ui/references/tableviews.md +6 -56
- package/lib/commands/install.js +0 -188
- package/skills/alloy-expert/references/anti-patterns.md +0 -133
- package/skills/alloy-expert/references/testing.md +0 -872
- package/skills/ti-guides/references/alloy-cli-advanced.md +0 -84
- package/skills/ti-guides/references/alloy-data-mastery.md +0 -29
- package/skills/ti-guides/references/alloy-widgets-and-themes.md +0 -19
- /package/skills/{alloy-expert → ti-expert}/assets/ControllerAutoCleanup.js +0 -0
- /package/skills/{alloy-expert → ti-expert}/references/contracts.md +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: "Titanium
|
|
2
|
+
name: ti-expert
|
|
3
|
+
description: "Titanium SDK architecture and implementation expert. Use when designing, reviewing, analyzing, or examining Titanium project structure (Alloy or Classic), creating controllers/views/services, choosing models vs collections, implementing communication patterns, handling memory cleanup, testing, auditing code, or migrating legacy apps. Automatically identifies project type."
|
|
4
4
|
argument-hint: "[architecture-topic]"
|
|
5
5
|
allowed-tools: Read, Grep, Glob, Edit, Write, Bash(git *), Bash(node *)
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Titanium
|
|
8
|
+
# Titanium Expert
|
|
9
9
|
|
|
10
|
-
Complete architectural and implementation guidance for building scalable, maintainable Titanium
|
|
10
|
+
Complete architectural and implementation guidance for building scalable, maintainable Titanium SDK applications (Alloy & Classic).
|
|
11
11
|
|
|
12
12
|
## Project Detection
|
|
13
13
|
|
|
@@ -31,28 +31,6 @@ This skill automatically detects project type when invoked and provides appropri
|
|
|
31
31
|
- **Unknown** → Asks user to clarify project type
|
|
32
32
|
:::
|
|
33
33
|
|
|
34
|
-
## Table of Contents
|
|
35
|
-
|
|
36
|
-
- [Titanium Alloy Expert](#titanium-alloy-expert)
|
|
37
|
-
- [Project Detection](#project-detection)
|
|
38
|
-
- [Table of Contents](#table-of-contents)
|
|
39
|
-
- [Workflow](#workflow)
|
|
40
|
-
- [Quick Start Example](#quick-start-example)
|
|
41
|
-
- [Code Standards (Low Freedom)](#code-standards-low-freedom)
|
|
42
|
-
- [PurgeTSS Rules (Low Freedom)](#purgetss-rules-low-freedom)
|
|
43
|
-
- [Quick Decision Matrix](#quick-decision-matrix)
|
|
44
|
-
- [Reference Guides (Progressive Disclosure)](#reference-guides-progressive-disclosure)
|
|
45
|
-
- [Architecture](#architecture)
|
|
46
|
-
- [Implementation](#implementation)
|
|
47
|
-
- [Quality \& Reliability](#quality--reliability)
|
|
48
|
-
- [Performance \& Security](#performance--security)
|
|
49
|
-
- [Migration](#migration)
|
|
50
|
-
- [Specialized Titanium Skills](#specialized-titanium-skills)
|
|
51
|
-
- [Guiding Principles](#guiding-principles)
|
|
52
|
-
- [Response Format](#response-format)
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
34
|
## Workflow
|
|
57
35
|
|
|
58
36
|
1. **Architecture**: Define structure (`lib/api`, `lib/services`, `lib/helpers`)
|
|
@@ -69,12 +47,12 @@ Minimal example following all conventions:
|
|
|
69
47
|
**View (views/user/card.xml)**
|
|
70
48
|
```xml
|
|
71
49
|
<Alloy>
|
|
72
|
-
<View
|
|
73
|
-
<View
|
|
74
|
-
<
|
|
75
|
-
<Label id="name"
|
|
50
|
+
<View id="cardContainer">
|
|
51
|
+
<View id="headerRow">
|
|
52
|
+
<ImageView id="userIcon" image="/images/user.png" />
|
|
53
|
+
<Label id="name" />
|
|
76
54
|
</View>
|
|
77
|
-
<Button
|
|
55
|
+
<Button id="viewProfileBtn"
|
|
78
56
|
title="L('view_profile')"
|
|
79
57
|
onClick="onViewProfile"
|
|
80
58
|
/>
|
|
@@ -82,9 +60,18 @@ Minimal example following all conventions:
|
|
|
82
60
|
</Alloy>
|
|
83
61
|
```
|
|
84
62
|
|
|
63
|
+
**Styles (styles/user/card.tss)**
|
|
64
|
+
```tss
|
|
65
|
+
"#cardContainer": { left: 8, right: 8, top: 8, height: Ti.UI.SIZE, borderRadius: 12, backgroundColor: '#fff' }
|
|
66
|
+
"#headerRow": { layout: 'horizontal', left: 12, right: 12, top: 12, height: Ti.UI.SIZE, width: Ti.UI.FILL }
|
|
67
|
+
"#userIcon": { width: 32, height: 32 }
|
|
68
|
+
"#name": { left: 12, font: { fontSize: 18, fontWeight: 'bold' } }
|
|
69
|
+
"#viewProfileBtn": { left: 12, right: 12, bottom: 12, height: 40, width: Ti.UI.FILL, borderRadius: 6, backgroundColor: '#2563eb', color: '#fff' }
|
|
70
|
+
```
|
|
71
|
+
|
|
85
72
|
**Controller (controllers/user/card.js)**
|
|
86
73
|
```javascript
|
|
87
|
-
const { Navigation } = require('
|
|
74
|
+
const { Navigation } = require('services/navigation')
|
|
88
75
|
|
|
89
76
|
function init() {
|
|
90
77
|
const user = $.args.user
|
|
@@ -128,7 +115,7 @@ exports.Navigation = {
|
|
|
128
115
|
- **ERROR HANDLING**: Use AppError classes, log with context, never swallow errors
|
|
129
116
|
- **TESTABLE**: Inject dependencies, avoid hard coupling
|
|
130
117
|
|
|
131
|
-
##
|
|
118
|
+
## Titanium Style Sheets Rules (Low Freedom)
|
|
132
119
|
|
|
133
120
|
:::danger CRITICAL: Platform-Specific Properties Require Modifiers
|
|
134
121
|
Using `Ti.UI.iOS.*` or `Ti.UI.Android.*` properties WITHOUT platform modifiers causes cross-platform compilation failures.
|
|
@@ -155,58 +142,63 @@ Using `Ti.UI.iOS.*` or `Ti.UI.Android.*` properties WITHOUT platform modifiers c
|
|
|
155
142
|
|
|
156
143
|
**Available modifiers:** `[platform=ios]`, `[platform=android]`, `[formFactor=handheld]`, `[formFactor=tablet]`, `[if=Alloy.Globals.customVar]`
|
|
157
144
|
|
|
158
|
-
**For more platform-specific patterns, see
|
|
145
|
+
**For more platform-specific patterns, see the `ti-ui` skill.**
|
|
159
146
|
:::
|
|
160
147
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
148
|
+
**Titanium layout system:**
|
|
149
|
+
- Three layout modes: `layout: 'horizontal'`, `layout: 'vertical'`, and composite (default — no `layout` needed)
|
|
150
|
+
- No padding on container Views — use margins on children instead
|
|
151
|
+
- `width: Ti.UI.FILL` fills available space (preferred), `width: '100%'` = 100% of parent
|
|
152
|
+
- `height: Ti.UI.SIZE` wraps content, `height: Ti.UI.FILL` fills available space
|
|
153
|
+
|
|
154
|
+
## Alloy Builtins Quick Reference
|
|
155
|
+
|
|
156
|
+
Key builtins: `OS_IOS`/`OS_ANDROID` (compile-time), `Alloy.CFG` (config.json), `Alloy.Globals` (shared state), `$.args` (controller params), `$.destroy()` (cleanup bindings), `platform="ios"` / `formFactor="tablet"` (XML conditionals).
|
|
170
157
|
|
|
171
|
-
**
|
|
172
|
-
- `w-full` → `width: '100%'` (100% of parent container) - exists and valid
|
|
173
|
-
- `w-screen` → `width: Ti.UI.FILL` (fills all available space) - use for full-width elements
|
|
158
|
+
For the complete reference with examples, see **[Alloy Builtins & Globals](references/alloy-builtins.md)**.
|
|
174
159
|
|
|
175
160
|
## Quick Decision Matrix
|
|
176
161
|
|
|
177
162
|
| Question | Answer |
|
|
178
163
|
| ---------------------------------- | -------------------------------------------------------------- |
|
|
179
164
|
| How to create a new Alloy project? | **`ti create -t app --alloy`** (not `--classic` + `alloy new`) |
|
|
165
|
+
| Fastest way to build? | **`tn <recipe>`** (using TiNy CLI wrapper) |
|
|
180
166
|
| Where does API call go? | `lib/api/` |
|
|
181
167
|
| Where does business logic go? | `lib/services/` |
|
|
182
168
|
| Where do I store auth tokens? | Keychain (iOS) / KeyStore (Android) via service |
|
|
183
169
|
| Models or Collections? | Collections for API data, Models for SQLite persistence |
|
|
184
170
|
| Ti.App.fireEvent or EventBus? | **Always EventBus** (Backbone.Events) |
|
|
185
171
|
| Direct navigation or service? | **Always Navigation service** (auto cleanup) |
|
|
186
|
-
|
|
|
172
|
+
| Inline styles or TSS files? | **Always TSS files** (per-controller + `app.tss` for global) |
|
|
187
173
|
| Controller 100+ lines? | Extract logic to services |
|
|
188
174
|
|
|
189
175
|
## Reference Guides (Progressive Disclosure)
|
|
190
176
|
|
|
191
177
|
### Architecture
|
|
192
|
-
- **[
|
|
178
|
+
- **[CLI Expert & TiNy](references/cli-expert.md)**: Advanced build workflows, LiveView, and TiNy (`tn`) recipes
|
|
179
|
+
- **[Structure & Organization](references/alloy-structure.md)**: Models vs Collections, folder maps, widget patterns, automatic cleanup
|
|
180
|
+
- **[Alloy Builtins & Globals](references/alloy-builtins.md)**: OS_IOS/OS_ANDROID, Alloy.CFG, Alloy.Globals, $.args, compiler directives
|
|
193
181
|
- **[ControllerAutoCleanup.js](assets/ControllerAutoCleanup.js)**: Drop-in utility for automatic controller cleanup (prevents memory leaks)
|
|
194
182
|
- **[Architectural Patterns](references/patterns.md)**: Repository, Service Layer, Event Bus, Factory, Singleton
|
|
195
183
|
- **[Contracts & Communication](references/contracts.md)**: Layer interaction examples and JSDoc specs
|
|
196
|
-
- **[Anti-Patterns](references/anti-patterns.md)**: Fat controllers,
|
|
184
|
+
- **[Anti-Patterns](references/anti-patterns.md)**: Fat controllers, memory leaks, inline styling, direct API calls
|
|
197
185
|
|
|
198
186
|
### Implementation
|
|
199
|
-
- **[Code Conventions](references/code-conventions.md)**: ES6 features,
|
|
187
|
+
- **[Code Conventions](references/code-conventions.md)**: ES6 features, TSS design system, accessibility
|
|
188
|
+
- **[Theming & Dark Mode](references/theming.md)**: Theme system, Alloy.Globals palette, runtime switching, design tokens
|
|
200
189
|
- **[Controller Patterns](references/controller-patterns.md)**: Templates, animation, dynamic styling
|
|
201
190
|
- **[Examples](references/examples.md)**: API clients, SQL models, full screen examples
|
|
202
191
|
|
|
203
192
|
### Quality & Reliability
|
|
204
|
-
- **[Testing](references/testing.md)**: Unit testing, mocking patterns, controller testing, test helpers
|
|
193
|
+
- **[Unit & Integration Testing](references/testing-unit.md)**: Unit testing, mocking patterns, controller testing, test helpers
|
|
194
|
+
- **[E2E Testing & CI/CD](references/testing-e2e-ci.md)**: Appium, WebdriverIO, GitHub Actions, Fastlane
|
|
205
195
|
- **[Error Handling & Logging](references/error-handling.md)**: AppError classes, Logger service, validation
|
|
206
196
|
|
|
207
197
|
### Performance & Security
|
|
208
|
-
- **[Performance
|
|
209
|
-
- **[
|
|
198
|
+
- **[ListView & ScrollView Performance](references/performance-listview.md)**: ListView templates, data binding, image caching, ScrollView optimization
|
|
199
|
+
- **[Performance Optimization](references/performance-optimization.md)**: Bridge crossings, memory management, animations, debounce/throttle, database
|
|
200
|
+
- **[Security Fundamentals](references/security-fundamentals.md)**: Token storage, certificate pinning, encryption, HTTPS, OWASP
|
|
201
|
+
- **[Device Security](references/security-device.md)**: Biometric auth, deep link validation, jailbreak/root detection
|
|
210
202
|
- **[State Management](references/state-management.md)**: Centralized store, reactive patterns, synchronization
|
|
211
203
|
|
|
212
204
|
### Migration
|
|
@@ -218,7 +210,6 @@ For specific feature implementations, defer to these specialized skills:
|
|
|
218
210
|
|
|
219
211
|
| Task | Use This Skill |
|
|
220
212
|
| ----------------------------------------------------- | -------------- |
|
|
221
|
-
| PurgeTSS setup, advanced styling, animations | `purgetss` |
|
|
222
213
|
| Location, Maps, Push Notifications, Media APIs | `ti-howtos` |
|
|
223
214
|
| UI layouts, ListViews, gestures, platform-specific UI | `ti-ui` |
|
|
224
215
|
| Alloy CLI, configuration files, debugging | `alloy-howtos` |
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
# Alloy Builtins & Globals
|
|
2
|
+
|
|
3
|
+
## Compiler Directives
|
|
4
|
+
|
|
5
|
+
Alloy provides compile-time constants that are replaced with `true`/`false` during build. Use them for platform-specific code without runtime cost.
|
|
6
|
+
|
|
7
|
+
### OS_IOS / OS_ANDROID
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
// These are compile-time constants — dead code is removed at build
|
|
11
|
+
if (OS_IOS) {
|
|
12
|
+
$.window.applyProperties({
|
|
13
|
+
largeTitleEnabled: true,
|
|
14
|
+
largeTitleDisplayMode: Ti.UI.iOS.LARGE_TITLE_DISPLAY_MODE_ALWAYS
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (OS_ANDROID) {
|
|
19
|
+
$.window.activity.onCreateOptionsMenu = (e) => {
|
|
20
|
+
const menu = e.menu
|
|
21
|
+
menu.add({ title: L('settings'), showAsAction: Ti.Android.SHOW_AS_ACTION_NEVER })
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
:::warning These are NOT runtime checks
|
|
27
|
+
`OS_IOS` and `OS_ANDROID` are replaced by the Alloy compiler with literal `true`/`false`. The opposite platform's code is completely removed from the build output. This is different from `Ti.Platform.osname === 'iphone'` which remains in the code.
|
|
28
|
+
|
|
29
|
+
**Use for:** Platform-specific APIs, platform-specific UI configuration
|
|
30
|
+
**Do NOT use for:** Logic that should be testable on both platforms
|
|
31
|
+
:::
|
|
32
|
+
|
|
33
|
+
### ENV_DEV / ENV_TEST / ENV_PRODUCTION
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
if (ENV_DEV) {
|
|
37
|
+
Ti.API.info('Debug mode: API URL = ' + Alloy.CFG.apiUrl)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (ENV_PRODUCTION) {
|
|
41
|
+
// Enable crash reporting
|
|
42
|
+
crashReporter.init()
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Set environment during build:
|
|
47
|
+
```bash
|
|
48
|
+
ti build -p ios -T simulator -D development
|
|
49
|
+
ti build -p ios -T dist-appstore -D production
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Alloy.Globals
|
|
55
|
+
|
|
56
|
+
Shared state and utilities accessible from any controller or lib file. Set in `alloy.js`, available everywhere.
|
|
57
|
+
|
|
58
|
+
### Common Patterns
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
// alloy.js
|
|
62
|
+
const Backbone = require('alloy/backbone')
|
|
63
|
+
|
|
64
|
+
// --- Theme / Design Tokens ---
|
|
65
|
+
Alloy.Globals.theme = {
|
|
66
|
+
primary: '#2563eb',
|
|
67
|
+
bg: '#ffffff',
|
|
68
|
+
text: '#111827'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// --- Device Info (cached once) ---
|
|
72
|
+
Alloy.Globals.isTablet = Alloy.isTablet
|
|
73
|
+
Alloy.Globals.screenWidth = Ti.Platform.displayCaps.platformWidth
|
|
74
|
+
Alloy.Globals.screenHeight = Ti.Platform.displayCaps.platformHeight
|
|
75
|
+
Alloy.Globals.density = Ti.Platform.displayCaps.dpi
|
|
76
|
+
|
|
77
|
+
// --- App State Flags ---
|
|
78
|
+
Alloy.Globals.isLoggedIn = false
|
|
79
|
+
Alloy.Globals.currentUserId = null
|
|
80
|
+
|
|
81
|
+
// --- Collections ---
|
|
82
|
+
Alloy.Collections.products = new Backbone.Collection()
|
|
83
|
+
Alloy.Collections.notifications = new Backbone.Collection()
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Access from Anywhere
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
// In any controller
|
|
90
|
+
const theme = Alloy.Globals.theme
|
|
91
|
+
$.label.color = theme.primary
|
|
92
|
+
|
|
93
|
+
// In TSS (evaluated at compile time for controller creation)
|
|
94
|
+
"#header": {
|
|
95
|
+
backgroundColor: Alloy.Globals.theme.primary
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// In XML with conditional binding
|
|
99
|
+
// <View if="Alloy.Globals.isLoggedIn">
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Globals vs Services
|
|
103
|
+
|
|
104
|
+
| Use `Alloy.Globals` for | Use a Service for |
|
|
105
|
+
| ---------------------------------- | ----------------------------- |
|
|
106
|
+
| Static config (theme, device info) | Business logic |
|
|
107
|
+
| Simple flags (isLoggedIn) | Complex state with listeners |
|
|
108
|
+
| Values set once in `alloy.js` | Values that change frequently |
|
|
109
|
+
| Read-only data | Data with side effects |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Alloy.CFG
|
|
114
|
+
|
|
115
|
+
Values from `app/config.json`, automatically resolved by environment and platform.
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// config.json
|
|
119
|
+
{
|
|
120
|
+
"global": { "appName": "MyApp" },
|
|
121
|
+
"env:development": { "apiUrl": "https://dev.api.com", "debug": true },
|
|
122
|
+
"env:production": { "apiUrl": "https://api.com", "debug": false },
|
|
123
|
+
"os:ios": { "statusBarStyle": "light" },
|
|
124
|
+
"os:android": { "exitOnBack": true }
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
// Access anywhere
|
|
130
|
+
const url = Alloy.CFG.apiUrl // Resolved by environment
|
|
131
|
+
const debug = Alloy.CFG.debug // true in dev, false in prod
|
|
132
|
+
const appName = Alloy.CFG.appName // From global
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
:::tip CFG is read-only
|
|
136
|
+
`Alloy.CFG` values are set at build time and cannot be modified at runtime. For runtime configuration, use `Alloy.Globals` or `Ti.App.Properties`.
|
|
137
|
+
:::
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Alloy.isTablet / Alloy.isHandheld
|
|
142
|
+
|
|
143
|
+
Detect device form factor at runtime.
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
if (Alloy.isTablet) {
|
|
147
|
+
// Show split-view layout
|
|
148
|
+
Navigation.open('tablet/splitView')
|
|
149
|
+
} else {
|
|
150
|
+
// Show phone layout
|
|
151
|
+
Navigation.open('phone/list')
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### In TSS
|
|
156
|
+
|
|
157
|
+
```tss
|
|
158
|
+
"#sidebar[formFactor=tablet]": {
|
|
159
|
+
width: 320,
|
|
160
|
+
visible: true
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
"#sidebar[formFactor=handheld]": {
|
|
164
|
+
width: 0,
|
|
165
|
+
visible: false
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### In XML
|
|
170
|
+
|
|
171
|
+
```xml
|
|
172
|
+
<Alloy>
|
|
173
|
+
<!-- Only rendered on tablet -->
|
|
174
|
+
<View formFactor="tablet" id="sidebar">
|
|
175
|
+
<Require src="sidebar/menu" />
|
|
176
|
+
</View>
|
|
177
|
+
|
|
178
|
+
<!-- Only rendered on phone -->
|
|
179
|
+
<View formFactor="handheld" id="content">
|
|
180
|
+
<Require src="phone/content" />
|
|
181
|
+
</View>
|
|
182
|
+
</Alloy>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## $.args — Controller Arguments
|
|
188
|
+
|
|
189
|
+
Every controller receives arguments via `$.args`. This is the standard way to pass data between controllers.
|
|
190
|
+
|
|
191
|
+
### Basic Usage
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
// Opening controller with args
|
|
195
|
+
const ctrl = Alloy.createController('user/profile', {
|
|
196
|
+
userId: 123,
|
|
197
|
+
mode: 'edit',
|
|
198
|
+
onSave: handleSave
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
// Receiving in target controller
|
|
202
|
+
// controllers/user/profile.js
|
|
203
|
+
const { userId, mode, onSave } = $.args
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Common Patterns
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
// Pattern 1: Default values with destructuring
|
|
210
|
+
const {
|
|
211
|
+
userId,
|
|
212
|
+
mode = 'view',
|
|
213
|
+
showHeader = true,
|
|
214
|
+
onComplete = () => {}
|
|
215
|
+
} = $.args
|
|
216
|
+
|
|
217
|
+
// Pattern 2: Validation
|
|
218
|
+
function init() {
|
|
219
|
+
if (!$.args.userId) {
|
|
220
|
+
Ti.API.error('user/profile requires userId')
|
|
221
|
+
$.getView().close()
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
loadUser($.args.userId)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Pattern 3: Passing callbacks for communication
|
|
229
|
+
// Parent controller
|
|
230
|
+
const editor = Alloy.createController('editor', {
|
|
231
|
+
item: selectedItem,
|
|
232
|
+
onSave: (updatedItem) => {
|
|
233
|
+
refreshList()
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
// Child controller (editor.js)
|
|
238
|
+
function save() {
|
|
239
|
+
const data = collectFormData()
|
|
240
|
+
$.args.onSave(data)
|
|
241
|
+
$.getView().close()
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### $.args in Widgets
|
|
246
|
+
|
|
247
|
+
Widgets also receive args, but through the `<Widget>` tag attributes:
|
|
248
|
+
|
|
249
|
+
```xml
|
|
250
|
+
<Widget id="header" src="appHeader" title="L('home')" showBack="false" />
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
// widgets/appHeader/controllers/widget.js
|
|
255
|
+
const title = $.args.title || ''
|
|
256
|
+
const showBack = $.args.showBack !== 'false' // XML passes strings
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
:::warning XML attributes are always strings
|
|
260
|
+
When passing values through XML attributes, they arrive as strings in `$.args`. Numbers and booleans need to be parsed:
|
|
261
|
+
```javascript
|
|
262
|
+
const count = parseInt($.args.count, 10) // "5" → 5
|
|
263
|
+
const visible = $.args.visible !== 'false' // "false" → false
|
|
264
|
+
```
|
|
265
|
+
For complex data, pass via `Alloy.createController()` in the parent controller instead.
|
|
266
|
+
:::
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Alloy.createController / Alloy.createWidget
|
|
271
|
+
|
|
272
|
+
### Controller Creation
|
|
273
|
+
|
|
274
|
+
```javascript
|
|
275
|
+
// Create and open
|
|
276
|
+
const ctrl = Alloy.createController('user/profile', { userId: 123 })
|
|
277
|
+
ctrl.getView().open()
|
|
278
|
+
|
|
279
|
+
// Create and embed
|
|
280
|
+
const card = Alloy.createController('components/userCard', { user: userData })
|
|
281
|
+
$.container.add(card.getView())
|
|
282
|
+
|
|
283
|
+
// Access controller methods
|
|
284
|
+
ctrl.refresh()
|
|
285
|
+
ctrl.setData(newData)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Widget Creation
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
// Create widget programmatically (alternative to XML <Widget>)
|
|
292
|
+
const loader = Alloy.createWidget('loadingOverlay')
|
|
293
|
+
$.window.add(loader.getView())
|
|
294
|
+
|
|
295
|
+
loader.show(L('loading'))
|
|
296
|
+
// ... later
|
|
297
|
+
loader.hide()
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Alloy.createModel / Alloy.createCollection
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
// Create a model instance
|
|
306
|
+
const user = Alloy.createModel('User', {
|
|
307
|
+
name: 'John',
|
|
308
|
+
email: 'john@example.com'
|
|
309
|
+
})
|
|
310
|
+
user.save()
|
|
311
|
+
|
|
312
|
+
// Create a collection (fetches from adapter)
|
|
313
|
+
const users = Alloy.createCollection('User')
|
|
314
|
+
users.fetch()
|
|
315
|
+
|
|
316
|
+
// Collection with query (SQL adapter)
|
|
317
|
+
users.fetch({
|
|
318
|
+
query: 'SELECT * FROM users WHERE active = 1 ORDER BY name'
|
|
319
|
+
})
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Conditional Code in XML
|
|
325
|
+
|
|
326
|
+
### Platform Conditional
|
|
327
|
+
|
|
328
|
+
```xml
|
|
329
|
+
<Alloy>
|
|
330
|
+
<Window>
|
|
331
|
+
<!-- iOS only -->
|
|
332
|
+
<NavigationWindow platform="ios" id="navWin">
|
|
333
|
+
<Require src="home" />
|
|
334
|
+
</NavigationWindow>
|
|
335
|
+
|
|
336
|
+
<!-- Android only -->
|
|
337
|
+
<Require platform="android" src="home" />
|
|
338
|
+
</Window>
|
|
339
|
+
</Alloy>
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Form Factor Conditional
|
|
343
|
+
|
|
344
|
+
```xml
|
|
345
|
+
<Alloy>
|
|
346
|
+
<View formFactor="tablet" id="splitView">
|
|
347
|
+
<!-- Tablet layout -->
|
|
348
|
+
</View>
|
|
349
|
+
<View formFactor="handheld" id="phoneView">
|
|
350
|
+
<!-- Phone layout -->
|
|
351
|
+
</View>
|
|
352
|
+
</Alloy>
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Custom Conditional (if attribute)
|
|
356
|
+
|
|
357
|
+
```xml
|
|
358
|
+
<!-- Only render if condition is true at creation time -->
|
|
359
|
+
<View if="Alloy.Globals.isLoggedIn" id="userMenu">
|
|
360
|
+
<Label text="L('welcome_back')" />
|
|
361
|
+
</View>
|
|
362
|
+
|
|
363
|
+
<View if="Alloy.Globals.featureFlags.newDashboard" id="newDashboard">
|
|
364
|
+
<Require src="dashboard/v2" />
|
|
365
|
+
</View>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
:::warning `if` is evaluated once at controller creation
|
|
369
|
+
The `if` attribute is checked when the controller is created. It does NOT react to later changes in the condition. For dynamic visibility, use the `visible` property in the controller.
|
|
370
|
+
:::
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Quick Reference
|
|
375
|
+
|
|
376
|
+
| Builtin | Type | Where Set | Mutable |
|
|
377
|
+
| ------------------- | ----------------- | ----------------- | ------- |
|
|
378
|
+
| `OS_IOS` | Compiler constant | Build time | No |
|
|
379
|
+
| `OS_ANDROID` | Compiler constant | Build time | No |
|
|
380
|
+
| `ENV_DEV` | Compiler constant | Build flag | No |
|
|
381
|
+
| `ENV_PRODUCTION` | Compiler constant | Build flag | No |
|
|
382
|
+
| `Alloy.CFG` | Object | `config.json` | No |
|
|
383
|
+
| `Alloy.Globals` | Object | `alloy.js` | Yes |
|
|
384
|
+
| `Alloy.isTablet` | Boolean | Runtime | No |
|
|
385
|
+
| `Alloy.isHandheld` | Boolean | Runtime | No |
|
|
386
|
+
| `Alloy.Collections` | Object | `alloy.js` | Yes |
|
|
387
|
+
| `$.args` | Object | Parent controller | No |
|