@maccesar/titools 2.6.1 → 2.7.1

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 CHANGED
@@ -48,7 +48,9 @@ What you get:
48
48
  - ti-pro research agent
49
49
  - Session hook that auto-detects Titanium projects (`tiapp.xml`, Alloy, PurgeTSS)
50
50
  - Slash commands: `/ti-check`, `/ti-new-screen`, `/ti-audit`
51
- - Auto-updates via marketplace
51
+ - Auto-updates via marketplace (opt-in — see note below)
52
+
53
+ > **Note on auto-updates:** Claude Code disables auto-updates by default for third-party marketplaces like this one. To receive new versions automatically, open `/plugin` → **Marketplaces** tab and enable auto-update for `maccesar-titools`. When an update is applied, Claude Code prompts you to run `/reload-plugins` to activate the new code.
52
54
 
53
55
  ### Option B: CLI (Claude Code, Gemini CLI, Codex CLI)
54
56
 
@@ -89,15 +91,15 @@ Why NPM?
89
91
 
90
92
  ### Which option should I use?
91
93
 
92
- | | Plugin (Option A) | CLI (Option B) |
93
- |---|---|---|
94
- | **Claude Code** | Recommended | Supported |
95
- | **Gemini CLI** | Not available | Supported |
96
- | **Codex CLI** | Not available | Supported |
97
- | **Knowledge Index** | Not included | Included (`titools sync`) |
98
- | **Auto-updates** | Via marketplace | Via SessionStart hook |
99
- | **Slash commands** | `/ti-check`, `/ti-new-screen`, `/ti-audit` | Not available |
100
- | **Session hook** | Auto-detects Titanium projects | Auto-update only |
94
+ | | Plugin (Option A) | CLI (Option B) |
95
+ | ------------------- | ------------------------------------------ | ------------------------- |
96
+ | **Claude Code** | Recommended | Supported |
97
+ | **Gemini CLI** | Not available | Supported |
98
+ | **Codex CLI** | Not available | Supported |
99
+ | **Knowledge Index** | Not included | Included (`titools sync`) |
100
+ | **Auto-updates** | Marketplace (opt-in, enable in `/plugin`) | SessionStart hook (daily) |
101
+ | **Slash commands** | `/ti-check`, `/ti-new-screen`, `/ti-audit` | Not available |
102
+ | **Session hook** | Auto-detects Titanium projects | Auto-update only |
101
103
 
102
104
  Use **Option A** if you only use Claude Code. Use **Option B** if you use multiple AI assistants or want the Knowledge Index feature.
103
105
 
@@ -176,17 +178,17 @@ The knowledge index is based on the latest Titanium SDK documentation. If your p
176
178
 
177
179
  ## Skills overview
178
180
 
179
- | Skill | Purpose | Best For |
180
- | ------------ | ------------------------------- | --------------------------------------- |
181
- | alloy-guides | Alloy MVC reference | Models, Views, Controllers, Widgets |
182
- | alloy-howtos | Alloy CLI and debugging | Project setup, CLI commands, errors |
183
- | purgetss | Utility-first styling | UI styling and animations |
184
- | ti-api | Complete API reference | Properties, methods, events, constants |
181
+ | Skill | Purpose | Best For |
182
+ | ------------ | ------------------------------- | ------------------------------------------------------------------------------- |
183
+ | alloy-guides | Alloy MVC reference | Models, Views, Controllers, Widgets |
184
+ | alloy-howtos | Alloy CLI and debugging | Project setup, CLI commands, errors |
185
+ | purgetss | Utility-first styling | UI styling and animations |
186
+ | ti-api | Complete API reference | Properties, methods, events, constants |
185
187
  | ti-branding | Icon and splash generator | App icons, adaptive icons, splash, notifications, store artwork, legacy cleanup |
186
- | ti-expert | Architecture and implementation | Starting point for most tasks |
187
- | ti-guides | SDK fundamentals | Hyperloop, distribution, configuration |
188
- | ti-howtos | Native feature integration | Location, Push, Media, Platform APIs |
189
- | ti-ui | UI/UX patterns | Complex layouts, ListViews, platform UI |
188
+ | ti-expert | Architecture and implementation | Starting point for most tasks |
189
+ | ti-guides | SDK fundamentals | Hyperloop, distribution, configuration |
190
+ | ti-howtos | Native feature integration | Location, Push, Media, Platform APIs |
191
+ | ti-ui | UI/UX patterns | Complex layouts, ListViews, platform UI |
190
192
 
191
193
  Note: `ti-guides`, `ti-howtos`, `ti-ui`, `alloy-guides`, and `alloy-howtos` are based on official Titanium SDK and Alloy documentation. `purgetss` is opinionated in workflow and conventions, but its reference files are audited against the official PurgeTSS documentation for verifiable classes and behavior. `ti-expert` and `purgetss` reflect personal coding conventions (biased toward PurgeTSS).
192
194
 
@@ -200,11 +202,11 @@ In addition to skills, this repository includes sub-agents for Claude Code. Sub-
200
202
 
201
203
  Deep-dive research specialist that preloads all 8 titanium-related documentation skills.
202
204
 
203
- | Aspect | Details |
204
- | ---------------- | ------------------------------------------------- |
205
- | Location | `~/.claude/agents/ti-pro.md` |
206
- | Model | Sonnet (comprehensive analysis) |
207
- | Tools | Read-only (Read, Grep, Glob) |
205
+ | Aspect | Details |
206
+ | ---------------- | ------------------------------------------------------- |
207
+ | Location | `~/.claude/agents/ti-pro.md` |
208
+ | Model | Sonnet (comprehensive analysis) |
209
+ | Tools | Read-only (Read, Grep, Glob) |
208
210
  | Preloaded Skills | All 8 Titanium documentation skills injected at startup |
209
211
 
210
212
  When to use the agent vs skills:
@@ -238,11 +240,11 @@ Key difference:
238
240
 
239
241
  When installed as a plugin, TiTools provides slash commands for common tasks:
240
242
 
241
- | Command | Description |
242
- |---|---|
243
- | `/ti-check` | Verify project setup: SDK version, Alloy structure, PurgeTSS config, common issues |
243
+ | Command | Description |
244
+ | ----------------------- | ----------------------------------------------------------------------------------- |
245
+ | `/ti-check` | Verify project setup: SDK version, Alloy structure, PurgeTSS config, common issues |
244
246
  | `/ti-new-screen <name>` | Create a new Alloy screen (controller + view + style) following project conventions |
245
- | `/ti-audit` | Audit project for anti-patterns, memory leaks, and best practice violations |
247
+ | `/ti-audit` | Audit project for anti-patterns, memory leaks, and best practice violations |
246
248
 
247
249
  These commands automatically invoke the relevant skills:
248
250
  - `/ti-check` reads `tiapp.xml` and reports project health
@@ -660,8 +662,8 @@ titools auto-update --silent # No output (for hooks)
660
662
  ```
661
663
 
662
664
  Options:
663
- | Option | Description |
664
- | -------------- | ---------------------------------- |
665
+ | Option | Description |
666
+ | -------------- | --------------------------------- |
665
667
  | `-s, --silent` | Suppress all output except errors |
666
668
 
667
669
  What it does:
@@ -798,11 +800,11 @@ The TiTools skills include **Community-Discovered Patterns** — verified iOS be
798
800
 
799
801
  When using Large Titles with a ScrollView inside NavigationWindow or TabGroup, three Window properties must be set together. Without all three, the ScrollView content overlaps behind the navigation bar — or the large title renders with a visible delay.
800
802
 
801
- | Class | Property | Purpose |
802
- |---|---|---|
803
- | `auto-adjust-scroll-view-insets` | `autoAdjustScrollViewInsets` | Adjusts ScrollView insets to prevent content overlap |
804
- | `extend-edges-all` | `extendEdges` | Content extends behind bars (blur/translucent effect) |
805
- | `large-title-enabled` | `largeTitleEnabled` | Large title that collapses on scroll |
803
+ | Class | Property | Purpose |
804
+ | -------------------------------- | ---------------------------- | ----------------------------------------------------- |
805
+ | `auto-adjust-scroll-view-insets` | `autoAdjustScrollViewInsets` | Adjusts ScrollView insets to prevent content overlap |
806
+ | `extend-edges-all` | `extendEdges` | Content extends behind bars (blur/translucent effect) |
807
+ | `large-title-enabled` | `largeTitleEnabled` | Large title that collapses on scroll |
806
808
 
807
809
  **Recommended:** set the base properties as global Window defaults in `config.cjs`:
808
810
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maccesar/titools",
3
- "version": "2.6.1",
3
+ "version": "2.7.1",
4
4
  "description": "Titanium SDK skills and agents for AI coding assistants (Claude Code, Gemini CLI, Codex CLI)",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ti-branding
3
- description: "Generate complete app branding assets for modern Titanium SDK 13.x projects — launcher icons, adaptive icons, splash-screen icons, notification icons, and marketplace artwork — from a single SVG or PNG master. Use when the user asks to brand their app, update the app icon, set up splash screens, prepare store assets, fix generic/placeholder icons, add a notification icon, generate a launcher for Android 8+/13+, replace the TiTools default icon, or anything related to visual identity of a Titanium app (Alloy or Classic). Auto-detects Alloy vs Classic layout. Outputs iOS `DefaultIcon-ios.png` (flattened), Android adaptive triplet (foreground + background + monochrome) across 5 densities, Android legacy launcher × 5, marketplace artwork (1024² + 512²), and optionally notification icons and Android 12+ splash icons. Targets SDK 13.0–13.2 minimums without legacy cruft (post-Xcode 14 iOS minimums, no 9-patch splash, no pre-adaptive Android icons). Delegates raster work to ImageMagick + librsvg (system tools) — zero npm/pip dependencies. Invoke this skill whenever the user mentions icons, splash screens, branding, launcher, adaptive icon, mipmap, appiconset, DefaultIcon, iTunesConnect, Play Store artwork, or any visual asset for a Titanium app."
4
- argument-hint: "[master-path] [--bg-color <hex>] [--padding <pct>] [--with-notification] [--with-splash-icon] [--cleanup-legacy] [--aggressive] [--dry-run]"
3
+ description: "Generate complete app branding assets for modern Titanium SDK 13.x projects — launcher icons, adaptive icons, splash-screen icons, notification icons, and marketplace artwork — from a single SVG or PNG master. Use when the user asks to brand their app, update the app icon, set up splash screens, prepare store assets, fix generic/placeholder icons, add a notification icon, generate a launcher for Android 8+/13+, replace the TiTools default icon, or anything related to visual identity of a Titanium app (Alloy or Classic). Auto-detects Alloy vs Classic layout. Outputs iOS `DefaultIcon.png` (alpha-preserved source) + `DefaultIcon-ios.png` (alpha-flattened for Apple), Android adaptive triplet (foreground + background + monochrome) across 5 densities, Android legacy launcher × 5, marketplace artwork (1024² + 512², alpha-preserved), and optionally notification icons and Android 12+ splash icons. Targets SDK 13.0–13.2 minimums without legacy cruft (post-Xcode 14 iOS minimums, no 9-patch splash, no pre-adaptive Android icons). Delegates raster work to ImageMagick + librsvg (system tools) — zero npm/pip dependencies. Invoke this skill whenever the user mentions icons, splash screens, branding, launcher, adaptive icon, mipmap, appiconset, DefaultIcon, iTunesConnect, Play Store artwork, or any visual asset for a Titanium app."
4
+ argument-hint: "[master-path] [--bg-color <hex>] [--padding <pct>] [--with-notification] [--with-splash-icon] [--cleanup-legacy] [--aggressive] [--in-place] [--monochrome-master <path>] [--notes] [--dry-run]"
5
5
  allowed-tools: Read, Glob, Bash, Write, Edit
6
6
  ---
7
7
 
@@ -29,9 +29,10 @@ Every invocation produces (in a staging directory, reviewed before copy):
29
29
 
30
30
  | Asset | Path in project | Why |
31
31
  |---|---|---|
32
- | `DefaultIcon-ios.png` (1024×1024, no alpha) | Project root | iOS SDK generates the full appiconset from this at build time. Flattened because Apple rejects alpha channels. |
33
- | `iTunesConnect.png` (1024×1024, no alpha) | Project root | App Store submission requirement. |
34
- | `MarketplaceArtwork.png` (512×512, no alpha) | Project root | Google Play submission requirement. |
32
+ | `DefaultIcon.png` (1024×1024, alpha preserved) | Project root | Universal source Titanium's `ti create` template ships this with alpha. Used for Android / Alloy references and as the alpha-intact source of truth. |
33
+ | `DefaultIcon-ios.png` (1024×1024, no alpha) | Project root | iOS SDK generates the full appiconset from this at build time. Flattened because Apple rejects alpha channels on App Store icon uploads. |
34
+ | `iTunesConnect.png` (1024×1024, alpha preserved) | Project root | App Store artwork template. Matches `ti create` default — alpha preserved so the developer can composite over any background before upload. |
35
+ | `MarketplaceArtwork.png` (512×512, alpha preserved) | Project root | Google Play feature graphic template. Matches `ti create` default — alpha preserved. |
35
36
  | `ic_launcher_foreground.png` × 5 densities | `app/platform/android/res/mipmap-{m,h,x,xx,xxx}hdpi/` | Adaptive icon foreground layer. Logo centered in 108dp canvas with configurable padding (default 22% ≈ 66dp safe-zone). |
36
37
  | `ic_launcher_background.png` × 5 densities | idem | Adaptive icon background layer — solid `--bg-color`. |
37
38
  | `ic_launcher_monochrome.png` × 5 densities | idem | Android 13+ themed icons (all non-transparent pixels → white). |
@@ -68,12 +69,16 @@ Options:
68
69
  | Flag | Default | Purpose |
69
70
  |---|---|---|
70
71
  | `--bg-color <hex>` | `#FFFFFF` | Solid color for adaptive background layer. Also used for iOS alpha flatten. |
71
- | `--padding <pct>` | `22` | Safe-zone padding per side (Android official minimum is 19.44% — 22% adds a small buffer against launcher masking). Range 0–40. |
72
+ | `--padding <pct>` | `20` | Safe-zone padding per side. Material spec floor is 19.44% — default of 20 gives a tiny buffer while keeping the logo visibly prominent across launcher masks. Range 0–40. |
73
+ | `--ios-padding <pct>` | `4` | iOS + marketplace aesthetic padding per side. iOS icons have no launcher mask — this is purely aesthetic breathing room. Apple's HIG + production apps typically use 2-6%. Override with `--ios-padding 8` for more conservative (prior default) or `--ios-padding 2` for near-edge La Baraja-style. Range 0–40. |
72
74
  | `--with-notification` | off | Emit `ic_stat_notify.png` × 5 densities. |
73
75
  | `--with-splash-icon` | off | Emit `splash_icon.png` × 5 densities (Android 12+ SplashScreen API). |
74
76
  | `--cleanup-legacy` | off | After generating (or standalone), scan the project for legacy branding artifacts — iOS launch image PNGs, Android `default.png`, `appicon.png`, `res-long-*/res-notlong-*`, etc. — and remove them. Context-aware: reads `tiapp.xml` to decide what's safe. See `references/cleanup-legacy.md`. |
75
77
  | `--aggressive` | off | With `--cleanup-legacy`, also remove `ldpi` density folders (<1% of active devices globally in 2026). Off by default to be conservative. |
76
78
  | `--output <dir>` | `<project>/.ti-branding/` | Staging directory. Review before copying to `app/`. |
79
+ | `--in-place` | off | Skip the staging directory and write files directly into the project root. **Overwrites existing icons.** Ideal right after `ti create` when you want to replace the default Titanium/Alloy icons in one command. `--output` takes precedence if both are passed. |
80
+ | `--monochrome-master <path>` | — | Optional dedicated silhouette master for `ic_launcher_monochrome.png` + `ic_stat_notify.png`. Use this when your colored logo has multi-color detail that would collapse into a featureless blob when naively whitened (e.g. a painter's palette with 4 color dots — provide a monochrome variant with cutout holes instead so the detail survives in themed icons and notification status bar). Falls back to whitening the main master when not provided. |
81
+ | `--notes` | off | Print the full tiapp.xml snippets (iOS launch storyboard, Android launcher wiring, Android 12+ splash theme with Option A/B, FCM notification tint) and the padding tuning guide. Default output is a compact summary (~15 lines). |
77
82
  | `--dry-run` | off | Print what would be generated/removed without writing or deleting. Works with both generation and `--cleanup-legacy`. |
78
83
 
79
84
  ## Safety reminders
@@ -13,8 +13,9 @@
13
13
  gen_android_adaptive() {
14
14
  local master="$1"
15
15
  local bg="$2"
16
- local padding="$3" # percent per side
17
- local res_root="$4" # e.g. /path/app/platform/android/res
16
+ local padding="$3" # percent per side
17
+ local res_root="$4" # e.g. /path/app/platform/android/res
18
+ local mono_master="${5:-}" # optional dedicated silhouette master
18
19
 
19
20
  local densities=(mdpi hdpi xhdpi xxhdpi xxxhdpi)
20
21
  local sizes=(108 162 216 324 432)
@@ -38,11 +39,22 @@ gen_android_adaptive() {
38
39
  -strip \
39
40
  "$dir/ic_launcher_background.png"
40
41
 
41
- # Monochrome: foreground tinted to pure white, alpha preserved
42
- magick "$dir/ic_launcher_foreground.png" \
43
- -channel RGB -fill white -colorize 100 +channel \
44
- -strip \
45
- "$dir/ic_launcher_monochrome.png"
42
+ # Monochrome: white silhouette with alpha. If a dedicated mono master was
43
+ # provided, render it fresh with the same padding. Otherwise derive from
44
+ # the colored foreground (naive whitening may flatten complex logos).
45
+ if [[ -n "$mono_master" ]]; then
46
+ magick "$mono_master" \
47
+ -resize "${inner}x${inner}" \
48
+ -background none -gravity center -extent "${size}x${size}" \
49
+ -channel RGB -fill white -colorize 100 +channel \
50
+ -strip \
51
+ "$dir/ic_launcher_monochrome.png"
52
+ else
53
+ magick "$dir/ic_launcher_foreground.png" \
54
+ -channel RGB -fill white -colorize 100 +channel \
55
+ -strip \
56
+ "$dir/ic_launcher_monochrome.png"
57
+ fi
46
58
  done
47
59
 
48
60
  # anydpi-v26 binder directory (XML copied by caller from assets/ic_launcher.xml)
@@ -1,12 +1,17 @@
1
1
  #!/usr/bin/env bash
2
- # gen-ios.sh — produce DefaultIcon-ios.png (1024×1024, alpha flattened over bg-color).
2
+ # gen-ios.sh — produce Titanium's two root-level iOS/Android icons:
3
3
  #
4
- # Unlike Android adaptive icons, iOS app icons have no "safe zone" — the launcher
5
- # doesn't mask them. What you see is what ships. So padding is purely visual
6
- # breathing room around the logo. Default 8% per side (logo fills 84% of the
7
- # canvas), which matches Apple's HIG aesthetic for branded wordmarks.
4
+ # DefaultIcon.png 1024×1024, alpha preserved (universal / Android source)
5
+ # DefaultIcon-ios.png 1024×1024, alpha flattened over bg-color (iOS)
8
6
  #
9
- # iOS rejects icons with alpha, so the final output is flattened over bg-color.
7
+ # This matches what `titanium` / `alloy new` ships out of the box: a fresh
8
+ # Alloy project contains both files in the project root, with DefaultIcon.png
9
+ # keeping transparency and DefaultIcon-ios.png flattened (Apple rejects alpha
10
+ # on App Store icon uploads).
11
+ #
12
+ # Padding is purely visual breathing room — iOS app icons have no launcher
13
+ # mask. Default 8% per side (logo fills 84% of the canvas), which matches
14
+ # Apple's HIG aesthetic for branded wordmarks.
10
15
 
11
16
  gen_ios() {
12
17
  local tight="$1" # tight master (aspect-preserved, transparent bg)
@@ -19,6 +24,16 @@ gen_ios() {
19
24
  local size=1024
20
25
  local inner=$(( size * (100 - 2 * padding) / 100 ))
21
26
 
27
+ # DefaultIcon.png — alpha preserved (matches `ti create` default for the
28
+ # universal icon source; Alloy/Android use this directly).
29
+ magick "$tight" \
30
+ -resize "${inner}x${inner}" \
31
+ -background none -gravity center -extent "${size}x${size}" \
32
+ -strip \
33
+ "$out_root/DefaultIcon.png"
34
+
35
+ # DefaultIcon-ios.png — flattened over bg-color. This is the file iOS
36
+ # actually ships; Apple rejects alpha on App Store icon uploads.
22
37
  magick "$tight" \
23
38
  -resize "${inner}x${inner}" \
24
39
  -background none -gravity center -extent "${size}x${size}" \
@@ -26,5 +41,6 @@ gen_ios() {
26
41
  -strip \
27
42
  "$out_root/DefaultIcon-ios.png"
28
43
 
44
+ log_ok "DefaultIcon.png (1024×1024, ${padding}% padding, alpha preserved)"
29
45
  log_ok "DefaultIcon-ios.png (1024×1024, ${padding}% padding, alpha flattened over $bg)"
30
46
  }
@@ -1,28 +1,43 @@
1
1
  #!/usr/bin/env bash
2
2
  # gen-marketplace.sh — store-submission artwork.
3
3
  #
4
- # iTunesConnect.png: 1024×1024, no alpha (App Store)
5
- # MarketplaceArtwork.png: 512×512, no alpha (Google Play)
4
+ # iTunesConnect.png 1024×1024 (App Store)
5
+ # MarketplaceArtwork.png 512×512 (Google Play)
6
6
  #
7
- # Uses the same --ios-padding as the iOS master (default 8%). Store assets are
8
- # scrutinized at large sizes and need visual breathing room — no safe-zone to
9
- # comply with, but aesthetically they should match the DefaultIcon-ios look.
7
+ # Alpha handling depends on whether --bg-color was EXPLICITLY provided
8
+ # (tracked via the 5th argument, `flatten`):
9
+ # - flatten=0 (no --bg-color) alpha preserved, matches `ti create` default
10
+ # - flatten=1 (--bg-color X) → alpha flattened on bg-color. Prevents the
11
+ # dark-mode-muddy-icon issue on Play Store
12
+ # and macOS App Store when the master has
13
+ # significant transparent areas.
14
+ #
15
+ # Uses the same --ios-padding as the iOS master (default 8%) so the three
16
+ # square icons share the same visual weight.
10
17
 
11
18
  gen_marketplace() {
12
19
  local tight="$1"
13
20
  local bg="$2"
14
21
  local padding="$3" # ios-padding percent per side
15
22
  local out_root="$4"
23
+ local flatten="${5:-0}" # 1 when --bg-color was explicitly provided
16
24
 
17
25
  mkdir -p "$out_root"
18
26
 
27
+ local flatten_args=()
28
+ local alpha_label="alpha"
29
+ if [[ "$flatten" == "1" ]]; then
30
+ flatten_args=(-background "$bg" -alpha remove -alpha off)
31
+ alpha_label="flat on $bg"
32
+ fi
33
+
19
34
  # App Store (1024²)
20
35
  local size_ios=1024
21
36
  local inner_ios=$(( size_ios * (100 - 2 * padding) / 100 ))
22
37
  magick "$tight" \
23
38
  -resize "${inner_ios}x${inner_ios}" \
24
39
  -background none -gravity center -extent "${size_ios}x${size_ios}" \
25
- -background "$bg" -alpha remove -alpha off \
40
+ "${flatten_args[@]}" \
26
41
  -strip \
27
42
  "$out_root/iTunesConnect.png"
28
43
 
@@ -32,9 +47,9 @@ gen_marketplace() {
32
47
  magick "$tight" \
33
48
  -resize "${inner_play}x${inner_play}" \
34
49
  -background none -gravity center -extent "${size_play}x${size_play}" \
35
- -background "$bg" -alpha remove -alpha off \
50
+ "${flatten_args[@]}" \
36
51
  -strip \
37
52
  "$out_root/MarketplaceArtwork.png"
38
53
 
39
- log_ok "Marketplace artwork: iTunesConnect.png (1024², ${padding}% padding), MarketplaceArtwork.png (512², ${padding}% padding)"
54
+ log_ok "Marketplace artwork: iTunesConnect.png (1024², ${padding}% padding, ${alpha_label}), MarketplaceArtwork.png (512², ${padding}% padding, ${alpha_label})"
40
55
  }
@@ -4,11 +4,21 @@
4
4
  # all non-transparent pixels become white and color information is discarded.
5
5
  #
6
6
  # Sizes per Android spec: mdpi=24px, hdpi=36, xhdpi=48, xxhdpi=72, xxxhdpi=96.
7
+ #
8
+ # Notification icons are NOT masked by the launcher, so they render as drawn.
9
+ # We trim any transparent padding baked into the master first, then scale the
10
+ # logo to fill the canvas edge-to-edge on its longer axis (with a 1px
11
+ # anti-aliasing margin per side). This matches what first-party Android apps
12
+ # ship (Gmail, Slack, Chrome) — the logo reaches the edge instead of sitting
13
+ # in a visibly padded box in the status bar.
14
+ #
15
+ # Material's 22dp-inside-24dp "live area" is a conservative guideline; in
16
+ # practice notification icons benefit from going closer to the edge because
17
+ # the status bar is already tiny.
7
18
 
8
19
  gen_notification() {
9
20
  local master="$1"
10
- local padding="$2"
11
- local res_root="$3"
21
+ local res_root="$2"
12
22
 
13
23
  local densities=(mdpi hdpi xhdpi xxhdpi xxxhdpi)
14
24
  local sizes=(24 36 48 72 96)
@@ -16,13 +26,15 @@ gen_notification() {
16
26
  for i in "${!densities[@]}"; do
17
27
  local d="${densities[$i]}"
18
28
  local size="${sizes[$i]}"
19
- # Notification icons get pretty heavily masked in the status bar, so use
20
- # slightly tighter padding than the full safe-zone.
21
- local inner=$(( size * (100 - 2 * padding) / 100 ))
29
+ # Edge-to-edge with a 1px anti-aliasing margin per side.
30
+ local inner=$(( size - 2 ))
31
+ (( inner < 1 )) && inner=1
22
32
  local dir="$res_root/drawable-$d"
23
33
  mkdir -p "$dir"
24
34
 
35
+ # Trim baked-in transparent padding from the master, then scale to inner.
25
36
  magick "$master" \
37
+ -trim +repage \
26
38
  -resize "${inner}x${inner}" \
27
39
  -channel RGB -fill white -colorize 100 +channel \
28
40
  -background none -gravity center -extent "${size}x${size}" \
@@ -30,5 +42,5 @@ gen_notification() {
30
42
  "$dir/ic_stat_notify.png"
31
43
  done
32
44
 
33
- log_ok "Notification icons (white+alpha) × 5 densities"
45
+ log_ok "Notification icons (white+alpha, edge-to-edge) × 5 densities"
34
46
  }
@@ -34,15 +34,21 @@ source "$LIB_DIR/gen-splash-icon.sh"
34
34
  # -----------------------------------------------------------------------------
35
35
 
36
36
  MASTER=""
37
+ MONOCHROME_MASTER=""
37
38
  BG_COLOR="#FFFFFF"
38
- PADDING=22
39
- IOS_PADDING=8
39
+ BG_COLOR_EXPLICIT=0
40
+ PADDING=20
41
+ IOS_PADDING=4
40
42
  WITH_NOTIFICATION=0
41
43
  WITH_SPLASH_ICON=0
42
44
  CLEANUP_LEGACY=0
43
45
  AGGRESSIVE=0
44
46
  OUTPUT=""
47
+ OUTPUT_EXPLICIT=0
45
48
  DRY_RUN=0
49
+ IN_PLACE=0
50
+ IS_IN_PLACE=0
51
+ NOTES=0
46
52
  PROJECT_ROOT="$(pwd)"
47
53
 
48
54
  # -----------------------------------------------------------------------------
@@ -82,11 +88,13 @@ ARGUMENTS:
82
88
  OPTIONS:
83
89
  --bg-color <hex> Background color for adaptive layer + iOS alpha flatten.
84
90
  Default: #FFFFFF
85
- --padding <pct> Android safe-zone padding per side (0–40). Default: 22
86
- (Android official minimum is 19.44%.)
91
+ --padding <pct> Android safe-zone padding per side (0–40). Default: 20
92
+ (Material spec floor is 19.44%; default 20 gives a
93
+ tiny buffer while keeping the logo visibly prominent.)
87
94
  --ios-padding <pct> iOS/marketplace aesthetic padding per side (0–40).
88
- Default: 8. iOS icons have no launcher mask — this
89
- is purely breathing room around the logo.
95
+ Default: 4. iOS icons have no launcher mask — this
96
+ is purely breathing room. Production reference apps
97
+ (Mail, Safari, La Baraja) use 2-6% per side.
90
98
  --with-notification Also generate ic_stat_notify.png × 5 densities.
91
99
  --with-splash-icon Also generate splash_icon.png × 5 densities (Android 12+).
92
100
  --cleanup-legacy After generating (or standalone), remove legacy branding
@@ -96,6 +104,17 @@ OPTIONS:
96
104
  (<1% global market in 2026). Off by default.
97
105
  --output <dir> Staging directory. Default: <project>/.ti-branding
98
106
  --project <dir> Project root (default: current working directory).
107
+ --in-place Skip the staging directory — write files directly into
108
+ the project root. OVERWRITES existing icons. --output
109
+ takes precedence when both are passed.
110
+ --monochrome-master <p> Optional dedicated silhouette master for
111
+ ic_launcher_monochrome.png + ic_stat_notify.png.
112
+ Use when the colored logo has multi-color detail
113
+ that would collapse into a featureless blob when
114
+ naively whitened. Falls back to main master if omitted.
115
+ --notes Print full tiapp.xml snippets + padding tuning guide
116
+ after the run. Default is a compact summary — use this
117
+ when you need the config snippets to paste into tiapp.xml.
99
118
  --dry-run Print what would be generated without writing files.
100
119
  -h, --help Show this help.
101
120
 
@@ -113,15 +132,18 @@ EOF
113
132
  while [[ $# -gt 0 ]]; do
114
133
  case "$1" in
115
134
  -h|--help) usage; exit 0 ;;
116
- --bg-color) BG_COLOR="$2"; shift 2 ;;
135
+ --bg-color) BG_COLOR="$2"; BG_COLOR_EXPLICIT=1; shift 2 ;;
117
136
  --padding) PADDING="$2"; shift 2 ;;
118
137
  --ios-padding) IOS_PADDING="$2"; shift 2 ;;
119
138
  --with-notification) WITH_NOTIFICATION=1; shift ;;
120
139
  --with-splash-icon) WITH_SPLASH_ICON=1; shift ;;
121
140
  --cleanup-legacy) CLEANUP_LEGACY=1; shift ;;
122
141
  --aggressive) AGGRESSIVE=1; shift ;;
123
- --output) OUTPUT="$2"; shift 2 ;;
142
+ --output) OUTPUT="$2"; OUTPUT_EXPLICIT=1; shift 2 ;;
124
143
  --project) PROJECT_ROOT="$2"; shift 2 ;;
144
+ --in-place) IN_PLACE=1; shift ;;
145
+ --monochrome-master) MONOCHROME_MASTER="$2"; shift 2 ;;
146
+ --notes) NOTES=1; shift ;;
125
147
  --dry-run) DRY_RUN=1; shift ;;
126
148
  --) shift; break ;;
127
149
  -*) log_err "Unknown option: $1"; usage >&2; exit 2 ;;
@@ -172,6 +194,14 @@ if [[ ! "$BG_COLOR" =~ ^#[0-9A-Fa-f]{6}$ ]]; then
172
194
  exit 2
173
195
  fi
174
196
 
197
+ # Resolve staging dir:
198
+ # explicit --output wins over --in-place (avoids ambiguity)
199
+ # --in-place (no --output) → write directly into the project root
200
+ # neither → default to .ti-branding/ inside the project
201
+ if [[ $IN_PLACE -eq 1 && $OUTPUT_EXPLICIT -eq 0 ]]; then
202
+ OUTPUT="$PROJECT_ROOT"
203
+ IS_IN_PLACE=1
204
+ fi
175
205
  OUTPUT="${OUTPUT:-$PROJECT_ROOT/.ti-branding}"
176
206
 
177
207
  # -----------------------------------------------------------------------------
@@ -191,11 +221,16 @@ if [[ -n "$MASTER" ]]; then
191
221
  log_info "Master: $MASTER"
192
222
  log_info "Background: $BG_COLOR"
193
223
  log_info "Padding: Android ${PADDING}% / iOS ${IOS_PADDING}% per side"
194
- log_info "Staging: $OUTPUT"
224
+ if [[ $IS_IN_PLACE -eq 1 ]]; then
225
+ log_info "Writing IN PLACE to: $PROJECT_ROOT"
226
+ else
227
+ log_info "Staging: $OUTPUT"
228
+ fi
195
229
  fi
196
230
  [[ $WITH_NOTIFICATION -eq 1 ]] && log_info "Extras: + notification icons"
197
231
  [[ $WITH_SPLASH_ICON -eq 1 ]] && log_info "Extras: + Android 12+ splash icon"
198
232
  [[ $CLEANUP_LEGACY -eq 1 ]] && log_info "Cleanup: --cleanup-legacy$([[ $AGGRESSIVE -eq 1 ]] && echo " --aggressive")"
233
+ [[ $IS_IN_PLACE -eq 1 && $DRY_RUN -eq 0 ]] && log_warn "⚠ --in-place mode: files in your project will be OVERWRITTEN. Commit first if you want a rollback."
199
234
  [[ $DRY_RUN -eq 1 ]] && log_warn "DRY RUN — no files will be written"
200
235
 
201
236
  # -----------------------------------------------------------------------------
@@ -227,13 +262,27 @@ log_step "3/6 Preparing masters (square for iOS, tight for Android)"
227
262
  PREPARED_BASE="$OUTPUT/_master"
228
263
  MASTER_SQUARE="${PREPARED_BASE}_square.png"
229
264
  MASTER_TIGHT="${PREPARED_BASE}_tight.png"
265
+ MONO_TIGHT=""
230
266
  if [[ $DRY_RUN -eq 0 ]]; then
231
267
  mkdir -p "$OUTPUT"
232
268
  prepare_master "$MASTER" "$PREPARED_BASE"
233
269
  log_ok "Square master: $MASTER_SQUARE"
234
270
  log_ok "Tight master: $MASTER_TIGHT"
271
+
272
+ # Optional: prepare a dedicated monochrome master if provided.
273
+ if [[ -n "$MONOCHROME_MASTER" ]]; then
274
+ if [[ ! -f "$MONOCHROME_MASTER" ]]; then
275
+ log_err "Monochrome master not found: $MONOCHROME_MASTER"
276
+ exit 2
277
+ fi
278
+ local_mono_base="$OUTPUT/_master_mono"
279
+ prepare_master "$MONOCHROME_MASTER" "$local_mono_base"
280
+ MONO_TIGHT="${local_mono_base}_tight.png"
281
+ log_ok "Monochrome master (for ic_launcher_monochrome + ic_stat_notify): $MONO_TIGHT"
282
+ fi
235
283
  else
236
284
  log_info "[dry-run] would prepare: $MASTER_SQUARE + $MASTER_TIGHT"
285
+ [[ -n "$MONOCHROME_MASTER" ]] && log_info "[dry-run] would prepare monochrome master from: $MONOCHROME_MASTER"
237
286
  fi
238
287
 
239
288
  # Resolve target paths based on project layout
@@ -247,14 +296,14 @@ ROOT_STAGING="$OUTPUT"
247
296
  log_step "4/6 Generating iOS master + marketplace artwork (square)"
248
297
  if [[ $DRY_RUN -eq 0 ]]; then
249
298
  gen_ios "$MASTER_TIGHT" "$BG_COLOR" "$IOS_PADDING" "$ROOT_STAGING"
250
- gen_marketplace "$MASTER_TIGHT" "$BG_COLOR" "$IOS_PADDING" "$ROOT_STAGING"
299
+ gen_marketplace "$MASTER_TIGHT" "$BG_COLOR" "$IOS_PADDING" "$ROOT_STAGING" "$BG_COLOR_EXPLICIT"
251
300
  else
252
- log_info "[dry-run] would emit DefaultIcon-ios.png, iTunesConnect.png, MarketplaceArtwork.png"
301
+ log_info "[dry-run] would emit DefaultIcon.png, DefaultIcon-ios.png, iTunesConnect.png, MarketplaceArtwork.png"
253
302
  fi
254
303
 
255
304
  log_step "5/6 Generating Android adaptive + legacy launcher icons (tight)"
256
305
  if [[ $DRY_RUN -eq 0 ]]; then
257
- gen_android_adaptive "$MASTER_TIGHT" "$BG_COLOR" "$PADDING" "$ANDROID_RES"
306
+ gen_android_adaptive "$MASTER_TIGHT" "$BG_COLOR" "$PADDING" "$ANDROID_RES" "$MONO_TIGHT"
258
307
  gen_android_legacy "$MASTER_TIGHT" "$BG_COLOR" "$PADDING" "$ANDROID_RES"
259
308
  cp "$ASSETS_DIR/ic_launcher.xml" "$ANDROID_RES/mipmap-anydpi-v26/ic_launcher.xml"
260
309
  log_ok "Adaptive icon XML bind: $ANDROID_RES/mipmap-anydpi-v26/ic_launcher.xml"
@@ -265,7 +314,8 @@ fi
265
314
  if [[ $WITH_NOTIFICATION -eq 1 || $WITH_SPLASH_ICON -eq 1 ]]; then
266
315
  log_step "6/6 Generating optional extras"
267
316
  if [[ $WITH_NOTIFICATION -eq 1 && $DRY_RUN -eq 0 ]]; then
268
- gen_notification "$MASTER_TIGHT" "$PADDING" "$ANDROID_RES"
317
+ # Use monochrome master if provided, else fall back to main (whitened by the generator).
318
+ gen_notification "${MONO_TIGHT:-$MASTER_TIGHT}" "$ANDROID_RES"
269
319
  elif [[ $WITH_NOTIFICATION -eq 1 ]]; then
270
320
  log_info "[dry-run] would emit ic_stat_notify.png × 5 densities"
271
321
  fi
@@ -285,11 +335,62 @@ fi
285
335
 
286
336
  log_step "Done"
287
337
  if [[ $DRY_RUN -eq 0 ]]; then
288
- log_ok "All assets staged at: $OUTPUT"
338
+ # In --in-place mode, intermediate master files (_master_square.png /
339
+ # _master_tight.png) land directly in the project root alongside the real
340
+ # branded assets. Clean them up so the user is only left with the 4 icons.
341
+ if [[ $IS_IN_PLACE -eq 1 ]]; then
342
+ rm -f "$OUTPUT/_master_square.png" "$OUTPUT/_master_tight.png"
343
+ log_ok "All assets written IN PLACE at: $PROJECT_ROOT"
344
+ else
345
+ log_ok "All assets staged at: $OUTPUT"
346
+ fi
347
+
348
+ # ---------------------------------------------------------------------------
349
+ # Post-generation output — compact summary by default, full notes with --notes.
350
+ # ---------------------------------------------------------------------------
351
+
352
+ if [[ $NOTES -eq 0 ]]; then
353
+ # Compact summary — only config/destination + 3-line next steps + hint.
354
+ echo
355
+ echo "${C_BOLD}Summary${C_RESET}"
356
+ echo " Background: ${BG_COLOR} Padding: Android ${PADDING}% / iOS ${IOS_PADDING}%"
357
+ if [[ $IS_IN_PLACE -eq 1 ]]; then
358
+ echo " Written in place to: $PROJECT_ROOT"
359
+ else
360
+ echo " Staged at: $OUTPUT"
361
+ fi
362
+ echo
363
+ echo "${C_BOLD}Next steps${C_RESET}"
364
+ if [[ $IS_IN_PLACE -eq 1 ]]; then
365
+ echo " • Preview the new icons in ${C_YELLOW}Preview.app${C_RESET}."
366
+ echo " • If something looks wrong: ${C_DIM}git checkout -- .${C_RESET}"
367
+ echo " • Rebuild: ${C_DIM}ti clean && ti build -p android -T emulator${C_RESET}"
368
+ else
369
+ case "$PROJECT_TYPE" in
370
+ alloy)
371
+ echo " • Preview in ${C_YELLOW}Preview.app${C_RESET}, then copy to project:"
372
+ echo " ${C_DIM}cp $OUTPUT/{DefaultIcon,DefaultIcon-ios,iTunesConnect,MarketplaceArtwork}.png $PROJECT_ROOT/${C_RESET}"
373
+ echo " ${C_DIM}cp -R $OUTPUT/app/platform/android/res/. $PROJECT_ROOT/app/platform/android/res/${C_RESET}"
374
+ ;;
375
+ classic)
376
+ echo " • Preview in ${C_YELLOW}Preview.app${C_RESET}, then copy to project:"
377
+ echo " ${C_DIM}cp $OUTPUT/{DefaultIcon,DefaultIcon-ios,iTunesConnect,MarketplaceArtwork}.png $PROJECT_ROOT/${C_RESET}"
378
+ echo " ${C_DIM}cp -R $OUTPUT/platform/android/res/. $PROJECT_ROOT/platform/android/res/${C_RESET}"
379
+ ;;
380
+ *)
381
+ echo " • Review ${C_YELLOW}$OUTPUT/${C_RESET} and copy files to their final paths manually."
382
+ ;;
383
+ esac
384
+ echo " • Cleanup staging: ${C_DIM}rm -rf $OUTPUT${C_RESET}"
385
+ fi
386
+ echo
387
+ log_info "Pass ${C_BOLD}--notes${C_RESET} to print tiapp.xml snippets + padding tuning guide."
388
+ echo
389
+ exit 0
390
+ fi
289
391
 
290
392
  # ---------------------------------------------------------------------------
291
- # Post-generation notes (aclaraciones) — help the user understand what was
292
- # made, how to adjust, and what tiapp.xml glue is still needed.
393
+ # Full notes (with --notes) — tiapp.xml snippets, padding tuning, etc.
293
394
  # ---------------------------------------------------------------------------
294
395
 
295
396
  echo
@@ -302,11 +403,11 @@ if [[ $DRY_RUN -eq 0 ]]; then
302
403
  echo
303
404
  echo " If the logo looks ${C_DIM}pegado / cramped${C_RESET}: re-run with higher padding"
304
405
  echo " --padding ${C_YELLOW}25-30${C_RESET} (Android)"
305
- echo " --ios-padding ${C_YELLOW}10-14${C_RESET} (iOS)"
406
+ echo " --ios-padding ${C_YELLOW}8-12${C_RESET} (iOS)"
306
407
  echo
307
408
  echo " If the logo looks ${C_DIM}too small / lost${C_RESET}: re-run with lower padding"
308
409
  echo " --padding ${C_YELLOW}19${C_RESET} (Android spec floor)"
309
- echo " --ios-padding ${C_YELLOW}4-6${C_RESET} (iOS)"
410
+ echo " --ios-padding ${C_YELLOW}2-3${C_RESET} (matches first-party apps like Mail, Safari)"
310
411
 
311
412
  echo
312
413
  echo "${C_BOLD}Configuration reminders${C_RESET}"
@@ -339,72 +440,58 @@ EOF
339
440
 
340
441
  if [[ $WITH_SPLASH_ICON -eq 1 ]]; then
341
442
  case "$PROJECT_TYPE" in
342
- alloy) SPLASH_DIR="app/platform/android/res/values-v31" ;;
343
- classic) SPLASH_DIR="platform/android/res/values-v31" ;;
344
- *) SPLASH_DIR="platform/android/res/values-v31" ;;
443
+ alloy) SPLASH_DIR="app/platform/android/res/values" ;;
444
+ classic) SPLASH_DIR="platform/android/res/values" ;;
445
+ *) SPLASH_DIR="platform/android/res/values" ;;
345
446
  esac
346
447
 
347
448
  echo
348
- echo " ${C_BOLD}3. Android 12+ splash screen — READ FIRST${C_RESET}"
449
+ echo " ${C_BOLD}3. Android 12+ splash screen — RECOMMENDED: match Titanium activity theme${C_RESET}"
349
450
  echo
350
- echo " ${C_YELLOW}Titanium SDK 13.x already generates a splash screen automatically${C_RESET}"
351
- echo " ${C_YELLOW}from your launcher icon + <default-background-color>.${C_RESET} For most apps,"
352
- echo " the default is GOOD: the logo centered on your brand color, mask-aware."
451
+ echo " ${C_YELLOW}Titanium SDK 13.x${C_RESET} shows a system splash using your launcher icon on"
452
+ echo " Android 12+. If the system splash background does NOT match your first"
453
+ echo " Titanium activity background, you get a visible ${C_BOLD}FLICKER${C_RESET} at the end of"
454
+ echo " the splash (navy → white → content) right before index.js renders."
353
455
  echo
354
- echo " The ${C_DIM}splash_icon.png${C_RESET} × 5 densities were generated for ADVANCED users who"
355
- echo " want a custom splash icon distinct from the launcher icon. Wiring it up"
356
- echo " requires a theme override, which has two flavors:"
456
+ echo " ${C_BOLD}Fix${C_RESET}: define a custom theme that inherits from a ${C_BOLD}Titanium parent${C_RESET} theme"
457
+ echo " and applies to the whole application. Keeps the ActionBar intact while"
458
+ echo " synchronizing the splash background with the activity background."
357
459
  echo
358
- echo " ${C_BOLD}Option A — Native platform (API 31+ only, no lib needed)${C_RESET}"
359
- echo " ${C_DIM}Simpler. Works without adding any Gradle dependency. API <31 falls back${C_RESET}"
360
- echo " ${C_DIM}to Titanium's default splash (your launcher icon).${C_RESET}"
361
460
  echo " ${C_DIM}Create ${SPLASH_DIR}/splash_theme.xml:${C_RESET}"
362
461
  cat <<EOF
363
462
  <?xml version="1.0" encoding="utf-8"?>
364
463
  <resources>
365
- <style name="Theme.App.SplashScreen" parent="@android:style/Theme.DeviceDefault.NoActionBar">
464
+ <style name="Theme.App.Splash" parent="@style/Theme.Titanium.Light.NoTitle">
366
465
  <item name="android:windowSplashScreenBackground">${BG_COLOR}</item>
367
- <item name="android:windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>
466
+ <item name="android:windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
368
467
  </style>
369
468
  </resources>
370
469
  EOF
371
470
  echo
372
- echo " ${C_BOLD}Option B — androidx.core:core-splashscreen (works API 21+)${C_RESET}"
373
- echo " ${C_DIM}More complete (backward-compat, postSplashScreenTheme handoff). Requires${C_RESET}"
374
- echo " ${C_DIM}adding the androidx.core:core-splashscreen library as a Gradle dep, which${C_RESET}"
375
- echo " ${C_DIM}Titanium 13.x does NOT ship by default. To add it, create/edit${C_RESET}"
376
- echo " ${C_DIM}app/platform/android/build.gradle with:${C_RESET}"
471
+ echo " ${C_DIM}Then in tiapp.xml under <android><manifest>:${C_RESET}"
377
472
  cat <<'EOF'
378
- dependencies {
379
- implementation 'androidx.core:core-splashscreen:1.0.1'
380
- }
381
- EOF
382
- echo " ${C_DIM}Then ${SPLASH_DIR}/splash_theme.xml uses the library theme:${C_RESET}"
383
- cat <<EOF
384
- <?xml version="1.0" encoding="utf-8"?>
385
- <resources>
386
- <style name="Theme.App.SplashScreen" parent="Theme.SplashScreen">
387
- <item name="windowSplashScreenBackground">${BG_COLOR}</item>
388
- <item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>
389
- <item name="postSplashScreenTheme">@style/Theme.AppDerived</item>
390
- </style>
391
- </resources>
473
+ <application android:icon="@mipmap/ic_launcher"
474
+ android:theme="@style/Theme.App.Splash"
475
+ android:usesCleartextTraffic="false"/>
392
476
  EOF
393
477
  echo
394
- echo " ${C_BOLD}Either Option A or B needs this meta-data${C_RESET}"
395
- echo " ${C_DIM}under <android><manifest><application> in tiapp.xml:${C_RESET}"
396
- cat <<'EOF'
397
- <meta-data android:name="io.tidev.titanium.splash.theme"
398
- android:value="@style/Theme.App.SplashScreen"/>
399
- EOF
478
+ echo " ${C_BOLD}Parent theme options${C_RESET} (pick per your ActionBar needs):"
479
+ echo " ${C_DIM}@style/Theme.Titanium.Light — ActionBar + title bar${C_RESET}"
480
+ echo " ${C_DIM}@style/Theme.Titanium.Light.NoTitle — ActionBar, no title (common)${C_RESET}"
481
+ echo " ${C_DIM}@style/Theme.Titanium.Light.Fullscreen — no ActionBar, no status bar${C_RESET}"
482
+ echo " ${C_DIM}(plus Dark variants)${C_RESET}"
483
+ echo
484
+ echo " ${C_YELLOW}⚠ Inherit ONLY from Titanium parents${C_RESET} (${C_BOLD}Theme.Titanium.*${C_RESET}). Do NOT"
485
+ echo " inherit from ${C_DIM}@android:style/Theme.DeviceDefault.NoActionBar${C_RESET} on"
486
+ echo " ${C_BOLD}<application>${C_RESET} — that strips the ActionBar from every screen."
400
487
  echo
401
- echo " ${C_YELLOW}⚠ CRITICAL${C_RESET}: NEVER set android:theme=\"@style/Theme.App.SplashScreen\""
402
- echo " on ${C_BOLD}<application>${C_RESET} or any ${C_BOLD}<activity>${C_RESET}. That breaks the ActionBar in every"
403
- echo " screen. The ${C_BOLD}meta-data${C_RESET} above is the ONLY correct way to register a splash"
404
- echo " theme in Titanium."
488
+ echo " ${C_DIM}The splash_icon.png × 5 files are OPTIONAL — the theme above points${C_RESET}"
489
+ echo " ${C_DIM}windowSplashScreenAnimatedIcon at the launcher icon, which is usually${C_RESET}"
490
+ echo " ${C_DIM}what you want. Point it at @drawable/splash_icon only if you designed${C_RESET}"
491
+ echo " ${C_DIM}a distinct custom splash icon.${C_RESET}"
405
492
  echo
406
- echo " ${C_DIM}Skipping the splash theme entirely is a valid choice the launcher icon${C_RESET}"
407
- echo " ${C_DIM}already provides a perfectly good Android 12+ splash via Titanium's default.${C_RESET}"
493
+ echo " ${C_DIM}Reference: LM - La Baraja uses this exact pattern in production with${C_RESET}"
494
+ echo " ${C_DIM}zero flicker on Android 12+.${C_RESET}"
408
495
  fi
409
496
 
410
497
  if [[ $WITH_NOTIFICATION -eq 1 ]]; then
@@ -438,24 +525,31 @@ EOF
438
525
  echo
439
526
  echo "${C_BOLD}Next steps${C_RESET}"
440
527
  echo
441
- echo " 1. Preview in ${C_YELLOW}Preview.app${C_RESET} (never use ${C_DIM}open${C_RESET} without -a triggers heavy editors)"
528
+ if [[ $IS_IN_PLACE -eq 1 ]]; then
529
+ echo " 1. Preview the new icons in ${C_YELLOW}Preview.app${C_RESET} — the files in your project"
530
+ echo " were overwritten directly (no staging directory was used)."
531
+ echo " 2. If something looks wrong, restore from git: ${C_DIM}git checkout -- .${C_RESET}"
532
+ echo " 3. Rebuild: ${C_DIM}ti clean && ti build -p android -T emulator${C_RESET}"
533
+ else
534
+ echo " 1. Preview in ${C_YELLOW}Preview.app${C_RESET} (never use ${C_DIM}open${C_RESET} without -a — triggers heavy editors)"
442
535
  case "$PROJECT_TYPE" in
443
536
  alloy)
444
537
  echo " 2. If good, copy to project:"
445
- echo " cp $OUTPUT/DefaultIcon-ios.png $OUTPUT/iTunesConnect.png $OUTPUT/MarketplaceArtwork.png $PROJECT_ROOT/"
538
+ echo " cp $OUTPUT/DefaultIcon.png $OUTPUT/DefaultIcon-ios.png $OUTPUT/iTunesConnect.png $OUTPUT/MarketplaceArtwork.png $PROJECT_ROOT/"
446
539
  echo " cp -R $OUTPUT/app/platform/android/res/. $PROJECT_ROOT/app/platform/android/res/"
447
540
  ;;
448
541
  classic)
449
542
  echo " 2. If good, copy to project:"
450
- echo " cp $OUTPUT/DefaultIcon-ios.png $OUTPUT/iTunesConnect.png $OUTPUT/MarketplaceArtwork.png $PROJECT_ROOT/"
543
+ echo " cp $OUTPUT/DefaultIcon.png $OUTPUT/DefaultIcon-ios.png $OUTPUT/iTunesConnect.png $OUTPUT/MarketplaceArtwork.png $PROJECT_ROOT/"
451
544
  echo " cp -R $OUTPUT/platform/android/res/. $PROJECT_ROOT/platform/android/res/"
452
545
  ;;
453
546
  *)
454
547
  echo " 2. Review staging dir and copy files to their final paths manually."
455
548
  ;;
456
549
  esac
457
- echo " 3. Cleanup staging: rm -rf $OUTPUT"
458
- echo " 4. Rebuild: ti clean && ti build -p android -T emulator"
550
+ echo " 3. Cleanup staging: rm -rf $OUTPUT"
551
+ echo " 4. Rebuild: ${C_DIM}ti clean && ti build -p android -T emulator${C_RESET}"
552
+ fi
459
553
  echo
460
554
  else
461
555
  log_info "Dry-run complete. Re-run without --dry-run to write files."