diff --git a/app/src/main/java/com/ganjoor/android/ui/PoemScreen.kt b/app/src/main/java/com/ganjoor/android/ui/PoemScreen.kt index 11a3d47..82a1ba2 100644 --- a/app/src/main/java/com/ganjoor/android/ui/PoemScreen.kt +++ b/app/src/main/java/com/ganjoor/android/ui/PoemScreen.kt @@ -7,6 +7,10 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkHorizontally import androidx.compose.foundation.clickable +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -251,6 +255,9 @@ fun PoemScreen( } } +/** The positions that make a line of verse; anything else (Single, Paragraph, Comment) is prose. */ +private val VERSE_POSITIONS = setOf(Verse.RIGHT, Verse.LEFT, Verse.CENTERED_1, Verse.CENTERED_2) + /** A word someone tapped: what to look up, the couplet it came from, and where it sits in its verse. */ private data class WordTap(val word: String, val passage: Bookmark, val verse: Int, val range: IntRange) @@ -379,7 +386,26 @@ private fun Couplet( val oneLine = sideBySide && couplet.size == 2 && couplet[0].position == Verse.RIGHT && couplet[1].position == Verse.LEFT - Column(modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp)) { + // Each line of verse sits in its own soft card, so the eye finds where one couplet ends and + // the next begins, and the couplet's actions visibly belong to it. Prose (Golestan, + // Nowruznameh) stays bare: a paragraph in a box reads as a quotation, not as the text. + val isVerse = couplet.all { it.position in VERSE_POSITIONS } + val colors = MaterialTheme.colorScheme + // A step lighter than the page. On OLED black the usual step is all but black itself, so + // the card takes the next one up: still dim, but there. + val cardColor = + if (colors.surface == Color.Black) colors.surfaceContainerHighest else colors.surfaceContainerHigh + val card = if (isVerse) { + Modifier + .padding(vertical = 4.dp) + .clip(RoundedCornerShape(12.dp)) + .background(cardColor) + .padding(horizontal = 12.dp, vertical = 8.dp) + } else { + Modifier.padding(vertical = 6.dp) + } + + Column(modifier = Modifier.fillMaxWidth().then(card)) { if (oneLine) { Row(modifier = Modifier.fillMaxWidth()) { couplet.forEachIndexed { index, verse -> diff --git a/design/components/ColumnBrowser/README.md b/design/components/ColumnBrowser/README.md index 5a7c830..3498562 100644 --- a/design/components/ColumnBrowser/README.md +++ b/design/components/ColumnBrowser/README.md @@ -1,6 +1,6 @@ # ColumnBrowser -The layout for tablets and unfolded foldables. A narrow column of poets sits on the right. Beside it is a column for each level of the open book (books › chapters › poems), and the open page fills the rest of the screen on the left. Phones keep today's navigation. Built in `app/src/main/java/com/ganjoor/android/ui/ColumnBrowser.kt`; wireframes are in `design/wireframes/` (1–8). +The layout for tablets and unfolded foldables. A narrow column of poets sits on the right. Beside it is a column for each level of the open book (books › chapters › poems), and the open page fills the rest of the screen on the left. Phones keep today's navigation. Built in `app/src/main/java/com/ganjoor/android/ui/ColumnBrowser.kt`; wireframes are in `design/wireframes/` (1–9). ## Window sizes diff --git a/design/components/Couplet/README.md b/design/components/Couplet/README.md index bc584d3..821963b 100644 --- a/design/components/Couplet/README.md +++ b/design/components/Couplet/README.md @@ -4,7 +4,9 @@ One line of poetry: two hemistichs stacked on a phone, the first pushed to the s - **Consumer provides:** the couplet's verses (each with its position), the reading style from settings (`poem-naskh` or `poem-nastaliq` at the reader's size and weight), and handlers for a tapped word and for the actions. - Alignment by verse position: first hemistich `start`, second `end`, centred verses `center`, prose (single/paragraph/comment) `justify` so Golestan and Nowruznameh fill the column. -- `space-6` above and below each couplet. Text is `on-surface`. +- Every line of verse sits in its own **card**: `surface-container-high` (`surface-container-highest` on OLED black, where the usual step is all but black), `radius-md` (12dp) corners, 12dp/8dp inner padding and 4dp above and below. The card holds the couplet's options chevron, its actions and its summary, so they visibly belong to it. Text is `on-surface`, at least 6:1 on the card in every theme. +- Prose (Single, Paragraph or Comment positions: Golestan, Nowruznameh) has no card; it keeps `space-6` above and below. A paragraph in a box would read as a quotation. +- The cards are the same on phones, tablets and foldables (wireframes 4–9). - Tapping a word opens the dictionary sheet; tapping between words, or the 32px chevron (`touch-compact`, 20px icon, `on-surface-variant`), opens the couplet's actions: **Save this passage**, **Copy**, **Share** as TextButtons. Save keeps the link back to the poem; Copy doesn't. - Long-press belongs to text selection — never bind actions to it here. - With summaries on, Ganjoor's couplet summary sits underneath in `body-small` / `on-surface-variant`. diff --git a/design/components/bundle.css b/design/components/bundle.css index 688dd83..90c1124 100644 --- a/design/components/bundle.css +++ b/design/components/bundle.css @@ -28,7 +28,8 @@ .gj-metre { font-size: 12px; line-height: 16px; letter-spacing: .4px; color: var(--on-surface-variant); } /* Couplet: two hemistichs stacked; first to the start, second to the end. */ -.gj-couplet { padding: var(--space-6) 0; } +.gj-couplet { margin: var(--space-4) 0; padding: var(--space-8) var(--space-12); border-radius: var(--radius-md); background: var(--surface-container-high); } +.gj-couplet.is-prose { margin: 0; padding: var(--space-6) 0; background: none; } .gj-verse { font-family: var(--font-naskh); font-size: 22px; line-height: 1.8; color: var(--on-surface); margin: 0; } .gj-couplet.is-nastaliq .gj-verse { font-family: var(--font-nastaliq); line-height: 2.4; } .gj-verse.is-first { text-align: start; } diff --git a/design/wireframes/4-reading.png b/design/wireframes/4-reading.png index aebcf6d..7d1b024 100644 Binary files a/design/wireframes/4-reading.png and b/design/wireframes/4-reading.png differ diff --git a/design/wireframes/5-reader-view.png b/design/wireframes/5-reader-view.png index 4ede9e1..922b625 100644 Binary files a/design/wireframes/5-reader-view.png and b/design/wireframes/5-reader-view.png differ diff --git a/design/wireframes/6-dictionary.png b/design/wireframes/6-dictionary.png index 82642cc..d0994ea 100644 Binary files a/design/wireframes/6-dictionary.png and b/design/wireframes/6-dictionary.png differ diff --git a/design/wireframes/7-foldable.png b/design/wireframes/7-foldable.png index 7d789ae..35a7566 100644 Binary files a/design/wireframes/7-foldable.png and b/design/wireframes/7-foldable.png differ diff --git a/design/wireframes/8-settings.png b/design/wireframes/8-settings.png index 8fd6896..068b1fd 100644 Binary files a/design/wireframes/8-settings.png and b/design/wireframes/8-settings.png differ diff --git a/design/wireframes/9-phone-couplets.png b/design/wireframes/9-phone-couplets.png new file mode 100644 index 0000000..a901552 Binary files /dev/null and b/design/wireframes/9-phone-couplets.png differ