~repos /only-bible-app

#kotlin#android#ios

git clone https://pyrossh.dev/repos/only-bible-app.git
Discussions: https://groups.google.com/g/rust-embed-devs

The only bible app you will ever need. No ads. No in-app purchases. No distractions.


d8dfaf1d Peter John

1 year ago
nfix avigation
app/src/main/java/dev/pyros/bibleapp/AppHost.kt CHANGED
@@ -2,10 +2,7 @@ package dev.pyros.bibleapp
2
2
 
3
3
  import androidx.compose.animation.AnimatedContentTransitionScope
4
4
  import androidx.compose.animation.core.tween
5
- import androidx.compose.material3.rememberModalBottomSheetState
6
5
  import androidx.compose.runtime.Composable
7
- import androidx.compose.runtime.rememberCoroutineScope
8
- import androidx.compose.ui.Modifier
9
6
  import androidx.navigation.NavType
10
7
  import androidx.navigation.compose.NavHost
11
8
  import androidx.navigation.compose.composable
@@ -13,52 +10,54 @@ import androidx.navigation.compose.rememberNavController
13
10
  import androidx.navigation.navArgument
14
11
 
15
12
  @Composable
16
- fun AppHost(verses: List<Verse>, modifier: Modifier = Modifier) {
13
+ fun AppHost(verses: List<Verse>) {
17
14
  val navController = rememberNavController()
15
+ Drawer(navController = navController) { openDrawer ->
18
- NavHost(
16
+ NavHost(
19
- modifier = modifier,
20
- navController = navController,
17
+ navController = navController,
21
- startDestination = "/books/{book}/chapters/{chapter}",
18
+ startDestination = "/books/{book}/chapters/{chapter}",
22
- enterTransition = {
19
+ enterTransition = {
23
- slideIntoContainer(
20
+ slideIntoContainer(
24
- AnimatedContentTransitionScope.SlideDirection.Left,
21
+ AnimatedContentTransitionScope.SlideDirection.Left,
25
- tween(500),
22
+ tween(500),
26
- )
23
+ )
27
- },
24
+ },
25
+ // exitTransition = {
26
+ // slideOutOfContainer(
27
+ // AnimatedContentTransitionScope.SlideDirection.Left,
28
+ // tween(500),
29
+ // )
30
+ // },
31
+ popEnterTransition = {
32
+ slideIntoContainer(
33
+ AnimatedContentTransitionScope.SlideDirection.Right,
34
+ tween(500),
35
+ )
36
+ },
28
- exitTransition = {
37
+ popExitTransition = {
29
- slideOutOfContainer(
38
+ slideOutOfContainer(
30
- AnimatedContentTransitionScope.SlideDirection.Left,
39
+ AnimatedContentTransitionScope.SlideDirection.Right,
31
- tween(500),
40
+ tween(500),
32
- )
41
+ )
33
- },
42
+ }
34
- // popEnterTransition = {
35
- // slideIntoContainer(
36
- // AnimatedContentTransitionScope.SlideDirection.Right,
37
- // tween(500),
38
- // )
39
- // },
40
- // popExitTransition = {
41
- // slideOutOfContainer(
42
- // AnimatedContentTransitionScope.SlideDirection.Right,
43
- // tween(500),
44
- // )
45
- // }
46
- ) {
47
- composable(
48
- route = "/books/{book}/chapters/{chapter}",
49
- arguments = listOf(
50
- navArgument("book") { type = NavType.IntType },
51
- navArgument("chapter") { type = NavType.IntType },
52
- )
53
43
  ) {
44
+ composable(
45
+ route = "/books/{book}/chapters/{chapter}",
46
+ arguments = listOf(
47
+ navArgument("book") { type = NavType.IntType },
48
+ navArgument("chapter") { type = NavType.IntType },
49
+ )
50
+ ) {
54
- ChapterScreen(
51
+ ChapterScreen(
55
- verses = verses,
52
+ verses = verses,
56
- bookIndex = it.arguments?.getInt("book") ?: 0,
53
+ bookIndex = it.arguments?.getInt("book") ?: 0,
57
- chapterIndex = it.arguments?.getInt("chapter") ?: 0,
54
+ chapterIndex = it.arguments?.getInt("chapter") ?: 0,
58
- navController = navController,
55
+ navController = navController,
56
+ openDrawer = openDrawer,
59
- )
57
+ )
58
+ }
60
59
  }
61
- }
60
+
62
61
  // val scope = rememberCoroutineScope()
63
62
  // val sheetState = rememberModalBottomSheetState()
64
63
  // var showBottomSheet by rememberSaveable { mutableStateOf(false) }
@@ -73,32 +72,7 @@ fun AppHost(verses: List<Verse>, modifier: Modifier = Modifier) {
73
72
  // sheetState = sheetState
74
73
  // ) {
75
74
  // Text("All Chapters")
76
- // LazyVerticalGrid(
77
- // columns = GridCells.Adaptive(minSize = 128.dp)
78
- // ) {
79
- // items(chapters.size) { c ->
80
- // Button(onClick = {
81
- // changeChapter(c)
82
- // scope.launch {
83
- // sheetState.hide()
84
- // }.invokeOnCompletion {
85
- // if (!sheetState.isVisible) {
86
- // showBottomSheet = false
87
- // }
88
- // }
89
- // }) {
90
- // Text(
91
- // modifier = Modifier.padding(bottom = 4.dp),
92
- // style = TextStyle(
93
- // fontSize = 16.sp,
94
- // fontWeight = FontWeight.W500,
95
- // color = Color(0xFF9A1111),
96
- // ),
97
- // text = (c + 1).toString(),
98
- // )
99
- // }
100
- // }
101
- // }
102
75
  // }
103
76
  // }
77
+ }
104
78
  }
app/src/main/java/dev/pyros/bibleapp/ChapterScreen.kt CHANGED
@@ -2,20 +2,37 @@ package dev.pyros.bibleapp
2
2
 
3
3
  import androidx.compose.animation.core.tween
4
4
  import androidx.compose.foundation.ExperimentalFoundationApi
5
+ import androidx.compose.foundation.border
5
6
  import androidx.compose.foundation.gestures.AnchoredDraggableState
6
7
  import androidx.compose.foundation.gestures.DraggableAnchors
7
8
  import androidx.compose.foundation.gestures.detectHorizontalDragGestures
8
9
  import androidx.compose.foundation.layout.Column
10
+ import androidx.compose.foundation.layout.WindowInsets
11
+ import androidx.compose.foundation.layout.absolutePadding
9
12
  import androidx.compose.foundation.layout.fillMaxSize
10
13
  import androidx.compose.foundation.layout.padding
11
14
  import androidx.compose.foundation.lazy.grid.GridCells
12
15
  import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
13
16
  import androidx.compose.foundation.rememberScrollState
14
17
  import androidx.compose.foundation.verticalScroll
18
+ import androidx.compose.material.icons.Icons
19
+ import androidx.compose.material.icons.filled.Menu
15
20
  import androidx.compose.material3.Button
21
+ import androidx.compose.material3.Divider
22
+ import androidx.compose.material3.DrawerValue
16
23
  import androidx.compose.material3.ExperimentalMaterial3Api
24
+ import androidx.compose.material3.Icon
25
+ import androidx.compose.material3.IconButton
26
+ import androidx.compose.material3.MaterialTheme
17
27
  import androidx.compose.material3.ModalBottomSheet
28
+ import androidx.compose.material3.ModalDrawerSheet
29
+ import androidx.compose.material3.ModalNavigationDrawer
30
+ import androidx.compose.material3.Scaffold
31
+ import androidx.compose.material3.Surface
18
32
  import androidx.compose.material3.Text
33
+ import androidx.compose.material3.TopAppBar
34
+ import androidx.compose.material3.TopAppBarDefaults.topAppBarColors
35
+ import androidx.compose.material3.rememberDrawerState
19
36
  import androidx.compose.material3.rememberModalBottomSheetState
20
37
  import androidx.compose.runtime.Composable
21
38
  import androidx.compose.runtime.getValue
@@ -35,6 +52,7 @@ import androidx.compose.ui.text.withStyle
35
52
  import androidx.compose.ui.unit.dp
36
53
  import androidx.compose.ui.unit.sp
37
54
  import androidx.navigation.NavController
55
+ import kotlinx.coroutines.Job
38
56
  import kotlinx.coroutines.launch
39
57
  import kotlinx.serialization.Serializable
40
58
 
@@ -44,6 +62,8 @@ enum class DragAnchors {
44
62
  End,
45
63
  }
46
64
 
65
+
66
+ // TODO: once androidx.navigation 2.8.0 is released
47
67
  @Serializable
48
68
  data class ChapterScreenProps(
49
69
  val bookIndex: Int,
@@ -56,7 +76,8 @@ fun ChapterScreen(
56
76
  verses: List<Verse>,
57
77
  bookIndex: Int,
58
78
  chapterIndex: Int,
59
- navController: NavController
79
+ navController: NavController,
80
+ openDrawer: () -> Job,
60
81
  ) {
61
82
  val chapters =
62
83
  verses.filter { it.bookIndex == bookIndex }.map { it.chapterIndex }.distinct();
@@ -85,52 +106,67 @@ fun ChapterScreen(
85
106
  }
86
107
  )
87
108
  }
88
-
89
-
90
109
  val chapterVerses =
91
110
  verses.filter { it.bookIndex == bookIndex && it.chapterIndex == chapterIndex };
92
- Column(
111
+ Scaffold(
93
- modifier = Modifier
112
+ modifier = Modifier.fillMaxSize(),
94
- .fillMaxSize()
113
+ topBar = {
95
- .padding(16.dp)
114
+ TopAppBar(
115
+ colors = topAppBarColors(
96
- .verticalScroll(rememberScrollState())
116
+ containerColor = Color(0xFFFFFFFF),
97
- // .anchoredDraggable(state, Orientation.Horizontal, reverseDirection = true)
98
- .pointerInput(Unit) {
99
- detectHorizontalDragGestures { change, dragAmount ->
117
+ titleContentColor = Color(0xFF000000),
118
+ ),
100
- change.consume()
119
+ title = {
101
- if (dragAmount < -5) {
120
+ Surface(onClick = { openDrawer() }) {
102
- changeChapter(chapterIndex - 1)
121
+ Text("Genesis ${chapterIndex + 1}")
103
122
  }
123
+ },
124
+ )
125
+ }
126
+ ) { innerPadding ->
127
+ Column(
128
+ modifier = Modifier
129
+ .fillMaxSize()
130
+ .padding(innerPadding)
131
+ .padding(horizontal = 16.dp)
132
+ .verticalScroll(rememberScrollState())
133
+ // .anchoredDraggable(state, Orientation.Horizontal, reverseDirection = true)
134
+ .pointerInput(Unit) {
135
+ detectHorizontalDragGestures { change, dragAmount ->
136
+ change.consume()
137
+ if (dragAmount < -5) {
138
+ changeChapter(chapterIndex - 1)
139
+ }
104
- if (dragAmount < 5) {
140
+ if (dragAmount < 5) {
105
- changeChapter(chapterIndex + 1)
141
+ changeChapter(chapterIndex + 1)
142
+ }
106
143
  }
107
144
  }
145
+ ) {
146
+ chapterVerses.map {
147
+ Text(
148
+ modifier = Modifier.padding(bottom = 4.dp),
149
+ text = buildAnnotatedString {
150
+ withStyle(
151
+ style = SpanStyle(
152
+ fontSize = 16.sp,
153
+ fontWeight = FontWeight.W500,
154
+ color = Color(0xFF9A1111),
155
+ )
156
+ ) {
157
+ append((it.verseIndex + 1).toString() + " ")
108
- }
158
+ }
159
+ withStyle(
160
+ style = SpanStyle(
161
+ fontSize = 18.sp,
162
+ fontWeight = FontWeight.W400,
163
+ )
109
- ) {
164
+ ) {
110
- Header(chapterIndex)
111
- chapterVerses.map {
165
+ append(it.text)
112
- Text(
113
- modifier = Modifier.padding(bottom = 4.dp),
114
- text = buildAnnotatedString {
115
- withStyle(
116
- style = SpanStyle(
117
- fontSize = 16.sp,
118
- fontWeight = FontWeight.W500,
119
- color = Color(0xFF9A1111),
120
- )
121
- ) {
122
- append((it.verseIndex + 1).toString() + " ")
123
- }
166
+ }
124
- withStyle(
125
- style = SpanStyle(
126
- fontSize = 18.sp,
127
- fontWeight = FontWeight.W400,
128
- )
129
- ) {
130
- append(it.text)
131
167
  }
168
+ )
132
- }
169
+ }
133
- )
134
170
  }
135
171
  }
136
172
  }
app/src/main/java/dev/pyros/bibleapp/Drawer.kt ADDED
@@ -0,0 +1,72 @@
1
+ package dev.pyros.bibleapp
2
+
3
+ import androidx.compose.foundation.layout.padding
4
+ import androidx.compose.foundation.lazy.grid.GridCells
5
+ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
6
+ import androidx.compose.material3.Button
7
+ import androidx.compose.material3.Divider
8
+ import androidx.compose.material3.DrawerValue
9
+ import androidx.compose.material3.ModalDrawerSheet
10
+ import androidx.compose.material3.ModalNavigationDrawer
11
+ import androidx.compose.material3.Text
12
+ import androidx.compose.material3.rememberDrawerState
13
+ import androidx.compose.runtime.Composable
14
+ import androidx.compose.runtime.rememberCoroutineScope
15
+ import androidx.compose.ui.Modifier
16
+ import androidx.compose.ui.graphics.Color
17
+ import androidx.compose.ui.text.TextStyle
18
+ import androidx.compose.ui.text.font.FontWeight
19
+ import androidx.compose.ui.unit.dp
20
+ import androidx.compose.ui.unit.sp
21
+ import androidx.navigation.NavController
22
+ import kotlinx.coroutines.Job
23
+ import kotlinx.coroutines.launch
24
+
25
+ @Composable
26
+ fun Drawer(navController: NavController, content: @Composable (() -> Job) -> Unit) {
27
+ val scope = rememberCoroutineScope()
28
+ val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
29
+ val openDrawer = {
30
+ scope.launch {
31
+ drawerState.apply {
32
+ if (isClosed) open() else close()
33
+ }
34
+ }
35
+ }
36
+ ModalNavigationDrawer(
37
+ gesturesEnabled = false,
38
+ drawerState = drawerState,
39
+ drawerContent = {
40
+ ModalDrawerSheet {
41
+ Text("Choose a chapter", modifier = Modifier.padding(16.dp))
42
+ Divider()
43
+ LazyVerticalGrid(
44
+ columns = GridCells.Adaptive(minSize = 80.dp)
45
+ ) {
46
+ items(32) { c ->
47
+ Button(
48
+ modifier = Modifier.padding(12.dp),
49
+ onClick = {
50
+ scope.launch {
51
+ navController.navigate(route = "/books/0/chapters/${c}")
52
+ drawerState.close();
53
+ }
54
+ }) {
55
+ Text(
56
+ modifier = Modifier.padding(bottom = 4.dp),
57
+ style = TextStyle(
58
+ fontSize = 16.sp,
59
+ fontWeight = FontWeight.W500,
60
+ color = Color(0xFFFFFFFF),
61
+ ),
62
+ text = (c + 1).toString(),
63
+ )
64
+ }
65
+ }
66
+ }
67
+ }
68
+ },
69
+ ) {
70
+ content(openDrawer)
71
+ }
72
+ }
app/src/main/java/dev/pyros/bibleapp/Header.kt DELETED
@@ -1,36 +0,0 @@
1
- package dev.pyros.bibleapp
2
-
3
- import androidx.compose.foundation.ExperimentalFoundationApi
4
- import androidx.compose.foundation.combinedClickable
5
- import androidx.compose.foundation.layout.Row
6
- import androidx.compose.foundation.layout.padding
7
- import androidx.compose.material3.Text
8
- import androidx.compose.runtime.Composable
9
- import androidx.compose.ui.Modifier
10
- import androidx.compose.ui.text.TextStyle
11
- import androidx.compose.ui.text.font.FontWeight
12
- import androidx.compose.ui.unit.dp
13
- import androidx.compose.ui.unit.sp
14
-
15
- @OptIn(ExperimentalFoundationApi::class)
16
- @Composable
17
- fun Header(
18
- chapterIndex: Int,
19
- ) {
20
- Row(modifier = Modifier.padding(bottom = 8.dp)) {
21
- Text(
22
- modifier = Modifier.combinedClickable(
23
- enabled = true,
24
- onClick = {
25
- },
26
- onDoubleClick = {
27
- }
28
- ),
29
- style = TextStyle(
30
- fontSize = 22.sp,
31
- fontWeight = FontWeight.W600,
32
- ),
33
- text = "Genesis ${chapterIndex + 1}"
34
- )
35
- }
36
- }
app/src/main/java/dev/pyros/bibleapp/MainActivity.kt CHANGED
@@ -5,10 +5,6 @@ import android.util.Log
5
5
  import androidx.activity.ComponentActivity
6
6
  import androidx.activity.compose.setContent
7
7
  import androidx.activity.enableEdgeToEdge
8
- import androidx.compose.foundation.layout.fillMaxSize
9
- import androidx.compose.foundation.layout.padding
10
- import androidx.compose.material3.Scaffold
11
- import androidx.compose.ui.Modifier
12
8
  import dev.pyros.bibleapp.ui.theme.BibleAppTheme
13
9
  import java.io.BufferedReader
14
10
 
@@ -48,12 +44,9 @@ class MainActivity : ComponentActivity() {
48
44
  val verses = parseBibleTxt("English", assets.open("English.txt").bufferedReader())
49
45
  setContent {
50
46
  BibleAppTheme {
51
- Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
52
- AppHost(verses = verses, modifier = Modifier.padding(innerPadding))
47
+ AppHost(verses = verses)
53
- }
54
48
  }
55
49
  }
56
50
  }
57
51
  }
58
52
 
59
-
app/src/main/java/dev/pyros/bibleapp/ui/theme/Theme.kt CHANGED
@@ -14,7 +14,7 @@ import androidx.compose.ui.platform.LocalContext
14
14
  private val DarkColorScheme = darkColorScheme(
15
15
  primary = Purple80,
16
16
  secondary = PurpleGrey80,
17
- tertiary = Pink80
17
+ tertiary = Pink80,
18
18
  )
19
19
 
20
20
  private val LightColorScheme = lightColorScheme(