@maccesar/titools 2.0.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 +173 -0
- package/README.md +867 -0
- package/agents/ti-researcher.md +108 -0
- package/bin/titools.js +53 -0
- package/lib/commands/agents.js +126 -0
- package/lib/commands/install.js +188 -0
- package/lib/commands/uninstall.js +215 -0
- package/lib/commands/update.js +159 -0
- package/lib/config.js +119 -0
- package/lib/downloader.js +153 -0
- package/lib/installer.js +253 -0
- package/lib/platform.js +108 -0
- package/lib/symlink.js +142 -0
- package/lib/utils.js +270 -0
- package/package.json +67 -0
- package/skills/alloy-expert/SKILL.md +247 -0
- package/skills/alloy-expert/assets/ControllerAutoCleanup.js +182 -0
- package/skills/alloy-expert/references/alloy-structure.md +381 -0
- package/skills/alloy-expert/references/anti-patterns.md +133 -0
- package/skills/alloy-expert/references/code-conventions.md +469 -0
- package/skills/alloy-expert/references/contracts.md +280 -0
- package/skills/alloy-expert/references/controller-patterns.md +520 -0
- package/skills/alloy-expert/references/error-handling.md +484 -0
- package/skills/alloy-expert/references/examples.md +735 -0
- package/skills/alloy-expert/references/migration-patterns.md +298 -0
- package/skills/alloy-expert/references/patterns.md +448 -0
- package/skills/alloy-expert/references/performance-patterns.md +855 -0
- package/skills/alloy-expert/references/security-patterns.md +847 -0
- package/skills/alloy-expert/references/state-management.md +779 -0
- package/skills/alloy-expert/references/testing.md +872 -0
- package/skills/alloy-guides/SKILL.md +214 -0
- package/skills/alloy-guides/references/CLI_TASKS.md +243 -0
- package/skills/alloy-guides/references/CONCEPTS.md +191 -0
- package/skills/alloy-guides/references/CONTROLLERS.md +298 -0
- package/skills/alloy-guides/references/MODELS.md +1028 -0
- package/skills/alloy-guides/references/PURGETSS.md +56 -0
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +242 -0
- package/skills/alloy-guides/references/VIEWS_STYLES.md +388 -0
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +109 -0
- package/skills/alloy-guides/references/VIEWS_XML.md +558 -0
- package/skills/alloy-guides/references/WIDGETS.md +176 -0
- package/skills/alloy-howtos/SKILL.md +203 -0
- package/skills/alloy-howtos/references/best_practices.md +138 -0
- package/skills/alloy-howtos/references/cli_reference.md +253 -0
- package/skills/alloy-howtos/references/config_files.md +87 -0
- package/skills/alloy-howtos/references/custom_tags.md +147 -0
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +101 -0
- package/skills/alloy-howtos/references/samples.md +167 -0
- package/skills/purgetss/SKILL.md +442 -0
- package/skills/purgetss/assets/purgetss.config.cjs +17 -0
- package/skills/purgetss/references/EXAMPLES.md +247 -0
- package/skills/purgetss/references/animation-system.md +1294 -0
- package/skills/purgetss/references/apply-directive.md +375 -0
- package/skills/purgetss/references/arbitrary-values.md +612 -0
- package/skills/purgetss/references/class-index.md +1350 -0
- package/skills/purgetss/references/cli-commands.md +948 -0
- package/skills/purgetss/references/configurable-properties.md +654 -0
- package/skills/purgetss/references/custom-rules.md +161 -0
- package/skills/purgetss/references/customization-deep-dive.md +722 -0
- package/skills/purgetss/references/dynamic-component-creation.md +489 -0
- package/skills/purgetss/references/grid-layout.md +455 -0
- package/skills/purgetss/references/icon-fonts.md +609 -0
- package/skills/purgetss/references/installation-setup.md +366 -0
- package/skills/purgetss/references/opacity-modifier.md +291 -0
- package/skills/purgetss/references/platform-modifiers.md +479 -0
- package/skills/purgetss/references/smart-mappings.md +42 -0
- package/skills/purgetss/references/titanium-resets.md +359 -0
- package/skills/purgetss/references/ui-ux-design.md +1526 -0
- package/skills/ti-guides/SKILL.md +94 -0
- package/skills/ti-guides/references/advanced-data-and-images.md +19 -0
- package/skills/ti-guides/references/alloy-cli-advanced.md +84 -0
- package/skills/ti-guides/references/alloy-data-mastery.md +29 -0
- package/skills/ti-guides/references/alloy-widgets-and-themes.md +19 -0
- package/skills/ti-guides/references/android-manifest.md +97 -0
- package/skills/ti-guides/references/app-distribution.md +258 -0
- package/skills/ti-guides/references/application-frameworks.md +377 -0
- package/skills/ti-guides/references/cli-reference.md +402 -0
- package/skills/ti-guides/references/coding-best-practices.md +102 -0
- package/skills/ti-guides/references/commonjs-advanced.md +134 -0
- package/skills/ti-guides/references/hello-world.md +100 -0
- package/skills/ti-guides/references/hyperloop-native-access.md +62 -0
- package/skills/ti-guides/references/javascript-primer.md +411 -0
- package/skills/ti-guides/references/reserved-words.md +36 -0
- package/skills/ti-guides/references/resources.md +183 -0
- package/skills/ti-guides/references/style-and-conventions.md +48 -0
- package/skills/ti-guides/references/tiapp-config.md +609 -0
- package/skills/ti-howtos/SKILL.md +174 -0
- package/skills/ti-howtos/references/android-platform-deep-dives.md +658 -0
- package/skills/ti-howtos/references/automation-fastlane-appium.md +95 -0
- package/skills/ti-howtos/references/buffer-codec-streams.md +140 -0
- package/skills/ti-howtos/references/cross-platform-development.md +348 -0
- package/skills/ti-howtos/references/debugging-profiling.md +543 -0
- package/skills/ti-howtos/references/extending-titanium.md +723 -0
- package/skills/ti-howtos/references/google-maps-v2.md +169 -0
- package/skills/ti-howtos/references/ios-map-kit.md +143 -0
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +783 -0
- package/skills/ti-howtos/references/local-data-sources.md +301 -0
- package/skills/ti-howtos/references/location-and-maps.md +252 -0
- package/skills/ti-howtos/references/media-apis.md +210 -0
- package/skills/ti-howtos/references/notification-services.md +599 -0
- package/skills/ti-howtos/references/remote-data-sources.md +349 -0
- package/skills/ti-howtos/references/tutorials.md +502 -0
- package/skills/ti-howtos/references/using-modules.md +237 -0
- package/skills/ti-howtos/references/web-content-integration.md +307 -0
- package/skills/ti-howtos/references/webpack-build-pipeline.md +78 -0
- package/skills/ti-ui/SKILL.md +179 -0
- package/skills/ti-ui/references/accessibility-deep-dive.md +242 -0
- package/skills/ti-ui/references/animation-and-matrices.md +599 -0
- package/skills/ti-ui/references/application-structures.md +655 -0
- package/skills/ti-ui/references/custom-fonts-styling.md +579 -0
- package/skills/ti-ui/references/event-handling.md +393 -0
- package/skills/ti-ui/references/gestures.md +473 -0
- package/skills/ti-ui/references/icons-and-splash-screens.md +409 -0
- package/skills/ti-ui/references/layouts-and-positioning.md +462 -0
- package/skills/ti-ui/references/listviews-and-performance.md +619 -0
- package/skills/ti-ui/references/orientation.md +362 -0
- package/skills/ti-ui/references/platform-ui-android.md +635 -0
- package/skills/ti-ui/references/platform-ui-ios.md +469 -0
- package/skills/ti-ui/references/scrolling-views.md +252 -0
- package/skills/ti-ui/references/tableviews.md +568 -0
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
# Titanium SDK Tutorials
|
|
2
|
+
|
|
3
|
+
Practical tutorials and guides for building real-world Titanium applications.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Titanium SDK Tutorials](#titanium-sdk-tutorials)
|
|
8
|
+
- [Table of Contents](#table-of-contents)
|
|
9
|
+
- [RESTe - API Integration](#reste---api-integration)
|
|
10
|
+
- [Overview](#overview)
|
|
11
|
+
- [Installation](#installation)
|
|
12
|
+
- [Basic Configuration](#basic-configuration)
|
|
13
|
+
- [Usage](#usage)
|
|
14
|
+
- [Backbone.js Models/Collections](#backbonejs-modelscollections)
|
|
15
|
+
- [Important Notes](#important-notes)
|
|
16
|
+
- [Mock Data (On-The-Fly)](#mock-data-on-the-fly)
|
|
17
|
+
- [Resources](#resources)
|
|
18
|
+
- [Camera App Tutorial](#camera-app-tutorial)
|
|
19
|
+
- [Basic Camera Access](#basic-camera-access)
|
|
20
|
+
- [Photo Gallery](#photo-gallery)
|
|
21
|
+
- [Saving Images](#saving-images)
|
|
22
|
+
- [Geolocation Tutorial](#geolocation-tutorial)
|
|
23
|
+
- [Basic Location](#basic-location)
|
|
24
|
+
- [Continuous Tracking](#continuous-tracking)
|
|
25
|
+
- [Reverse Geocoding](#reverse-geocoding)
|
|
26
|
+
- [Alloy Controller Chaining](#alloy-controller-chaining)
|
|
27
|
+
- [Pattern Overview](#pattern-overview)
|
|
28
|
+
- [Basic Pattern](#basic-pattern)
|
|
29
|
+
- [Benefits](#benefits)
|
|
30
|
+
- [Build Automation with Fastlane](#build-automation-with-fastlane)
|
|
31
|
+
- [Overview](#overview-1)
|
|
32
|
+
- [Installing Fastlane](#installing-fastlane)
|
|
33
|
+
- [Basic Fastfile](#basic-fastfile)
|
|
34
|
+
- [Usage](#usage-1)
|
|
35
|
+
- [Advanced Options](#advanced-options)
|
|
36
|
+
- [Additional Tutorials](#additional-tutorials)
|
|
37
|
+
- [Alloy Boilerplates](#alloy-boilerplates)
|
|
38
|
+
- [Complete Sample Apps](#complete-sample-apps)
|
|
39
|
+
- [Resources](#resources-1)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## RESTe - API Integration
|
|
44
|
+
|
|
45
|
+
### Overview
|
|
46
|
+
|
|
47
|
+
**RESTe** by Jason Kneen - A module for consuming web APIs in Titanium.
|
|
48
|
+
|
|
49
|
+
**Benefits:**
|
|
50
|
+
- Eliminates boilerplate HTTP code
|
|
51
|
+
- Auto-generates JavaScript API from config
|
|
52
|
+
- Supports Backbone.js Models/Collections in Alloy
|
|
53
|
+
- Works with any API (not just REST)
|
|
54
|
+
|
|
55
|
+
### Installation
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install reste
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Basic Configuration
|
|
62
|
+
|
|
63
|
+
**alloy.js:**
|
|
64
|
+
```javascript
|
|
65
|
+
const reste = require("reste");
|
|
66
|
+
const api = new reste();
|
|
67
|
+
|
|
68
|
+
api.config({
|
|
69
|
+
debug: true, // Console logging
|
|
70
|
+
errorsAsObjects: true, // Return errors as objects (1.4.5+)
|
|
71
|
+
autoValidateParams: false, // Throw error if params missing
|
|
72
|
+
validatesSecureCertificate: false,
|
|
73
|
+
timeout: 4000,
|
|
74
|
+
url: "https://api.example.com/", // Base URL
|
|
75
|
+
requestHeaders: {
|
|
76
|
+
"X-API-Key": "your-key-here",
|
|
77
|
+
"Content-Type": "application/json"
|
|
78
|
+
},
|
|
79
|
+
methods: [
|
|
80
|
+
{
|
|
81
|
+
name: "getVideos",
|
|
82
|
+
get: "videos"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "getVideoById",
|
|
86
|
+
get: "videos/"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "createVideo",
|
|
90
|
+
post: "videos"
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
onError: (e, retry) => {
|
|
94
|
+
const dialog = Ti.UI.createAlertDialog({
|
|
95
|
+
title: "Connection error",
|
|
96
|
+
message: "Check your network and retry.",
|
|
97
|
+
buttonNames: ['Retry']
|
|
98
|
+
});
|
|
99
|
+
dialog.addEventListener("click", () => {
|
|
100
|
+
retry();
|
|
101
|
+
});
|
|
102
|
+
dialog.show();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Usage
|
|
108
|
+
|
|
109
|
+
**Auto-generated methods:**
|
|
110
|
+
```javascript
|
|
111
|
+
// Fetch single video
|
|
112
|
+
api.getVideoById({
|
|
113
|
+
videoId: "abc123"
|
|
114
|
+
}, (video) => {
|
|
115
|
+
Ti.API.info(`Got video: ${video.title}`);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Create video
|
|
119
|
+
api.createVideo({
|
|
120
|
+
body: {
|
|
121
|
+
title: "My Video",
|
|
122
|
+
categoryId: 2
|
|
123
|
+
}
|
|
124
|
+
}, (response) => {
|
|
125
|
+
Ti.API.info(`Created: ${response.id}`);
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Backbone.js Models/Collections
|
|
130
|
+
|
|
131
|
+
**Configuration:**
|
|
132
|
+
```javascript
|
|
133
|
+
api.config({
|
|
134
|
+
// ... other config
|
|
135
|
+
models: [{
|
|
136
|
+
name: "video",
|
|
137
|
+
id: "objectId", // Primary key field
|
|
138
|
+
read: "getVideo",
|
|
139
|
+
create: "createVideo",
|
|
140
|
+
update: "updateVideo",
|
|
141
|
+
delete: "deleteVideo",
|
|
142
|
+
collections: [{
|
|
143
|
+
name: "videos",
|
|
144
|
+
content: "results", // Array wrapper in response
|
|
145
|
+
read: "getVideos"
|
|
146
|
+
}]
|
|
147
|
+
}]
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**In Alloy Controller:**
|
|
152
|
+
```javascript
|
|
153
|
+
// Fetch collection
|
|
154
|
+
Alloy.Collections.videos.fetch();
|
|
155
|
+
|
|
156
|
+
// Or fetch with parameters
|
|
157
|
+
Alloy.Collections.videos.fetch({
|
|
158
|
+
data: {category: "sports"}
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**In Alloy View:**
|
|
163
|
+
```xml
|
|
164
|
+
<TableView dataCollection="videos" onClick="selectVideo">
|
|
165
|
+
<TableViewRow model="{objectId}">
|
|
166
|
+
<Label class="title" text="{title}"/>
|
|
167
|
+
<Label class="subtitle" text="{description}"/>
|
|
168
|
+
</TableViewRow>
|
|
169
|
+
</TableView>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Important Notes
|
|
173
|
+
|
|
174
|
+
- **Don't use `<Model>` or `<Collection>` tags** with RESTe
|
|
175
|
+
- RESTe creates models/collections automatically
|
|
176
|
+
- Use data-binding like normal Alloy collections
|
|
177
|
+
- Great for mocking data during UI development
|
|
178
|
+
|
|
179
|
+
### Mock Data (On-The-Fly)
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
// Create model without API
|
|
183
|
+
const videoModel = api.createModel('video', {
|
|
184
|
+
title: 'Test Video',
|
|
185
|
+
description: 'Mock data'
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Create collection
|
|
189
|
+
const videoCollection = api.createCollection('videos', [
|
|
190
|
+
{title: 'Video 1'},
|
|
191
|
+
{title: 'Video 2'}
|
|
192
|
+
]);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Resources
|
|
196
|
+
|
|
197
|
+
- **npm:** https://www.npmjs.com/package/reste
|
|
198
|
+
- **GitHub:** https://github.com/jasonkneen/reste
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Camera App Tutorial
|
|
203
|
+
|
|
204
|
+
### Basic Camera Access
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
// Show camera
|
|
208
|
+
Ti.Media.showCamera({
|
|
209
|
+
success: (event) => {
|
|
210
|
+
const image = event.media;
|
|
211
|
+
if (event.mediaType === Ti.Media.MEDIA_TYPE_PHOTO) {
|
|
212
|
+
// Use the photo
|
|
213
|
+
const imageView = Ti.UI.createImageView({
|
|
214
|
+
image: image,
|
|
215
|
+
width: 300,
|
|
216
|
+
height: 300
|
|
217
|
+
});
|
|
218
|
+
win.add(imageView);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
cancel: () => {
|
|
222
|
+
Ti.API.info('Camera canceled');
|
|
223
|
+
},
|
|
224
|
+
error: (error) => {
|
|
225
|
+
const a = Ti.UI.createAlertDialog({title: 'Camera Error'});
|
|
226
|
+
if (error.code === Ti.Media.NO_CAMERA) {
|
|
227
|
+
a.setMessage('Device does not have camera');
|
|
228
|
+
} else {
|
|
229
|
+
a.setMessage(`Unexpected error: ${error.code}`);
|
|
230
|
+
}
|
|
231
|
+
a.show();
|
|
232
|
+
},
|
|
233
|
+
saveToPhotoGallery: true,
|
|
234
|
+
allowEditing: true,
|
|
235
|
+
mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO],
|
|
236
|
+
videoQuality: Ti.Media.QUALITY_HIGH
|
|
237
|
+
});
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Photo Gallery
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
// Open photo gallery
|
|
244
|
+
Ti.Media.openPhotoGallery({
|
|
245
|
+
success: (event) => {
|
|
246
|
+
const image = event.media;
|
|
247
|
+
// Process selected image
|
|
248
|
+
},
|
|
249
|
+
cancel: () => {
|
|
250
|
+
// User canceled
|
|
251
|
+
},
|
|
252
|
+
error: (error) => {
|
|
253
|
+
// Handle error
|
|
254
|
+
},
|
|
255
|
+
mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO]
|
|
256
|
+
});
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Saving Images
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
// Save to gallery
|
|
263
|
+
Ti.Media.saveToPhotoGallery({
|
|
264
|
+
media: myImageBlob,
|
|
265
|
+
success: () => {
|
|
266
|
+
alert('Saved!');
|
|
267
|
+
},
|
|
268
|
+
error: (e) => {
|
|
269
|
+
alert(`Error: ${e.error}`);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Geolocation Tutorial
|
|
277
|
+
|
|
278
|
+
### Basic Location
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
// One-time location
|
|
282
|
+
if (Ti.Geolocation.locationServicesEnabled) {
|
|
283
|
+
Ti.Geolocation.getCurrentPosition((e) => {
|
|
284
|
+
if (!e.error) {
|
|
285
|
+
Ti.API.info(`Lat: ${e.coords.latitude}`);
|
|
286
|
+
Ti.API.info(`Lon: ${e.coords.longitude}`);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Continuous Tracking
|
|
293
|
+
|
|
294
|
+
```javascript
|
|
295
|
+
// Configure accuracy
|
|
296
|
+
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST;
|
|
297
|
+
Ti.Geolocation.distanceFilter = 10; // Meters
|
|
298
|
+
|
|
299
|
+
// Track location changes
|
|
300
|
+
Ti.Geolocation.addEventListener('location', (e) => {
|
|
301
|
+
if (!e.error) {
|
|
302
|
+
const lat = e.coords.latitude;
|
|
303
|
+
const lon = e.coords.longitude;
|
|
304
|
+
updateMap(lat, lon);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Reverse Geocoding
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
// Coordinates to address
|
|
313
|
+
Ti.Geolocation.reverseGeocoder(37.389569, -122.050212, (e) => {
|
|
314
|
+
if (e.success) {
|
|
315
|
+
e.places.forEach((place) => {
|
|
316
|
+
Ti.API.info(place.address);
|
|
317
|
+
Ti.API.info(place.city);
|
|
318
|
+
Ti.API.info(place.country);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Alloy Controller Chaining
|
|
327
|
+
|
|
328
|
+
### Pattern Overview
|
|
329
|
+
|
|
330
|
+
Chain controller methods to pass data between Alloy controllers in a clean, maintainable way.
|
|
331
|
+
|
|
332
|
+
### Basic Pattern
|
|
333
|
+
|
|
334
|
+
**Parent Controller:**
|
|
335
|
+
```javascript
|
|
336
|
+
const childController = Alloy.createController('child', {
|
|
337
|
+
data: someData,
|
|
338
|
+
onAction: (result) => {
|
|
339
|
+
// Handle result from child
|
|
340
|
+
Ti.API.info(`Child returned: ${result}`);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
childController.on('customEvent', (data) => {
|
|
345
|
+
// Handle child events
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
childController.open();
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Child Controller:**
|
|
352
|
+
```javascript
|
|
353
|
+
const args = arguments[0] || {};
|
|
354
|
+
|
|
355
|
+
// Access parent data
|
|
356
|
+
const parentData = args.data;
|
|
357
|
+
|
|
358
|
+
// Call parent callback
|
|
359
|
+
function notifyParent(result) {
|
|
360
|
+
if (args.onAction) {
|
|
361
|
+
args.onAction(result);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Trigger parent events
|
|
366
|
+
function triggerEvent(data) {
|
|
367
|
+
$.trigger('customEvent', data);
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Benefits
|
|
372
|
+
|
|
373
|
+
- **Clean separation** - Controllers remain independent
|
|
374
|
+
- **Reusable** - Child works in different contexts
|
|
375
|
+
- **Testable** - Can mock parent callbacks
|
|
376
|
+
- **Maintainable** - Clear data flow
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Build Automation with Fastlane
|
|
381
|
+
|
|
382
|
+
### Overview
|
|
383
|
+
|
|
384
|
+
Automate building and deploying Titanium apps with Fastlane.
|
|
385
|
+
|
|
386
|
+
### Installing Fastlane
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
# Using Homebrew (macOS)
|
|
390
|
+
brew install fastlane
|
|
391
|
+
|
|
392
|
+
# Or using Ruby gems
|
|
393
|
+
sudo gem install fastlane -NV
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Basic Fastfile
|
|
397
|
+
|
|
398
|
+
**fastlane/Fastfile:**
|
|
399
|
+
```ruby
|
|
400
|
+
platform :ios do
|
|
401
|
+
desc "Build and deploy to TestFlight"
|
|
402
|
+
lane :beta do
|
|
403
|
+
# Build the app
|
|
404
|
+
sh "ti build -p ios -F"
|
|
405
|
+
|
|
406
|
+
# Upload to TestFlight
|
|
407
|
+
upload_to_testflight(
|
|
408
|
+
skip_waiting_for_build_processing: true
|
|
409
|
+
)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
desc "Build for development"
|
|
413
|
+
lane :dev do
|
|
414
|
+
sh "ti build -p ios -T developer"
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
platform :android do
|
|
419
|
+
desc "Build Android APK"
|
|
420
|
+
lane :build do
|
|
421
|
+
sh "ti build -p android -A"
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
desc "Deploy to Play Store (Beta)"
|
|
425
|
+
lane :beta do
|
|
426
|
+
# Build
|
|
427
|
+
sh "ti build -p android -F"
|
|
428
|
+
|
|
429
|
+
# Upload to Play Store
|
|
430
|
+
upload_to_play_store(
|
|
431
|
+
track: 'beta',
|
|
432
|
+
apk: 'app/build/android/bin/app.apk'
|
|
433
|
+
)
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### Usage
|
|
439
|
+
|
|
440
|
+
```bash
|
|
441
|
+
# iOS Beta
|
|
442
|
+
fastlane ios beta
|
|
443
|
+
|
|
444
|
+
# Android Build
|
|
445
|
+
fastlane android build
|
|
446
|
+
|
|
447
|
+
# Android Beta
|
|
448
|
+
fastlane android beta
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Advanced Options
|
|
452
|
+
|
|
453
|
+
**Multiple environments:**
|
|
454
|
+
```ruby
|
|
455
|
+
lane :staging do
|
|
456
|
+
sh "ti build -p ios -T dist --config ../staging.js"
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
lane :production do
|
|
460
|
+
sh "ti build -p ios -T dist --config ../production.js"
|
|
461
|
+
end
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Environment-specific configs:**
|
|
465
|
+
```javascript
|
|
466
|
+
// staging.js
|
|
467
|
+
module.exports = {
|
|
468
|
+
apiURL: 'https://staging-api.example.com',
|
|
469
|
+
analyticsEnabled: true
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// production.js
|
|
473
|
+
module.exports = {
|
|
474
|
+
apiURL: 'https://api.example.com',
|
|
475
|
+
analyticsEnabled: true
|
|
476
|
+
};
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## Additional Tutorials
|
|
482
|
+
|
|
483
|
+
### Alloy Boilerplates
|
|
484
|
+
|
|
485
|
+
See **Titanium_Boilerplates** folder for:
|
|
486
|
+
- TypeScript boilerplates
|
|
487
|
+
- App templates
|
|
488
|
+
- Project scaffolding
|
|
489
|
+
|
|
490
|
+
### Complete Sample Apps
|
|
491
|
+
|
|
492
|
+
- **ToDoList** - CommonJS module pattern example
|
|
493
|
+
- **Tweetanium** - Namespaced pattern example
|
|
494
|
+
- **KitchenSink** - Complete API reference (built with Alloy)
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
## Resources
|
|
499
|
+
|
|
500
|
+
- **RESTe:** https://github.com/jasonkneen/reste
|
|
501
|
+
- **Fastlane:** https://fastlane.tools
|
|
502
|
+
- **Alloy Framework:** See alloy-guides skill
|