@maccesar/titools 2.6.1 → 2.7.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 +38 -36
- package/package.json +1 -1
- package/skills/ti-branding/SKILL.md +10 -6
- package/skills/ti-branding/scripts/lib/gen-android-adaptive.sh +19 -7
- package/skills/ti-branding/scripts/lib/gen-ios.sh +22 -6
- package/skills/ti-branding/scripts/lib/gen-marketplace.sh +23 -8
- package/skills/ti-branding/scripts/lib/gen-notification.sh +18 -6
- package/skills/ti-branding/scripts/ti-branding +125 -18
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
|
-
|
|
|
93
|
-
|
|
94
|
-
| **Claude Code**
|
|
95
|
-
| **Gemini CLI**
|
|
96
|
-
| **Codex CLI**
|
|
97
|
-
| **Knowledge Index** | Not included
|
|
98
|
-
| **Auto-updates**
|
|
99
|
-
| **Slash commands**
|
|
100
|
-
| **Session hook**
|
|
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
|
|
242
|
-
|
|
243
|
-
| `/ti-check`
|
|
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`
|
|
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
|
|
802
|
-
|
|
803
|
-
| `auto-adjust-scroll-view-insets` | `autoAdjustScrollViewInsets` | Adjusts ScrollView insets to prevent content overlap
|
|
804
|
-
| `extend-edges-all`
|
|
805
|
-
| `large-title-enabled`
|
|
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,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
|
|
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
|
|
33
|
-
| `
|
|
34
|
-
| `
|
|
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,15 @@ 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>` | `
|
|
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. |
|
|
72
73
|
| `--with-notification` | off | Emit `ic_stat_notify.png` × 5 densities. |
|
|
73
74
|
| `--with-splash-icon` | off | Emit `splash_icon.png` × 5 densities (Android 12+ SplashScreen API). |
|
|
74
75
|
| `--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
76
|
| `--aggressive` | off | With `--cleanup-legacy`, also remove `ldpi` density folders (<1% of active devices globally in 2026). Off by default to be conservative. |
|
|
76
77
|
| `--output <dir>` | `<project>/.ti-branding/` | Staging directory. Review before copying to `app/`. |
|
|
78
|
+
| `--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. |
|
|
79
|
+
| `--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. |
|
|
80
|
+
| `--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
81
|
| `--dry-run` | off | Print what would be generated/removed without writing or deleting. Works with both generation and `--cleanup-legacy`. |
|
|
78
82
|
|
|
79
83
|
## 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"
|
|
17
|
-
local res_root="$4"
|
|
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:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"$
|
|
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
|
|
2
|
+
# gen-ios.sh — produce Titanium's two root-level iOS/Android icons:
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
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
|
-
#
|
|
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
|
|
5
|
-
# MarketplaceArtwork.png
|
|
4
|
+
# iTunesConnect.png 1024×1024 (App Store)
|
|
5
|
+
# MarketplaceArtwork.png 512×512 (Google Play)
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
39
|
+
BG_COLOR_EXPLICIT=0
|
|
40
|
+
PADDING=20
|
|
39
41
|
IOS_PADDING=8
|
|
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,8 +88,9 @@ 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:
|
|
86
|
-
(
|
|
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
95
|
Default: 8. iOS icons have no launcher mask — this
|
|
89
96
|
is purely breathing room around the logo.
|
|
@@ -96,6 +103,17 @@ OPTIONS:
|
|
|
96
103
|
(<1% global market in 2026). Off by default.
|
|
97
104
|
--output <dir> Staging directory. Default: <project>/.ti-branding
|
|
98
105
|
--project <dir> Project root (default: current working directory).
|
|
106
|
+
--in-place Skip the staging directory — write files directly into
|
|
107
|
+
the project root. OVERWRITES existing icons. --output
|
|
108
|
+
takes precedence when both are passed.
|
|
109
|
+
--monochrome-master <p> Optional dedicated silhouette master for
|
|
110
|
+
ic_launcher_monochrome.png + ic_stat_notify.png.
|
|
111
|
+
Use when the colored logo has multi-color detail
|
|
112
|
+
that would collapse into a featureless blob when
|
|
113
|
+
naively whitened. Falls back to main master if omitted.
|
|
114
|
+
--notes Print full tiapp.xml snippets + padding tuning guide
|
|
115
|
+
after the run. Default is a compact summary — use this
|
|
116
|
+
when you need the config snippets to paste into tiapp.xml.
|
|
99
117
|
--dry-run Print what would be generated without writing files.
|
|
100
118
|
-h, --help Show this help.
|
|
101
119
|
|
|
@@ -113,15 +131,18 @@ EOF
|
|
|
113
131
|
while [[ $# -gt 0 ]]; do
|
|
114
132
|
case "$1" in
|
|
115
133
|
-h|--help) usage; exit 0 ;;
|
|
116
|
-
--bg-color) BG_COLOR="$2"; shift 2 ;;
|
|
134
|
+
--bg-color) BG_COLOR="$2"; BG_COLOR_EXPLICIT=1; shift 2 ;;
|
|
117
135
|
--padding) PADDING="$2"; shift 2 ;;
|
|
118
136
|
--ios-padding) IOS_PADDING="$2"; shift 2 ;;
|
|
119
137
|
--with-notification) WITH_NOTIFICATION=1; shift ;;
|
|
120
138
|
--with-splash-icon) WITH_SPLASH_ICON=1; shift ;;
|
|
121
139
|
--cleanup-legacy) CLEANUP_LEGACY=1; shift ;;
|
|
122
140
|
--aggressive) AGGRESSIVE=1; shift ;;
|
|
123
|
-
--output) OUTPUT="$2"; shift 2 ;;
|
|
141
|
+
--output) OUTPUT="$2"; OUTPUT_EXPLICIT=1; shift 2 ;;
|
|
124
142
|
--project) PROJECT_ROOT="$2"; shift 2 ;;
|
|
143
|
+
--in-place) IN_PLACE=1; shift ;;
|
|
144
|
+
--monochrome-master) MONOCHROME_MASTER="$2"; shift 2 ;;
|
|
145
|
+
--notes) NOTES=1; shift ;;
|
|
125
146
|
--dry-run) DRY_RUN=1; shift ;;
|
|
126
147
|
--) shift; break ;;
|
|
127
148
|
-*) log_err "Unknown option: $1"; usage >&2; exit 2 ;;
|
|
@@ -172,6 +193,14 @@ if [[ ! "$BG_COLOR" =~ ^#[0-9A-Fa-f]{6}$ ]]; then
|
|
|
172
193
|
exit 2
|
|
173
194
|
fi
|
|
174
195
|
|
|
196
|
+
# Resolve staging dir:
|
|
197
|
+
# explicit --output wins over --in-place (avoids ambiguity)
|
|
198
|
+
# --in-place (no --output) → write directly into the project root
|
|
199
|
+
# neither → default to .ti-branding/ inside the project
|
|
200
|
+
if [[ $IN_PLACE -eq 1 && $OUTPUT_EXPLICIT -eq 0 ]]; then
|
|
201
|
+
OUTPUT="$PROJECT_ROOT"
|
|
202
|
+
IS_IN_PLACE=1
|
|
203
|
+
fi
|
|
175
204
|
OUTPUT="${OUTPUT:-$PROJECT_ROOT/.ti-branding}"
|
|
176
205
|
|
|
177
206
|
# -----------------------------------------------------------------------------
|
|
@@ -191,11 +220,16 @@ if [[ -n "$MASTER" ]]; then
|
|
|
191
220
|
log_info "Master: $MASTER"
|
|
192
221
|
log_info "Background: $BG_COLOR"
|
|
193
222
|
log_info "Padding: Android ${PADDING}% / iOS ${IOS_PADDING}% per side"
|
|
194
|
-
|
|
223
|
+
if [[ $IS_IN_PLACE -eq 1 ]]; then
|
|
224
|
+
log_info "Writing IN PLACE to: $PROJECT_ROOT"
|
|
225
|
+
else
|
|
226
|
+
log_info "Staging: $OUTPUT"
|
|
227
|
+
fi
|
|
195
228
|
fi
|
|
196
229
|
[[ $WITH_NOTIFICATION -eq 1 ]] && log_info "Extras: + notification icons"
|
|
197
230
|
[[ $WITH_SPLASH_ICON -eq 1 ]] && log_info "Extras: + Android 12+ splash icon"
|
|
198
231
|
[[ $CLEANUP_LEGACY -eq 1 ]] && log_info "Cleanup: --cleanup-legacy$([[ $AGGRESSIVE -eq 1 ]] && echo " --aggressive")"
|
|
232
|
+
[[ $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
233
|
[[ $DRY_RUN -eq 1 ]] && log_warn "DRY RUN — no files will be written"
|
|
200
234
|
|
|
201
235
|
# -----------------------------------------------------------------------------
|
|
@@ -227,13 +261,27 @@ log_step "3/6 Preparing masters (square for iOS, tight for Android)"
|
|
|
227
261
|
PREPARED_BASE="$OUTPUT/_master"
|
|
228
262
|
MASTER_SQUARE="${PREPARED_BASE}_square.png"
|
|
229
263
|
MASTER_TIGHT="${PREPARED_BASE}_tight.png"
|
|
264
|
+
MONO_TIGHT=""
|
|
230
265
|
if [[ $DRY_RUN -eq 0 ]]; then
|
|
231
266
|
mkdir -p "$OUTPUT"
|
|
232
267
|
prepare_master "$MASTER" "$PREPARED_BASE"
|
|
233
268
|
log_ok "Square master: $MASTER_SQUARE"
|
|
234
269
|
log_ok "Tight master: $MASTER_TIGHT"
|
|
270
|
+
|
|
271
|
+
# Optional: prepare a dedicated monochrome master if provided.
|
|
272
|
+
if [[ -n "$MONOCHROME_MASTER" ]]; then
|
|
273
|
+
if [[ ! -f "$MONOCHROME_MASTER" ]]; then
|
|
274
|
+
log_err "Monochrome master not found: $MONOCHROME_MASTER"
|
|
275
|
+
exit 2
|
|
276
|
+
fi
|
|
277
|
+
local_mono_base="$OUTPUT/_master_mono"
|
|
278
|
+
prepare_master "$MONOCHROME_MASTER" "$local_mono_base"
|
|
279
|
+
MONO_TIGHT="${local_mono_base}_tight.png"
|
|
280
|
+
log_ok "Monochrome master (for ic_launcher_monochrome + ic_stat_notify): $MONO_TIGHT"
|
|
281
|
+
fi
|
|
235
282
|
else
|
|
236
283
|
log_info "[dry-run] would prepare: $MASTER_SQUARE + $MASTER_TIGHT"
|
|
284
|
+
[[ -n "$MONOCHROME_MASTER" ]] && log_info "[dry-run] would prepare monochrome master from: $MONOCHROME_MASTER"
|
|
237
285
|
fi
|
|
238
286
|
|
|
239
287
|
# Resolve target paths based on project layout
|
|
@@ -247,14 +295,14 @@ ROOT_STAGING="$OUTPUT"
|
|
|
247
295
|
log_step "4/6 Generating iOS master + marketplace artwork (square)"
|
|
248
296
|
if [[ $DRY_RUN -eq 0 ]]; then
|
|
249
297
|
gen_ios "$MASTER_TIGHT" "$BG_COLOR" "$IOS_PADDING" "$ROOT_STAGING"
|
|
250
|
-
gen_marketplace "$MASTER_TIGHT" "$BG_COLOR" "$IOS_PADDING" "$ROOT_STAGING"
|
|
298
|
+
gen_marketplace "$MASTER_TIGHT" "$BG_COLOR" "$IOS_PADDING" "$ROOT_STAGING" "$BG_COLOR_EXPLICIT"
|
|
251
299
|
else
|
|
252
|
-
log_info "[dry-run] would emit DefaultIcon-ios.png, iTunesConnect.png, MarketplaceArtwork.png"
|
|
300
|
+
log_info "[dry-run] would emit DefaultIcon.png, DefaultIcon-ios.png, iTunesConnect.png, MarketplaceArtwork.png"
|
|
253
301
|
fi
|
|
254
302
|
|
|
255
303
|
log_step "5/6 Generating Android adaptive + legacy launcher icons (tight)"
|
|
256
304
|
if [[ $DRY_RUN -eq 0 ]]; then
|
|
257
|
-
gen_android_adaptive "$MASTER_TIGHT" "$BG_COLOR" "$PADDING" "$ANDROID_RES"
|
|
305
|
+
gen_android_adaptive "$MASTER_TIGHT" "$BG_COLOR" "$PADDING" "$ANDROID_RES" "$MONO_TIGHT"
|
|
258
306
|
gen_android_legacy "$MASTER_TIGHT" "$BG_COLOR" "$PADDING" "$ANDROID_RES"
|
|
259
307
|
cp "$ASSETS_DIR/ic_launcher.xml" "$ANDROID_RES/mipmap-anydpi-v26/ic_launcher.xml"
|
|
260
308
|
log_ok "Adaptive icon XML bind: $ANDROID_RES/mipmap-anydpi-v26/ic_launcher.xml"
|
|
@@ -265,7 +313,8 @@ fi
|
|
|
265
313
|
if [[ $WITH_NOTIFICATION -eq 1 || $WITH_SPLASH_ICON -eq 1 ]]; then
|
|
266
314
|
log_step "6/6 Generating optional extras"
|
|
267
315
|
if [[ $WITH_NOTIFICATION -eq 1 && $DRY_RUN -eq 0 ]]; then
|
|
268
|
-
|
|
316
|
+
# Use monochrome master if provided, else fall back to main (whitened by the generator).
|
|
317
|
+
gen_notification "${MONO_TIGHT:-$MASTER_TIGHT}" "$ANDROID_RES"
|
|
269
318
|
elif [[ $WITH_NOTIFICATION -eq 1 ]]; then
|
|
270
319
|
log_info "[dry-run] would emit ic_stat_notify.png × 5 densities"
|
|
271
320
|
fi
|
|
@@ -285,11 +334,62 @@ fi
|
|
|
285
334
|
|
|
286
335
|
log_step "Done"
|
|
287
336
|
if [[ $DRY_RUN -eq 0 ]]; then
|
|
288
|
-
|
|
337
|
+
# In --in-place mode, intermediate master files (_master_square.png /
|
|
338
|
+
# _master_tight.png) land directly in the project root alongside the real
|
|
339
|
+
# branded assets. Clean them up so the user is only left with the 4 icons.
|
|
340
|
+
if [[ $IS_IN_PLACE -eq 1 ]]; then
|
|
341
|
+
rm -f "$OUTPUT/_master_square.png" "$OUTPUT/_master_tight.png"
|
|
342
|
+
log_ok "All assets written IN PLACE at: $PROJECT_ROOT"
|
|
343
|
+
else
|
|
344
|
+
log_ok "All assets staged at: $OUTPUT"
|
|
345
|
+
fi
|
|
289
346
|
|
|
290
347
|
# ---------------------------------------------------------------------------
|
|
291
|
-
# Post-generation
|
|
292
|
-
#
|
|
348
|
+
# Post-generation output — compact summary by default, full notes with --notes.
|
|
349
|
+
# ---------------------------------------------------------------------------
|
|
350
|
+
|
|
351
|
+
if [[ $NOTES -eq 0 ]]; then
|
|
352
|
+
# Compact summary — only config/destination + 3-line next steps + hint.
|
|
353
|
+
echo
|
|
354
|
+
echo "${C_BOLD}Summary${C_RESET}"
|
|
355
|
+
echo " Background: ${BG_COLOR} Padding: Android ${PADDING}% / iOS ${IOS_PADDING}%"
|
|
356
|
+
if [[ $IS_IN_PLACE -eq 1 ]]; then
|
|
357
|
+
echo " Written in place to: $PROJECT_ROOT"
|
|
358
|
+
else
|
|
359
|
+
echo " Staged at: $OUTPUT"
|
|
360
|
+
fi
|
|
361
|
+
echo
|
|
362
|
+
echo "${C_BOLD}Next steps${C_RESET}"
|
|
363
|
+
if [[ $IS_IN_PLACE -eq 1 ]]; then
|
|
364
|
+
echo " • Preview the new icons in ${C_YELLOW}Preview.app${C_RESET}."
|
|
365
|
+
echo " • If something looks wrong: ${C_DIM}git checkout -- .${C_RESET}"
|
|
366
|
+
echo " • Rebuild: ${C_DIM}ti clean && ti build -p android -T emulator${C_RESET}"
|
|
367
|
+
else
|
|
368
|
+
case "$PROJECT_TYPE" in
|
|
369
|
+
alloy)
|
|
370
|
+
echo " • Preview in ${C_YELLOW}Preview.app${C_RESET}, then copy to project:"
|
|
371
|
+
echo " ${C_DIM}cp $OUTPUT/{DefaultIcon,DefaultIcon-ios,iTunesConnect,MarketplaceArtwork}.png $PROJECT_ROOT/${C_RESET}"
|
|
372
|
+
echo " ${C_DIM}cp -R $OUTPUT/app/platform/android/res/. $PROJECT_ROOT/app/platform/android/res/${C_RESET}"
|
|
373
|
+
;;
|
|
374
|
+
classic)
|
|
375
|
+
echo " • Preview in ${C_YELLOW}Preview.app${C_RESET}, then copy to project:"
|
|
376
|
+
echo " ${C_DIM}cp $OUTPUT/{DefaultIcon,DefaultIcon-ios,iTunesConnect,MarketplaceArtwork}.png $PROJECT_ROOT/${C_RESET}"
|
|
377
|
+
echo " ${C_DIM}cp -R $OUTPUT/platform/android/res/. $PROJECT_ROOT/platform/android/res/${C_RESET}"
|
|
378
|
+
;;
|
|
379
|
+
*)
|
|
380
|
+
echo " • Review ${C_YELLOW}$OUTPUT/${C_RESET} and copy files to their final paths manually."
|
|
381
|
+
;;
|
|
382
|
+
esac
|
|
383
|
+
echo " • Cleanup staging: ${C_DIM}rm -rf $OUTPUT${C_RESET}"
|
|
384
|
+
fi
|
|
385
|
+
echo
|
|
386
|
+
log_info "Pass ${C_BOLD}--notes${C_RESET} to print tiapp.xml snippets + padding tuning guide."
|
|
387
|
+
echo
|
|
388
|
+
exit 0
|
|
389
|
+
fi
|
|
390
|
+
|
|
391
|
+
# ---------------------------------------------------------------------------
|
|
392
|
+
# Full notes (with --notes) — tiapp.xml snippets, padding tuning, etc.
|
|
293
393
|
# ---------------------------------------------------------------------------
|
|
294
394
|
|
|
295
395
|
echo
|
|
@@ -438,24 +538,31 @@ EOF
|
|
|
438
538
|
echo
|
|
439
539
|
echo "${C_BOLD}Next steps${C_RESET}"
|
|
440
540
|
echo
|
|
441
|
-
|
|
541
|
+
if [[ $IS_IN_PLACE -eq 1 ]]; then
|
|
542
|
+
echo " 1. Preview the new icons in ${C_YELLOW}Preview.app${C_RESET} — the files in your project"
|
|
543
|
+
echo " were overwritten directly (no staging directory was used)."
|
|
544
|
+
echo " 2. If something looks wrong, restore from git: ${C_DIM}git checkout -- .${C_RESET}"
|
|
545
|
+
echo " 3. Rebuild: ${C_DIM}ti clean && ti build -p android -T emulator${C_RESET}"
|
|
546
|
+
else
|
|
547
|
+
echo " 1. Preview in ${C_YELLOW}Preview.app${C_RESET} (never use ${C_DIM}open${C_RESET} without -a — triggers heavy editors)"
|
|
442
548
|
case "$PROJECT_TYPE" in
|
|
443
549
|
alloy)
|
|
444
550
|
echo " 2. If good, copy to project:"
|
|
445
|
-
echo " cp $OUTPUT/DefaultIcon-ios.png $OUTPUT/iTunesConnect.png $OUTPUT/MarketplaceArtwork.png $PROJECT_ROOT/"
|
|
551
|
+
echo " cp $OUTPUT/DefaultIcon.png $OUTPUT/DefaultIcon-ios.png $OUTPUT/iTunesConnect.png $OUTPUT/MarketplaceArtwork.png $PROJECT_ROOT/"
|
|
446
552
|
echo " cp -R $OUTPUT/app/platform/android/res/. $PROJECT_ROOT/app/platform/android/res/"
|
|
447
553
|
;;
|
|
448
554
|
classic)
|
|
449
555
|
echo " 2. If good, copy to project:"
|
|
450
|
-
echo " cp $OUTPUT/DefaultIcon-ios.png $OUTPUT/iTunesConnect.png $OUTPUT/MarketplaceArtwork.png $PROJECT_ROOT/"
|
|
556
|
+
echo " cp $OUTPUT/DefaultIcon.png $OUTPUT/DefaultIcon-ios.png $OUTPUT/iTunesConnect.png $OUTPUT/MarketplaceArtwork.png $PROJECT_ROOT/"
|
|
451
557
|
echo " cp -R $OUTPUT/platform/android/res/. $PROJECT_ROOT/platform/android/res/"
|
|
452
558
|
;;
|
|
453
559
|
*)
|
|
454
560
|
echo " 2. Review staging dir and copy files to their final paths manually."
|
|
455
561
|
;;
|
|
456
562
|
esac
|
|
457
|
-
|
|
458
|
-
|
|
563
|
+
echo " 3. Cleanup staging: rm -rf $OUTPUT"
|
|
564
|
+
echo " 4. Rebuild: ${C_DIM}ti clean && ti build -p android -T emulator${C_RESET}"
|
|
565
|
+
fi
|
|
459
566
|
echo
|
|
460
567
|
else
|
|
461
568
|
log_info "Dry-run complete. Re-run without --dry-run to write files."
|