mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-14 18:26:11 -04:00
- Add Compose screenshot test infrastructure (build config, screenshotTest source set) - Add 7 localized screenshots covering all key app screens - Device spec set to Pixel 8 (1080x2400, 428dpi); batch size 4 for 1080p memory budget - Add screen title heading and fix appearance card header layout in WidgetConfigurationScreen - Balance padding on requires-Pro notice in widget config bottom bar
226 lines
6.0 KiB
Bash
Executable File
226 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
# Generates localized Play Store screenshots in batches to work around
|
||
# layoutlib ImagePoolImpl memory leak (accumulates rendered images without release).
|
||
#
|
||
# Usage:
|
||
# ./fastlane/generate_screenshots.sh # Full run (all locales, ~12 batches)
|
||
# ./fastlane/generate_screenshots.sh --smoke # Smoke test (6 locales, 1 batch)
|
||
# ./fastlane/generate_screenshots.sh --batch-size 10 # Custom batch size
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
LOCALES_FILE="$PROJECT_DIR/app/src/screenshotTest/kotlin/eu/darken/capod/screenshots/PlayStoreLocales.kt"
|
||
REF_DIR="$PROJECT_DIR/app/src/screenshotTestGplayDebug/reference"
|
||
|
||
# Default batch size — 6 locales × 7 composables = 42 renders per batch.
|
||
# Kept small to avoid layoutlib OOM (leaks ~4MB per rendered image at 720p; more at 1080p).
|
||
BATCH_SIZE=4
|
||
SMOKE=false
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--smoke) SMOKE=true; shift ;;
|
||
--batch-size) BATCH_SIZE="$2"; shift 2 ;;
|
||
*) echo "Unknown option: $1"; exit 1 ;;
|
||
esac
|
||
done
|
||
|
||
# Each entry: "android_locale:fastlane_name"
|
||
ALL_LOCALES=(
|
||
"en:en-US"
|
||
"af:af"
|
||
"am:am"
|
||
"ar:ar"
|
||
"az:az-AZ"
|
||
"be:be"
|
||
"bg:bg"
|
||
"bn-BD:bn-BD"
|
||
"ca:ca"
|
||
"cs:cs-CZ"
|
||
"da:da-DK"
|
||
"de:de-DE"
|
||
"el:el-GR"
|
||
"es:es-ES"
|
||
"es-MX:es-419"
|
||
"et-EE:et"
|
||
"eu-ES:eu-ES"
|
||
"fa:fa"
|
||
"fi:fi-FI"
|
||
"fil:fil"
|
||
"fr:fr-FR"
|
||
"gl-ES:gl-ES"
|
||
"hi-IN:hi-IN"
|
||
"hr:hr"
|
||
"hu:hu-HU"
|
||
"hy-AM:hy-AM"
|
||
"in:id"
|
||
"is:is-IS"
|
||
"it:it-IT"
|
||
"iw:iw-IL"
|
||
"ja:ja-JP"
|
||
"ka-GE:ka-GE"
|
||
"km-KH:km-KH"
|
||
"kn-IN:kn-IN"
|
||
"ko:ko-KR"
|
||
"ky-KG:ky-KG"
|
||
"lo-LA:lo-LA"
|
||
"lt:lt"
|
||
"lv:lv"
|
||
"mk-MK:mk-MK"
|
||
"ml-IN:ml-IN"
|
||
"mn-MN:mn-MN"
|
||
"mr-IN:mr-IN"
|
||
"ms:ms"
|
||
"my-MM:my-MM"
|
||
"nb:no-NO"
|
||
"ne-NP:ne-NP"
|
||
"nl:nl-NL"
|
||
"pl:pl-PL"
|
||
"pt:pt-PT"
|
||
"pt-BR:pt-BR"
|
||
"rm:rm"
|
||
"ro:ro"
|
||
"ru:ru-RU"
|
||
"sk:sk"
|
||
"sl:sl"
|
||
"sr:sr"
|
||
"sv:sv-SE"
|
||
"sw:sw"
|
||
"ta-IN:ta-IN"
|
||
"te-IN:te-IN"
|
||
"th:th"
|
||
"tr:tr-TR"
|
||
"uk:uk"
|
||
"vi:vi"
|
||
"zh-CN:zh-CN"
|
||
"zh-HK:zh-HK"
|
||
"zh-TW:zh-TW"
|
||
)
|
||
|
||
SMOKE_LOCALES=(
|
||
"en:en-US"
|
||
"de:de-DE"
|
||
"ja:ja-JP"
|
||
"ar:ar"
|
||
"zh-CN:zh-CN"
|
||
"pt-BR:pt-BR"
|
||
)
|
||
|
||
if $SMOKE; then
|
||
LOCALES=("${SMOKE_LOCALES[@]}")
|
||
BATCH_SIZE=${#LOCALES[@]} # Single batch for smoke
|
||
else
|
||
LOCALES=("${ALL_LOCALES[@]}")
|
||
fi
|
||
|
||
TOTAL=${#LOCALES[@]}
|
||
NUM_BATCHES=$(( (TOTAL + BATCH_SIZE - 1) / BATCH_SIZE ))
|
||
|
||
echo "=== Localized Screenshot Generation ==="
|
||
echo "Locales: $TOTAL | Batch size: $BATCH_SIZE | Batches: $NUM_BATCHES"
|
||
echo ""
|
||
|
||
# Back up the original file
|
||
cp "$LOCALES_FILE" "$LOCALES_FILE.bak"
|
||
trap 'mv "$LOCALES_FILE.bak" "$LOCALES_FILE"; echo "Restored original PlayStoreLocales.kt"' EXIT
|
||
|
||
# Clean reference directory from previous runs
|
||
rm -rf "$REF_DIR"
|
||
echo "Cleaned reference directory"
|
||
|
||
generate_locales_file() {
|
||
local -n batch_locales=$1
|
||
local file="$2"
|
||
|
||
cat > "$file" << 'HEADER'
|
||
package eu.darken.capod.screenshots
|
||
|
||
import android.content.res.Configuration
|
||
import androidx.compose.ui.tooling.preview.Preview
|
||
|
||
/**
|
||
* Multi-preview annotation generating one preview per Play Store-supported locale (light mode).
|
||
* Each [name] is the fastlane metadata directory name for direct use in the copy script.
|
||
*/
|
||
HEADER
|
||
|
||
# Light annotations
|
||
for entry in "${batch_locales[@]}"; do
|
||
local locale="${entry%%:*}"
|
||
local name="${entry##*:}"
|
||
echo "@Preview(locale = \"$locale\", name = \"$name\", device = DS)" >> "$file"
|
||
done
|
||
echo "annotation class PlayStoreLocales" >> "$file"
|
||
echo "" >> "$file"
|
||
|
||
# Dark annotations
|
||
echo "/**" >> "$file"
|
||
echo " * Same locales but with night mode enabled for dark theme screenshots." >> "$file"
|
||
echo " */" >> "$file"
|
||
for entry in "${batch_locales[@]}"; do
|
||
local locale="${entry%%:*}"
|
||
local name="${entry##*:}"
|
||
echo "@Preview(locale = \"$locale\", name = \"$name\", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)" >> "$file"
|
||
done
|
||
echo "annotation class PlayStoreLocalesDark" >> "$file"
|
||
echo "" >> "$file"
|
||
|
||
# Smoke annotation (single entry placeholder)
|
||
echo "/**" >> "$file"
|
||
echo " * Smoke test subset for fast iteration (6 locales covering LTR, RTL, CJK)." >> "$file"
|
||
echo " */" >> "$file"
|
||
echo "@Preview(locale = \"en\", name = \"en-US\", device = DS)" >> "$file"
|
||
echo "annotation class PlayStoreLocalesSmoke" >> "$file"
|
||
}
|
||
|
||
for (( batch=0; batch < NUM_BATCHES; batch++ )); do
|
||
start=$(( batch * BATCH_SIZE ))
|
||
end=$(( start + BATCH_SIZE ))
|
||
if (( end > TOTAL )); then
|
||
end=$TOTAL
|
||
fi
|
||
|
||
# Extract batch slice
|
||
BATCH_SLICE=("${LOCALES[@]:$start:$((end - start))}")
|
||
batch_num=$(( batch + 1 ))
|
||
|
||
echo "--- Batch $batch_num/$NUM_BATCHES (locales $((start+1))-$end of $TOTAL) ---"
|
||
|
||
# Generate locales file for this batch
|
||
generate_locales_file BATCH_SLICE "$LOCALES_FILE"
|
||
|
||
# Stop daemon to release memory from previous batch
|
||
echo "Stopping Gradle daemon..."
|
||
cd "$PROJECT_DIR"
|
||
./gradlew --stop 2>/dev/null || true
|
||
|
||
# Run screenshot generation
|
||
echo "Generating screenshots..."
|
||
if ! ./gradlew updateGplayDebugScreenshotTest --no-daemon 2>&1; then
|
||
echo "ERROR: Batch $batch_num failed! Check output above."
|
||
echo "Generated images so far are preserved in: $REF_DIR"
|
||
exit 1
|
||
fi
|
||
|
||
count=$(find "$REF_DIR" -name "*.png" 2>/dev/null | wc -l)
|
||
echo "Batch $batch_num complete. Total images so far: $count"
|
||
echo ""
|
||
done
|
||
|
||
# Count final results
|
||
FINAL_COUNT=$(find "$REF_DIR" -name "*.png" 2>/dev/null | wc -l)
|
||
EXPECTED=$(( TOTAL * 7 )) # 7 composables per locale
|
||
|
||
echo "=== Generation Complete ==="
|
||
echo "Generated: $FINAL_COUNT images (expected: $EXPECTED)"
|
||
|
||
if (( FINAL_COUNT != EXPECTED )); then
|
||
echo "WARNING: Count mismatch! Some screenshots may be missing."
|
||
echo "Check $REF_DIR for details."
|
||
fi
|
||
|
||
echo ""
|
||
echo "Next step: run ./fastlane/copy_screenshots.sh to sort into fastlane directories."
|