diff --git a/README.md b/README.md index 29a29b4..1a92b50 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ The whole interface lays out and navigates right-to-left, whichever UI language On a tablet or an unfolded foldable (600dp and wider) the poets become a narrow column on the right, with the open poet's books, chapters and poems in columns beside it and the page in the rest of the screen. The columns narrow while a poem is open and can be hidden for a reader view. The dictionary -opens in a panel to the left of the poem instead of over it. Phones are unchanged. +and reading settings open in a panel to the left of the poem instead of over it. Phones are unchanged. ## Fonts diff --git a/app/src/main/java/com/ganjoor/android/ui/GanjoorApp.kt b/app/src/main/java/com/ganjoor/android/ui/GanjoorApp.kt index 71519e4..786ded0 100644 --- a/app/src/main/java/com/ganjoor/android/ui/GanjoorApp.kt +++ b/app/src/main/java/com/ganjoor/android/ui/GanjoorApp.kt @@ -1,9 +1,16 @@ package com.ganjoor.android.ui import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandHorizontally +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkHorizontally import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -102,6 +109,10 @@ fun GanjoorApp() { val wide by rememberUpdatedState(maxWidth >= 600.dp) // Up to three list columns beside the poets; below this, only the newest one. val expanded by rememberUpdatedState(maxWidth >= 840.dp) + // 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. + Row(Modifier.fillMaxSize()) { + Box(Modifier.weight(1f)) { NavHost( navController = nav, startDestination = PoetsRoute, @@ -226,8 +237,19 @@ fun GanjoorApp() { } } } + if (wide) { + AnimatedVisibility( + visible = settingsOpen, + enter = expandHorizontally() + fadeIn(), + exit = shrinkHorizontally() + fadeOut(), + ) { + ReadingSettingsPanel(onDismiss = { settingsOpen = false }) + } + } + } // Inside the provider: the sheet reads LocalOpenAbout, so it has to be in scope. - if (settingsOpen) ReadingSettingsSheet(onDismiss = { settingsOpen = false }) + if (settingsOpen && !wide) ReadingSettingsSheet(onDismiss = { settingsOpen = false }) + } } } diff --git a/app/src/main/java/com/ganjoor/android/ui/ReadingSettings.kt b/app/src/main/java/com/ganjoor/android/ui/ReadingSettings.kt index 396d614..23bc60d 100644 --- a/app/src/main/java/com/ganjoor/android/ui/ReadingSettings.kt +++ b/app/src/main/java/com/ganjoor/android/ui/ReadingSettings.kt @@ -1,24 +1,32 @@ package com.ganjoor.android.ui import android.app.Activity +import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FilterChip +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Slider +import androidx.compose.material3.Surface import androidx.compose.material3.Switch import androidx.compose.material3.TextButton import androidx.compose.material3.Text @@ -58,11 +66,53 @@ fun ReadingSettingsAction() { @OptIn(ExperimentalMaterial3Api::class) @Composable fun ReadingSettingsSheet(onDismiss: () -> Unit) { + ModalBottomSheet(onDismissRequest = onDismiss) { + ReadingSettingsContent() + } +} + +/** + * The same settings as [ReadingSettingsSheet], as a panel on the left of a large screen — the + * place the dictionary opens too. The page stays in view beside it, so a change of theme, font + * or size shows on the poem itself as it is made. The cross, or Back, closes it. + */ +@Composable +fun ReadingSettingsPanel(onDismiss: () -> Unit) { + BackHandler(onBack = onDismiss) + Surface( + color = MaterialTheme.colorScheme.surfaceContainerLow, + modifier = Modifier.width(360.dp).fillMaxHeight(), + ) { + Column(Modifier.statusBarsPadding()) { + Row( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 56.dp) + .padding(start = 20.dp, end = 4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = stringResource(R.string.reading_settings), + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.primary, + modifier = Modifier.weight(1f), + ) + IconButton(onClick = onDismiss) { + Icon(Icons.Default.Close, stringResource(R.string.close)) + } + } + HorizontalDivider(modifier = Modifier.padding(bottom = 8.dp)) + ReadingSettingsContent() + } + } +} + +@Composable +private fun ReadingSettingsContent() { val settings = LocalSettings.current val prefs = settings.value val context = LocalContext.current - ModalBottomSheet(onDismissRequest = onDismiss) { Column( modifier = Modifier // Inset first, then scroll: the viewport has to stop above the nav bar, @@ -148,7 +198,6 @@ fun ReadingSettingsSheet(onDismiss: () -> Unit) { Text(stringResource(R.string.about)) } } - } } @Composable diff --git a/design/README.md b/design/README.md index 8ef7df8..41a52f3 100644 --- a/design/README.md +++ b/design/README.md @@ -60,4 +60,4 @@ Poet portraits come from Ganjoor and are cropped into a circle on `secondary-con Material Icons in the filled style, at 24px, tinted with colour roles (see the Icons group). Use the standard Android share glyph wherever there is sharing, because people recognise it before reading the label. The brand mark is the eight-pointed khatam star (see Logos). There is no wordmark: گنجور is set in Naskh. ## Large screens -Tablets and unfolded foldables use **ColumnBrowser**. Tapping a poet collapses the home grid into a narrow poets column on the far right (portrait with the name underneath). To its left come the poet's books, then the chapters or poems of the open book, each column scrolling on its own. Older columns narrow as new ones open, so the poem stays near the middle, and a top-bar button hides the columns when the reader wants to focus on the poem. Phones are unchanged. +Tablets and unfolded foldables use **ColumnBrowser**. Tapping a poet collapses the home grid into a narrow poets column on the far right (portrait with the name underneath). To its left come the poet's books, then the chapters or poems of the open book, each column scrolling on its own. Older columns narrow as new ones open, so the poem stays near the middle, and a top-bar button hides the columns when the reader wants to focus on the poem. The dictionary and reading settings open in a panel on the left, beside the poem rather than over it. Phones are unchanged. diff --git a/design/components/ColumnBrowser/README.md b/design/components/ColumnBrowser/README.md index b8fc458..b249451 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/`. +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). ## Window sizes @@ -46,6 +46,13 @@ On large screens, tapping a word opens **WordPanel** on the left instead of the - The tapped word stays highlighted in the verse (`secondary-container` / `on-secondary-container`), on phones too. - ✕ or Back closes the panel. +## Reading settings + +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. +- 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. + ## Loading Nothing covers the whole screen while it loads, on phones as well: diff --git a/design/components/ReadingSettingsSheet/README.md b/design/components/ReadingSettingsSheet/README.md index 5ffc1b8..35aeab6 100644 --- a/design/components/ReadingSettingsSheet/README.md +++ b/design/components/ReadingSettingsSheet/README.md @@ -7,3 +7,4 @@ The Material bottom sheet behind the gear icon: theme, OLED, font, weight, text - Order: Theme chips → OLED toggle → Font chips → Weight chips → Text size slider (14–40, steps of 2) → **live preview** of a hemistich in the chosen reading style → Language chips → Offline mode → Show summaries → AI assistant, About & licences as TextButtons. - Every group has a **SectionLabel**. Changes apply immediately; there is no Save. - Changing language recreates the activity. +- On tablets and unfolded foldables the same settings open as a panel on the left instead (`ReadingSettingsPanel`, see ColumnBrowser), so the poem stays in view while they change. diff --git a/design/wireframes/8-settings.png b/design/wireframes/8-settings.png new file mode 100644 index 0000000..c018dcb Binary files /dev/null and b/design/wireframes/8-settings.png differ