Compare commits

...
Author SHA1 Message Date
anasandClaude Opus 5 41d776a35d Merge main, keeping only the part of this branch that is still needed
main has moved on since this branch opened, and most of what it carried has been
answered better there:

- the reading settings no longer need a fallback to the sheet, because they fold
  the columns away and take the room that frees (aab8b2e);
- the two panels no longer share a width, because the dictionary is now 216dp
  against the settings' 360dp.

Both were dropped: the conflicting files are taken from main as they stand.

What survives is the reason this branch exists. Which container the dictionary
uses is still decided by the width of the *window*, and that is the wrong
question — what matters is what is left of the page once the columns have taken
theirs. On a 700dp foldable that is about 450dp, and a panel beside it leaves
the verse a couple of characters a line. It now opens beside the poem only while
the page keeps 400dp, and falls back to the sheet below that, which covers the
foot of the poem but leaves every line whole.

Recalculated for the narrower panel: a tablet keeps the panel (~900dp page less
216dp leaves 684dp), a foldable in portrait does not (236dp).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-07 18:33:24 +02:00
anasandClaude Opus 5 bcdad2e699 Merge fix/one-side-panel-at-a-time
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-07 18:28:34 +02:00
anasandClaude Opus 5 ce26676d4e Merge fix/recitation-keeps-playing
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-07 18:28:34 +02:00
anasandClaude Opus 5 f60f9b4079 One side panel at a time, and a narrower one for the dictionary
Two fixes to the left of the reader.

The dictionary and the reading settings both want that side of the screen, and
opening the second put two panels there at once — or, where there was no longer
room for two, left the dictionary as a sheet in the middle of the page while the
settings sat beside it. Either way the reader is asked to look in two places.
The settings now replace the dictionary; closing them leaves the poem, which is
where the reader was.

The dictionary also no longer takes the settings' full 360dp. It is read against
the line it came from, so the verse should keep the width: 216dp, a little over
half. The settings keep 360dp, which costs nothing — they fold the columns away
and take the room that frees.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-07 18:25:13 +02:00
anasandClaude Opus 5 936fd3cf3b Open the dictionary as a sheet where a panel would crush the poem
On a book-style foldable held open in portrait — 700dp, inside the 600–839dp
band — tapping a word made the poem unreadable. The panel is a fixed 360dp and
the columns keep their widths, so the page was left about 75dp: the verse broke
to one or two characters a line, and the breadcrumbs and the metre shattered the
same way.

The panel was chosen from the width of the window. That is the wrong question.
What matters is what is left of the page once the columns have taken their room,
so both panels now ask that instead:

- the dictionary opens beside the poem only while the page keeps 400dp;
- reading settings open beside the browser only while it keeps its own 600dp,
  below which the panel would squeeze the columns and the poem into less than
  the layout is built for.

Where they do not fit, the bottom sheet is used, exactly as on a phone: it
covers the foot of the poem but leaves every line whole. A tablet is unaffected
— verified at 2560x1600 that the panel still opens and the poem still reads.

The two panels now share one width, and the design notes record the rule.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-07 18:04:39 +02:00
3 changed files with 40 additions and 3 deletions

No files matched your search

@@ -97,6 +97,22 @@ fun PoemScreen(
// finds, so the couplet's own actions live at its foot rather than behind a tap between words.
var tapped by remember { mutableStateOf<WordTap?>(null) }
// One side panel at a time. The dictionary and the reading settings both want the left of the
// screen, and opening the second put two panels there at once — or, where there was no longer
// room for two, left the dictionary as a sheet in the middle of the page while the settings
// sat beside it. Either way the reader is asked to look in two places. The settings replace
// the dictionary instead; closing them leaves the poem, which is where the reader was.
val sidePanelOpen = LocalSidePanelOpen.current
LaunchedEffect(sidePanelOpen) { if (sidePanelOpen) tapped = null }
BoxWithConstraints(Modifier.fillMaxSize()) {
// Whether the dictionary gets a column of its own is not a question about the window but
// about what is left of this page once the columns have taken theirs. On a book-style
// foldable held open in portrait the page is already down to ~450dp, and a panel beside it
// left the verse a couple of characters a line. Where it does not fit, the sheet is the
// better answer: it covers the foot of the poem but leaves the lines whole.
val roomForPanel = wide && maxWidth - DictionaryPanelWidth >= MinPageMeasure
Load(
key = fullUrl,
block = { Ganjoor.poem(fullUrl) },
@@ -231,7 +247,7 @@ fun PoemScreen(
}
}
}
if (wide) {
if (roomForPanel) {
AnimatedVisibility(
visible = tapped != null,
enter = expandHorizontally() + fadeIn(),
@@ -249,7 +265,7 @@ fun PoemScreen(
}
}
if (!wide) {
if (!roomForPanel) {
tapped?.let { tap ->
WordSheet(
word = tap.word,
@@ -258,6 +274,7 @@ fun PoemScreen(
)
}
}
}
}
/** The positions that make a line of verse; anything else (Single, Paragraph, Comment) is prose. */
@@ -48,6 +48,22 @@ import com.ganjoor.android.data.LocalAssistant
import com.ganjoor.android.data.Pronunciation
import com.ganjoor.android.ui.theme.readingStyle
/**
* How wide the dictionary sits beside the poem.
*
* Narrower than the reading settings, deliberately: the settings fold the columns away and take
* the room that frees, while the dictionary is read *against* the line it came from, so the verse
* keeps the width instead. A definition is short; a hemistich is not.
*/
val DictionaryPanelWidth = 216.dp
/**
* The narrowest the page may be left once the dictionary opens beside it. Below this the panel is
* not worth its room: on a book-style foldable held open in portrait the columns have already
* taken theirs, and a panel there left the verse a couple of characters a line.
*/
val MinPageMeasure = 400.dp
/** English prose inside an otherwise right-to-left sheet. */
@Composable
private fun LeftToRight(content: @Composable () -> Unit) {
@@ -102,7 +118,7 @@ fun WordPanel(word: String, onDismiss: () -> Unit, passage: Bookmark? = null) {
BackHandler(onBack = onDismiss)
Surface(
color = MaterialTheme.colorScheme.surfaceContainerLow,
modifier = Modifier.width(360.dp).fillMaxHeight(),
modifier = Modifier.width(DictionaryPanelWidth).fillMaxHeight(),
) {
Column(Modifier.statusBarsPadding()) {
Row(
@@ -45,6 +45,10 @@ On large screens, tapping a word opens **WordPanel** on the left instead of the
- The poem moves over to make room, so nothing being read is covered.
- The tapped word stays highlighted in the verse (`secondary-container` / `on-secondary-container`), on phones too.
- ✕ or Back closes the panel.
- The panel only opens where the page keeps at least **400dp** beside it. On a book-style
foldable held open in portrait the columns have already taken their room, and a panel
there left the verse a couple of characters a line. Below that the sheet is used instead:
it covers the foot of the poem but leaves the lines whole.
## Reading settings