Podlite 1.9: radio icon
New launcher icon (the Podcasts Radio pack, master in art/icon-master.png). The status-bar icon was cut out of the old headphones artwork; make_icons.py now draws a white radio silhouette. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No files matched your search
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.miniabs"
|
package="com.miniabs"
|
||||||
android:versionCode="9"
|
android:versionCode="10"
|
||||||
android:versionName="1.8"
|
android:versionName="1.9"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="10" />
|
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="10" />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Podlite
|
# Podlite
|
||||||
|
|
||||||
A tiny Audiobookshelf **podcast** client for the Samsung Galaxy Mini (GT-S5570) and other Android 2.2+ phones. Native Java; the APK is about 1.1 MB, nearly all of it the bundled TLS stack. Formerly MiniABS. The interface is in Galician, with large text and touch targets sized for the Mini's 240×320 screen. Its purple colour scheme and launcher icon come from the Audiobookshelf icon pack (`art/icon_master_512.png`); `tools/make_icons.py` derives the notification and player icons from it.
|
A tiny Audiobookshelf **podcast** client for the Samsung Galaxy Mini (GT-S5570) and other Android 2.2+ phones. Native Java; the APK is about 1.1 MB, nearly all of it the bundled TLS stack. Formerly MiniABS. The interface is in Galician, with large text and touch targets sized for the Mini's 240×320 screen. The launcher icon is the "Podcasts Radio" pack (master in `art/icon-master.png`); `tools/make_icons.py` draws the notification icon (a white radio silhouette) and the player icons. The purple colour scheme comes from the earlier Audiobookshelf icon.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 977 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 434 B After Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 615 B |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 19 KiB |
@@ -50,7 +50,7 @@
|
|||||||
<PreferenceCategory android:title="Acerca de">
|
<PreferenceCategory android:title="Acerca de">
|
||||||
<Preference
|
<Preference
|
||||||
android:key="about"
|
android:key="about"
|
||||||
android:title="Podlite 1.8"
|
android:title="Podlite 1.9"
|
||||||
android:summary="Un pequeno cliente de podcasts de Audiobookshelf para Android 2.2+" />
|
android:summary="Un pequeno cliente de podcasts de Audiobookshelf para Android 2.2+" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
@@ -26,7 +26,7 @@ import android.os.Build;
|
|||||||
|
|
||||||
/** Audiobookshelf REST client (API as of server 2.x, including the 2.26+ token system). */
|
/** Audiobookshelf REST client (API as of server 2.x, including the 2.26+ token system). */
|
||||||
final class Api {
|
final class Api {
|
||||||
static final String VERSION = "1.8";
|
static final String VERSION = "1.9";
|
||||||
|
|
||||||
static class ApiException extends IOException {
|
static class ApiException extends IOException {
|
||||||
final int code;
|
final int code;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"""Draws Podlite's PNG icons for ldpi (Galaxy Mini), mdpi and hdpi.
|
"""Draws Podlite's PNG icons for ldpi (Galaxy Mini), mdpi and hdpi.
|
||||||
|
|
||||||
The launcher icon (res/drawable-*/ic_launcher.png) comes from the supplied
|
The launcher icon (res/drawable-*/ic_launcher.png) comes from the supplied
|
||||||
Audiobookshelf icon pack and is not generated here. The notification icon is
|
"Podcasts Radio" icon pack (master in art/icon-master.png) and is not generated
|
||||||
cut out of that same artwork (art/icon_master_512.png): the white headphones
|
here. The notification icon is a white silhouette of that radio, as Android
|
||||||
and equalizer become a white silhouette, as Android 2.3's status bar expects.
|
2.3's status bar expects.
|
||||||
|
|
||||||
Android 2.x has no vector drawables, so the player icons are rendered at 4x and
|
Android 2.x has no vector drawables, so the player icons are rendered at 4x and
|
||||||
downsampled for smooth edges.
|
downsampled for smooth edges.
|
||||||
@@ -33,22 +33,24 @@ def save(img, px, folder, name):
|
|||||||
|
|
||||||
|
|
||||||
def status_silhouette():
|
def status_silhouette():
|
||||||
"""White mask of the icon's light parts (headphones, bars, waves) on transparency."""
|
"""White silhouette of the launcher icon's old radio (handle, grille, two knobs) on transparency:
|
||||||
src = Image.open(os.path.join(ROOT, "art", "icon_master_512.png")).convert("RGBA")
|
Android 2.3's status bar expects a light glyph, not the colour artwork."""
|
||||||
out = Image.new("RGBA", src.size, (0, 0, 0, 0))
|
S = 24 * 32 # drawn on a 24-unit grid, supersampled
|
||||||
sp, op = src.load(), out.load()
|
u = lambda v: int(round(v * 32))
|
||||||
for y in range(src.size[1]):
|
m = Image.new("L", (S, S), 0)
|
||||||
for x in range(src.size[0]):
|
d = ImageDraw.Draw(m)
|
||||||
r, g, b, a = sp[x, y]
|
d.arc((u(6), u(1.2), u(18), u(11)), 200, 340, fill=255, width=u(1.8)) # carrying handle
|
||||||
# the purple background has a low green channel; the white/lilac artwork a high one
|
d.rounded_rectangle((u(1.5), u(6.5), u(22.5), u(21.5)), radius=u(3.5), fill=255)
|
||||||
level = min(255, max(0, (g - 80) * 255 // 50))
|
d.rounded_rectangle((u(4), u(9), u(14), u(19)), radius=u(1.2), fill=0) # grille window
|
||||||
op[x, y] = (255, 255, 255, level * a // 255)
|
for i in range(3): # grille bars
|
||||||
box = out.getbbox()
|
y = 10.6 + i * 2.9
|
||||||
out = out.crop(box)
|
d.rounded_rectangle((u(5.2), u(y), u(12.8), u(y + 1.5)), radius=u(0.7), fill=255)
|
||||||
side = max(out.size)
|
for cy, r in ((11.6, 2.4), (17.0, 2.0)): # knobs as rings
|
||||||
sq = Image.new("RGBA", (side, side), (0, 0, 0, 0))
|
d.ellipse((u(18 - r), u(cy - r), u(18 + r), u(cy + r)), fill=0)
|
||||||
sq.paste(out, ((side - out.size[0]) // 2, (side - out.size[1]) // 2))
|
d.ellipse((u(18 - r + 1.1), u(cy - r + 1.1), u(18 + r - 1.1), u(cy + r - 1.1)), fill=255)
|
||||||
return sq
|
out = Image.new("RGBA", (S, S), (255, 255, 255, 0))
|
||||||
|
out.putalpha(m)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def status(sil, px, folder):
|
def status(sil, px, folder):
|
||||||
|
|||||||