@maccesar/titools 4.4.0 → 4.4.2

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 (39) hide show
  1. package/README.md +9 -12
  2. package/package.json +1 -1
  3. package/skills/purgetss/SKILL.md +4 -9
  4. package/skills/ti-api/references/api-core.md +24 -69
  5. package/skills/ti-api/references/api-data-network.md +18 -63
  6. package/skills/ti-api/references/api-media.md +15 -49
  7. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +6 -20
  8. package/skills/ti-api/references/api-modules-map.md +17 -40
  9. package/skills/ti-api/references/api-modules-nfc.md +23 -56
  10. package/skills/ti-api/references/api-ui-android.md +16 -37
  11. package/skills/ti-api/references/api-ui-extras.md +28 -72
  12. package/skills/ti-api/references/api-ui-lists.md +14 -35
  13. package/skills/ti-api/references/api-ui-text-input.md +13 -39
  14. package/skills/ti-api/references/api-ui-windows-navigation.md +17 -43
  15. package/skills/ti-api/references/api-xml-global.md +25 -60
  16. package/skills/ti-expert/SKILL.md +8 -11
  17. package/skills/ti-expert/references/adaptive-layouts.md +15 -43
  18. package/skills/ti-expert/references/alloy-builtins.md +1 -4
  19. package/skills/ti-expert/references/alloy-structure.md +4 -12
  20. package/skills/ti-expert/references/anti-patterns.md +16 -45
  21. package/skills/ti-expert/references/code-conventions.md +2 -6
  22. package/skills/ti-expert/references/controller-patterns.md +1 -3
  23. package/skills/ti-expert/references/examples.md +3 -10
  24. package/skills/ti-expert/references/feedback-migration.md +17 -39
  25. package/skills/ti-expert/references/feedback-surfaces.md +19 -48
  26. package/skills/ti-expert/references/feedback-widget-contracts.md +31 -69
  27. package/skills/ti-expert/references/file-type-association.md +265 -0
  28. package/skills/ti-expert/references/migration-patterns.md +8 -18
  29. package/skills/ti-expert/references/sharing.md +227 -0
  30. package/skills/ti-expert/references/theming.md +20 -45
  31. package/skills/ti-guides/references/coding-best-practices.md +1 -2
  32. package/skills/ti-guides/references/style-and-conventions.md +1 -2
  33. package/skills/ti-howtos/references/debugging-profiling.md +1 -2
  34. package/skills/ti-howtos/references/location-and-maps.md +1 -2
  35. package/skills/ti-howtos/references/using-modules.md +1 -2
  36. package/skills/ti-howtos/references/web-content-integration.md +1 -2
  37. package/skills/ti-howtos/references/webpack-build-pipeline.md +1 -2
  38. package/skills/ti-ui/references/listviews-and-performance.md +5 -10
  39. package/skills/ti-ui/references/orientation.md +1 -2
@@ -39,8 +39,7 @@
39
39
 
40
40
  The API for this module is based on the W3C DOM specification.
41
41
 
42
- Android and iOS implement the [DOM Level 2](https://www.w3.org/TR/DOM-Level-2-Core/core.html) specification
43
- with some non-standard extensions, which are documented in the appropriate places.
42
+ Android and iOS implement the [DOM Level 2](https://www.w3.org/TR/DOM-Level-2-Core/core.html) specification with some non-standard extensions, which are documented in the appropriate places.
44
43
 
45
44
  Both iOS and Android lack DTD support.
46
45
 
@@ -59,8 +58,7 @@ Both iOS and Android lack DTD support.
59
58
  > Extends Ti.XML.Node
60
59
  > Platforms: both
61
60
 
62
- Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-637646024) on
63
- Android and iOS.
61
+ Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-637646024) on Android and iOS.
64
62
 
65
63
  ### Properties (unique: 4/35)
66
64
  | Property | Type | Default | Platform | Description |
@@ -80,8 +78,7 @@ Android and iOS.
80
78
  > Extends Ti.XML.Text
81
79
  > Platforms: both
82
80
 
83
- Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-667469212) on
84
- Android and iOS with some non-standard extensions.
81
+ Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-667469212) on Android and iOS with some non-standard extensions.
85
82
 
86
83
 
87
84
 
@@ -117,8 +114,7 @@ Android and iOS with some non-standard extensions.
117
114
  > Extends Ti.XML.CharacterData
118
115
  > Platforms: both
119
116
 
120
- Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1728279322) on
121
- Android and iOS with some non-standard extensions.
117
+ Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1728279322) on Android and iOS with some non-standard extensions.
122
118
 
123
119
 
124
120
 
@@ -146,12 +142,9 @@ Android and iOS with some non-standard extensions.
146
142
  > Extends Ti.XML.Node
147
143
  > Platforms: both
148
144
 
149
- Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#i-Document) on
150
- Android and iOS.
145
+ Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#i-Document) on Android and iOS.
151
146
 
152
- As of version 3.1, Android does not truly support DTDs. A document with a DTD can be
153
- parsed, however it is not validated, its default attributes are not be automatically
154
- added into the DOM tree, and so on.
147
+ As of version 3.1, Android does not truly support DTDs. A document with a DTD can be parsed, however it is not validated, its default attributes are not be automatically added into the DOM tree, and so on.
155
148
 
156
149
  This has been reported as [Android Issue #7395](http://code.google.com/p/android/issues/detail?id=7395).
157
150
 
@@ -189,11 +182,9 @@ This has been reported as [Android Issue #7395](http://code.google.com/p/android
189
182
  > Extends Ti.XML.Node
190
183
  > Platforms: both
191
184
 
192
- When a `DocumentFragment` is inserted into a DOM tree, children of the `DocumentFragment` are
193
- added, not the `DocumentFragment` itself.
185
+ When a `DocumentFragment` is inserted into a DOM tree, children of the `DocumentFragment` are added, not the `DocumentFragment` itself.
194
186
 
195
- Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-B63ED1A3) on
196
- Android and iOS with some non-standard extensions.
187
+ Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-B63ED1A3) on Android and iOS with some non-standard extensions.
197
188
 
198
189
 
199
190
 
@@ -205,12 +196,9 @@ Android and iOS with some non-standard extensions.
205
196
  > Extends Ti.XML.Node
206
197
  > Platforms: both
207
198
 
208
- This provides an interface to the list of entities that are defined for the document. Implements the
209
- [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-412266927) on Android and iOS.
199
+ This provides an interface to the list of entities that are defined for the document. Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-412266927) on Android and iOS.
210
200
 
211
- As of version 3.1, Android still does not truly support DTDs. A document with a DTD can be
212
- parsed, however it is not validated, none of its default attributes will automatically be put
213
- into the tree, etc. [Google is aware of the issue](http://code.google.com/p/android/issues/detail?id=7395).
201
+ As of version 3.1, Android still does not truly support DTDs. A document with a DTD can be parsed, however it is not validated, none of its default attributes will automatically be put into the tree, etc. [Google is aware of the issue](http://code.google.com/p/android/issues/detail?id=7395).
214
202
 
215
203
  ### Properties (unique: 6/37)
216
204
  | Property | Type | Default | Platform | Description |
@@ -284,8 +272,7 @@ into the tree, etc. [Google is aware of the issue](http://code.google.com/p/and
284
272
  > Extends Ti.XML.Node
285
273
  > Platforms: both
286
274
 
287
- Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-11C98490)
288
- on Android and iOS.
275
+ Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-11C98490) on Android and iOS.
289
276
 
290
277
 
291
278
 
@@ -322,13 +309,9 @@ on Android and iOS.
322
309
  > Extends Ti.Proxy
323
310
  > Platforms: both
324
311
 
325
- Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247)
326
- on Android and iOS.
312
+ Implements the [DOM Level 2 API](https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247) on Android and iOS.
327
313
 
328
- Note that on iOS, only [Element](Titanium.XML.Element) nodes are mutable. This means
329
- that the methods `appendChild`, `insertBefore`, `removeChild`, and
330
- `replaceChild` only work on `Element` objects. If one of these methods is called on
331
- another type of node, it throws an exception.
314
+ Note that on iOS, only [Element](Titanium.XML.Element) nodes are mutable. This means that the methods `appendChild`, `insertBefore`, `removeChild`, and `replaceChild` only work on `Element` objects. If one of these methods is called on another type of node, it throws an exception.
332
315
 
333
316
  ### Properties (unique: 16/31)
334
317
  | Property | Type | Default | Platform | Description |
@@ -461,13 +444,11 @@ Titanium provides a number of global built-in objects, detailed below.
461
444
 
462
445
  ### String Utilities
463
446
 
464
- Titanium includes several extra utility functions for formatting text, attached to the
465
- global [String](Global.String) object.
447
+ Titanium includes several extra utility functions for formatting text, attached to the global [String](Global.String) object.
466
448
 
467
449
  ### console
468
450
 
469
- Titanium provides [console](Global.Console) support familiar to many JavaScript developers
470
- for logging at the toplevel, in addition to the [Titanium](Titanium.API) logging facilities.
451
+ Titanium provides [console](Global.Console) support familiar to many JavaScript developers for logging at the toplevel, in addition to the [Titanium](Titanium.API) logging facilities.
471
452
 
472
453
  ### Timers
473
454
 
@@ -551,13 +532,9 @@ Titanium has built-in support for one-off and repeating timers:
551
532
  > Platforms: both
552
533
  > Type: module
553
534
 
554
- The toplevel `console` support is intended to supplement <Titanium.API>
555
- and make it easier for developers to port existing JavaScript code
556
- (especially CommonJS modules) to Titanium.
535
+ The toplevel `console` support is intended to supplement <Titanium.API> and make it easier for developers to port existing JavaScript code (especially CommonJS modules) to Titanium.
557
536
 
558
- Note that `console` does not currently implement the complete
559
- [Console](https://developer.mozilla.org/de/docs/Web/API/Console) specification.
560
- See the following supported methods for details and submit a pull request to add more!
537
+ Note that `console` does not currently implement the complete [Console](https://developer.mozilla.org/de/docs/Web/API/Console) specification. See the following supported methods for details and submit a pull request to add more!
561
538
 
562
539
 
563
540
  ### Methods (15)
@@ -588,11 +565,9 @@ See the following supported methods for details and submit a pull request to add
588
565
  > Platforms: both
589
566
  > Type: module
590
567
 
591
- Provides support for localized number formatting, date/time formatting,
592
- and language sensitive string comparisons.
568
+ Provides support for localized number formatting, date/time formatting, and language sensitive string comparisons.
593
569
 
594
- For more detail, see the MDN website about
595
- [Intl](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl).
570
+ For more detail, see the MDN website about [Intl](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl).
596
571
 
597
572
 
598
573
  ### Methods (1)
@@ -611,8 +586,7 @@ For more detail, see the MDN website about
611
586
 
612
587
  A collator is used to perform a localized string compare or sort using a given language locale.
613
588
 
614
- For more detail, see the MDN website about
615
- [Intl.Collator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator).
589
+ For more detail, see the MDN website about [Intl.Collator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator).
616
590
 
617
591
  ### Properties (unique: 1/1)
618
592
  | Property | Type | Default | Platform | Description |
@@ -650,13 +624,9 @@ For more detail, see the MDN website about
650
624
  > Platforms: both
651
625
  > Type: module
652
626
 
653
- A `DateTimeFormat` object is used to format a `Date` object to a localized date and/or time string.
654
- This will respect the system's current language setting when outputting a full month or weekday name.
655
- It will also respect the current locale's date component ordering such as Month/Day/Year,
656
- Day/Month/Year, and Year/Month/Day.
627
+ A `DateTimeFormat` object is used to format a `Date` object to a localized date and/or time string. This will respect the system's current language setting when outputting a full month or weekday name. It will also respect the current locale's date component ordering such as Month/Day/Year, Day/Month/Year, and Year/Month/Day.
657
628
 
658
- For more detail, see the MDN website about
659
- [Intl.DateTimeFormat](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat).
629
+ For more detail, see the MDN website about [Intl.DateTimeFormat](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat).
660
630
 
661
631
  ### Properties (unique: 1/1)
662
632
  | Property | Type | Default | Platform | Description |
@@ -707,13 +677,9 @@ For more detail, see the MDN website about
707
677
  > Platforms: both
708
678
  > Type: module
709
679
 
710
- A `NumberFormat` object is used to convert a `Number` value to a localized numeric string.
711
- It provides various formatting options controlling the number of integer and fractional digits
712
- to be displayed. It can also output currency values, percentage based values, and
713
- scientific notation.
680
+ A `NumberFormat` object is used to convert a `Number` value to a localized numeric string. It provides various formatting options controlling the number of integer and fractional digits to be displayed. It can also output currency values, percentage based values, and scientific notation.
714
681
 
715
- For more detail, see the MDN website about
716
- [Intl.NumberFormat](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat).
682
+ For more detail, see the MDN website about [Intl.NumberFormat](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat).
717
683
 
718
684
  ### Properties (unique: 1/1)
719
685
  | Property | Type | Default | Platform | Description |
@@ -756,8 +722,7 @@ For more detail, see the MDN website about
756
722
  > Platforms: both
757
723
  > Type: module
758
724
 
759
- This module contains Titanium-only extensions for formatting data into locale-specific strings.
760
- The target locale is configured by the user in the device's system Settings.
725
+ This module contains Titanium-only extensions for formatting data into locale-specific strings. The target locale is configured by the user in the device's system Settings.
761
726
 
762
727
 
763
728
  ### Methods (5)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ti-expert
3
- description: "Use when designing, reviewing, auditing, analyzing, or examining Titanium SDK architecture and implementation (Alloy or Classic) — creating controllers/views/services, choosing models vs collections, deciding between app-owned and system UI, designing reusable Widgets or feedback/modality patterns, hunting memory leaks and cleanup gaps, testing, migrating legacy apps, or building adaptive layouts for tablets, foldables, and large screens. AUTO-DETECT: If tiapp.xml exists, invoke BEFORE architectural decisions, new controllers/views, feedback components, or restructuring. Titanium navigation, memory, event, and modal patterns differ from web frameworks."
3
+ description: "Use when designing, reviewing, auditing, or analyzing Titanium SDK architecture and implementation (Alloy or Classic) — creating controllers/views/services, choosing models vs collections, deciding between app-owned and system UI, designing reusable Widgets or feedback/modality patterns, hunting memory leaks and cleanup gaps, testing, migrating legacy apps, building adaptive layouts for tablets, foldables and large screens, or moving documents in and out of the app: custom file types, UTIs, CFBundleDocumentTypes, Android intent filters, AirDrop/Quick Share, document icons, sharing a link or file via the iOS share sheet or Android intent chooser. AUTO-DETECT: If tiapp.xml exists, invoke BEFORE architectural decisions, new controllers/views, feedback components, or restructuring. Titanium navigation, memory, event, and modal patterns differ from web frameworks."
4
4
  argument-hint: "[architecture-topic]"
5
5
  allowed-tools: Read, Grep, Glob, Edit, Write, Bash(git *), Bash(node *)
6
6
  ---
@@ -11,8 +11,7 @@ Practical architecture and implementation guidance for Titanium SDK apps (Alloy
11
11
 
12
12
  ## Required workflow
13
13
 
14
- This file is an index. Read the references that govern the task before making a
15
- recommendation or changing code.
14
+ This file is an index. Read the references that govern the task before making a recommendation or changing code.
16
15
 
17
16
  | Task | Required reading |
18
17
  | --- | --- |
@@ -22,12 +21,12 @@ recommendation or changing code.
22
21
  | Migrating native dialogs, Toasts, or local overlays | [Feedback migration](references/feedback-migration.md), [Migration patterns](references/migration-patterns.md) |
23
22
  | Theme or dark mode | [Theming](references/theming.md); if PurgeTSS is detected, invoke the `purgetss` skill before styling |
24
23
  | Tablet, foldable, large screen, or responsive behavior | [Adaptive layouts](references/adaptive-layouts.md) |
24
+ | Opening or receiving files: custom extensions, UTIs, intent filters, AirDrop, Quick Share, document icons | [File type association](references/file-type-association.md) |
25
+ | Sending content out: share sheet, intent chooser, sharing a link or a file, `dk.napp.social`, `com.alcoapps.socialshare` | [Sharing content out](references/sharing.md) |
25
26
  | Security architecture | [Security fundamentals](references/security-fundamentals.md), [Device security](references/security-device.md) |
26
27
  | Testing or performance | Load the matching guide under Quality & Performance below |
27
28
 
28
- Support recommendations with `[source: references/<file>.md]`. If a claim cannot
29
- be verified from the loaded references or inspected project, prefix it with
30
- `FROM_MEMORY (unverified):` and do not present it as a settled project fact.
29
+ Support recommendations with `[source: references/<file>.md]`. If a claim cannot be verified from the loaded references or inspected project, prefix it with `FROM_MEMORY (unverified):` and do not present it as a settled project fact.
31
30
 
32
31
  ## Project detection
33
32
 
@@ -105,11 +104,7 @@ Detailed examples and full implementation samples are available in: [Architectur
105
104
 
106
105
  ## Titanium style sheets rules (low freedom)
107
106
 
108
- Before styling, detect `purgetss/` or `purgetss/config.cjs`. If present, invoke
109
- the `purgetss` skill, verify every utility, and never edit the generated
110
- `app/styles/app.tss`. Without PurgeTSS, use standard Alloy TSS files. In either
111
- case, keep behavior in XML/controllers and use semantic colors for app-owned
112
- surfaces when the project supports them.
107
+ Before styling, detect `purgetss/` or `purgetss/config.cjs`. If present, invoke the `purgetss` skill, verify every utility, and never edit the generated `app/styles/app.tss`. Without PurgeTSS, use standard Alloy TSS files. In either case, keep behavior in XML/controllers and use semantic colors for app-owned surfaces when the project supports them.
113
108
 
114
109
  > **🚨 Critical: platform-specific properties require modifiers**
115
110
  > Using `Ti.UI.iOS.*` or `Ti.UI.Android.*` properties without platform modifiers breaks cross-platform builds.
@@ -185,6 +180,8 @@ For the complete reference with examples, see [Alloy builtins and globals](refer
185
180
  - [Alloy Builtins & Globals](references/alloy-builtins.md)
186
181
  - [Code Conventions](references/code-conventions.md)
187
182
  - [Controller Patterns](references/controller-patterns.md)
183
+ - [File Type Association](references/file-type-association.md) (custom extensions and UTIs, `CFBundleDocumentTypes`, Android intent filters, receiving files from AirDrop/Quick Share, document icons)
184
+ - [Sharing Content Out](references/sharing.md) (share sheet and intent chooser, why iOS still needs `dk.napp.social` and Android does not, text versus file, iPad popovers)
188
185
  - [Feedback Surfaces & App-Owned UI](references/feedback-surfaces.md)
189
186
  - [Feedback Widget Contracts](references/feedback-widget-contracts.md)
190
187
  - [Feedback Migration](references/feedback-migration.md)
@@ -35,9 +35,7 @@ What this means: portrait-only apps will be forced into landscape/resized on lar
35
35
 
36
36
  ### It already started in Android 16 (API 36)
37
37
 
38
- This is usually described as an API 37 change, but it lands one release earlier: an app
39
- targeting **API 36** already has `android:screenOrientation` ignored on >= 600dp displays
40
- running Android 16. The difference is that API 36 still ships an opt-out:
38
+ This is usually described as an API 37 change, but it lands one release earlier: an app targeting **API 36** already has `android:screenOrientation` ignored on >= 600dp displays running Android 16. The difference is that API 36 still ships an opt-out:
41
39
 
42
40
  ```xml
43
41
  <!-- inside <application>, or on an individual <activity> -->
@@ -46,12 +44,9 @@ running Android 16. The difference is that API 36 still ships an opt-out:
46
44
  android:value="true"/>
47
45
  ```
48
46
 
49
- The opt-out stops working the moment you target API 37, so treat it as a bridge while the
50
- layout is made adaptive — not as a fix. Source: [Android 16 behavior changes](https://developer.android.com/about/versions/16/behavior-changes-16).
47
+ The opt-out stops working the moment you target API 37, so treat it as a bridge while the layout is made adaptive — not as a fix. Source: [Android 16 behavior changes](https://developer.android.com/about/versions/16/behavior-changes-16).
51
48
 
52
- Worth knowing when debugging: this only kicks in at >= 600dp. If a **phone** is rotating
53
- despite a portrait lock, the cause is in the app, not in Android — see the orientation
54
- debugging recipe in section 7.
49
+ Worth knowing when debugging: this only kicks in at >= 600dp. If a **phone** is rotating despite a portrait lock, the cause is in the app, not in Android — see the orientation debugging recipe in section 7.
55
50
 
56
51
  ### Related: edge-to-edge (API 36)
57
52
 
@@ -429,9 +424,7 @@ To verify the exact generated activity name, check `build/android/app/src/main/A
429
424
 
430
425
  ### Which activities a lock has to cover
431
426
 
432
- `android:screenOrientation` is per-activity — it is not inherited from `<application>`. Every
433
- window the app opens runs inside one of a small, fixed set of activities declared by the
434
- Titanium AAR, so read the canonical list from the SDK instead of memorising it:
427
+ `android:screenOrientation` is per-activity — it is not inherited from `<application>`. Every window the app opens runs inside one of a small, fixed set of activities declared by the Titanium AAR, so read the canonical list from the SDK instead of memorising it:
435
428
 
436
429
  ```bash
437
430
  cat ~/.gradle/caches/*/transforms/*/transformed/jetified-titanium-*/AndroidManifest.xml
@@ -448,8 +441,7 @@ ti.modules.titanium.media.TiVideoActivity
448
441
  ti.modules.titanium.ui.android.TiPreferencesActivity
449
442
  ```
450
443
 
451
- The seventh is the app's own root activity, generated from the `<name>` in tiapp.xml (see the
452
- derivation rule above). Which one hosts what:
444
+ The seventh is the app's own root activity, generated from the `<name>` in tiapp.xml (see the derivation rule above). Which one hosts what:
453
445
 
454
446
  | What the app does | Activity |
455
447
  |---|---|
@@ -461,23 +453,12 @@ derivation rule above). Which one hosts what:
461
453
 
462
454
  Two things are better left undeclared:
463
455
 
464
- - **`android:configChanges`.** The CLI strips it before the merge even happens — `_build.js`
465
- keeps a list of the `TiBaseActivity`-derived activities and calls
466
- `removeActivityAttribute(name, 'android:configChanges')` on each, with the reason spelled out
467
- in the source: *"Most devs don't set this right, causing UI to disappear when a config change
468
- occurs for a missing setting."* So a hand-written subset is not dangerous, just dead weight —
469
- Titanium's full list always wins.
470
- - **A lock on `TiTranslucentActivity`.** Android 8–11 throws `IllegalStateException` ("Only
471
- fullscreen opaque activities can request orientation") when a translucent activity requests a
472
- fixed orientation. Declaring `orientationModes` on those windows is safer: the SDK applies it
473
- inside a try/catch (`TiWindowProxy.setOrientationModes`), so the worst case is a modal that
474
- rotates instead of an app that crashes.
456
+ - **`android:configChanges`.** The CLI strips it before the merge even happens — `_build.js` keeps a list of the `TiBaseActivity`-derived activities and calls `removeActivityAttribute(name, 'android:configChanges')` on each, with the reason spelled out in the source: *"Most devs don't set this right, causing UI to disappear when a config change occurs for a missing setting."* So a hand-written subset is not dangerous, just dead weight — Titanium's full list always wins.
457
+ - **A lock on `TiTranslucentActivity`.** Android 8–11 throws `IllegalStateException` ("Only fullscreen opaque activities can request orientation") when a translucent activity requests a fixed orientation. Declaring `orientationModes` on those windows is safer: the SDK applies it inside a try/catch (`TiWindowProxy.setOrientationModes`), so the worst case is a modal that rotates instead of an app that crashes.
475
458
 
476
459
  ### Prefer orientationModes over the manifest
477
460
 
478
- `orientationModes` is defined on `TiWindowProxy`, so the same declaration works on `Window`,
479
- `TabGroup` and `NavigationWindow`. Being per-window it also composes with form-factor queries,
480
- which is what you usually want:
461
+ `orientationModes` is defined on `TiWindowProxy`, so the same declaration works on `Window`, `TabGroup` and `NavigationWindow`. Being per-window it also composes with form-factor queries, which is what you usually want:
481
462
 
482
463
  ```xml
483
464
  <!-- PurgeTSS -->
@@ -489,14 +470,11 @@ which is what you usually want:
489
470
  '#tabs[formFactor=handheld]': { orientationModes: [ Ti.UI.PORTRAIT ] }
490
471
  ```
491
472
 
492
- Alloy resolves `formFactor` from `Ti.Platform.Android.physicalSizeCategory`, which is why this
493
- is more reliable than any width comparison you could write yourself.
473
+ Alloy resolves `formFactor` from `Ti.Platform.Android.physicalSizeCategory`, which is why this is more reliable than any width comparison you could write yourself.
494
474
 
495
- Keep the manifest for what Alloy cannot reach: the root activity, which shows the splash before
496
- any JS runs, and optionally `TiActivity` as a blanket fallback for windows that carry no class.
475
+ Keep the manifest for what Alloy cannot reach: the root activity, which shows the splash before any JS runs, and optionally `TiActivity` as a blanket fallback for windows that carry no class.
497
476
 
498
- A single Ti Element rule covers every window in the app without touching a single view, which
499
- is usually all an Alloy app needs:
477
+ A single Ti Element rule covers every window in the app without touching a single view, which is usually all an Alloy app needs:
500
478
 
501
479
  ```javascript
502
480
  // purgetss/config.cjs
@@ -511,8 +489,7 @@ module.exports = {
511
489
  'Window[formFactor=handheld]': { orientationModes: [ Ti.UI.PORTRAIT ] }
512
490
  ```
513
491
 
514
- Note it matches `Window` only, so a `TabGroup` still needs its own class. And because the
515
- declaration is per-window, it does nothing for the splash — that one stays in the manifest.
492
+ Note it matches `Window` only, so a `TabGroup` still needs its own class. And because the declaration is per-window, it does nothing for the splash — that one stays in the manifest.
516
493
 
517
494
  ### Debugging a rotation that shouldn't happen
518
495
 
@@ -522,13 +499,9 @@ Ask the system for the effective value instead of re-reading the manifest:
522
499
  adb shell dumpsys activity activities | grep -E "topResumedActivity|requestedOrientation"
523
500
  ```
524
501
 
525
- If `requestedOrientation` disagrees with what tiapp.xml declares, something overrode it at
526
- runtime — grep the app for `requestedOrientation` and `orientationModes` before touching the
527
- manifest again. Note that an *existing* `orientationModes` can be the bug rather than the fix:
528
- an empty array unlocks rotation (see the anti-patterns above).
502
+ If `requestedOrientation` disagrees with what tiapp.xml declares, something overrode it at runtime — grep the app for `requestedOrientation` and `orientationModes` before touching the manifest again. Note that an *existing* `orientationModes` can be the bug rather than the fix: an empty array unlocks rotation (see the anti-patterns above).
529
503
 
530
- Before blaming the OS, let the SDK tell you. Titanium logs a warning when Android drops the
531
- request on a large screen, so this either hits or rules that cause out immediately:
504
+ Before blaming the OS, let the SDK tell you. Titanium logs a warning when Android drops the request on a large screen, so this either hits or rules that cause out immediately:
532
505
 
533
506
  ```bash
534
507
  adb logcat | grep "Orientation request will be ignored"
@@ -536,8 +509,7 @@ adb logcat | grep "Orientation request will be ignored"
536
509
  # Orientation request will be ignored on Android 16+.
537
510
  ```
538
511
 
539
- And to see the size bucket the device actually reports — `normal` means a phone, so the >= 600dp
540
- rule does not apply and the cause is in the app:
512
+ And to see the size bucket the device actually reports — `normal` means a phone, so the >= 600dp rule does not apply and the cause is in the app:
541
513
 
542
514
  ```bash
543
515
  adb shell am get-config # e.g. ...-sw360dp-w360dp-h802dp-normal-...
@@ -97,10 +97,7 @@ Alloy.Collections.notifications = new Backbone.Collection()
97
97
  // <View if="Alloy.Globals.isLoggedIn">
98
98
  ```
99
99
 
100
- Do not use `Alloy.Globals` as the default dark-mode palette. Prefer Titanium
101
- semantic colors; when PurgeTSS is detected, use its semantic color and Appearance
102
- workflow. Reserve a global runtime palette for custom theme requirements that
103
- semantic light/dark/system roles cannot model. See [Theming](theming.md).
100
+ Do not use `Alloy.Globals` as the default dark-mode palette. Prefer Titanium semantic colors; when PurgeTSS is detected, use its semantic color and Appearance workflow. Reserve a global runtime palette for custom theme requirements that semantic light/dark/system roles cannot model. See [Theming](theming.md).
104
101
 
105
102
  ### Globals vs services
106
103
 
@@ -188,8 +188,7 @@ api.getFrames()
188
188
  ## Controller rules
189
189
 
190
190
  **DO:**
191
- - Use verified PurgeTSS utilities when detected; otherwise define styles in
192
- per-controller TSS and manually maintained global TSS.
191
+ - Use verified PurgeTSS utilities when detected; otherwise define styles in per-controller TSS and manually maintained global TSS.
193
192
  - Orchestrate view and model/collection interactions.
194
193
  - Handle UI events and delegate to services.
195
194
  - Format data for display (simple cases).
@@ -246,10 +245,7 @@ See [ControllerAutoCleanup.js](../assets/ControllerAutoCleanup.js) for the compl
246
245
 
247
246
  ## Widget structure
248
247
 
249
- Widgets are self-contained components with their own public API, state, assets,
250
- and lifecycle. Choose one for a portable boundary, not after an arbitrary number
251
- of usages. A first-use component with timers, modal state, and cleanup can merit
252
- a Widget; repeated static styling does not.
248
+ Widgets are self-contained components with their own public API, state, assets, and lifecycle. Choose one for a portable boundary, not after an arbitrary number of usages. A first-use component with timers, modal state, and cleanup can merit a Widget; repeated static styling does not.
253
249
 
254
250
  ```
255
251
  app/widgets/
@@ -280,8 +276,7 @@ app/widgets/
280
276
  }
281
277
  ```
282
278
 
283
- Register the Widget in the app's `app/config.json`; the dependency key must
284
- match the manifest `id`:
279
+ Register the Widget in the app's `app/config.json`; the dependency key must match the manifest `id`:
285
280
 
286
281
  ```json
287
282
  {
@@ -491,10 +486,7 @@ render()
491
486
  | Could be extracted to another project | Has no independent package contract |
492
487
  | Needs its own `widget.json` manifest | Remains lightweight and app-local |
493
488
 
494
- Usage count is supporting evidence only. Also consider a screen-local XML state
495
- for loading/empty/error content, a style class for appearance without behavior,
496
- or native UI when the operating system owns the workflow. See
497
- [Feedback Widget Contracts](feedback-widget-contracts.md).
489
+ Usage count is supporting evidence only. Also consider a screen-local XML state for loading/empty/error content, a style class for appearance without behavior, or native UI when the operating system owns the workflow. See [Feedback Widget Contracts](feedback-widget-contracts.md).
498
490
 
499
491
  ## config.json reference
500
492
 
@@ -1,46 +1,35 @@
1
1
  # Titanium Alloy anti-patterns
2
2
 
3
3
  ## 1. Inline styling instead of TSS
4
- **Symptom:** Using inline attributes like `backgroundColor="#fff"` directly in XML views.
5
- **Problem:** Inline attributes make theme changes impossible and scatter visual definitions across views.
6
- **Solution:** Define styles in TSS files using IDs or class selectors.
4
+ **Symptom:** Using inline attributes like `backgroundColor="#fff"` directly in XML views. **Problem:** Inline attributes make theme changes impossible and scatter visual definitions across views. **Solution:** Define styles in TSS files using IDs or class selectors.
7
5
 
8
6
  ## 2. Fat controllers
9
- **Symptom:** Controllers with 100+ lines handling logic, API, and UI.
10
- **Solution:** Delegate business logic to `lib/services/` and API calls to `lib/api/`.
7
+ **Symptom:** Controllers with 100+ lines handling logic, API, and UI. **Solution:** Delegate business logic to `lib/services/` and API calls to `lib/api/`.
11
8
 
12
9
  ## 3. Memory leaks (Missing Cleanup)
13
- **Symptom:** Adding `Ti.App` or `Alloy.Collections` listeners without a `cleanup()` function.
14
- **Solution:** Always implement `$.cleanup = cleanup` and remove listeners there.
10
+ **Symptom:** Adding `Ti.App` or `Alloy.Collections` listeners without a `cleanup()` function. **Solution:** Always implement `$.cleanup = cleanup` and remove listeners there.
15
11
 
16
12
  ## 4. Direct native module calls
17
- **Symptom:** Calling `require('ti.module')` directly in a controller.
18
- **Solution:** Wrap it in a service in `lib/services/` (e.g., `audioService.js`).
13
+ **Symptom:** Calling `require('ti.module')` directly in a controller. **Solution:** Wrap it in a service in `lib/services/` (e.g., `audioService.js`).
19
14
 
20
15
  ## 5. Direct controller navigation
21
- **Symptom:** `Alloy.createController('name').getView().open()`.
22
- **Solution:** Use a Navigation Service to centralize `open/close` and trigger the `cleanup()` function automatically.
16
+ **Symptom:** `Alloy.createController('name').getView().open()`. **Solution:** Use a Navigation Service to centralize `open/close` and trigger the `cleanup()` function automatically.
23
17
 
24
18
  ## 6. Complex matrix animations
25
- **Symptom:** Manual use of `Ti.UI.create2DMatrix()` for simple animations.
26
- **Solution:** Use `Ti.UI.createAnimation()` for opacity, transform, and duration-based animations. Reserve 2D Matrix for complex multi-property transforms.
19
+ **Symptom:** Manual use of `Ti.UI.create2DMatrix()` for simple animations. **Solution:** Use `Ti.UI.createAnimation()` for opacity, transform, and duration-based animations. Reserve 2D Matrix for complex multi-property transforms.
27
20
 
28
21
  ## 7. Hardcoded strings & missing a11y
29
- **Symptom:** `text="Login"` instead of `text="L('login')"`, or missing `accessibilityLabel`.
30
- **Solution:** Always use i18n and accessibility properties.
22
+ **Symptom:** `text="Login"` instead of `text="L('login')"`, or missing `accessibilityLabel`. **Solution:** Always use i18n and accessibility properties.
31
23
 
32
24
  ## 8. Logic in TSS
33
- **Symptom:** Using conditionals or calculations inside TSS.
34
- **Solution:** Keep styling declarative in TSS files.
25
+ **Symptom:** Using conditionals or calculations inside TSS. **Solution:** Keep styling declarative in TSS files.
35
26
 
36
27
  ---
37
28
 
38
29
  ## Titanium layout anti-patterns
39
30
 
40
31
  ## 9. Padding on container views
41
- **Symptom:** Setting `padding` on View, Window, ScrollView, or TableView.
42
- **Problem:** Base container elements don't support padding in Titanium.
43
- **Solution:** Use margins on children instead:
32
+ **Symptom:** Setting `padding` on View, Window, ScrollView, or TableView. **Problem:** Base container elements don't support padding in Titanium. **Solution:** Use margins on children instead:
44
33
  ```tss
45
34
  /* WRONG */
46
35
  "#container": { padding: 16 }
@@ -50,39 +39,21 @@
50
39
  ```
51
40
 
52
41
  ## 10. Redundant composite layout
53
- **Symptom:** Adding `layout: 'composite'` to Views.
54
- **Problem:** Composite (absolute positioning) is the DEFAULT layout. Setting it is redundant.
55
- **Solution:** Omit `layout` for composite, only specify `layout: 'horizontal'` or `layout: 'vertical'` when needed.
42
+ **Symptom:** Adding `layout: 'composite'` to Views. **Problem:** Composite (absolute positioning) is the DEFAULT layout. Setting it is redundant. **Solution:** Omit `layout` for composite, only specify `layout: 'horizontal'` or `layout: 'vertical'` when needed.
56
43
 
57
44
  ## 11. Using `lib/` prefix in require statements
58
- **Symptom:** `const service = require('lib/services/picsum')`
59
- **Problem:** Alloy flattens the `lib/` folder during build. Files in `app/lib/services/` become `Resources/iphone/services/`.
60
- **Solution:** Omit the `lib/` prefix: `const service = require('services/picsum')`
45
+ **Symptom:** `const service = require('lib/services/picsum')` **Problem:** Alloy flattens the `lib/` folder during build. Files in `app/lib/services/` become `Resources/iphone/services/`. **Solution:** Omit the `lib/` prefix: `const service = require('services/picsum')`
61
46
 
62
47
  ## 12. Wrong window ID in controller
63
- **Symptom:** Using `$.index.open()` when the Window has `id="mainWindow"`.
64
- **Problem:** Alloy generates `$` references from XML IDs. If Window is `id="mainWindow"`, `$.index` doesn't exist.
65
- **Solution:** Match the ID: `$.mainWindow.open()`
48
+ **Symptom:** Using `$.index.open()` when the Window has `id="mainWindow"`. **Problem:** Alloy generates `$` references from XML IDs. If Window is `id="mainWindow"`, `$.index` doesn't exist. **Solution:** Match the ID: `$.mainWindow.open()`
66
49
 
67
50
  ## 13. Using `Ti.UI.createNotification`
68
- **Symptom:** `Ti.UI.createNotification({ message: 'Hi' }).show()`
69
- **Problem:** This API doesn't exist in Titanium. Causes "invalid method" error.
70
- **Solution:** Classify the feedback before choosing UI. Use the app's Snackbar
71
- Widget for transient foreground feedback, inline/Banner state for persistent
72
- conditions, and an app-owned Dialog only for blocking or critical information.
73
- Use the supported platform notification APIs only for actual OS notifications.
74
- See [Feedback Surfaces](feedback-surfaces.md).
51
+ **Symptom:** `Ti.UI.createNotification({ message: 'Hi' }).show()` **Problem:** This API doesn't exist in Titanium. Causes "invalid method" error. **Solution:** Classify the feedback before choosing UI. Use the app's Snackbar Widget for transient foreground feedback, inline/Banner state for persistent conditions, and an app-owned Dialog only for blocking or critical information. Use the supported platform notification APIs only for actual OS notifications. See [Feedback Surfaces](feedback-surfaces.md).
75
52
 
76
53
  ## 14. Using nonexistent iOS share APIs
77
- **Symptom:** `Ti.UI.iOS.createActivityPopover` or `alloy/social` with wrong methods.
78
- **Problem:** These APIs either don't exist or have changed. Causes runtime errors.
79
- **Solution:**
80
- - Keep sharing system-owned. Use the currently supported Titanium share/document
81
- API or native module for the target platform and verify its current contract
82
- with the `ti-api` skill.
83
- - Do not imitate a share sheet with an app-owned `OptionDialog`. A Bottom Sheet
84
- may choose an app action such as an export format, but the OS share surface
85
- owns the final destination.
54
+ **Symptom:** `Ti.UI.iOS.createActivityPopover` or `alloy/social` with wrong methods. **Problem:** These APIs either don't exist or have changed. Causes runtime errors. **Solution:**
55
+ - Keep sharing system-owned. Use the currently supported Titanium share/document API or native module for the target platform and verify its current contract with the `ti-api` skill.
56
+ - Do not imitate a share sheet with an app-owned `OptionDialog`. A Bottom Sheet may choose an app action such as an export format, but the OS share surface owns the final destination.
86
57
 
87
58
  ## Community-Discovered Patterns
88
59
 
@@ -54,15 +54,11 @@ const name = user.name
54
54
 
55
55
  ## Styling with TSS
56
56
 
57
- First detect `purgetss/` or `purgetss/config.cjs`. If present, invoke the
58
- `purgetss` skill, use verified utilities, and do not edit generated
59
- `app/styles/app.tss`. The manual TSS organization below applies when PurgeTSS is
60
- not present or to specific properties for which that skill confirms no utility.
57
+ First detect `purgetss/` or `purgetss/config.cjs`. If present, invoke the `purgetss` skill, use verified utilities, and do not edit generated `app/styles/app.tss`. The manual TSS organization below applies when PurgeTSS is not present or to specific properties for which that skill confirms no utility.
61
58
 
62
59
  ### TSS file organization
63
60
 
64
- Every controller can have a matching TSS file. Standard Alloy also supports a
65
- manually maintained global `app.tss`.
61
+ Every controller can have a matching TSS file. Standard Alloy also supports a manually maintained global `app.tss`.
66
62
 
67
63
  ```
68
64
  app/styles/
@@ -281,9 +281,7 @@ async function loadData() {
281
281
 
282
282
  ## Modal and dialog patterns
283
283
 
284
- Declare the app-owned `dialog` and `bottomSheet` Widgets in the window XML.
285
- Attach them after the host exists and destroy them from the controller cleanup.
286
- Keep a modal Window for a distinct multi-step task, not for ordinary feedback.
284
+ Declare the app-owned `dialog` and `bottomSheet` Widgets in the window XML. Attach them after the host exists and destroy them from the controller cleanup. Keep a modal Window for a distinct multi-step task, not for ordinary feedback.
287
285
 
288
286
  ```javascript
289
287
  function attachFeedback(hostWindow) {
@@ -20,16 +20,9 @@
20
20
 
21
21
  ## Reading these examples
22
22
 
23
- Snippets that call `$.dialog`, `$.bottomSheet`, or `$.snackbar` expect the app to
24
- own those surfaces as Alloy Widgets under `app/widgets/`. Their public API,
25
- queueing, and cleanup rules live in [Feedback Widget Contracts](feedback-widget-contracts.md);
26
- [Feedback Surfaces](feedback-surfaces.md) covers which surface a given event
27
- deserves. The `<Widget>` declaration alone will not compile until those Widgets
28
- exist and are registered in `app/config.json`.
29
-
30
- Styles below carry literal hex values so each example reads on its own. Production
31
- code should name semantic color roles instead, so light and dark resolve without a
32
- second code path — see [Theming and dark mode](theming.md).
23
+ Snippets that call `$.dialog`, `$.bottomSheet`, or `$.snackbar` expect the app to own those surfaces as Alloy Widgets under `app/widgets/`. Their public API, queueing, and cleanup rules live in [Feedback Widget Contracts](feedback-widget-contracts.md); [Feedback Surfaces](feedback-surfaces.md) covers which surface a given event deserves. The `<Widget>` declaration alone will not compile until those Widgets exist and are registered in `app/config.json`.
24
+
25
+ Styles below carry literal hex values so each example reads on its own. Production code should name semantic color roles instead, so light and dark resolve without a second code path — see [Theming and dark mode](theming.md).
33
26
 
34
27
  ## API client service
35
28
  Standard logic for network requests.