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>
This commit is contained in:
parent
f21f4fa727
commit
936fd3cf3b
@ -110,7 +110,11 @@ fun GanjoorApp() {
|
|||||||
// Up to three list columns beside the poets; below this, only the newest one.
|
// Up to three list columns beside the poets; below this, only the newest one.
|
||||||
val expanded by rememberUpdatedState(maxWidth >= 840.dp)
|
val expanded by rememberUpdatedState(maxWidth >= 840.dp)
|
||||||
// On a large screen reading settings open in a panel on the left, where the dictionary
|
// On a large screen reading settings open in a panel on the left, where the dictionary
|
||||||
// opens, so the page stays in view and shows each change as it is made.
|
// opens, so the page stays in view and shows each change as it is made — but only where
|
||||||
|
// the browser still has its own room beside the panel. Below that the panel would squeeze
|
||||||
|
// the columns and the poem into less than the layout is built for, so the sheet is used
|
||||||
|
// instead, exactly as on a phone.
|
||||||
|
val settingsPanel by rememberUpdatedState(maxWidth - SidePanelWidth >= 600.dp)
|
||||||
Row(Modifier.fillMaxSize()) {
|
Row(Modifier.fillMaxSize()) {
|
||||||
Box(Modifier.weight(1f)) {
|
Box(Modifier.weight(1f)) {
|
||||||
NavHost(
|
NavHost(
|
||||||
@ -237,7 +241,7 @@ fun GanjoorApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wide) {
|
if (settingsPanel) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = settingsOpen,
|
visible = settingsOpen,
|
||||||
enter = expandHorizontally() + fadeIn(),
|
enter = expandHorizontally() + fadeIn(),
|
||||||
@ -249,7 +253,7 @@ fun GanjoorApp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inside the provider: the sheet reads LocalOpenAbout, so it has to be in scope.
|
// Inside the provider: the sheet reads LocalOpenAbout, so it has to be in scope.
|
||||||
if (settingsOpen && !wide) ReadingSettingsSheet(onDismiss = { settingsOpen = false })
|
if (settingsOpen && !settingsPanel) ReadingSettingsSheet(onDismiss = { settingsOpen = false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,6 +93,14 @@ fun PoemScreen(
|
|||||||
// finds, so the couplet's own actions live at its foot rather than behind a tap between words.
|
// 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) }
|
var tapped by remember { mutableStateOf<WordTap?>(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 about 75dp wide — one or two 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 - SidePanelWidth >= MinPageMeasure
|
||||||
|
|
||||||
Load(
|
Load(
|
||||||
key = fullUrl,
|
key = fullUrl,
|
||||||
block = { Ganjoor.poem(fullUrl) },
|
block = { Ganjoor.poem(fullUrl) },
|
||||||
@ -222,7 +230,7 @@ fun PoemScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wide) {
|
if (roomForPanel) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = tapped != null,
|
visible = tapped != null,
|
||||||
enter = expandHorizontally() + fadeIn(),
|
enter = expandHorizontally() + fadeIn(),
|
||||||
@ -240,7 +248,7 @@ fun PoemScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wide) {
|
if (!roomForPanel) {
|
||||||
tapped?.let { tap ->
|
tapped?.let { tap ->
|
||||||
WordSheet(
|
WordSheet(
|
||||||
word = tap.word,
|
word = tap.word,
|
||||||
@ -249,6 +257,7 @@ fun PoemScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A word someone tapped: what to look up, the couplet it came from, and where it sits in its verse. */
|
/** A word someone tapped: what to look up, the couplet it came from, and where it sits in its verse. */
|
||||||
|
|||||||
@ -81,7 +81,7 @@ fun ReadingSettingsPanel(onDismiss: () -> Unit) {
|
|||||||
BackHandler(onBack = onDismiss)
|
BackHandler(onBack = onDismiss)
|
||||||
Surface(
|
Surface(
|
||||||
color = MaterialTheme.colorScheme.surfaceContainerLow,
|
color = MaterialTheme.colorScheme.surfaceContainerLow,
|
||||||
modifier = Modifier.width(360.dp).fillMaxHeight(),
|
modifier = Modifier.width(SidePanelWidth).fillMaxHeight(),
|
||||||
) {
|
) {
|
||||||
Column(Modifier.statusBarsPadding()) {
|
Column(Modifier.statusBarsPadding()) {
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@ -48,6 +48,16 @@ import com.ganjoor.android.data.LocalAssistant
|
|||||||
import com.ganjoor.android.data.Pronunciation
|
import com.ganjoor.android.data.Pronunciation
|
||||||
import com.ganjoor.android.ui.theme.readingStyle
|
import com.ganjoor.android.ui.theme.readingStyle
|
||||||
|
|
||||||
|
/** The width of a side panel — the dictionary and the reading settings share it. */
|
||||||
|
val SidePanelWidth = 360.dp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The narrowest the page may be left once a side panel opens beside it. Below this the panel is
|
||||||
|
* not worth its room: on a book-style foldable the columns had already taken theirs, and a 360dp
|
||||||
|
* panel left the verse about 75dp wide, breaking it to one or two characters a line.
|
||||||
|
*/
|
||||||
|
val MinPageMeasure = 400.dp
|
||||||
|
|
||||||
/** English prose inside an otherwise right-to-left sheet. */
|
/** English prose inside an otherwise right-to-left sheet. */
|
||||||
@Composable
|
@Composable
|
||||||
private fun LeftToRight(content: @Composable () -> Unit) {
|
private fun LeftToRight(content: @Composable () -> Unit) {
|
||||||
@ -102,7 +112,7 @@ fun WordPanel(word: String, onDismiss: () -> Unit, passage: Bookmark? = null) {
|
|||||||
BackHandler(onBack = onDismiss)
|
BackHandler(onBack = onDismiss)
|
||||||
Surface(
|
Surface(
|
||||||
color = MaterialTheme.colorScheme.surfaceContainerLow,
|
color = MaterialTheme.colorScheme.surfaceContainerLow,
|
||||||
modifier = Modifier.width(360.dp).fillMaxHeight(),
|
modifier = Modifier.width(SidePanelWidth).fillMaxHeight(),
|
||||||
) {
|
) {
|
||||||
Column(Modifier.statusBarsPadding()) {
|
Column(Modifier.statusBarsPadding()) {
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@ -45,13 +45,18 @@ 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 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.
|
- The tapped word stays highlighted in the verse (`secondary-container` / `on-secondary-container`), on phones too.
|
||||||
- ✕ or Back closes the panel.
|
- ✕ or Back closes the panel.
|
||||||
|
- A panel is only opened 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 about 75dp wide — one or two characters a line. Below that the sheet
|
||||||
|
is used instead: it covers the foot of the poem but leaves the lines whole.
|
||||||
|
|
||||||
## Reading settings
|
## Reading settings
|
||||||
|
|
||||||
On large screens the gear opens **ReadingSettingsPanel** on the left, where the dictionary opens, instead of the bottom sheet:
|
On large screens the gear opens **ReadingSettingsPanel** on the left, where the dictionary opens, instead of the bottom sheet:
|
||||||
- It has the same width and surface as the dictionary panel, with a "Reading settings" header and a ✕ button. The settings and their order are the same as in the sheet.
|
- It has the same width and surface as the dictionary panel, with a "Reading settings" header and a ✕ button. The settings and their order are the same as in the sheet.
|
||||||
- The page stays in view beside the panel, so a change of theme, font, weight or size shows on the poem as it's made.
|
- The page stays in view beside the panel, so a change of theme, font, weight or size shows on the poem as it's made.
|
||||||
- ✕ or Back closes it. Phones keep the bottom sheet.
|
- ✕ or Back closes it. Phones keep the bottom sheet, and so does any window too narrow to
|
||||||
|
leave the browser its own 600dp beside the panel.
|
||||||
|
|
||||||
## Loading
|
## Loading
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user