565a2d1eca
Rounds out the phoenix rebrand for assets the earlier logo.svg swap missed: - public/icon-192.png / icon-512.png (PWA install icons, referenced by manifest.webmanifest) still had the old bolt-on-circle mark. - Android's push-notification status-bar icon (ic_stat_ditto, all densities) was carrying an even older mark — a ringed-planet icon from 'Ditto', the project two forks back. Regenerated as a white phoenix silhouette (status-bar icons must be flat white on transparent; the OS tints them). - android/.../splash_icon_vector.xml, the actual live Android 12+ splash icon (wired via styles.xml's windowSplashScreenAnimatedIcon), had the old double-bolt path hardcoded. Replaced with the phoenix path and recomputed the scale/center math for its 1446x1246 viewBox. - ios/.../Splash.imageset (wired into LaunchScreen.storyboard) had an even older blue crossed-arrow mark predating Agora. Regenerated as the brand-orange phoenix on white, matching the existing small centered-mark proportions. Also deleted the legacy per-density drawable*/splash.png and drawable/splash_icon.png rasters: confirmed unreferenced by any theme, manifest, or code (the app fully migrated to the Android 12 SplashScreen API / splash_icon_vector.xml), so they were dead weight carrying outdated branding no user could ever see. generate-icons.sh now produces all of the above so future logo changes regenerate everything in one pass instead of missing assets again. Note: unlike the web assets, the Android/iOS changes here only take effect on the next native app build + store release — there's no web deploy step for them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
248 lines
9.7 KiB
Bash
248 lines
9.7 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
# Colors for output
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo -e "${GREEN}Generating app icons...${NC}\n"
|
|
|
|
# Check for inkscape (preferred) or rsvg-convert as fallback
|
|
if command -v inkscape &> /dev/null; then
|
|
SVG_RENDERER="inkscape"
|
|
elif command -v rsvg-convert &> /dev/null; then
|
|
SVG_RENDERER="rsvg"
|
|
else
|
|
echo -e "${YELLOW}Warning: neither inkscape nor rsvg-convert found. Install one to render SVG icons.${NC}"
|
|
echo "On Fedora/RHEL: sudo dnf install inkscape"
|
|
echo "On Ubuntu/Debian: sudo apt-get install inkscape"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if ImageMagick is installed (needed for compositing).
|
|
# ImageMagick 7+ uses `magick`; ImageMagick 6 (Ubuntu/Debian) uses `convert`.
|
|
if command -v magick &> /dev/null; then
|
|
MAGICK="magick"
|
|
elif command -v convert &> /dev/null; then
|
|
MAGICK="convert"
|
|
else
|
|
echo -e "${YELLOW}Warning: ImageMagick not found. Please install it to generate icons.${NC}"
|
|
echo "On Fedora/RHEL: sudo dnf install ImageMagick"
|
|
echo "On Ubuntu/Debian: sudo apt-get install imagemagick"
|
|
exit 1
|
|
fi
|
|
|
|
# Source SVG logo
|
|
SOURCE_SVG="public/logo.svg"
|
|
|
|
if [ ! -f "$SOURCE_SVG" ]; then
|
|
echo -e "${YELLOW}Error: Source logo not found at $SOURCE_SVG${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Brand colors
|
|
BG_COLOR="#e9673f" # Agora orange (hsl(14 79% 58%))
|
|
|
|
TMPDIR=$(mktemp -d)
|
|
LOGO_WHITE_SVG="$TMPDIR/logo_white.svg"
|
|
LOGO_WHITE="$TMPDIR/logo_white.png"
|
|
|
|
# Recolor the SVG fill to white before rasterizing. The phoenix logo.svg
|
|
# declares fill="#fcd414"; older sources used black/purple, kept for safety.
|
|
sed -e 's/fill="black"/fill="#ffffff"/g' \
|
|
-e 's/#000000/#ffffff/g' \
|
|
-e 's/#7c52e0/#ffffff/g' \
|
|
-e 's/#fcd414/#ffffff/g' "$SOURCE_SVG" > "$LOGO_WHITE_SVG"
|
|
|
|
echo "Rendering white SVG (preserving aspect ratio)..."
|
|
|
|
# Render at 1024px tall and let the renderer derive the width from the SVG
|
|
# viewBox, so the non-square logo (720x880) is NOT stretched into a square.
|
|
# The composite steps below use -resize WxH which fits-inside (aspect-
|
|
# preserving), keeping the glyph's true proportions.
|
|
if [ "$SVG_RENDERER" = "inkscape" ]; then
|
|
inkscape --export-type=png --export-filename="$LOGO_WHITE" -h 1024 "$LOGO_WHITE_SVG" 2>/dev/null
|
|
else
|
|
rsvg-convert -h 1024 "$LOGO_WHITE_SVG" -o "$LOGO_WHITE"
|
|
fi
|
|
|
|
# Orange-fill render, for marks placed on a white/light background (iOS splash).
|
|
LOGO_ORANGE_SVG="$TMPDIR/logo_orange.svg"
|
|
LOGO_ORANGE="$TMPDIR/logo_orange.png"
|
|
sed -e 's/fill="black"/fill="'"$BG_COLOR"'"/g' \
|
|
-e 's/#000000/'"$BG_COLOR"'/g' \
|
|
-e 's/#7c52e0/'"$BG_COLOR"'/g' \
|
|
-e 's/#fcd414/'"$BG_COLOR"'/g' "$SOURCE_SVG" > "$LOGO_ORANGE_SVG"
|
|
if [ "$SVG_RENDERER" = "inkscape" ]; then
|
|
inkscape --export-type=png --export-filename="$LOGO_ORANGE" -h 1024 "$LOGO_ORANGE_SVG" 2>/dev/null
|
|
else
|
|
rsvg-convert -h 1024 "$LOGO_ORANGE_SVG" -o "$LOGO_ORANGE"
|
|
fi
|
|
|
|
# ── Adaptive icon foreground PNGs (transparent bg, white logo, safe-zone padding) ──
|
|
# Content at 47% of canvas to fit within Android's adaptive icon safe zone.
|
|
|
|
echo "Generating adaptive foreground PNGs..."
|
|
|
|
make_foreground() {
|
|
local size=$1
|
|
local content_size=$(echo "$size * 47 / 100" | bc)
|
|
local dest=$2
|
|
$MAGICK -size "${size}x${size}" "xc:none" \
|
|
\( "$LOGO_WHITE" -resize "${content_size}x${content_size}" \) \
|
|
-gravity center -compose over -composite \
|
|
"$dest"
|
|
}
|
|
|
|
make_foreground 48 android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
|
|
make_foreground 72 android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
|
|
make_foreground 96 android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
|
|
make_foreground 144 android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
|
|
make_foreground 192 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
|
|
|
|
# ── Legacy launcher icons (ic_launcher.png and ic_launcher_round.png) ──
|
|
# These are used on pre-API-26 devices and as fallback on some launchers.
|
|
# Both are the white logo composited onto an orange circle (brand mark).
|
|
|
|
echo "Generating legacy launcher icons (ic_launcher.png and ic_launcher_round.png)..."
|
|
|
|
# make_legacy_square: white logo on an orange circle (transparent corners)
|
|
make_legacy_square() {
|
|
local size=$1
|
|
local content_size=$(echo "$size * 60 / 100" | bc)
|
|
local dest=$2
|
|
local mask="$TMPDIR/circle_mask_sq_${size}.png"
|
|
$MAGICK -size "${size}x${size}" "xc:none" \
|
|
-fill white -draw "circle $((size/2)),$((size/2)) $((size/2)),0" \
|
|
"$mask"
|
|
$MAGICK -size "${size}x${size}" "xc:${BG_COLOR}" \
|
|
"$mask" -compose dst-in -composite \
|
|
\( "$LOGO_WHITE" -resize "${content_size}x${content_size}" \) \
|
|
-gravity center -compose over -composite \
|
|
"$dest"
|
|
}
|
|
|
|
# make_legacy_round: white logo on circular orange background (alpha-masked circle)
|
|
make_legacy_round() {
|
|
local size=$1
|
|
local content_size=$(echo "$size * 60 / 100" | bc)
|
|
local dest=$2
|
|
local mask="$TMPDIR/circle_mask_${size}.png"
|
|
# Create a white circle mask
|
|
$MAGICK -size "${size}x${size}" "xc:none" \
|
|
-fill white -draw "circle $((size/2)),$((size/2)) $((size/2)),0" \
|
|
"$mask"
|
|
# Fill orange, apply circle mask, composite logo
|
|
$MAGICK -size "${size}x${size}" "xc:${BG_COLOR}" \
|
|
"$mask" -compose dst-in -composite \
|
|
\( "$LOGO_WHITE" -resize "${content_size}x${content_size}" \) \
|
|
-gravity center -compose over -composite \
|
|
"$dest"
|
|
}
|
|
|
|
make_legacy_square 48 android/app/src/main/res/mipmap-mdpi/ic_launcher.png
|
|
make_legacy_square 72 android/app/src/main/res/mipmap-hdpi/ic_launcher.png
|
|
make_legacy_square 96 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
|
|
make_legacy_square 144 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
|
|
make_legacy_square 192 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
|
|
|
|
# Web logo.png (AppDownloadNudge) uses the same round brand-mark style.
|
|
make_legacy_round 512 public/logo.png
|
|
|
|
# PWA install icons (manifest.webmanifest "any" + "maskable" purposes).
|
|
make_legacy_round 192 public/icon-192.png
|
|
make_legacy_round 512 public/icon-512.png
|
|
|
|
make_legacy_round 48 android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
|
|
make_legacy_round 72 android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
|
|
make_legacy_round 96 android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
|
|
make_legacy_round 144 android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
|
|
make_legacy_round 192 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
|
|
|
|
# ── Android push-notification status-bar icon (ic_stat_ditto) ──
|
|
# Must be a flat white silhouette on transparent — the OS tints it, any
|
|
# color/gradient gets ignored or looks wrong. Referenced directly by
|
|
# NostrPoller.java / NotificationRelayService.java via R.drawable.ic_stat_ditto.
|
|
|
|
echo "Generating notification status-bar icon (ic_stat_ditto)..."
|
|
|
|
make_notification_icon() {
|
|
local size=$1
|
|
local content_size=$(echo "$size * 80 / 100" | bc)
|
|
local dest=$2
|
|
$MAGICK -size "${size}x${size}" "xc:none" \
|
|
\( "$LOGO_WHITE" -resize "${content_size}x${content_size}" \) \
|
|
-gravity center -compose over -composite \
|
|
"$dest"
|
|
}
|
|
|
|
for dir in drawable mipmap; do
|
|
make_notification_icon 24 android/app/src/main/res/${dir}-mdpi/ic_stat_ditto.png
|
|
make_notification_icon 48 android/app/src/main/res/${dir}-xhdpi/ic_stat_ditto.png
|
|
make_notification_icon 72 android/app/src/main/res/${dir}-xxhdpi/ic_stat_ditto.png
|
|
make_notification_icon 96 android/app/src/main/res/${dir}-xxxhdpi/ic_stat_ditto.png
|
|
done
|
|
make_notification_icon 36 android/app/src/main/res/drawable-hdpi/ic_stat_ditto.png
|
|
|
|
# Update background color
|
|
BACKGROUND_COLOR_FILE="android/app/src/main/res/values/ic_launcher_background.xml"
|
|
mkdir -p android/app/src/main/res/values
|
|
cat > "$BACKGROUND_COLOR_FILE" << 'EOF'
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<resources>
|
|
<color name="ic_launcher_background">#e9673f</color>
|
|
</resources>
|
|
EOF
|
|
|
|
# ── iOS App Icon (1024x1024, white logo on orange background) ──
|
|
|
|
echo "Generating iOS app icon..."
|
|
|
|
IOS_ICON_DIR="ios/App/App/Assets.xcassets/AppIcon.appiconset"
|
|
|
|
if [ -d "$IOS_ICON_DIR" ]; then
|
|
IOS_ICON="$IOS_ICON_DIR/AppIcon-512@2x.png"
|
|
# Logo at ~60% of canvas, centered on orange background (matches Android style)
|
|
$MAGICK -size "1024x1024" "xc:${BG_COLOR}" \
|
|
\( "$LOGO_WHITE" -resize "614x614" \) \
|
|
-gravity center -compose over -composite \
|
|
"$IOS_ICON"
|
|
echo -e " ${GREEN}✓${NC} $IOS_ICON"
|
|
else
|
|
echo -e " ${YELLOW}Skipped: $IOS_ICON_DIR not found${NC}"
|
|
fi
|
|
|
|
# ── iOS launch screen (Splash.imageset, 2732x2732, white bg + small mark) ──
|
|
# Referenced by LaunchScreen.storyboard. Ships one image for all 3 scale
|
|
# slots (1x/2x/3x), matching how the project already had it set up.
|
|
|
|
echo "Generating iOS launch screen..."
|
|
|
|
IOS_SPLASH_DIR="ios/App/App/Assets.xcassets/Splash.imageset"
|
|
|
|
if [ -d "$IOS_SPLASH_DIR" ]; then
|
|
$MAGICK -size "2732x2732" "xc:white" \
|
|
\( "$LOGO_ORANGE" -resize "160x160" \) \
|
|
-gravity center -compose over -composite \
|
|
"$IOS_SPLASH_DIR/splash-2732x2732.png"
|
|
cp "$IOS_SPLASH_DIR/splash-2732x2732.png" "$IOS_SPLASH_DIR/splash-2732x2732-1.png"
|
|
cp "$IOS_SPLASH_DIR/splash-2732x2732.png" "$IOS_SPLASH_DIR/splash-2732x2732-2.png"
|
|
echo -e " ${GREEN}✓${NC} $IOS_SPLASH_DIR (3 files)"
|
|
else
|
|
echo -e " ${YELLOW}Skipped: $IOS_SPLASH_DIR not found${NC}"
|
|
fi
|
|
|
|
# Cleanup temp files
|
|
rm -rf "$TMPDIR"
|
|
|
|
echo -e "\n${GREEN}App icons generated successfully!${NC}"
|
|
echo -e "Icon: white Agora logo on ${GREEN}${BG_COLOR}${NC} (Agora orange)"
|
|
echo -e "Generated:"
|
|
echo -e " Android:"
|
|
echo -e " - ic_launcher_foreground.png (adaptive, all densities)"
|
|
echo -e " - ic_launcher.png (legacy square, all densities)"
|
|
echo -e " - ic_launcher_round.png (legacy round, all densities)"
|
|
echo -e " iOS:"
|
|
echo -e " - AppIcon-512@2x.png (1024x1024)"
|