Add app icon, feature graphic, and justfile

- Network nodes tech-style icon (dark theme, cyan accents)
- Feature graphic for Play Store (1024x500)
- PNG icons for all densities
- Justfile with build, release, icons, install tasks
This commit is contained in:
2025-12-19 06:04:51 +01:00
parent a70f338e06
commit f496380603
15 changed files with 287 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/feature-graphic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

131
assets/feature-graphic.svg Normal file
View File

@@ -0,0 +1,131 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 500">
<defs>
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#0f172a"/>
<stop offset="100%" style="stop-color:#1e293b"/>
</linearGradient>
</defs>
<!-- Background -->
<rect width="1024" height="500" fill="url(#bgGrad)"/>
<!-- Grid pattern -->
<g stroke="#334155" stroke-width="1" opacity="0.3">
<line x1="0" y1="100" x2="1024" y2="100"/>
<line x1="0" y1="200" x2="1024" y2="200"/>
<line x1="0" y1="300" x2="1024" y2="300"/>
<line x1="0" y1="400" x2="1024" y2="400"/>
<line x1="200" y1="0" x2="200" y2="500"/>
<line x1="400" y1="0" x2="400" y2="500"/>
<line x1="600" y1="0" x2="600" y2="500"/>
<line x1="800" y1="0" x2="800" y2="500"/>
</g>
<!-- Left side network visualization -->
<g transform="translate(120, 250)">
<!-- Connection lines -->
<g stroke="#0ea5e9" stroke-width="3" opacity="0.6">
<line x1="0" y1="0" x2="-60" y2="-80"/>
<line x1="0" y1="0" x2="-80" y2="0"/>
<line x1="0" y1="0" x2="-60" y2="80"/>
<line x1="0" y1="0" x2="80" y2="0"/>
</g>
<!-- Data pulses -->
<g fill="#22d3ee">
<circle cx="-30" cy="-40" r="3"/>
<circle cx="-40" cy="0" r="3"/>
<circle cx="-30" cy="40" r="3"/>
<circle cx="40" cy="0" r="3"/>
</g>
<!-- Outer nodes -->
<g fill="#0f172a" stroke="#0ea5e9" stroke-width="2">
<circle cx="-60" cy="-80" r="16"/>
<circle cx="-80" cy="0" r="16"/>
<circle cx="-60" cy="80" r="16"/>
</g>
<g fill="#22d3ee">
<circle cx="-60" cy="-80" r="6"/>
<circle cx="-80" cy="0" r="6"/>
<circle cx="-60" cy="80" r="6"/>
</g>
<!-- Center hub -->
<circle cx="0" cy="0" r="36" fill="#0f172a" stroke="#0ea5e9" stroke-width="3"/>
<circle cx="0" cy="0" r="26" fill="#0ea5e9"/>
<!-- Signal bars -->
<g fill="#0f172a">
<rect x="-14" y="4" width="6" height="12" rx="1"/>
<rect x="-5" cy="0" y="-2" width="6" height="18" rx="1"/>
<rect x="4" y="-8" width="6" height="24" rx="1"/>
</g>
</g>
<!-- Flowing data lines to right -->
<g stroke="#0ea5e9" stroke-width="2" fill="none" opacity="0.5">
<path d="M 200 250 Q 300 200, 400 250 T 600 250"/>
<path d="M 200 250 Q 300 300, 400 250 T 600 250"/>
</g>
<g fill="#22d3ee">
<circle cx="280" cy="220" r="4"/>
<circle cx="350" cy="260" r="4"/>
<circle cx="450" cy="240" r="4"/>
<circle cx="520" cy="255" r="4"/>
</g>
<!-- App name -->
<text x="500" y="180" font-family="system-ui, -apple-system, sans-serif" font-size="64" font-weight="700" fill="#ffffff">Tether API</text>
<!-- Tagline -->
<text x="500" y="240" font-family="system-ui, -apple-system, sans-serif" font-size="24" font-weight="400" fill="#94a3b8">Phone status on your desktop</text>
<!-- Feature chips -->
<g font-family="system-ui, sans-serif" font-size="14" fill="#e2e8f0">
<g transform="translate(500, 290)">
<rect x="0" y="0" width="120" height="32" rx="16" fill="#0ea5e9" opacity="0.2" stroke="#0ea5e9" stroke-width="1"/>
<text x="60" y="21" text-anchor="middle">5G / LTE / WiFi</text>
</g>
<g transform="translate(635, 290)">
<rect x="0" y="0" width="100" height="32" rx="16" fill="#0ea5e9" opacity="0.2" stroke="#0ea5e9" stroke-width="1"/>
<text x="50" y="21" text-anchor="middle">REST API</text>
</g>
<g transform="translate(750, 290)">
<rect x="0" y="0" width="90" height="32" rx="16" fill="#0ea5e9" opacity="0.2" stroke="#0ea5e9" stroke-width="1"/>
<text x="45" y="21" text-anchor="middle">Waybar</text>
</g>
<g transform="translate(855, 290)">
<rect x="0" y="0" width="100" height="32" rx="16" fill="#0ea5e9" opacity="0.2" stroke="#0ea5e9" stroke-width="1"/>
<text x="50" y="21" text-anchor="middle">Auto-start</text>
</g>
</g>
<!-- Right side: laptop illustration -->
<g transform="translate(780, 380)">
<!-- Laptop -->
<rect x="0" y="50" width="160" height="8" rx="2" fill="#334155"/>
<rect x="15" y="-20" width="130" height="75" rx="4" fill="#1e293b" stroke="#334155" stroke-width="2"/>
<rect x="22" y="-13" width="116" height="60" rx="2" fill="#0f172a"/>
<!-- Terminal content -->
<text x="28" y="5" font-family="monospace" font-size="10" fill="#22d3ee">$ curl /status</text>
<text x="28" y="18" font-family="monospace" font-size="9" fill="#94a3b8">{"type":"LTE"}</text>
<text x="28" y="30" font-family="monospace" font-size="9" fill="#94a3b8">{"signal":3}</text>
<text x="28" y="42" font-family="monospace" font-size="9" fill="#94a3b8">{"battery":87}</text>
</g>
<!-- Decorative corner nodes -->
<g fill="#0ea5e9" opacity="0.3">
<circle cx="50" cy="50" r="8"/>
<circle cx="974" cy="50" r="8"/>
<circle cx="50" cy="450" r="8"/>
<circle cx="974" cy="450" r="8"/>
</g>
<g stroke="#0ea5e9" stroke-width="1" fill="none" opacity="0.2">
<line x1="50" y1="50" x2="120" y2="50"/>
<line x1="50" y1="50" x2="50" y2="120"/>
<line x1="974" y1="50" x2="904" y2="50"/>
<line x1="974" y1="50" x2="974" y2="120"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
assets/icon-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

85
assets/icon.svg Normal file
View File

@@ -0,0 +1,85 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<defs>
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#0f172a"/>
<stop offset="100%" style="stop-color:#1e293b"/>
</linearGradient>
</defs>
<!-- Dark background -->
<rect width="512" height="512" rx="96" fill="url(#bg)"/>
<!-- Circuit traces -->
<g stroke="#0ea5e9" stroke-width="3" fill="none" opacity="0.4">
<path d="M 80 256 H 140"/>
<path d="M 372 256 H 432"/>
<path d="M 256 80 V 140"/>
<path d="M 256 372 V 432"/>
<path d="M 140 180 L 180 140"/>
<path d="M 332 140 L 372 180"/>
<path d="M 140 332 L 180 372"/>
<path d="M 332 372 L 372 332"/>
</g>
<!-- Main connection lines -->
<g stroke="#0ea5e9" stroke-width="4" fill="none">
<!-- Center to outer nodes -->
<line x1="256" y1="256" x2="160" y2="160"/>
<line x1="256" y1="256" x2="352" y2="160"/>
<line x1="256" y1="256" x2="160" y2="352"/>
<line x1="256" y1="256" x2="352" y2="352"/>
<!-- Horizontal and vertical -->
<line x1="256" y1="256" x2="140" y2="256"/>
<line x1="256" y1="256" x2="372" y2="256"/>
<line x1="256" y1="256" x2="256" y2="140"/>
<line x1="256" y1="256" x2="256" y2="372"/>
</g>
<!-- Data flow dots (animated feel) -->
<g fill="#22d3ee">
<circle cx="190" cy="190" r="4"/>
<circle cx="322" cy="190" r="4"/>
<circle cx="190" cy="322" r="4"/>
<circle cx="322" cy="322" r="4"/>
<circle cx="180" cy="256" r="3"/>
<circle cx="332" cy="256" r="3"/>
<circle cx="256" cy="180" r="3"/>
<circle cx="256" cy="332" r="3"/>
</g>
<!-- Outer nodes -->
<g fill="#0f172a" stroke="#0ea5e9" stroke-width="3">
<circle cx="160" cy="160" r="24"/>
<circle cx="352" cy="160" r="24"/>
<circle cx="160" cy="352" r="24"/>
<circle cx="352" cy="352" r="24"/>
<circle cx="140" cy="256" r="20"/>
<circle cx="372" cy="256" r="20"/>
<circle cx="256" cy="140" r="20"/>
<circle cx="256" cy="372" r="20"/>
</g>
<!-- Inner node fills -->
<g fill="#22d3ee">
<circle cx="160" cy="160" r="10"/>
<circle cx="352" cy="160" r="10"/>
<circle cx="160" cy="352" r="10"/>
<circle cx="352" cy="352" r="10"/>
<circle cx="140" cy="256" r="8"/>
<circle cx="372" cy="256" r="8"/>
<circle cx="256" cy="140" r="8"/>
<circle cx="256" cy="372" r="8"/>
</g>
<!-- Center hub (phone) -->
<circle cx="256" cy="256" r="56" fill="#0f172a" stroke="#0ea5e9" stroke-width="4"/>
<circle cx="256" cy="256" r="40" fill="#0ea5e9"/>
<!-- Signal bars in center -->
<g fill="#0f172a">
<rect x="236" y="268" width="8" height="16" rx="2"/>
<rect x="248" y="258" width="8" height="26" rx="2"/>
<rect x="260" y="248" width="8" height="36" rx="2"/>
<rect x="272" y="238" width="8" height="46" rx="2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

71
justfile Normal file
View File

@@ -0,0 +1,71 @@
# Tether API build tasks
# Docker image for Android builds
android_image := "cimg/android:2025.12"
gradle_cache := "gradle-cache"
# Default task
default:
@just --list
# Build debug APK
build:
docker run --rm \
-v {{justfile_directory()}}:/project \
-v {{gradle_cache}}:/home/circleci/.gradle \
-w /project \
{{android_image}} \
./gradlew assembleDebug --no-daemon
@echo "APK: app/build/outputs/apk/debug/app-debug.apk"
# Build release APK (requires keystore and env vars)
release:
docker run --rm \
-v {{justfile_directory()}}:/project \
-v {{gradle_cache}}:/home/circleci/.gradle \
-w /project \
-e KEYSTORE_PASSWORD \
-e KEY_ALIAS \
-e KEY_PASSWORD \
{{android_image}} \
./gradlew assembleRelease --no-daemon
@echo "APK: app/build/outputs/apk/release/app-release.apk"
# Clean build artifacts
clean:
rm -rf app/build build .gradle
@echo "Cleaned"
# Run gradle tasks
gradle *ARGS:
docker run --rm \
-v {{justfile_directory()}}:/project \
-v {{gradle_cache}}:/home/circleci/.gradle \
-w /project \
{{android_image}} \
./gradlew {{ARGS}} --no-daemon
# Generate icons from SVG
icons:
inkscape assets/icon.svg -w 512 -h 512 -o assets/icon-512.png
inkscape assets/icon.svg -w 192 -h 192 -o app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
inkscape assets/icon.svg -w 144 -h 144 -o app/src/main/res/mipmap-xxhdpi/ic_launcher.png
inkscape assets/icon.svg -w 96 -h 96 -o app/src/main/res/mipmap-xhdpi/ic_launcher.png
inkscape assets/icon.svg -w 72 -h 72 -o app/src/main/res/mipmap-hdpi/ic_launcher.png
inkscape assets/icon.svg -w 48 -h 48 -o app/src/main/res/mipmap-mdpi/ic_launcher.png
cp app/src/main/res/mipmap-xxxhdpi/ic_launcher.png app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
cp app/src/main/res/mipmap-xxhdpi/ic_launcher.png app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
cp app/src/main/res/mipmap-xhdpi/ic_launcher.png app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
cp app/src/main/res/mipmap-hdpi/ic_launcher.png app/src/main/res/mipmap-hdpi/ic_launcher_round.png
cp app/src/main/res/mipmap-mdpi/ic_launcher.png app/src/main/res/mipmap-mdpi/ic_launcher_round.png
inkscape assets/feature-graphic.svg -w 1024 -h 500 -o assets/feature-graphic.png
@echo "Generated all icons"
# Install APK on connected device
install: build
adb install -r app/build/outputs/apk/debug/app-debug.apk
# Generate keystore for release signing
keystore:
keytool -genkey -v -keystore keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias release
@echo "Created keystore.jks - keep this safe!"