@maccesar/titools 4.17.1 → 4.19.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/README.md +12 -8
- package/commands/ti-audit.md +1 -1
- package/package.json +1 -1
- package/skills/purgetss/SKILL.md +45 -22
- package/skills/purgetss/references/animation-advanced.md +93 -226
- package/skills/purgetss/references/animation-system.md +26 -17
- package/skills/purgetss/references/app-branding.md +53 -26
- package/skills/purgetss/references/appearance-module.md +63 -9
- package/skills/purgetss/references/class-categories.md +2 -2
- package/skills/purgetss/references/class-index.md +1 -1
- package/skills/purgetss/references/classic-projects.md +115 -0
- package/skills/purgetss/references/cli-commands.md +71 -74
- package/skills/purgetss/references/custom-fonts.md +57 -8
- package/skills/purgetss/references/customization-deep-dive.md +12 -7
- package/skills/purgetss/references/dynamic-component-creation.md +1 -1
- package/skills/purgetss/references/icon-fonts.md +33 -6
- package/skills/purgetss/references/installation-setup.md +12 -2
- package/skills/purgetss/references/multi-density-images.md +10 -10
- package/skills/purgetss/references/purgetss-ui-classic.md +341 -0
- package/skills/purgetss/references/semantic-colors.md +17 -7
- package/skills/purgetss/references/version-history.md +28 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# App Icons & Branding
|
|
2
2
|
|
|
3
|
-
The `purgetss brand` command
|
|
3
|
+
The `purgetss brand` command generates the complete Titanium branding set from one main SVG or PNG logo: launcher icons, adaptive icons, iOS 18+ Dark/Tinted variants, marketplace artwork, and both splash sets. Per-piece overrides are available when needed. Alloy and Classic layouts are auto-detected, and since v7.14.0 a normal run follows the platforms enabled in `tiapp.xml`.
|
|
4
4
|
|
|
5
|
-
The
|
|
5
|
+
The command also creates Titanium-consumed Classic paths that a fresh Classic template does not seed, including the 11 Android `Resources/android/images/res-*` splash variants. An explicit `--only` is an intentional override that can prepare assets for a disabled deployment target.
|
|
6
6
|
|
|
7
7
|
For the terse flag reference, see the [`brand` command reference](./cli-commands.md#brand-command). For sibling UI assets, see [Multi-Density Images](./multi-density-images.md).
|
|
8
8
|
|
|
@@ -30,6 +30,7 @@ For the terse flag reference, see the [`brand` command reference](./cli-commands
|
|
|
30
30
|
- [iOS 18+ Dark and Tinted variants](#ios-18-dark-and-tinted-variants)
|
|
31
31
|
- [Brand color](#brand-color)
|
|
32
32
|
- [Padding guidance](#padding-guidance)
|
|
33
|
+
- [Rounded non-icon artwork](#rounded-non-icon-artwork)
|
|
33
34
|
- [Cleanup legacy branding artifacts](#cleanup-legacy-branding-artifacts)
|
|
34
35
|
- [Troubleshooting](#troubleshooting)
|
|
35
36
|
- [Flag reference](#flag-reference)
|
|
@@ -51,9 +52,10 @@ purgetss brand
|
|
|
51
52
|
|
|
52
53
|
On a first run the command:
|
|
53
54
|
|
|
54
|
-
1. Creates
|
|
55
|
-
2.
|
|
56
|
-
3.
|
|
55
|
+
1. Creates `purgetss/config.cjs` from the canonical template if the file is missing, including in standalone Classic projects.
|
|
56
|
+
2. Creates or updates the `brand:` section with current defaults.
|
|
57
|
+
3. Generates branding files for the enabled deployment targets directly into the project.
|
|
58
|
+
4. Prints a compact summary of what was written.
|
|
57
59
|
|
|
58
60
|
Pass `--dry-run` to preview without writing any files:
|
|
59
61
|
|
|
@@ -61,6 +63,8 @@ Pass `--dry-run` to preview without writing any files:
|
|
|
61
63
|
purgetss brand --dry-run
|
|
62
64
|
```
|
|
63
65
|
|
|
66
|
+
You may also pass a source directly. When a standalone Classic project has no canonical `purgetss/brand/logo.{svg,png}`, the confirmed run moves that positional source into the convention and reports the destination. An existing canonical logo is never replaced silently.
|
|
67
|
+
|
|
64
68
|
## The `purgetss/brand/` convention
|
|
65
69
|
|
|
66
70
|
`init` creates `purgetss/brand/` (alongside `fonts/` and `images/`) so the folder is already there the first time you look for it, even before you've dropped in a logo.
|
|
@@ -140,13 +144,15 @@ On the first run, `purgetss brand` adds a `brand:` block to your existing `purge
|
|
|
140
144
|
|
|
141
145
|
```javascript
|
|
142
146
|
brand: {
|
|
143
|
-
background: '#FFFFFF',
|
|
144
|
-
|
|
145
|
-
|
|
147
|
+
background: '#FFFFFF', // inherited by every piece that doesn't set its own
|
|
148
|
+
artworkCornerRadius: '0%', // rounded non-icon artwork: splashes, Feature Graphic and LaunchLogo
|
|
149
|
+
confirmOverwrites: true, // prompt before overwriting files (set false to skip)
|
|
150
|
+
optimize: false, // true = quantize the generated PNGs to a palette (lossy, ~71% smaller)
|
|
146
151
|
|
|
147
152
|
// One block per piece. Artwork comes from purgetss/brand/logo-<piece>.{svg,png};
|
|
148
153
|
// these keys are for numbers, colors and activation. Padding is never inherited.
|
|
149
|
-
|
|
154
|
+
// Only iosSplash, androidSplash, featureGraphic and launchLogo accept cornerRadius.
|
|
155
|
+
icon: { padding: '0%' }, // DefaultIcon.png + DefaultIcon-ios.png
|
|
150
156
|
dark: { background: null }, // DefaultIcon-Dark.png
|
|
151
157
|
tinted: {}, // DefaultIcon-Tinted.png
|
|
152
158
|
iosSplash: { padding: '26%' }, // assets/iphone/Default*.png × 16
|
|
@@ -155,7 +161,7 @@ brand: {
|
|
|
155
161
|
featureGraphic: { padding: '12%' }, // MarketplaceArtworkFeature.png (1024×500)
|
|
156
162
|
adaptive: { padding: '18%' }, // ic_launcher_{foreground,background,monochrome}.png × 5 + ic_launcher.xml
|
|
157
163
|
legacyIcon: { padding: '10%' }, // ic_launcher.png × 5
|
|
158
|
-
appicon: {},
|
|
164
|
+
appicon: { padding: '10%' }, // appicon.png (128×128)
|
|
159
165
|
androidSplash: { padding: '26%' }, // assets/android/default.png + images/res-*/default.png × 11
|
|
160
166
|
|
|
161
167
|
// Opt-in: inert until you edit the Android theme / FCM meta-data by hand.
|
|
@@ -167,6 +173,8 @@ brand: {
|
|
|
167
173
|
|
|
168
174
|
Change only what you want to keep as a project default. CLI flags still win for one-off runs.
|
|
169
175
|
|
|
176
|
+
Use flags for temporary artwork, geometry, the shared background, selection, activation, and optimization. Keep persistent choices such as `confirmOverwrites`, permanent `enabled` values, and exceptional per-piece backgrounds in `config.cjs`.
|
|
177
|
+
|
|
170
178
|
### Older configs update themselves
|
|
171
179
|
|
|
172
180
|
PurgeTSS keeps `config.cjs` current the same way it renamed `config.js` to `config.cjs`: **on the file, once**. When the `brand:` block uses a shape from an earlier version, the next run rewrites it to the per-piece structure and carries over everything that had been customized (paddings, colors, logo paths, enabled flags), then lists each value it moved:
|
|
@@ -198,11 +206,12 @@ A key `brand:` does not define stops the run before a single file is written, at
|
|
|
198
206
|
Unknown key(s) in the brand: section of purgetss/config.cjs:
|
|
199
207
|
• brand.adaptive.paddig
|
|
200
208
|
|
|
201
|
-
Top-level keys: background,
|
|
209
|
+
Top-level keys: background, artworkCornerRadius, splashCornerRadius, confirmOverwrites,
|
|
210
|
+
optimize, logo, monochromeLogo
|
|
202
211
|
Piece blocks: icon, dark, tinted, iosSplash, launchLogo, marketplace, featureGraphic,
|
|
203
212
|
adaptive, legacyIcon, appicon, androidSplash, splashIcon,
|
|
204
213
|
notificationIcon, ninePatch
|
|
205
|
-
Inside a piece: logo, padding, background, enabled
|
|
214
|
+
Inside a piece: logo, padding, cornerRadius, background, enabled
|
|
206
215
|
|
|
207
216
|
Check the spelling. Nothing was written.
|
|
208
217
|
```
|
|
@@ -211,12 +220,13 @@ A typo is deliberately **not** treated as an old structure: rewriting the block
|
|
|
211
220
|
|
|
212
221
|
## Brand config reference
|
|
213
222
|
|
|
214
|
-
Every piece accepts the same
|
|
223
|
+
Every piece accepts the same five keys, where they apply:
|
|
215
224
|
|
|
216
225
|
| Key | What it does |
|
|
217
226
|
| --- | --- |
|
|
218
227
|
| `logo` | Path to this piece's artwork, when it lives outside `purgetss/brand/`. |
|
|
219
228
|
| `padding` | Inset per side, as a number or a percentage string like `'19%'`. **Never inherited.** |
|
|
229
|
+
| `cornerRadius` | Rounded artwork corners, only for `iosSplash`, `androidSplash`, `featureGraphic`, and `launchLogo`; integer or percentage string from `0` through `50`. |
|
|
220
230
|
| `background` | Hex color, or `null` for transparent. Inherited from `brand.background`. |
|
|
221
231
|
| `enabled` | `false` turns a default piece off; `true` turns an opt-in piece on. |
|
|
222
232
|
|
|
@@ -225,6 +235,8 @@ And these live at the top level:
|
|
|
225
235
|
| Key | Default | Purpose |
|
|
226
236
|
| --- | --- | --- |
|
|
227
237
|
| `background` | `'#FFFFFF'` | The background every piece inherits unless it declares its own: the Android adaptive background layer, the `DefaultIcon-ios.png` flatten, the splash canvases, and the marketplace flatten when a background is explicitly configured. |
|
|
238
|
+
| `artworkCornerRadius` | `'0%'` | Shared radius for the four supported non-icon artwork pieces. It never changes store or launcher icons. |
|
|
239
|
+
| `splashCornerRadius` | — | Optional splash-only override for `iosSplash` and `androidSplash`. |
|
|
228
240
|
| `confirmOverwrites` | `true` | Whether `brand` asks before overwriting project files in place. |
|
|
229
241
|
| `optimize` | `false` | Quantize the generated PNGs to a palette. Lossy — see [Shrinking the generated files](#shrinking-the-generated-files). |
|
|
230
242
|
| `logo` | — | Path override for the main logo. |
|
|
@@ -234,12 +246,12 @@ And these live at the top level:
|
|
|
234
246
|
|
|
235
247
|
| Piece | Config key | Generates | Default padding | On by default |
|
|
236
248
|
| --- | --- | --- | --- | --- |
|
|
237
|
-
| `icon` | `icon` | `DefaultIcon.png` + `DefaultIcon-ios.png` | `
|
|
238
|
-
| `dark` | `dark` | `DefaultIcon-Dark.png` | `
|
|
239
|
-
| `tinted` | `tinted` | `DefaultIcon-Tinted.png` | `
|
|
249
|
+
| `icon` | `icon` | `DefaultIcon.png` + `DefaultIcon-ios.png` | `0%` | yes |
|
|
250
|
+
| `dark` | `dark` | `DefaultIcon-Dark.png` | `0%` | yes |
|
|
251
|
+
| `tinted` | `tinted` | `DefaultIcon-Tinted.png` | `0%` | yes |
|
|
240
252
|
| `ios-splash` | `iosSplash` | `assets/iphone/Default*.png` × 16 | `26%` | yes |
|
|
241
253
|
| `launch-logo` | `launchLogo` | `LaunchLogo.png` (1024×1024) | `12%` | when `logo-launch.*` exists |
|
|
242
|
-
| `marketplace` | `marketplace` | `iTunesConnect.png` + `MarketplaceArtwork.png` | `
|
|
254
|
+
| `marketplace` | `marketplace` | `iTunesConnect.png` + `MarketplaceArtwork.png` | `0%` | yes |
|
|
243
255
|
| `feature-graphic` | `featureGraphic` | `MarketplaceArtworkFeature.png` (1024×500) | `12%` | yes |
|
|
244
256
|
| `adaptive` | `adaptive` | `ic_launcher_{foreground,background,monochrome}.png` × 5 + `ic_launcher.xml` | `18%` | yes |
|
|
245
257
|
| `legacy-icon` | `legacyIcon` | `ic_launcher.png` × 5 | `10%` | yes |
|
|
@@ -255,7 +267,7 @@ Only three pieces are opt-in, and for one reason: they produce nothing useful un
|
|
|
255
267
|
|
|
256
268
|
### `background` is inherited, `padding` is not
|
|
257
269
|
|
|
258
|
-
Set `brand.background` once and every piece picks it up. Padding works the other way on purpose: the
|
|
270
|
+
Set `brand.background` once and every piece picks it up. Padding works the other way on purpose: the adaptive `18%` answers to the Android launcher mask, while finished iOS/store artwork defaults to full-bleed `0%`. A single inherited number could quietly break the launcher mask or frame finished square artwork, so padding is set per piece or not at all.
|
|
259
271
|
|
|
260
272
|
## Overwrite confirmation
|
|
261
273
|
|
|
@@ -290,7 +302,7 @@ The output is automatically routed to the right directory for your project layou
|
|
|
290
302
|
|
|
291
303
|
```text
|
|
292
304
|
<project>/
|
|
293
|
-
├── DefaultIcon.png ← 1024×1024, universal fallback (
|
|
305
|
+
├── DefaultIcon.png ← 1024×1024, universal fallback (brand.icon.padding)
|
|
294
306
|
├── DefaultIcon-ios.png ← 1024×1024, iOS flattened on brand.background
|
|
295
307
|
├── DefaultIcon-Dark.png ← 1024×1024, iOS 18+ dark (transparent per Apple HIG)
|
|
296
308
|
├── DefaultIcon-Tinted.png ← 1024×1024, iOS 18+ tinted (grayscale on black)
|
|
@@ -326,7 +338,8 @@ The output is automatically routed to the right directory for your project layou
|
|
|
326
338
|
│ ├── iphone/Default*.png ← the launch images the template ships
|
|
327
339
|
│ └── android/
|
|
328
340
|
│ ├── appicon.png ← 128×128
|
|
329
|
-
│
|
|
341
|
+
│ ├── default.png ← Android <12 splash
|
|
342
|
+
│ └── images/res-*/default.png ← 11 Titanium qualifier splashes
|
|
330
343
|
└── platform/
|
|
331
344
|
└── android/res/
|
|
332
345
|
├── mipmap-*/ ← same 5 densities as Alloy
|
|
@@ -334,7 +347,7 @@ The output is automatically routed to the right directory for your project layou
|
|
|
334
347
|
└── mipmap-anydpi-v26/ic_launcher.xml
|
|
335
348
|
```
|
|
336
349
|
|
|
337
|
-
A Classic project
|
|
350
|
+
A fresh Classic project may not contain `images/res-*`, but `brand` creates all 11 `Resources/android/images/res-*` variants because Titanium consumes those qualifier paths.
|
|
338
351
|
|
|
339
352
|
The Android outputs are related, but they are not interchangeable:
|
|
340
353
|
|
|
@@ -475,7 +488,7 @@ Below Android 12 there is no system splash: the launch screen comes from the ima
|
|
|
475
488
|
`brand` regenerates the whole set on every run. It is the `android-splash` piece, on by default:
|
|
476
489
|
|
|
477
490
|
- `app/assets/android/default.png` (`Resources/android/default.png` in Classic)
|
|
478
|
-
- `app/assets/android/images/res-*/default.png` — the 11 per-qualifier images
|
|
491
|
+
- `app/assets/android/images/res-*/default.png` (`Resources/android/images/res-*/default.png` in Classic) — the 11 per-qualifier images Titanium consumes
|
|
479
492
|
|
|
480
493
|
Earlier versions regenerated only the first file and hid the other 11 behind a `--legacy-splash` flag, which is why a freshly branded project could still flash the grey Alloy logo on an older phone. That flag is gone: its output is part of `android-splash` and always generated.
|
|
481
494
|
|
|
@@ -509,7 +522,7 @@ The output keeps its alpha, so the storyboard's `<default-background-color>` sho
|
|
|
509
522
|
|
|
510
523
|
## iPhone launch images
|
|
511
524
|
|
|
512
|
-
The Alloy and Classic templates ship 16 `Default*.png` launch images under `assets/iphone/`, from the 320×480 original iPhone size up to 2688×1242. `brand` regenerates all of them, scaling the logo against the **shorter side** of each canvas so portrait and landscape carry the same visual weight.
|
|
525
|
+
The Alloy and Classic templates ship 16 `Default*.png` launch images under `app/assets/iphone/` or `Resources/iphone/`, from the 320×480 original iPhone size up to 2688×1242. `brand` regenerates all of them, scaling the logo against the **shorter side** of each canvas so portrait and landscape carry the same visual weight.
|
|
513
526
|
|
|
514
527
|
With `<enable-launch-screen-storyboard>` enabled (the default), iOS never reads these files. They are regenerated because they are in your project, they ship with the Alloy logo, and no one should have to audit their `tiapp.xml` to know whether that matters. If you are sure your project doesn't need them, [`--cleanup-legacy`](#cleanup-legacy-branding-artifacts) deletes them instead.
|
|
515
528
|
|
|
@@ -572,7 +585,8 @@ Padding belongs to the piece, not to the project. Each piece has its own key and
|
|
|
572
585
|
| --- | --- | --- | --- |
|
|
573
586
|
| `adaptive` | `brand.adaptive.padding` | `--android-adaptive-padding` | `18%` |
|
|
574
587
|
| `legacy-icon` | `brand.legacyIcon.padding` | `--android-legacy-padding` | `10%` |
|
|
575
|
-
| `
|
|
588
|
+
| `appicon` | `brand.appicon.padding` | `--appicon-padding` | `10%` |
|
|
589
|
+
| `icon` | `brand.icon.padding` | `--ios-padding` | `0%` |
|
|
576
590
|
| `feature-graphic` | `brand.featureGraphic.padding` | `--feature-graphic-padding` | `12%` |
|
|
577
591
|
| `launch-logo` | `brand.launchLogo.padding` | `--launch-logo-padding` | `12%` |
|
|
578
592
|
| `android-splash` | `brand.androidSplash.padding` | `--android-splash-padding` | `26%` |
|
|
@@ -580,7 +594,7 @@ Padding belongs to the piece, not to the project. Each piece has its own key and
|
|
|
580
594
|
|
|
581
595
|
`--padding` is a shortcut for the two Android launcher paddings in a single run, and `--splash-padding` for the two splash paddings. `--ios-padding` moves the four square iOS/marketplace pieces together (`icon`, `dark`, `tinted`, `marketplace`); in config each of them has its own key.
|
|
582
596
|
|
|
583
|
-
There is deliberately **no global padding value that cascades down**. The defaults answer to different constraints: `18%` answers to the Android launcher mask, while
|
|
597
|
+
There is deliberately **no global padding value that cascades down**. The defaults answer to different constraints: `18%` answers to the Android launcher mask, while finished square iOS/store artwork stays full-bleed at `0%`. One inherited number could silently break the launcher mask or add an unwanted frame to finished artwork. `background`, which has no such trap, is inherited from `brand.background`.
|
|
584
598
|
|
|
585
599
|
### How the source is read, and how sharp the output is
|
|
586
600
|
|
|
@@ -615,6 +629,19 @@ The `26%` default is calibrated against the Titanium template itself: the Alloy
|
|
|
615
629
|
|
|
616
630
|
Before v7.13.0 none of this was configurable: `default.png` used a hardcoded box of 72% × 26% of its own canvas, and the `res-*` set a separate hardcoded 60%. Two rules for the same piece, neither adjustable.
|
|
617
631
|
|
|
632
|
+
## Rounded non-icon artwork
|
|
633
|
+
|
|
634
|
+
`brand.artworkCornerRadius` rounds artwork only in the 16 iPhone launch images, Android `default.png` plus its 11 qualifier variants, `MarketplaceArtworkFeature.png`, and `LaunchLogo.png`. A piece may override it with `cornerRadius`; `brand.splashCornerRadius` is an optional shared override for the two legacy splash pieces.
|
|
635
|
+
|
|
636
|
+
Values are integer numbers or percentage strings from `0` through `50`, measured against the shorter side of the resized artwork. `0%` preserves the previous output byte for byte; `50%` makes square artwork circular and a wordmark capsule-shaped. Normal and `--dry-run` summaries report the effective padding and radius.
|
|
637
|
+
|
|
638
|
+
Precedence is:
|
|
639
|
+
|
|
640
|
+
- Feature Graphic / LaunchLogo: piece-specific flag → `--artwork-corner-radius` → piece config → `brand.artworkCornerRadius` → `0%`.
|
|
641
|
+
- Legacy splashes: platform flag → `--splash-corner-radius` → `--artwork-corner-radius` → piece config → `brand.splashCornerRadius` → `brand.artworkCornerRadius` → `0%`.
|
|
642
|
+
|
|
643
|
+
Store and launcher icons remain unmasked for platform processing. `cornerRadius` is rejected in `DefaultIcon*`, `iTunesConnect.png`, `MarketplaceArtwork.png`, adaptive, legacy, and app icons, Android 12+ `splash_icon.png`, notification icons, and any other unsupported piece; invalid, fractional, negative, non-numeric, or greater-than-50 values also abort before files are written.
|
|
644
|
+
|
|
618
645
|
### Adaptive icon padding
|
|
619
646
|
|
|
620
647
|
Android's adaptive canvas is 108 dp. The mask leaves roughly 72 dp visible, and the **guaranteed** safe area is a 66 dp circle inscribed in it. What each padding means in those terms:
|
|
@@ -749,7 +776,7 @@ All 5 Android densities, marketplace artwork, splash canvases, and iOS variants
|
|
|
749
776
|
|
|
750
777
|
## Flag reference
|
|
751
778
|
|
|
752
|
-
Every flag lives in the terse reference: [`brand` command](./cli-commands.md#brand-command) — project & output, `--only`, padding, optional asset types, the `--<piece>-logo` overrides, `--optimize`, appearance, legacy cleanup and diagnostics, with examples.
|
|
779
|
+
Every flag lives in the terse reference: [`brand` command](./cli-commands.md#brand-command) — project & output, `--only`, padding and corner radius, optional asset types, the `--<piece>-logo` overrides, `--optimize`, appearance, legacy cleanup and diagnostics, with examples.
|
|
753
780
|
|
|
754
781
|
## Community-Discovered Patterns
|
|
755
782
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Appearance Module
|
|
2
2
|
|
|
3
|
-
The `Appearance` export from `purgetss.ui` (added in **v7.5.3**) handles Light / Dark / System mode switching and persists the user's choice across app restarts. It is a thin, deterministic wrapper around Titanium's native `Ti.UI.overrideUserInterfaceStyle` plus `Ti.App.Properties`, exposed as a singleton so every controller
|
|
3
|
+
The `Appearance` export from `purgetss.ui` (added in **v7.5.3**) handles Light / Dark / System mode switching and persists the user's choice across app restarts. It is a thin, deterministic wrapper around Titanium's native `Ti.UI.overrideUserInterfaceStyle` plus `Ti.App.Properties`, exposed as a singleton so every Alloy controller or Classic module reads and writes the same state.
|
|
4
4
|
|
|
5
5
|
This reference follows the same workflow-first / API-second split the official PurgeTSS documentation now uses:
|
|
6
6
|
|
|
@@ -18,7 +18,7 @@ For the color wiring that actually makes the UI *respond* to mode changes, see [
|
|
|
18
18
|
The Appearance module sits between three moving parts: a JS singleton, the OS-level interface style, and the semantic colors generated by PurgeTSS. The diagram below shows how a single `Appearance.init()` call at startup wires them together, and what happens when the user later picks a mode in Settings.
|
|
19
19
|
|
|
20
20
|
```
|
|
21
|
-
┌─
|
|
21
|
+
┌─ Appearance singleton from purgetss.ui ──────────────────────────────┐
|
|
22
22
|
│ │
|
|
23
23
|
│ Appearance.init() ────► reads 'userInterfaceStyle' │
|
|
24
24
|
│ from Ti.App.Properties │
|
|
@@ -160,16 +160,67 @@ The background, text, border, and icon colors in the XML come from semantic colo
|
|
|
160
160
|
|
|
161
161
|
> **Why named functions in Alloy controllers?** Alloy resolves `onClick="selectDark"` by looking up a top-level identifier on the controller scope. Named function declarations (`function selectDark() { ... }`) hoist and are reliably resolvable; arrow functions assigned to `const` are not hoisted and tend to bite you when an XML attribute fires before the binding has executed. The official setup guide uses named functions for this reason.
|
|
162
162
|
|
|
163
|
+
## Titanium Classic
|
|
164
|
+
|
|
165
|
+
Classic loads the generated runtime from `Resources/lib/purgetss.ui.js` and keeps the native color catalog at `Resources/semantic.colors.json`:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"surfaceColor": { "light": "#F8FAFC", "dark": "#0F172A" },
|
|
170
|
+
"textColor": { "light": "#0F172A", "dark": "#F8FAFC" },
|
|
171
|
+
"accentColor": { "light": "#2563EB", "dark": "#60A5FA" }
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Use those semantic names directly in native Titanium color properties. Classic does not need PurgeTSS utility classes, TSS, `purgetss/config.cjs`, or any Alloy runtime file.
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
const { Appearance } = require('lib/purgetss.ui')
|
|
179
|
+
|
|
180
|
+
Appearance.init()
|
|
181
|
+
|
|
182
|
+
const window = Ti.UI.createWindow({ backgroundColor: 'surfaceColor' })
|
|
183
|
+
const title = Ti.UI.createLabel({
|
|
184
|
+
text: `Mode: ${Appearance.get()}`,
|
|
185
|
+
color: 'textColor'
|
|
186
|
+
})
|
|
187
|
+
const toggleButton = Ti.UI.createButton({
|
|
188
|
+
title: 'Toggle appearance',
|
|
189
|
+
color: 'surfaceColor',
|
|
190
|
+
backgroundColor: 'accentColor'
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
function toggleAppearance() {
|
|
194
|
+
Appearance.toggle()
|
|
195
|
+
title.text = `Mode: ${Appearance.get()}`
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function disposeWindow() {
|
|
199
|
+
toggleButton.removeEventListener('click', toggleAppearance)
|
|
200
|
+
window.removeEventListener('close', disposeWindow)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
toggleButton.addEventListener('click', toggleAppearance)
|
|
204
|
+
window.add(title)
|
|
205
|
+
window.add(toggleButton)
|
|
206
|
+
window.addEventListener('close', disposeWindow)
|
|
207
|
+
window.open()
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Run a full native build after adding or changing semantic keys. A LiveView reload alone does not refresh Titanium's native color catalog. The `purgetss semantic` command can create the JSON for a Classic project; it writes only `Resources/semantic.colors.json`, not `config.cjs`, TSS, or utility mappings.
|
|
211
|
+
|
|
212
|
+
For animation and runtime lifecycle examples in the same Classic application, see [purgetss-ui-classic.md](./purgetss-ui-classic.md).
|
|
213
|
+
|
|
163
214
|
## API reference
|
|
164
215
|
|
|
165
216
|
### Methods
|
|
166
217
|
|
|
167
|
-
| Method
|
|
168
|
-
|
|
|
169
|
-
| `init()`
|
|
170
|
-
| `set(mode)`
|
|
171
|
-
| `get()`
|
|
172
|
-
| `toggle()`
|
|
218
|
+
| Method | Description | Return |
|
|
219
|
+
| --- | --- | --- |
|
|
220
|
+
| `init()` | Restore the saved mode from `Ti.App.Properties` and apply it via `Ti.UI.overrideUserInterfaceStyle`. Call once at app startup before opening the first window. | `undefined` |
|
|
221
|
+
| `set(mode)` | Apply and persist a mode. Accepts `'system'`, `'light'`, or `'dark'`. Any other value is silently ignored. | `undefined` |
|
|
222
|
+
| `get()` | Read the current mode as `'system'`, `'light'`, or `'dark'`. | Mode string |
|
|
223
|
+
| `toggle()` | Switch between `'light'` and `'dark'`. Skips `'system'` — if current mode is `'system'` the next call produces `'dark'`. | `undefined` |
|
|
173
224
|
|
|
174
225
|
All four methods are **synchronous**. They do not fire events; if you need to react to a mode change, call your update logic right after `Appearance.set(...)`.
|
|
175
226
|
|
|
@@ -210,10 +261,13 @@ app startup
|
|
|
210
261
|
## Related
|
|
211
262
|
|
|
212
263
|
- [semantic-colors.md](./semantic-colors.md) — defining `app/assets/semantic.colors.json` and mapping the color names in `config.cjs` so views actually respond to mode changes.
|
|
213
|
-
- [cli-commands.md#semantic-command](./cli-commands.md#semantic-command) — the `purgetss semantic` command
|
|
264
|
+
- [cli-commands.md#semantic-command](./cli-commands.md#semantic-command) — the `purgetss semantic` command; Alloy also receives `config.cjs` mappings, while Classic receives only the native JSON.
|
|
214
265
|
- [customization-deep-dive.md](./customization-deep-dive.md) — full `config.cjs` structure, including the `theme.extend.colors` section where semantic names are registered.
|
|
266
|
+
- [purgetss-ui-classic.md](./purgetss-ui-classic.md) — generated module path, Classic animation factory, method contracts, and cleanup.
|
|
215
267
|
|
|
216
268
|
## Community-Discovered Patterns
|
|
217
269
|
|
|
270
|
+
These field-tested patterns are now also confirmed by the official Appearance documentation:
|
|
271
|
+
|
|
218
272
|
- **Always call `Appearance.init()` before opening the first window.** Opening the window first causes a visible flicker on cold launch as the UI repaints from the system default to the saved mode. The official best-practices guide puts `Appearance.init()` on line 3 of `app/controllers/index.js`, immediately before `$.navWin.open()`, for exactly this reason.
|
|
219
273
|
- **`toggle()` is not a three-state cycle.** It only alternates between `'light'` and `'dark'`. If the saved mode is `'system'`, the first `toggle()` call lands on `'dark'`. Build a cycle yourself with `get()` + `set(...)` when you need one.
|
|
@@ -193,8 +193,8 @@ Complete inventory of all class prefixes organized by functional category. For n
|
|
|
193
193
|
| `duration-*` | 22 | `duration-0`, `duration-50` to `duration-5000` |
|
|
194
194
|
| `delay-*` | 22 | `delay-0`, `delay-50` to `delay-5000` |
|
|
195
195
|
| `repeat-*` | ~31 | `repeat-*` variants |
|
|
196
|
-
| `snap-*` (v7.4.0+) |
|
|
197
|
-
| `keep-z-index` (v7.4.0+) | 2 | `keep-z-index`, `keep-z-index-false` —
|
|
196
|
+
| `snap-*` runtime behavior (v7.4.0+) | 4 | `snap-back`, `snap-back-false`, `snap-center`, `snap-center-false` — implemented drop behaviors. Generated inventories may still contain `snap-magnet*`, but the runtime does not consume them |
|
|
197
|
+
| `keep-z-index` (v7.4.0+) | 2 | `keep-z-index`, `keep-z-index-false` — prevents touch-start promotion; it does not stop `draggable(array)` from assigning index-based z-order |
|
|
198
198
|
|
|
199
199
|
### Shadows & Elevation
|
|
200
200
|
|
|
@@ -196,7 +196,7 @@ The rest of this document collects conventions, prohibitions, and insights surfa
|
|
|
196
196
|
|
|
197
197
|
## All 364 Unique Prefixes (Alphabetical)
|
|
198
198
|
|
|
199
|
-
> **NOTE**:
|
|
199
|
+
> **NOTE**: v7.4.0 introduced `snap-back`, `snap-back-false`, `snap-center`, `snap-center-false`, `snap-magnet`, `snap-magnet-false`, `keep-z-index`, and `keep-z-index-false`. The current runtime implements back, center, and touch-start z-index preservation but does not read `snap.magnet`; do not suggest the generated magnet classes as working behavior. v7.5.3 added `font-sans`, `font-serif`, and `font-mono`.
|
|
200
200
|
|
|
201
201
|
|
|
202
202
|
```
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Classic Project Support
|
|
2
|
+
|
|
3
|
+
Since PurgeTSS 7.15, the utility-class lifecycle remains Alloy-only while independent asset and CommonJS commands can run in Titanium Classic projects. Detect the project layout before choosing a command or output path.
|
|
4
|
+
|
|
5
|
+
Official source: <https://purgetss.com/docs/commands#alloy-and-classic-compatibility>
|
|
6
|
+
|
|
7
|
+
## Compatibility Matrix
|
|
8
|
+
|
|
9
|
+
| Command | Alloy | Classic | Classic behavior |
|
|
10
|
+
| --- | :---: | :---: | --- |
|
|
11
|
+
| `brand` | yes | yes | Writes branding assets to Classic paths and follows enabled `tiapp.xml` deployment targets; explicit `--only` overrides that filter. |
|
|
12
|
+
| `images` | yes | yes | Writes density variants under `Resources/android/images/res-*/` and `Resources/iphone/images/`; follows deployment targets unless `--android` or `--ios` is explicit. |
|
|
13
|
+
| `semantic` | yes | yes | Writes only `Resources/semantic.colors.json`; it does not create `purgetss/`, `config.cjs`, TSS, `app/`, or a hook. |
|
|
14
|
+
| `shades` | yes | yes | Output-only modes work anywhere. On a fresh Classic project, saving creates only `purgetss/config.cjs`; if the color module already exists, it is regenerated. |
|
|
15
|
+
| `color-module` | yes | yes | Writes `app/lib/purgetss.colors.js` or `Resources/lib/purgetss.colors.js`; Classic creates no unrelated empty source folders. |
|
|
16
|
+
| `module` | yes | yes | Writes `app/lib/purgetss.ui.js` or `Resources/lib/purgetss.ui.js`. |
|
|
17
|
+
| `icon-library` | yes | yes | Copies fonts to `Resources/fonts/` and optional modules to `Resources/lib/`; `--styles` is skipped in Classic. |
|
|
18
|
+
| `build-fonts` | yes | yes | Copies fonts to `Resources/fonts/` and optionally writes `Resources/lib/purgetss.fonts.js`; it does not generate TSS in Classic. |
|
|
19
|
+
| Root `purgetss`, `--all`, `init`, `create`, `install-dependencies`, `build`, `watch` | yes | no | These commands own the Alloy utility-class lifecycle. |
|
|
20
|
+
| `update`, `sudo-update` | yes | yes | Global CLI maintenance; no project layout is required. |
|
|
21
|
+
|
|
22
|
+
## The Hard Boundary
|
|
23
|
+
|
|
24
|
+
A Classic project does not receive or need:
|
|
25
|
+
|
|
26
|
+
- `app/`
|
|
27
|
+
- `app/styles/app.tss`
|
|
28
|
+
- `purgetss/styles/utilities.tss`
|
|
29
|
+
- `purgetss/styles/fonts.tss`
|
|
30
|
+
- `alloy.jmk`
|
|
31
|
+
- utility classes in views or controllers
|
|
32
|
+
- `$.UI.create()`
|
|
33
|
+
- the PurgeTSS CLI/package during application compilation or as an app dependency (generated CommonJS modules execute normally)
|
|
34
|
+
|
|
35
|
+
Files generated under `Resources/` are native Titanium resources. Compile the Classic app normally with `ti build`.
|
|
36
|
+
|
|
37
|
+
Do not interpret the presence of `purgetss/config.cjs` in a Classic project as permission to use utilities. Commands such as `brand`, `images`, `shades`, and `color-module` may use that file as development-time input without installing the Alloy lifecycle.
|
|
38
|
+
|
|
39
|
+
Classic `shades` and `color-module` do not scaffold the empty `purgetss/brand/`, `purgetss/fonts/`, or `purgetss/images/` conventions created by Alloy initialization. On a fresh project, `shades` creates only its config; `color-module` creates that config when missing plus its module. If the module already exists, saving a palette refreshes it automatically.
|
|
40
|
+
|
|
41
|
+
## Layout and Output Routing
|
|
42
|
+
|
|
43
|
+
| Artifact | Alloy | Classic |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| Semantic colors | `app/assets/semantic.colors.json` | `Resources/semantic.colors.json` |
|
|
46
|
+
| Android UI densities | `app/assets/android/images/res-*/` | `Resources/android/images/res-*/` |
|
|
47
|
+
| iPhone UI scales | `app/assets/iphone/images/` | `Resources/iphone/images/` |
|
|
48
|
+
| Font files | `app/assets/fonts/` | `Resources/fonts/` |
|
|
49
|
+
| Color module | `app/lib/purgetss.colors.js` | `Resources/lib/purgetss.colors.js` |
|
|
50
|
+
| UI module | `app/lib/purgetss.ui.js` | `Resources/lib/purgetss.ui.js` (see [`purgetss.ui` in Classic](./purgetss-ui-classic.md)) |
|
|
51
|
+
| Custom-font module | `app/lib/purgetss.fonts.js` | `Resources/lib/purgetss.fonts.js` |
|
|
52
|
+
|
|
53
|
+
## Loading Generated Modules in Classic
|
|
54
|
+
|
|
55
|
+
Titanium resolves local CommonJS paths from `Resources/`. Omit both the `Resources/` prefix and the `.js` extension from `require()`.
|
|
56
|
+
|
|
57
|
+
| Generated file | Classic `require()` path |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `Resources/lib/purgetss.colors.js` | `require('lib/purgetss.colors')` |
|
|
60
|
+
| `Resources/lib/purgetss.ui.js` | `require('lib/purgetss.ui')` |
|
|
61
|
+
| `Resources/lib/purgetss.fonts.js` | `require('lib/purgetss.fonts')` |
|
|
62
|
+
| `Resources/lib/fontawesome.js` | `require('lib/fontawesome')` |
|
|
63
|
+
| `Resources/lib/materialicons.js` | `require('lib/materialicons')` |
|
|
64
|
+
| `Resources/lib/materialsymbols.js` | `require('lib/materialsymbols')` |
|
|
65
|
+
| `Resources/lib/framework7icons.js` | `require('lib/framework7icons')` |
|
|
66
|
+
|
|
67
|
+
This follows Titanium's [CommonJS module path resolution](https://titaniumsdk.com/guide/Titanium_SDK/Titanium_SDK_Guide/Best_Practices_and_Recommendations/CommonJS_Modules_in_Titanium.html#javascript-module-path-resolution).
|
|
68
|
+
|
|
69
|
+
## Deployment Targets
|
|
70
|
+
|
|
71
|
+
`brand` and `images` read `<deployment-targets>` from `tiapp.xml` independently of whether the layout is Alloy or Classic.
|
|
72
|
+
|
|
73
|
+
- A normal run generates only enabled platform families.
|
|
74
|
+
- `images --android` and `images --ios` are explicit overrides.
|
|
75
|
+
- `brand --only <piece-or-group>` is an explicit override and may prepare assets for a platform before that target is enabled.
|
|
76
|
+
|
|
77
|
+
Do not assume that Classic means Android-only or that an Alloy project targets both platforms.
|
|
78
|
+
|
|
79
|
+
## Standalone First-Run Behavior
|
|
80
|
+
|
|
81
|
+
### `brand`
|
|
82
|
+
|
|
83
|
+
In a Classic project without `purgetss/config.cjs`, `brand` creates the canonical config before resolving settings. If a positional PNG/SVG is supplied and no canonical `purgetss/brand/logo.{png,svg}` exists, the command moves the source into that convention after overwrite confirmation and reports the destination. It never replaces an existing canonical logo silently.
|
|
84
|
+
|
|
85
|
+
Classic Android receives the 11 `Resources/android/images/res-*` splash variants even when a fresh `ti create` template did not seed those folders. Titanium consumes those qualifier paths.
|
|
86
|
+
|
|
87
|
+
### `images`
|
|
88
|
+
|
|
89
|
+
Running `images` without a positional source establishes the `purgetss/images/` convention. Passing an existing external file or directory does not create an empty `purgetss/images/` folder or a config file merely to process that source.
|
|
90
|
+
|
|
91
|
+
### `semantic`
|
|
92
|
+
|
|
93
|
+
Classic `semantic` is deliberately output-only: it writes the native JSON and does not bootstrap any other PurgeTSS artifact. Classic code uses semantic keys directly in Titanium color properties rather than through utility classes.
|
|
94
|
+
|
|
95
|
+
## Audit Checklist
|
|
96
|
+
|
|
97
|
+
When auditing a Classic project that uses PurgeTSS:
|
|
98
|
+
|
|
99
|
+
1. Confirm every invoked command is marked Classic-compatible in the matrix.
|
|
100
|
+
2. Confirm outputs use `Resources/`, never Alloy's `app/assets/` or `app/lib/`.
|
|
101
|
+
3. Reject any added `alloy.jmk`, generated TSS, utility classes, or `$.UI.create()`.
|
|
102
|
+
4. For `brand` and `images`, compare generated platform families with `tiapp.xml` deployment targets and any explicit override flags.
|
|
103
|
+
5. Confirm `semantic` did not create unrelated PurgeTSS setup files.
|
|
104
|
+
6. For `icon-library --styles`, expect Classic to skip TSS output.
|
|
105
|
+
7. For `build-fonts`, expect font files and optional CommonJS output only; no `fonts.tss`.
|
|
106
|
+
|
|
107
|
+
## Related References
|
|
108
|
+
|
|
109
|
+
- [CLI Commands](./cli-commands.md)
|
|
110
|
+
- [App Icons & Branding](./app-branding.md)
|
|
111
|
+
- [Multi-Density Images](./multi-density-images.md)
|
|
112
|
+
- [Semantic Colors](./semantic-colors.md)
|
|
113
|
+
- [Icon Font Libraries](./icon-fonts.md)
|
|
114
|
+
- [Custom Fonts](./custom-fonts.md)
|
|
115
|
+
- [`purgetss.ui` in Titanium Classic](./purgetss-ui-classic.md)
|