@maccesar/titools 2.10.1 → 3.1.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-VERCEL-RESEARCH.md +23 -12
- package/README.md +81 -182
- package/agents/ti-pro.md +8 -14
- package/lib/cleanup.js +13 -0
- package/lib/commands/skills.js +2 -1
- package/lib/config.js +9 -11
- package/lib/platform.js +1 -1
- package/package.json +2 -3
- package/skills/alloy-guides/SKILL.md +0 -190
- package/skills/alloy-guides/references/CLI_TASKS.md +0 -233
- package/skills/alloy-guides/references/CONCEPTS.md +0 -171
- package/skills/alloy-guides/references/CONTROLLERS.md +0 -279
- package/skills/alloy-guides/references/MODELS.md +0 -1214
- package/skills/alloy-guides/references/PURGETSS.md +0 -46
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +0 -235
- package/skills/alloy-guides/references/VIEWS_STYLES.md +0 -375
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +0 -102
- package/skills/alloy-guides/references/VIEWS_XML.md +0 -581
- package/skills/alloy-guides/references/WIDGETS.md +0 -160
- package/skills/alloy-howtos/SKILL.md +0 -181
- package/skills/alloy-howtos/references/best_practices.md +0 -121
- package/skills/alloy-howtos/references/cli_reference.md +0 -230
- package/skills/alloy-howtos/references/config_files.md +0 -158
- package/skills/alloy-howtos/references/custom_tags.md +0 -148
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +0 -78
- package/skills/alloy-howtos/references/samples.md +0 -156
- package/skills/ti-api/SKILL.md +0 -109
- package/skills/ti-api/references/api-android.md +0 -675
- package/skills/ti-api/references/api-app-platform.md +0 -636
- package/skills/ti-api/references/api-core.md +0 -764
- package/skills/ti-api/references/api-data-network.md +0 -641
- package/skills/ti-api/references/api-media.md +0 -655
- package/skills/ti-api/references/api-modules-ble-bluetooth.md +0 -657
- package/skills/ti-api/references/api-modules-coremotion-urlsession.md +0 -411
- package/skills/ti-api/references/api-modules-map.md +0 -632
- package/skills/ti-api/references/api-modules-nfc.md +0 -725
- package/skills/ti-api/references/api-modules-social-misc.md +0 -526
- package/skills/ti-api/references/api-services.md +0 -700
- package/skills/ti-api/references/api-ui-android.md +0 -499
- package/skills/ti-api/references/api-ui-extras.md +0 -702
- package/skills/ti-api/references/api-ui-ios-animator.md +0 -378
- package/skills/ti-api/references/api-ui-ios.md +0 -756
- package/skills/ti-api/references/api-ui-lists.md +0 -581
- package/skills/ti-api/references/api-ui-text-input.md +0 -607
- package/skills/ti-api/references/api-ui-views.md +0 -572
- package/skills/ti-api/references/api-ui-windows-navigation.md +0 -676
- package/skills/ti-api/references/api-xml-global.md +0 -743
- package/skills/ti-guides/SKILL.md +0 -75
- package/skills/ti-guides/references/advanced-data-and-images.md +0 -155
- package/skills/ti-guides/references/android-manifest.md +0 -97
- package/skills/ti-guides/references/app-distribution.md +0 -373
- package/skills/ti-guides/references/application-frameworks.md +0 -366
- package/skills/ti-guides/references/cli-reference.md +0 -700
- package/skills/ti-guides/references/coding-best-practices.md +0 -150
- package/skills/ti-guides/references/commonjs-advanced.md +0 -279
- package/skills/ti-guides/references/hello-world.md +0 -99
- package/skills/ti-guides/references/hyperloop-native-access.md +0 -458
- package/skills/ti-guides/references/javascript-primer.md +0 -402
- package/skills/ti-guides/references/reserved-words.md +0 -36
- package/skills/ti-guides/references/resources.md +0 -172
- package/skills/ti-guides/references/style-and-conventions.md +0 -104
- package/skills/ti-guides/references/tiapp-config.md +0 -655
- package/skills/ti-howtos/SKILL.md +0 -143
- package/skills/ti-howtos/references/android-platform-deep-dives.md +0 -609
- package/skills/ti-howtos/references/automation-fastlane-appium.md +0 -96
- package/skills/ti-howtos/references/buffer-codec-streams.md +0 -162
- package/skills/ti-howtos/references/cross-platform-development.md +0 -358
- package/skills/ti-howtos/references/debugging-profiling.md +0 -473
- package/skills/ti-howtos/references/extending-titanium.md +0 -684
- package/skills/ti-howtos/references/google-maps-v2.md +0 -172
- package/skills/ti-howtos/references/ios-map-kit.md +0 -149
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +0 -595
- package/skills/ti-howtos/references/local-data-sources.md +0 -310
- package/skills/ti-howtos/references/location-and-maps.md +0 -267
- package/skills/ti-howtos/references/media-apis.md +0 -268
- package/skills/ti-howtos/references/notification-services.md +0 -539
- package/skills/ti-howtos/references/remote-data-sources.md +0 -339
- package/skills/ti-howtos/references/tutorials.md +0 -552
- package/skills/ti-howtos/references/using-modules.md +0 -182
- package/skills/ti-howtos/references/web-content-integration.md +0 -288
- package/skills/ti-howtos/references/webpack-build-pipeline.md +0 -125
|
@@ -1,552 +0,0 @@
|
|
|
1
|
-
# Titanium SDK tutorials
|
|
2
|
-
|
|
3
|
-
Practical tutorials and guides for building real Titanium applications.
|
|
4
|
-
|
|
5
|
-
## RESTe - API integration
|
|
6
|
-
|
|
7
|
-
### Overview
|
|
8
|
-
RESTe by Jason Kneen is a module for consuming web APIs in Titanium.
|
|
9
|
-
|
|
10
|
-
Benefits:
|
|
11
|
-
- Eliminates boilerplate HTTP code
|
|
12
|
-
- Auto-generates JavaScript API from config
|
|
13
|
-
- Supports Backbone.js models and collections in Alloy
|
|
14
|
-
- Works with any API (not just REST)
|
|
15
|
-
|
|
16
|
-
### Installation
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm install reste
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Basic configuration
|
|
23
|
-
|
|
24
|
-
`alloy.js`:
|
|
25
|
-
|
|
26
|
-
```javascript
|
|
27
|
-
const reste = require('reste');
|
|
28
|
-
const api = new reste();
|
|
29
|
-
|
|
30
|
-
api.config({
|
|
31
|
-
debug: true, // Console logging
|
|
32
|
-
errorsAsObjects: true, // Return errors as objects (1.4.5+) - breaks apps written for 1.4.4 that handle errors differently
|
|
33
|
-
autoValidateParams: false, // Throw error if params missing
|
|
34
|
-
validatesSecureCertificate: false,
|
|
35
|
-
timeout: 4000,
|
|
36
|
-
url: 'https://api.example.com/', // Base URL
|
|
37
|
-
requestHeaders: {
|
|
38
|
-
'X-API-Key': 'your-key-here',
|
|
39
|
-
'Content-Type': 'application/json'
|
|
40
|
-
},
|
|
41
|
-
methods: [
|
|
42
|
-
{
|
|
43
|
-
name: 'getVideos',
|
|
44
|
-
get: 'videos'
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: 'getVideoById',
|
|
48
|
-
get: 'videos/'
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: 'createVideo',
|
|
52
|
-
post: 'videos'
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
onError: (e, retry) => {
|
|
56
|
-
const dialog = Ti.UI.createAlertDialog({
|
|
57
|
-
title: 'Connection error',
|
|
58
|
-
message: 'Check your network and retry.',
|
|
59
|
-
buttonNames: ['Retry']
|
|
60
|
-
});
|
|
61
|
-
dialog.addEventListener('click', () => {
|
|
62
|
-
retry();
|
|
63
|
-
});
|
|
64
|
-
dialog.show();
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Usage
|
|
70
|
-
|
|
71
|
-
Auto-generated methods:
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
// Fetch single video
|
|
75
|
-
api.getVideoById({
|
|
76
|
-
videoId: 'abc123'
|
|
77
|
-
}, (video) => {
|
|
78
|
-
Ti.API.info(`Got video: ${video.title}`);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// Create video
|
|
82
|
-
api.createVideo({
|
|
83
|
-
body: {
|
|
84
|
-
title: 'My Video',
|
|
85
|
-
categoryId: 2
|
|
86
|
-
}
|
|
87
|
-
}, (response) => {
|
|
88
|
-
Ti.API.info(`Created: ${response.id}`);
|
|
89
|
-
});
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Backbone.js models and collections
|
|
93
|
-
|
|
94
|
-
Configuration:
|
|
95
|
-
|
|
96
|
-
```javascript
|
|
97
|
-
api.config({
|
|
98
|
-
// ... other config
|
|
99
|
-
models: [{
|
|
100
|
-
name: 'video',
|
|
101
|
-
id: 'objectId', // Primary key field
|
|
102
|
-
read: 'getVideo',
|
|
103
|
-
create: 'createVideo',
|
|
104
|
-
update: 'updateVideo',
|
|
105
|
-
delete: 'deleteVideo',
|
|
106
|
-
collections: [{
|
|
107
|
-
name: 'videos',
|
|
108
|
-
content: 'results', // Array wrapper in response
|
|
109
|
-
read: 'getVideos'
|
|
110
|
-
}]
|
|
111
|
-
}]
|
|
112
|
-
});
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
In an Alloy controller:
|
|
116
|
-
|
|
117
|
-
```javascript
|
|
118
|
-
// Fetch collection
|
|
119
|
-
Alloy.Collections.videos.fetch();
|
|
120
|
-
|
|
121
|
-
// Or fetch with parameters
|
|
122
|
-
Alloy.Collections.videos.fetch({
|
|
123
|
-
data: { category: 'sports' }
|
|
124
|
-
});
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
In an Alloy view:
|
|
128
|
-
|
|
129
|
-
```xml
|
|
130
|
-
<TableView dataCollection="videos" onClick="selectVideo">
|
|
131
|
-
<TableViewRow model="{objectId}">
|
|
132
|
-
<Label class="title" text="{title}"/>
|
|
133
|
-
<Label class="subtitle" text="{description}"/>
|
|
134
|
-
</TableViewRow>
|
|
135
|
-
</TableView>
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### RESTe advanced features
|
|
139
|
-
|
|
140
|
-
- Caching: built-in response caching
|
|
141
|
-
- Promises: use with `q.js` for Promise-based API calls
|
|
142
|
-
- Mock data: create models and collections on the fly for testing
|
|
143
|
-
|
|
144
|
-
```javascript
|
|
145
|
-
const mockUser = api.createModel('users', {
|
|
146
|
-
id: 1,
|
|
147
|
-
name: 'Test User'
|
|
148
|
-
});
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
- Backbone.js binding: use RESTe models directly with Alloy data binding without `<Model>` tags
|
|
152
|
-
|
|
153
|
-
### Important notes
|
|
154
|
-
|
|
155
|
-
- Do not use `<Model>` or `<Collection>` tags with RESTe
|
|
156
|
-
- RESTe creates models and collections automatically
|
|
157
|
-
- Use data binding like normal Alloy collections
|
|
158
|
-
- Useful for mocking data during UI development
|
|
159
|
-
|
|
160
|
-
### Mock data (on the fly)
|
|
161
|
-
|
|
162
|
-
```javascript
|
|
163
|
-
// Create model without API
|
|
164
|
-
const videoModel = api.createModel('video', {
|
|
165
|
-
title: 'Test Video',
|
|
166
|
-
description: 'Mock data'
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Create collection
|
|
170
|
-
const videoCollection = api.createCollection('videos', [
|
|
171
|
-
{ title: 'Video 1' },
|
|
172
|
-
{ title: 'Video 2' }
|
|
173
|
-
]);
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### Resources
|
|
177
|
-
|
|
178
|
-
- npm: https://www.npmjs.com/package/reste
|
|
179
|
-
- GitHub: https://github.com/jasonkneen/reste
|
|
180
|
-
|
|
181
|
-
---
|
|
182
|
-
|
|
183
|
-
## Camera app tutorial
|
|
184
|
-
|
|
185
|
-
### Camera permissions setup
|
|
186
|
-
|
|
187
|
-
iOS - add to `tiapp.xml` plist:
|
|
188
|
-
|
|
189
|
-
```xml
|
|
190
|
-
<key>NSCameraUsageDescription</key>
|
|
191
|
-
<string>This app needs camera access to take photos</string>
|
|
192
|
-
<key>NSMicrophoneUsageDescription</key>
|
|
193
|
-
<string>This app needs microphone access for video recording</string>
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
Android: camera permissions are automatically added by the build system when you use `Ti.Media.showCamera()`.
|
|
197
|
-
|
|
198
|
-
Always check permissions at runtime:
|
|
199
|
-
|
|
200
|
-
```javascript
|
|
201
|
-
if (!Ti.Media.hasCameraPermissions()) {
|
|
202
|
-
Ti.Media.requestCameraPermissions((e) => {
|
|
203
|
-
if (e.success) openCamera();
|
|
204
|
-
});
|
|
205
|
-
} else {
|
|
206
|
-
openCamera();
|
|
207
|
-
}
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
### Basic camera access
|
|
211
|
-
|
|
212
|
-
```javascript
|
|
213
|
-
// Show camera
|
|
214
|
-
Ti.Media.showCamera({
|
|
215
|
-
success: (event) => {
|
|
216
|
-
const image = event.media;
|
|
217
|
-
if (event.mediaType === Ti.Media.MEDIA_TYPE_PHOTO) {
|
|
218
|
-
// Use the photo
|
|
219
|
-
const imageView = Ti.UI.createImageView({
|
|
220
|
-
image: image,
|
|
221
|
-
width: 300,
|
|
222
|
-
height: 300
|
|
223
|
-
});
|
|
224
|
-
win.add(imageView);
|
|
225
|
-
}
|
|
226
|
-
},
|
|
227
|
-
cancel: () => {
|
|
228
|
-
Ti.API.info('Camera canceled');
|
|
229
|
-
},
|
|
230
|
-
error: (error) => {
|
|
231
|
-
const a = Ti.UI.createAlertDialog({ title: 'Camera Error' });
|
|
232
|
-
if (error.code === Ti.Media.NO_CAMERA) {
|
|
233
|
-
a.setMessage('Device does not have camera');
|
|
234
|
-
} else {
|
|
235
|
-
a.setMessage(`Unexpected error: ${error.code}`);
|
|
236
|
-
}
|
|
237
|
-
a.show();
|
|
238
|
-
},
|
|
239
|
-
saveToPhotoGallery: true,
|
|
240
|
-
allowEditing: true,
|
|
241
|
-
mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO],
|
|
242
|
-
videoQuality: Ti.Media.QUALITY_HIGH
|
|
243
|
-
});
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Photo gallery
|
|
247
|
-
|
|
248
|
-
```javascript
|
|
249
|
-
// Open photo gallery
|
|
250
|
-
Ti.Media.openPhotoGallery({
|
|
251
|
-
success: (event) => {
|
|
252
|
-
const image = event.media;
|
|
253
|
-
// Process selected image
|
|
254
|
-
},
|
|
255
|
-
cancel: () => {
|
|
256
|
-
// User canceled
|
|
257
|
-
},
|
|
258
|
-
error: (error) => {
|
|
259
|
-
// Handle error
|
|
260
|
-
},
|
|
261
|
-
mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO]
|
|
262
|
-
});
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### Saving images
|
|
266
|
-
|
|
267
|
-
```javascript
|
|
268
|
-
// Save to gallery
|
|
269
|
-
Ti.Media.saveToPhotoGallery({
|
|
270
|
-
media: myImageBlob,
|
|
271
|
-
success: () => {
|
|
272
|
-
alert('Saved!');
|
|
273
|
-
},
|
|
274
|
-
error: (e) => {
|
|
275
|
-
alert(`Error: ${e.error}`);
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
## Geolocation tutorial
|
|
283
|
-
|
|
284
|
-
### Geolocation permissions setup
|
|
285
|
-
|
|
286
|
-
iOS - add to `tiapp.xml` plist:
|
|
287
|
-
|
|
288
|
-
```xml
|
|
289
|
-
<key>NSLocationWhenInUseUsageDescription</key>
|
|
290
|
-
<string>We need your location to show nearby places</string>
|
|
291
|
-
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
|
292
|
-
<string>We need your location for background tracking</string>
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
Android - add to `tiapp.xml` manifest:
|
|
296
|
-
|
|
297
|
-
```xml
|
|
298
|
-
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
|
299
|
-
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
Runtime permission check:
|
|
303
|
-
```javascript
|
|
304
|
-
if (!Ti.Geolocation.hasLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE)) {
|
|
305
|
-
Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE, (e) => {
|
|
306
|
-
if (e.success) startTracking();
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
### Basic location
|
|
312
|
-
|
|
313
|
-
```javascript
|
|
314
|
-
// One-time location
|
|
315
|
-
if (Ti.Geolocation.locationServicesEnabled) {
|
|
316
|
-
Ti.Geolocation.getCurrentPosition((e) => {
|
|
317
|
-
if (!e.error) {
|
|
318
|
-
Ti.API.info(`Lat: ${e.coords.latitude}`);
|
|
319
|
-
Ti.API.info(`Lon: ${e.coords.longitude}`);
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
### Continuous tracking
|
|
326
|
-
|
|
327
|
-
```javascript
|
|
328
|
-
// Configure accuracy
|
|
329
|
-
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST;
|
|
330
|
-
Ti.Geolocation.distanceFilter = 10; // Meters
|
|
331
|
-
|
|
332
|
-
// Track location changes
|
|
333
|
-
Ti.Geolocation.addEventListener('location', (e) => {
|
|
334
|
-
if (!e.error) {
|
|
335
|
-
const lat = e.coords.latitude;
|
|
336
|
-
const lon = e.coords.longitude;
|
|
337
|
-
updateMap(lat, lon);
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
### Reverse geocoding
|
|
343
|
-
|
|
344
|
-
```javascript
|
|
345
|
-
// Coordinates to address
|
|
346
|
-
Ti.Geolocation.reverseGeocoder(37.389569, -122.050212, (e) => {
|
|
347
|
-
if (e.success) {
|
|
348
|
-
e.places.forEach((place) => {
|
|
349
|
-
Ti.API.info(place.address);
|
|
350
|
-
Ti.API.info(place.city);
|
|
351
|
-
Ti.API.info(place.country);
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
### Accuracy tuning
|
|
358
|
-
|
|
359
|
-
```javascript
|
|
360
|
-
// iOS: minimum distance before firing event
|
|
361
|
-
Ti.Geolocation.distanceFilter = 10; // meters
|
|
362
|
-
|
|
363
|
-
// Android: use FusedLocationProvider for better battery (requires ti.playservices module)
|
|
364
|
-
// Automatically enabled with SDK 7.1.0+ when ti.playservices is present
|
|
365
|
-
|
|
366
|
-
// Android: custom location rules
|
|
367
|
-
Ti.Geolocation.Android.addLocationRule(Ti.Geolocation.Android.createLocationRule({
|
|
368
|
-
provider: Ti.Geolocation.Android.PROVIDER_GPS,
|
|
369
|
-
accuracy: 100, // meters
|
|
370
|
-
minAge: 1000 // milliseconds
|
|
371
|
-
}));
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
---
|
|
375
|
-
|
|
376
|
-
## Alloy controller chaining
|
|
377
|
-
|
|
378
|
-
### Pattern overview
|
|
379
|
-
|
|
380
|
-
Chain controller methods to pass data between Alloy controllers in a clean, maintainable way.
|
|
381
|
-
|
|
382
|
-
### Basic pattern
|
|
383
|
-
|
|
384
|
-
Parent controller:
|
|
385
|
-
```javascript
|
|
386
|
-
const childController = Alloy.createController('child', {
|
|
387
|
-
data: someData,
|
|
388
|
-
onAction: (result) => {
|
|
389
|
-
// Handle result from child
|
|
390
|
-
Ti.API.info(`Child returned: ${result}`);
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
childController.on('customEvent', (data) => {
|
|
395
|
-
// Handle child events
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
childController.open();
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
Child controller:
|
|
402
|
-
```javascript
|
|
403
|
-
const args = arguments[0] || {};
|
|
404
|
-
|
|
405
|
-
// Access parent data
|
|
406
|
-
const parentData = args.data;
|
|
407
|
-
|
|
408
|
-
// Call parent callback
|
|
409
|
-
function notifyParent(result) {
|
|
410
|
-
if (args.onAction) {
|
|
411
|
-
args.onAction(result);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// Trigger parent events
|
|
416
|
-
function triggerEvent(data) {
|
|
417
|
-
$.trigger('customEvent', data);
|
|
418
|
-
}
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
### Benefits
|
|
422
|
-
|
|
423
|
-
- Clean separation. Controllers remain independent.
|
|
424
|
-
- Reusable. Child works in different contexts.
|
|
425
|
-
- Testable. You can mock parent callbacks.
|
|
426
|
-
- Maintainable. Clear data flow.
|
|
427
|
-
|
|
428
|
-
---
|
|
429
|
-
|
|
430
|
-
## Build automation with Fastlane
|
|
431
|
-
|
|
432
|
-
### Overview
|
|
433
|
-
|
|
434
|
-
Automate building and deploying Titanium apps with Fastlane.
|
|
435
|
-
|
|
436
|
-
### Installing Fastlane
|
|
437
|
-
|
|
438
|
-
```bash
|
|
439
|
-
# Using Homebrew (macOS)
|
|
440
|
-
brew install fastlane
|
|
441
|
-
|
|
442
|
-
# Or using Ruby gems
|
|
443
|
-
sudo gem install fastlane -NV
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
### Basic Fastfile
|
|
447
|
-
|
|
448
|
-
`fastlane/Fastfile`:
|
|
449
|
-
```ruby
|
|
450
|
-
platform :ios do
|
|
451
|
-
desc "Build and deploy to TestFlight"
|
|
452
|
-
lane :beta do
|
|
453
|
-
# Build the app
|
|
454
|
-
sh "ti build -p ios -F"
|
|
455
|
-
|
|
456
|
-
# Upload to TestFlight
|
|
457
|
-
upload_to_testflight(
|
|
458
|
-
skip_waiting_for_build_processing: true
|
|
459
|
-
)
|
|
460
|
-
end
|
|
461
|
-
|
|
462
|
-
desc "Build for development"
|
|
463
|
-
lane :dev do
|
|
464
|
-
sh "ti build -p ios -T developer"
|
|
465
|
-
end
|
|
466
|
-
end
|
|
467
|
-
|
|
468
|
-
platform :android do
|
|
469
|
-
desc "Build Android APK"
|
|
470
|
-
lane :build do
|
|
471
|
-
sh "ti build -p android -A"
|
|
472
|
-
end
|
|
473
|
-
|
|
474
|
-
desc "Deploy to Play Store (Beta)"
|
|
475
|
-
lane :beta do
|
|
476
|
-
# Build
|
|
477
|
-
sh "ti build -p android -F"
|
|
478
|
-
|
|
479
|
-
# Upload to Play Store
|
|
480
|
-
upload_to_play_store(
|
|
481
|
-
track: 'beta',
|
|
482
|
-
apk: 'app/build/android/bin/app.apk'
|
|
483
|
-
)
|
|
484
|
-
end
|
|
485
|
-
end
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
### Usage
|
|
489
|
-
|
|
490
|
-
```bash
|
|
491
|
-
# iOS Beta
|
|
492
|
-
fastlane ios beta
|
|
493
|
-
|
|
494
|
-
# Android Build
|
|
495
|
-
fastlane android build
|
|
496
|
-
|
|
497
|
-
# Android Beta
|
|
498
|
-
fastlane android beta
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
### Advanced options
|
|
502
|
-
|
|
503
|
-
Multiple environments:
|
|
504
|
-
```ruby
|
|
505
|
-
lane :staging do
|
|
506
|
-
sh "ti build -p ios -T dist --config ../staging.js"
|
|
507
|
-
end
|
|
508
|
-
|
|
509
|
-
lane :production do
|
|
510
|
-
sh "ti build -p ios -T dist --config ../production.js"
|
|
511
|
-
end
|
|
512
|
-
```
|
|
513
|
-
|
|
514
|
-
Environment-specific configs:
|
|
515
|
-
```javascript
|
|
516
|
-
// staging.js
|
|
517
|
-
module.exports = {
|
|
518
|
-
apiURL: 'https://staging-api.example.com',
|
|
519
|
-
analyticsEnabled: true
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
// production.js
|
|
523
|
-
module.exports = {
|
|
524
|
-
apiURL: 'https://api.example.com',
|
|
525
|
-
analyticsEnabled: true
|
|
526
|
-
};
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
---
|
|
530
|
-
|
|
531
|
-
## Additional tutorials
|
|
532
|
-
|
|
533
|
-
### Alloy boilerplates
|
|
534
|
-
|
|
535
|
-
See `Titanium_Boilerplates` folder for:
|
|
536
|
-
- TypeScript boilerplates
|
|
537
|
-
- App templates
|
|
538
|
-
- Project scaffolding
|
|
539
|
-
|
|
540
|
-
### Complete sample apps
|
|
541
|
-
|
|
542
|
-
- ToDoList - CommonJS module pattern example
|
|
543
|
-
- Tweetanium - Namespaced pattern example
|
|
544
|
-
- KitchenSink - Complete API reference (built with Alloy)
|
|
545
|
-
|
|
546
|
-
---
|
|
547
|
-
|
|
548
|
-
## Resources
|
|
549
|
-
|
|
550
|
-
- RESTe: https://github.com/jasonkneen/reste
|
|
551
|
-
- Fastlane: https://fastlane.tools
|
|
552
|
-
- Alloy Framework: see alloy-guides skill
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
# Using modules
|
|
2
|
-
|
|
3
|
-
Guide to obtaining, installing, and using Titanium modules to extend app functionality.
|
|
4
|
-
|
|
5
|
-
## Obtaining modules
|
|
6
|
-
|
|
7
|
-
### Sources of modules
|
|
8
|
-
|
|
9
|
-
Official modules:
|
|
10
|
-
- Enterprise Extensions
|
|
11
|
-
- InAppBilling (Android)
|
|
12
|
-
- StoreKit (iOS)
|
|
13
|
-
- Barcode (iOS/Android)
|
|
14
|
-
- Compression (iOS/Android)
|
|
15
|
-
- OpenGL (iOS)
|
|
16
|
-
- AirPrint (iOS)
|
|
17
|
-
|
|
18
|
-
Open-source modules:
|
|
19
|
-
- GitHub: tidev
|
|
20
|
-
- https://github.com/tidev/ti.admob - AdMob ads
|
|
21
|
-
- https://github.com/tidev/ti.map - Native maps
|
|
22
|
-
- And more in the org
|
|
23
|
-
|
|
24
|
-
Community modules:
|
|
25
|
-
- From Zero To App list: https://fromzerotoapp.com/modules/
|
|
26
|
-
- Curated list of modules maintained by Michael Gangolf
|
|
27
|
-
|
|
28
|
-
Marketplace:
|
|
29
|
-
The original Appcelerator Marketplace is no longer available. Find community modules on GitHub and npm. A curated list is at https://fromzerotoapp.com/modules/.
|
|
30
|
-
|
|
31
|
-
### Pre-installed modules
|
|
32
|
-
Some modules ship with the SDK and do not need separate installation: `ti.map`, `ti.identity`, `ti.webdialog`, `ti.applesignin`.
|
|
33
|
-
|
|
34
|
-
## Installing modules
|
|
35
|
-
|
|
36
|
-
### Single project installation
|
|
37
|
-
1. Copy the module ZIP to your app root folder.
|
|
38
|
-
2. Add the module to `tiapp.xml` (see configuration below).
|
|
39
|
-
3. Build the project. The ZIP is extracted automatically.
|
|
40
|
-
|
|
41
|
-
### Global installation (all projects)
|
|
42
|
-
Modules install to platform-specific locations:
|
|
43
|
-
|
|
44
|
-
| Operating system | Path |
|
|
45
|
-
| ---------------- | ---------------------------------------- |
|
|
46
|
-
| macOS | `~/Library/Application Support/Titanium` |
|
|
47
|
-
| Windows | `%ProgramData%\Titanium\mobilesdk\win32` |
|
|
48
|
-
|
|
49
|
-
Show hidden Library folder on macOS:
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
# Permanently show
|
|
53
|
-
chflags nohidden ~/Library/
|
|
54
|
-
|
|
55
|
-
# Open once
|
|
56
|
-
open ~/Library
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Configuring your app
|
|
60
|
-
|
|
61
|
-
### Updating tiapp.xml
|
|
62
|
-
|
|
63
|
-
Using Studio/IDE:
|
|
64
|
-
1. Open `tiapp.xml`.
|
|
65
|
-
2. Go to the Overview tab.
|
|
66
|
-
3. Click the plus button in Modules.
|
|
67
|
-
4. Select module and version.
|
|
68
|
-
5. Save.
|
|
69
|
-
|
|
70
|
-
Manually (XML):
|
|
71
|
-
|
|
72
|
-
```xml
|
|
73
|
-
<modules>
|
|
74
|
-
<module version="3.0.2" platform="ios">ti.map</module>
|
|
75
|
-
<module version="5.0.0" platform="android">ti.admob</module>
|
|
76
|
-
</modules>
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Attributes:
|
|
80
|
-
- `version`: must match the module manifest
|
|
81
|
-
- `platform`: "ios" or "android"
|
|
82
|
-
|
|
83
|
-
### Selecting module versions
|
|
84
|
-
If multiple versions are installed, select specific versions per platform and build type (development/production).
|
|
85
|
-
|
|
86
|
-
In Studio, double-click the module to open the Module Properties dialog.
|
|
87
|
-
|
|
88
|
-
### Enable debugger (for native modules)
|
|
89
|
-
Required for debugging native modules:
|
|
90
|
-
|
|
91
|
-
```xml
|
|
92
|
-
<ti:app>
|
|
93
|
-
<android xmlns:android="http://schemas.android.com/apk/res/android">
|
|
94
|
-
<manifest>
|
|
95
|
-
<application android:debuggable="true">
|
|
96
|
-
</application>
|
|
97
|
-
</manifest>
|
|
98
|
-
</android>
|
|
99
|
-
</ti:app>
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Using a module
|
|
103
|
-
|
|
104
|
-
### Loading the module (ES5)
|
|
105
|
-
|
|
106
|
-
```javascript
|
|
107
|
-
const Module = require('module.id');
|
|
108
|
-
// Example: const Map = require('ti.map');
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### Loading the module (ES6+)
|
|
112
|
-
|
|
113
|
-
```javascript
|
|
114
|
-
import Module from 'module.id'
|
|
115
|
-
// Example: import Map from 'ti.map'
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Important: do not include the `.js` extension in the module ID.
|
|
119
|
-
|
|
120
|
-
### Using module functionality
|
|
121
|
-
After requiring, use the module's API:
|
|
122
|
-
|
|
123
|
-
```javascript
|
|
124
|
-
// ES6+ example with ti.admob
|
|
125
|
-
const Admob = require('ti.admob');
|
|
126
|
-
|
|
127
|
-
const adview = Admob.createView({
|
|
128
|
-
top: 0,
|
|
129
|
-
testing: true,
|
|
130
|
-
adBackgroundColor: 'black',
|
|
131
|
-
primaryTextColor: 'blue',
|
|
132
|
-
publisherId: 'YOUR_PUBLISHER_ID'
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
win.add(adview);
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Module patterns
|
|
139
|
-
|
|
140
|
-
Singleton pattern:
|
|
141
|
-
```javascript
|
|
142
|
-
const admob = require('ti.admob');
|
|
143
|
-
admob.createView({ ... });
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Constructor pattern:
|
|
147
|
-
```javascript
|
|
148
|
-
const Map = require('ti.map');
|
|
149
|
-
const view = Map.createView({ ... });
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
Refer to module documentation for its specific API.
|
|
153
|
-
|
|
154
|
-
## Troubleshooting
|
|
155
|
-
|
|
156
|
-
### "Requested module not found"
|
|
157
|
-
Solutions:
|
|
158
|
-
1. Check module ID spelling in `require()`.
|
|
159
|
-
2. Verify the module is added to `tiapp.xml`.
|
|
160
|
-
3. Confirm the module is installed (global or local path).
|
|
161
|
-
4. Remove the `version` attribute to use the latest version.
|
|
162
|
-
|
|
163
|
-
### Version conflicts
|
|
164
|
-
If multiple versions exist, specify the exact version in `tiapp.xml`, or remove the version attribute to use the latest.
|
|
165
|
-
|
|
166
|
-
### Platform-specific issues
|
|
167
|
-
- iOS: the module must support the iOS SDK version you are using.
|
|
168
|
-
- Android: the module manifest `platform` must match the target.
|
|
169
|
-
|
|
170
|
-
### Clean build
|
|
171
|
-
Sometimes needed after installing modules:
|
|
172
|
-
|
|
173
|
-
```bash
|
|
174
|
-
# Clean and rebuild
|
|
175
|
-
ti clean
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## Best practices
|
|
179
|
-
|
|
180
|
-
1. Pin versions for production.
|
|
181
|
-
2. Check compatibility with your Titanium SDK version.
|
|
182
|
-
3. Test on devices. Some modules behave differently on simulator vs device.
|