Download a poet from the list, and show when they are already here
A download control on each row in the list view: the arrow starts it, a spinner replaces it while it runs and cancels on a tap, and a green tick says the poems are already on the device. Only text is fetched — recitations stream when played, and nothing about that changes. The tick sits in a box the size of an IconButton although nothing about it is tappable. A bare icon lands where the button's padding would have put it, so the ticks and the arrows did not line up down the column. The green is derived from the scheme's own luminance rather than fixed: Material has no success colour, and one green goes muddy on sepia and glares on OLED black. Deleting stays on the downloads page, where the sizes are. A tap beside a poet's name should not be the thing that throws their poems away. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a5cc0421b6
commit
929aee2a02
@ -55,6 +55,11 @@ import coil3.compose.AsyncImage
|
||||
import java.text.Collator
|
||||
import java.util.Locale
|
||||
import com.ganjoor.android.R
|
||||
import com.ganjoor.android.ui.theme.downloaded
|
||||
import com.ganjoor.android.data.Offline
|
||||
import com.ganjoor.android.data.Downloads
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import com.ganjoor.android.data.Ganjoor
|
||||
import com.ganjoor.android.data.PoetRef
|
||||
|
||||
@ -249,6 +254,49 @@ private fun PinMark(modifier: Modifier = Modifier) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a poet's poems, or say they are already here. Three states and no menu: downloading shows
|
||||
* its progress and cancels on a tap, downloaded is a green tick, and anything else offers the
|
||||
* download. Deleting stays on the downloads page, where the sizes are — a tap next to a poet's
|
||||
* name should never be the thing that throws their poems away.
|
||||
*/
|
||||
@Composable
|
||||
private fun DownloadAction(slug: String) {
|
||||
val progress = Downloads.running[slug]
|
||||
val saved = remember(slug, Downloads.revision) { Offline.isSaved(slug) }
|
||||
|
||||
when {
|
||||
progress != null -> IconButton(onClick = { Downloads.cancel(slug) }) {
|
||||
CircularProgressIndicator(
|
||||
strokeWidth = 2.dp,
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
}
|
||||
|
||||
// In a box the size of an IconButton, even though nothing here is tappable: a bare icon
|
||||
// sits where the button's padding would have put it, so the ticks and the arrows would
|
||||
// not line up down the column.
|
||||
saved -> Box(
|
||||
modifier = Modifier.size(48.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.CheckCircle,
|
||||
contentDescription = stringResource(R.string.downloaded_poet),
|
||||
tint = MaterialTheme.colorScheme.downloaded,
|
||||
)
|
||||
}
|
||||
|
||||
else -> IconButton(onClick = { Downloads.start(slug) }) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_download),
|
||||
contentDescription = stringResource(R.string.download),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** One poet as a row, for readers who would rather scan names than faces. */
|
||||
@Composable
|
||||
private fun PoetRow(poet: PoetRef, pinned: Boolean, onClick: () -> Unit, onPin: () -> Unit) {
|
||||
@ -271,7 +319,15 @@ private fun PoetRow(poet: PoetRef, pinned: Boolean, onClick: () -> Unit, onPin:
|
||||
)
|
||||
}
|
||||
},
|
||||
trailingContent = { if (pinned) PinMark() },
|
||||
trailingContent = {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
if (pinned) PinMark()
|
||||
DownloadAction(poet.slug)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.combinedClickable(onClick = onClick, onLongClick = onPin),
|
||||
)
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import androidx.compose.ui.graphics.lerp
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
@ -202,3 +203,13 @@ fun GanjoorTheme(
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* The green on a poet whose poems are already on the device.
|
||||
*
|
||||
* Material's palette has no success colour, and a fixed green goes muddy on the sepia schemes and
|
||||
* glares on OLED black. Picking by the surface's luminance covers all five schemes without each
|
||||
* of them having to declare one.
|
||||
*/
|
||||
val ColorScheme.downloaded: Color
|
||||
get() = if (surface.luminance() < 0.5f) Color(0xFF81C784) else Color(0xFF2E7D32)
|
||||
|
||||
@ -113,4 +113,5 @@
|
||||
<string name="pin_hint">برای نگهداشتن یک شاعر در اینجا، انگشت را روی او نگه دارید</string>
|
||||
<string name="view_grid">نمایش کارتی</string>
|
||||
<string name="view_list">نمایش فهرستی</string>
|
||||
<string name="downloaded_poet">پیشتر دریافت شده</string>
|
||||
</resources>
|
||||
|
||||
@ -113,4 +113,5 @@
|
||||
<string name="pin_hint">کسی شاعر کو یہاں رکھنے کے لیے اُس پر دبا کر رکھیں</string>
|
||||
<string name="view_grid">کارڈ کی صورت</string>
|
||||
<string name="view_list">فہرست کی صورت</string>
|
||||
<string name="downloaded_poet">پہلے سے محفوظ ہے</string>
|
||||
</resources>
|
||||
|
||||
@ -118,4 +118,5 @@
|
||||
<string name="pin_hint">Press and hold a poet to keep them here</string>
|
||||
<string name="view_grid">Show as cards</string>
|
||||
<string name="view_list">Show as a list</string>
|
||||
<string name="downloaded_poet">Already downloaded</string>
|
||||
</resources>
|
||||
|
||||
@ -6,3 +6,6 @@ alphabetical listing a tap away. Until you pin anything the shelf is simply
|
||||
Ganjoor's order, so there is never an empty screen.
|
||||
|
||||
Poets can be shown as cards or as a list, whichever reads better.
|
||||
|
||||
Each poet in the list view carries a download button, and a green tick once their
|
||||
poems are on the device. Text only — recitations are still streamed when you play them.
|
||||
|
||||
@ -6,3 +6,6 @@
|
||||
صفحهای خالی نمیبینید.
|
||||
|
||||
شاعران را میتوان کارتی یا فهرستی دید، هرکدام که خواناتر است.
|
||||
|
||||
هر شاعر در نمایش فهرستی یک دکمهٔ دریافت دارد، و پس از ذخیرهشدن شعرهایش یک تیک سبز.
|
||||
فقط متن؛ خوانشها همچنان هنگام پخش از اینترنت میآیند.
|
||||
|
||||
@ -7,3 +7,6 @@
|
||||
سو خالی صفحہ کبھی نہیں ملتا۔
|
||||
|
||||
شاعروں کو کارڈ کی صورت یا فہرست کی صورت، جو بہتر لگے، دیکھا جا سکتا ہے۔
|
||||
|
||||
فہرست کی صورت میں ہر شاعر کے ساتھ ڈاؤن لوڈ کا بٹن ہے، اور اُن کا کلام محفوظ ہو جانے پر
|
||||
سبز نشان۔ صرف متن؛ تلاوتیں اب بھی سنتے وقت آن لائن چلتی ہیں۔
|
||||
|
||||
@ -12,7 +12,7 @@ from source and signs with its own key, so these are for direct installation onl
|
||||
| 0.2.0 | 2 | `d92445f` | Share a poem, couplet or selection; look a word up from any app's selection menu; the optional AI assistant. |
|
||||
| 0.2.1 | 3 | `ec05989` | Assistant answers in the page rather than over it, a visible chevron for each couplet's actions, and answers remembered so scrolling doesn't re-ask. |
|
||||
| 0.2.2 | 4 | `d7568d1` | Credits Material Symbols for the glyphs, and states the terms around the optional assistant. |
|
||||
| 0.3.0 | 5 | `HEAD` | Pin poets to the home screen: three views (pinned, Ganjoor's order, alphabetical), as cards or a list. |
|
||||
| 0.3.0 | 5 | `HEAD` | Pin poets to the home screen: three views (pinned, Ganjoor's order, alphabetical), as cards or a list, with a download control on each row. |
|
||||
|
||||
## Checksums
|
||||
|
||||
@ -21,7 +21,7 @@ from source and signs with its own key, so these are for direct installation onl
|
||||
43d78b773efca2b1aa2bf790c689b3086389d66c4ea0ffb72c9dba8bddb50770 ganjoor-0.2.0.apk
|
||||
5163554eb01845c131c31a9da7bdd748170bb9b5f82edaece754b4cf40b02b0c ganjoor-0.2.1.apk
|
||||
e473269044710813d2cf4119de663fe180f887239df7bdb1ccee0239ef84fd3e ganjoor-0.2.2.apk
|
||||
d9c49f109854793a0d96a3bd42dffff931dc37825dc49b4ed80cc4de1349ff72 ganjoor-0.3.0.apk
|
||||
5ac991ab8fe8676f89f4bc09a1a5d7464e32b6f74d789e7f29038b85f2c64f4a ganjoor-0.3.0.apk
|
||||
```
|
||||
|
||||
Installing: `adb install -r releases/ganjoor-<version>.apk`. A phone holding a *debug* build has
|
||||
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user