@maccesar/titools 2.2.4 → 2.2.8

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 (96) hide show
  1. package/README.md +23 -23
  2. package/lib/commands/update.js +4 -12
  3. package/package.json +1 -1
  4. package/skills/alloy-guides/SKILL.md +31 -31
  5. package/skills/alloy-guides/references/CONCEPTS.md +3 -3
  6. package/skills/alloy-guides/references/CONTROLLERS.md +1 -1
  7. package/skills/alloy-guides/references/MODELS.md +6 -6
  8. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +1 -1
  9. package/skills/alloy-guides/references/VIEWS_XML.md +1 -1
  10. package/skills/alloy-guides/references/WIDGETS.md +1 -1
  11. package/skills/alloy-howtos/SKILL.md +27 -27
  12. package/skills/alloy-howtos/references/best_practices.md +9 -9
  13. package/skills/alloy-howtos/references/cli_reference.md +14 -14
  14. package/skills/alloy-howtos/references/config_files.md +16 -16
  15. package/skills/alloy-howtos/references/custom_tags.md +16 -16
  16. package/skills/alloy-howtos/references/debugging_troubleshooting.md +11 -15
  17. package/skills/alloy-howtos/references/samples.md +19 -19
  18. package/skills/purgetss/SKILL.md +11 -1
  19. package/skills/purgetss/references/animation-system.md +1 -1
  20. package/skills/purgetss/references/cli-commands.md +3 -3
  21. package/skills/purgetss/references/customization-deep-dive.md +1 -1
  22. package/skills/purgetss/references/dynamic-component-creation.md +1 -1
  23. package/skills/purgetss/references/icon-fonts.md +4 -0
  24. package/skills/purgetss/references/installation-setup.md +8 -1
  25. package/skills/purgetss/references/migration-guide.md +4 -0
  26. package/skills/purgetss/references/tikit-components.md +193 -204
  27. package/skills/purgetss/references/ui-ux-design.md +1 -1
  28. package/skills/ti-expert/SKILL.md +78 -118
  29. package/skills/ti-expert/references/alloy-builtins.md +18 -18
  30. package/skills/ti-expert/references/alloy-structure.md +21 -21
  31. package/skills/ti-expert/references/anti-patterns.md +15 -15
  32. package/skills/ti-expert/references/cli-expert.md +15 -15
  33. package/skills/ti-expert/references/code-conventions.md +38 -38
  34. package/skills/ti-expert/references/contracts.md +8 -8
  35. package/skills/ti-expert/references/controller-patterns.md +14 -14
  36. package/skills/ti-expert/references/error-handling.md +11 -11
  37. package/skills/ti-expert/references/examples.md +12 -12
  38. package/skills/ti-expert/references/migration-patterns.md +24 -24
  39. package/skills/ti-expert/references/patterns.md +10 -10
  40. package/skills/ti-expert/references/performance-listview.md +16 -16
  41. package/skills/ti-expert/references/performance-optimization.md +41 -41
  42. package/skills/ti-expert/references/security-device.md +22 -22
  43. package/skills/ti-expert/references/security-fundamentals.md +19 -19
  44. package/skills/ti-expert/references/state-management.md +33 -33
  45. package/skills/ti-expert/references/testing-e2e-ci.md +25 -25
  46. package/skills/ti-expert/references/testing-unit.md +24 -24
  47. package/skills/ti-expert/references/theming.md +15 -15
  48. package/skills/ti-guides/SKILL.md +58 -60
  49. package/skills/ti-guides/references/advanced-data-and-images.md +33 -33
  50. package/skills/ti-guides/references/android-manifest.md +15 -15
  51. package/skills/ti-guides/references/app-distribution.md +70 -166
  52. package/skills/ti-guides/references/application-frameworks.md +96 -114
  53. package/skills/ti-guides/references/cli-reference.md +294 -294
  54. package/skills/ti-guides/references/coding-best-practices.md +42 -33
  55. package/skills/ti-guides/references/commonjs-advanced.md +57 -51
  56. package/skills/ti-guides/references/hello-world.md +36 -36
  57. package/skills/ti-guides/references/hyperloop-native-access.md +66 -66
  58. package/skills/ti-guides/references/javascript-primer.md +83 -101
  59. package/skills/ti-guides/references/reserved-words.md +9 -9
  60. package/skills/ti-guides/references/resources.md +75 -83
  61. package/skills/ti-guides/references/style-and-conventions.md +35 -28
  62. package/skills/ti-guides/references/tiapp-config.md +110 -74
  63. package/skills/ti-howtos/SKILL.md +88 -92
  64. package/skills/ti-howtos/references/android-platform-deep-dives.md +104 -104
  65. package/skills/ti-howtos/references/automation-fastlane-appium.md +39 -39
  66. package/skills/ti-howtos/references/buffer-codec-streams.md +60 -60
  67. package/skills/ti-howtos/references/cross-platform-development.md +115 -136
  68. package/skills/ti-howtos/references/debugging-profiling.md +167 -181
  69. package/skills/ti-howtos/references/extending-titanium.md +121 -121
  70. package/skills/ti-howtos/references/google-maps-v2.md +84 -82
  71. package/skills/ti-howtos/references/ios-map-kit.md +65 -60
  72. package/skills/ti-howtos/references/ios-platform-deep-dives.md +123 -123
  73. package/skills/ti-howtos/references/local-data-sources.md +79 -78
  74. package/skills/ti-howtos/references/location-and-maps.md +116 -120
  75. package/skills/ti-howtos/references/media-apis.md +87 -86
  76. package/skills/ti-howtos/references/notification-services.md +250 -260
  77. package/skills/ti-howtos/references/remote-data-sources.md +98 -93
  78. package/skills/ti-howtos/references/tutorials.md +226 -216
  79. package/skills/ti-howtos/references/using-modules.md +73 -102
  80. package/skills/ti-howtos/references/web-content-integration.md +101 -103
  81. package/skills/ti-howtos/references/webpack-build-pipeline.md +52 -44
  82. package/skills/ti-ui/SKILL.md +85 -85
  83. package/skills/ti-ui/references/accessibility-deep-dive.md +57 -57
  84. package/skills/ti-ui/references/animation-and-matrices.md +79 -79
  85. package/skills/ti-ui/references/application-structures.md +96 -99
  86. package/skills/ti-ui/references/custom-fonts-styling.md +99 -99
  87. package/skills/ti-ui/references/event-handling.md +58 -58
  88. package/skills/ti-ui/references/gestures.md +62 -64
  89. package/skills/ti-ui/references/icons-and-splash-screens.md +88 -88
  90. package/skills/ti-ui/references/layouts-and-positioning.md +87 -97
  91. package/skills/ti-ui/references/listviews-and-performance.md +107 -107
  92. package/skills/ti-ui/references/orientation.md +87 -88
  93. package/skills/ti-ui/references/platform-ui-android.md +87 -81
  94. package/skills/ti-ui/references/platform-ui-ios.md +63 -61
  95. package/skills/ti-ui/references/scrolling-views.md +29 -29
  96. package/skills/ti-ui/references/tableviews.md +56 -56
@@ -1,17 +1,16 @@
1
- # Titanium SDK Tutorials
1
+ # Titanium SDK tutorials
2
2
 
3
- Practical tutorials and guides for building real-world Titanium applications.
3
+ Practical tutorials and guides for building real Titanium applications.
4
4
 
5
- ## RESTe - API Integration
5
+ ## RESTe - API integration
6
6
 
7
7
  ### Overview
8
+ RESTe by Jason Kneen is a module for consuming web APIs in Titanium.
8
9
 
9
- **RESTe** by Jason Kneen - A module for consuming web APIs in Titanium.
10
-
11
- **Benefits:**
10
+ Benefits:
12
11
  - Eliminates boilerplate HTTP code
13
12
  - Auto-generates JavaScript API from config
14
- - Supports Backbone.js Models/Collections in Alloy
13
+ - Supports Backbone.js models and collections in Alloy
15
14
  - Works with any API (not just REST)
16
15
 
17
16
  ### Installation
@@ -20,108 +19,113 @@ Practical tutorials and guides for building real-world Titanium applications.
20
19
  npm install reste
21
20
  ```
22
21
 
23
- ### Basic Configuration
22
+ ### Basic configuration
23
+
24
+ `alloy.js`:
24
25
 
25
- **alloy.js:**
26
26
  ```javascript
27
- const reste = require("reste");
27
+ const reste = require('reste');
28
28
  const api = new reste();
29
29
 
30
30
  api.config({
31
- debug: true, // Console logging
32
- errorsAsObjects: true, // Return errors as objects (1.4.5+) WARNING: 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"
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/'
40
49
  },
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();
50
+ {
51
+ name: 'createVideo',
52
+ post: 'videos'
65
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
66
  });
67
67
  ```
68
68
 
69
69
  ### Usage
70
70
 
71
- **Auto-generated methods:**
71
+ Auto-generated methods:
72
+
72
73
  ```javascript
73
74
  // Fetch single video
74
75
  api.getVideoById({
75
- videoId: "abc123"
76
+ videoId: 'abc123'
76
77
  }, (video) => {
77
- Ti.API.info(`Got video: ${video.title}`);
78
+ Ti.API.info(`Got video: ${video.title}`);
78
79
  });
79
80
 
80
81
  // Create video
81
82
  api.createVideo({
82
- body: {
83
- title: "My Video",
84
- categoryId: 2
85
- }
83
+ body: {
84
+ title: 'My Video',
85
+ categoryId: 2
86
+ }
86
87
  }, (response) => {
87
- Ti.API.info(`Created: ${response.id}`);
88
+ Ti.API.info(`Created: ${response.id}`);
88
89
  });
89
90
  ```
90
91
 
91
- ### Backbone.js Models/Collections
92
+ ### Backbone.js models and collections
93
+
94
+ Configuration:
92
95
 
93
- **Configuration:**
94
96
  ```javascript
95
97
  api.config({
96
- // ... other config
97
- models: [{
98
- name: "video",
99
- id: "objectId", // Primary key field
100
- read: "getVideo",
101
- create: "createVideo",
102
- update: "updateVideo",
103
- delete: "deleteVideo",
104
- collections: [{
105
- name: "videos",
106
- content: "results", // Array wrapper in response
107
- read: "getVideos"
108
- }]
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'
109
110
  }]
111
+ }]
110
112
  });
111
113
  ```
112
114
 
113
- **In Alloy Controller:**
115
+ In an Alloy controller:
116
+
114
117
  ```javascript
115
118
  // Fetch collection
116
119
  Alloy.Collections.videos.fetch();
117
120
 
118
121
  // Or fetch with parameters
119
122
  Alloy.Collections.videos.fetch({
120
- data: {category: "sports"}
123
+ data: { category: 'sports' }
121
124
  });
122
125
  ```
123
126
 
124
- **In Alloy View:**
127
+ In an Alloy view:
128
+
125
129
  ```xml
126
130
  <TableView dataCollection="videos" onClick="selectVideo">
127
131
  <TableViewRow model="{objectId}">
@@ -131,54 +135,57 @@ Alloy.Collections.videos.fetch({
131
135
  </TableView>
132
136
  ```
133
137
 
134
- ### RESTe Advanced Features
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
135
143
 
136
- - **Caching**: Built-in response caching support
137
- - **Promises**: Use with `q.js` for Promise-based API calls
138
- - **Mock data**: Create models/collections on-the-fly for testing:
139
144
  ```javascript
140
145
  const mockUser = api.createModel('users', {
141
- id: 1,
142
- name: 'Test User'
146
+ id: 1,
147
+ name: 'Test User'
143
148
  });
144
149
  ```
145
- - **Backbone.js binding**: Use RESTe models directly with Alloy data binding without `<Model>` tags
146
150
 
147
- ### Important Notes
151
+ - Backbone.js binding: use RESTe models directly with Alloy data binding without `<Model>` tags
152
+
153
+ ### Important notes
148
154
 
149
- - **Don't use `<Model>` or `<Collection>` tags** with RESTe
150
- - RESTe creates models/collections automatically
151
- - Use data-binding like normal Alloy collections
152
- - Great for mocking data during UI development
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
153
159
 
154
- ### Mock Data (On-The-Fly)
160
+ ### Mock data (on the fly)
155
161
 
156
162
  ```javascript
157
163
  // Create model without API
158
164
  const videoModel = api.createModel('video', {
159
- title: 'Test Video',
160
- description: 'Mock data'
165
+ title: 'Test Video',
166
+ description: 'Mock data'
161
167
  });
162
168
 
163
169
  // Create collection
164
170
  const videoCollection = api.createCollection('videos', [
165
- {title: 'Video 1'},
166
- {title: 'Video 2'}
171
+ { title: 'Video 1' },
172
+ { title: 'Video 2' }
167
173
  ]);
168
174
  ```
169
175
 
170
176
  ### Resources
171
177
 
172
- - **npm:** https://www.npmjs.com/package/reste
173
- - **GitHub:** https://github.com/jasonkneen/reste
178
+ - npm: https://www.npmjs.com/package/reste
179
+ - GitHub: https://github.com/jasonkneen/reste
174
180
 
175
181
  ---
176
182
 
177
- ## Camera App Tutorial
183
+ ## Camera app tutorial
184
+
185
+ ### Camera permissions setup
178
186
 
179
- ### Camera Permissions Setup
187
+ iOS - add to `tiapp.xml` plist:
180
188
 
181
- **iOS** — add to tiapp.xml plist:
182
189
  ```xml
183
190
  <key>NSCameraUsageDescription</key>
184
191
  <string>This app needs camera access to take photos</string>
@@ -186,96 +193,98 @@ const videoCollection = api.createCollection('videos', [
186
193
  <string>This app needs microphone access for video recording</string>
187
194
  ```
188
195
 
189
- **Android**: Camera permissions are automatically added by the build system when using `Ti.Media.showCamera()`.
196
+ Android: camera permissions are automatically added by the build system when you use `Ti.Media.showCamera()`.
190
197
 
191
198
  Always check permissions at runtime:
199
+
192
200
  ```javascript
193
201
  if (!Ti.Media.hasCameraPermissions()) {
194
- Ti.Media.requestCameraPermissions((e) => {
195
- if (e.success) openCamera();
196
- });
202
+ Ti.Media.requestCameraPermissions((e) => {
203
+ if (e.success) openCamera();
204
+ });
197
205
  } else {
198
- openCamera();
206
+ openCamera();
199
207
  }
200
208
  ```
201
209
 
202
- ### Basic Camera Access
210
+ ### Basic camera access
203
211
 
204
212
  ```javascript
205
213
  // Show camera
206
214
  Ti.Media.showCamera({
207
- success: (event) => {
208
- const image = event.media;
209
- if (event.mediaType === Ti.Media.MEDIA_TYPE_PHOTO) {
210
- // Use the photo
211
- const imageView = Ti.UI.createImageView({
212
- image: image,
213
- width: 300,
214
- height: 300
215
- });
216
- win.add(imageView);
217
- }
218
- },
219
- cancel: () => {
220
- Ti.API.info('Camera canceled');
221
- },
222
- error: (error) => {
223
- const a = Ti.UI.createAlertDialog({title: 'Camera Error'});
224
- if (error.code === Ti.Media.NO_CAMERA) {
225
- a.setMessage('Device does not have camera');
226
- } else {
227
- a.setMessage(`Unexpected error: ${error.code}`);
228
- }
229
- a.show();
230
- },
231
- saveToPhotoGallery: true,
232
- allowEditing: true,
233
- mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO],
234
- videoQuality: Ti.Media.QUALITY_HIGH
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
235
243
  });
236
244
  ```
237
245
 
238
- ### Photo Gallery
246
+ ### Photo gallery
239
247
 
240
248
  ```javascript
241
249
  // Open photo gallery
242
250
  Ti.Media.openPhotoGallery({
243
- success: (event) => {
244
- const image = event.media;
245
- // Process selected image
246
- },
247
- cancel: () => {
248
- // User canceled
249
- },
250
- error: (error) => {
251
- // Handle error
252
- },
253
- mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO]
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]
254
262
  });
255
263
  ```
256
264
 
257
- ### Saving Images
265
+ ### Saving images
258
266
 
259
267
  ```javascript
260
268
  // Save to gallery
261
269
  Ti.Media.saveToPhotoGallery({
262
- media: myImageBlob,
263
- success: () => {
264
- alert('Saved!');
265
- },
266
- error: (e) => {
267
- alert(`Error: ${e.error}`);
268
- }
270
+ media: myImageBlob,
271
+ success: () => {
272
+ alert('Saved!');
273
+ },
274
+ error: (e) => {
275
+ alert(`Error: ${e.error}`);
276
+ }
269
277
  });
270
278
  ```
271
279
 
272
280
  ---
273
281
 
274
- ## Geolocation Tutorial
282
+ ## Geolocation tutorial
283
+
284
+ ### Geolocation permissions setup
275
285
 
276
- ### Geolocation Permissions Setup
286
+ iOS - add to `tiapp.xml` plist:
277
287
 
278
- **iOS** — add to tiapp.xml plist:
279
288
  ```xml
280
289
  <key>NSLocationWhenInUseUsageDescription</key>
281
290
  <string>We need your location to show nearby places</string>
@@ -283,7 +292,8 @@ Ti.Media.saveToPhotoGallery({
283
292
  <string>We need your location for background tracking</string>
284
293
  ```
285
294
 
286
- **Android** add to tiapp.xml manifest:
295
+ Android - add to `tiapp.xml` manifest:
296
+
287
297
  ```xml
288
298
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
289
299
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
@@ -292,59 +302,59 @@ Ti.Media.saveToPhotoGallery({
292
302
  Runtime permission check:
293
303
  ```javascript
294
304
  if (!Ti.Geolocation.hasLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE)) {
295
- Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE, (e) => {
296
- if (e.success) startTracking();
297
- });
305
+ Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE, (e) => {
306
+ if (e.success) startTracking();
307
+ });
298
308
  }
299
309
  ```
300
310
 
301
- ### Basic Location
311
+ ### Basic location
302
312
 
303
313
  ```javascript
304
314
  // One-time location
305
315
  if (Ti.Geolocation.locationServicesEnabled) {
306
- Ti.Geolocation.getCurrentPosition((e) => {
307
- if (!e.error) {
308
- Ti.API.info(`Lat: ${e.coords.latitude}`);
309
- Ti.API.info(`Lon: ${e.coords.longitude}`);
310
- }
311
- });
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
+ });
312
322
  }
313
323
  ```
314
324
 
315
- ### Continuous Tracking
325
+ ### Continuous tracking
316
326
 
317
327
  ```javascript
318
328
  // Configure accuracy
319
329
  Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST;
320
- Ti.Geolocation.distanceFilter = 10; // Meters
330
+ Ti.Geolocation.distanceFilter = 10; // Meters
321
331
 
322
332
  // Track location changes
323
333
  Ti.Geolocation.addEventListener('location', (e) => {
324
- if (!e.error) {
325
- const lat = e.coords.latitude;
326
- const lon = e.coords.longitude;
327
- updateMap(lat, lon);
328
- }
334
+ if (!e.error) {
335
+ const lat = e.coords.latitude;
336
+ const lon = e.coords.longitude;
337
+ updateMap(lat, lon);
338
+ }
329
339
  });
330
340
  ```
331
341
 
332
- ### Reverse Geocoding
342
+ ### Reverse geocoding
333
343
 
334
344
  ```javascript
335
345
  // Coordinates to address
336
346
  Ti.Geolocation.reverseGeocoder(37.389569, -122.050212, (e) => {
337
- if (e.success) {
338
- e.places.forEach((place) => {
339
- Ti.API.info(place.address);
340
- Ti.API.info(place.city);
341
- Ti.API.info(place.country);
342
- });
343
- }
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
+ }
344
354
  });
345
355
  ```
346
356
 
347
- ### Accuracy Tuning
357
+ ### Accuracy tuning
348
358
 
349
359
  ```javascript
350
360
  // iOS: minimum distance before firing event
@@ -355,40 +365,40 @@ Ti.Geolocation.distanceFilter = 10; // meters
355
365
 
356
366
  // Android: custom location rules
357
367
  Ti.Geolocation.Android.addLocationRule(Ti.Geolocation.Android.createLocationRule({
358
- provider: Ti.Geolocation.Android.PROVIDER_GPS,
359
- accuracy: 100, // meters
360
- minAge: 1000 // milliseconds
368
+ provider: Ti.Geolocation.Android.PROVIDER_GPS,
369
+ accuracy: 100, // meters
370
+ minAge: 1000 // milliseconds
361
371
  }));
362
372
  ```
363
373
 
364
374
  ---
365
375
 
366
- ## Alloy Controller Chaining
376
+ ## Alloy controller chaining
367
377
 
368
- ### Pattern Overview
378
+ ### Pattern overview
369
379
 
370
380
  Chain controller methods to pass data between Alloy controllers in a clean, maintainable way.
371
381
 
372
- ### Basic Pattern
382
+ ### Basic pattern
373
383
 
374
- **Parent Controller:**
384
+ Parent controller:
375
385
  ```javascript
376
386
  const childController = Alloy.createController('child', {
377
- data: someData,
378
- onAction: (result) => {
379
- // Handle result from child
380
- Ti.API.info(`Child returned: ${result}`);
381
- }
387
+ data: someData,
388
+ onAction: (result) => {
389
+ // Handle result from child
390
+ Ti.API.info(`Child returned: ${result}`);
391
+ }
382
392
  });
383
393
 
384
394
  childController.on('customEvent', (data) => {
385
- // Handle child events
395
+ // Handle child events
386
396
  });
387
397
 
388
398
  childController.open();
389
399
  ```
390
400
 
391
- **Child Controller:**
401
+ Child controller:
392
402
  ```javascript
393
403
  const args = arguments[0] || {};
394
404
 
@@ -397,27 +407,27 @@ const parentData = args.data;
397
407
 
398
408
  // Call parent callback
399
409
  function notifyParent(result) {
400
- if (args.onAction) {
401
- args.onAction(result);
402
- }
410
+ if (args.onAction) {
411
+ args.onAction(result);
412
+ }
403
413
  }
404
414
 
405
415
  // Trigger parent events
406
416
  function triggerEvent(data) {
407
- $.trigger('customEvent', data);
417
+ $.trigger('customEvent', data);
408
418
  }
409
419
  ```
410
420
 
411
421
  ### Benefits
412
422
 
413
- - **Clean separation** - Controllers remain independent
414
- - **Reusable** - Child works in different contexts
415
- - **Testable** - Can mock parent callbacks
416
- - **Maintainable** - Clear data flow
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.
417
427
 
418
428
  ---
419
429
 
420
- ## Build Automation with Fastlane
430
+ ## Build automation with Fastlane
421
431
 
422
432
  ### Overview
423
433
 
@@ -435,7 +445,7 @@ sudo gem install fastlane -NV
435
445
 
436
446
  ### Basic Fastfile
437
447
 
438
- **fastlane/Fastfile:**
448
+ `fastlane/Fastfile`:
439
449
  ```ruby
440
450
  platform :ios do
441
451
  desc "Build and deploy to TestFlight"
@@ -488,9 +498,9 @@ fastlane android build
488
498
  fastlane android beta
489
499
  ```
490
500
 
491
- ### Advanced Options
501
+ ### Advanced options
492
502
 
493
- **Multiple environments:**
503
+ Multiple environments:
494
504
  ```ruby
495
505
  lane :staging do
496
506
  sh "ti build -p ios -T dist --config ../staging.js"
@@ -501,42 +511,42 @@ lane :production do
501
511
  end
502
512
  ```
503
513
 
504
- **Environment-specific configs:**
514
+ Environment-specific configs:
505
515
  ```javascript
506
516
  // staging.js
507
517
  module.exports = {
508
- apiURL: 'https://staging-api.example.com',
509
- analyticsEnabled: true
518
+ apiURL: 'https://staging-api.example.com',
519
+ analyticsEnabled: true
510
520
  };
511
521
 
512
522
  // production.js
513
523
  module.exports = {
514
- apiURL: 'https://api.example.com',
515
- analyticsEnabled: true
524
+ apiURL: 'https://api.example.com',
525
+ analyticsEnabled: true
516
526
  };
517
527
  ```
518
528
 
519
529
  ---
520
530
 
521
- ## Additional Tutorials
531
+ ## Additional tutorials
522
532
 
523
- ### Alloy Boilerplates
533
+ ### Alloy boilerplates
524
534
 
525
- See **Titanium_Boilerplates** folder for:
535
+ See `Titanium_Boilerplates` folder for:
526
536
  - TypeScript boilerplates
527
537
  - App templates
528
538
  - Project scaffolding
529
539
 
530
- ### Complete Sample Apps
540
+ ### Complete sample apps
531
541
 
532
- - **ToDoList** - CommonJS module pattern example
533
- - **Tweetanium** - Namespaced pattern example
534
- - **KitchenSink** - Complete API reference (built with Alloy)
542
+ - ToDoList - CommonJS module pattern example
543
+ - Tweetanium - Namespaced pattern example
544
+ - KitchenSink - Complete API reference (built with Alloy)
535
545
 
536
546
  ---
537
547
 
538
548
  ## Resources
539
549
 
540
- - **RESTe:** https://github.com/jasonkneen/reste
541
- - **Fastlane:** https://fastlane.tools
542
- - **Alloy Framework:** See alloy-guides skill
550
+ - RESTe: https://github.com/jasonkneen/reste
551
+ - Fastlane: https://fastlane.tools
552
+ - Alloy Framework: see alloy-guides skill