~repos /only-bible-app

#kotlin#android#ios

git clone https://pyrossh.dev/repos/only-bible-app.git

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


70be3388 Peter John

1 year ago
more stuff
.idea/deploymentTargetSelector.xml CHANGED
@@ -13,9 +13,6 @@
13
13
  </DropdownSelection>
14
14
  <DialogSelection />
15
15
  </SelectionState>
16
- <SelectionState runConfigName="useAppContext()">
17
- <option name="selectionMode" value="DROPDOWN" />
18
- </SelectionState>
19
16
  </selectionStates>
20
17
  </component>
21
18
  </project>
app/build.gradle.kts CHANGED
@@ -65,6 +65,7 @@ dependencies {
65
65
  implementation(libs.androidx.ui.graphics)
66
66
  implementation(libs.androidx.ui.tooling.preview)
67
67
  implementation(libs.androidx.material3)
68
+ implementation(libs.androidx.material.icons.extended)
68
69
  implementation(libs.androidx.ui.util.android)
69
70
  implementation(libs.androidx.navigation.fragment.ktx)
70
71
  implementation(libs.androidx.navigation.ui.ktx)
@@ -81,4 +82,5 @@ dependencies {
81
82
  implementation(libs.androidx.ui.text.google.fonts)
82
83
  implementation(libs.client.sdk)
83
84
  implementation(libs.kotlinx.coroutines.core)
85
+ implementation(libs.androidx.datastore.preferences)
84
86
  }
app/src/main/java/dev/pyrossh/onlyBible/AppHost.kt CHANGED
@@ -1,15 +1,21 @@
1
1
  package dev.pyrossh.onlyBible
2
2
 
3
3
  import Verse
4
+ import android.content.Context
4
5
  import androidx.compose.animation.AnimatedContentTransitionScope
5
6
  import androidx.compose.animation.core.tween
6
7
  import androidx.compose.runtime.Composable
8
+ import androidx.datastore.core.DataStore
9
+ import androidx.datastore.preferences.core.Preferences
10
+ import androidx.datastore.preferences.preferencesDataStore
7
11
  import androidx.navigation.NavType
8
12
  import androidx.navigation.compose.NavHost
9
13
  import androidx.navigation.compose.composable
10
14
  import androidx.navigation.compose.rememberNavController
11
15
  import androidx.navigation.navArgument
12
16
 
17
+ val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
18
+
13
19
  @Composable
14
20
  fun AppHost(verses: List<Verse>) {
15
21
  val navController = rememberNavController()
@@ -64,22 +70,5 @@ fun AppHost(verses: List<Verse>) {
64
70
  )
65
71
  }
66
72
  }
67
-
68
- // val scope = rememberCoroutineScope()
69
- // val sheetState = rememberModalBottomSheetState()
70
- // var showBottomSheet by rememberSaveable { mutableStateOf(false) }
71
- // val showSheet = {
72
- // showBottomSheet = true
73
- // }
74
- // if (showBottomSheet) {
75
- // ModalBottomSheet(
76
- // onDismissRequest = {
77
- // showBottomSheet = false
78
- // },
79
- // sheetState = sheetState
80
- // ) {
81
- // Text("All Chapters")
82
- // }
83
- // }
84
73
  }
85
74
  }
app/src/main/java/dev/pyrossh/onlyBible/ChapterScreen.kt CHANGED
@@ -1,29 +1,50 @@
1
1
  package dev.pyrossh.onlyBible
2
2
 
3
+ import FontType
4
+ import PreferencesManager
3
5
  import Verse
4
6
  import android.annotation.SuppressLint
7
+ import android.content.Context
8
+ import androidx.compose.foundation.ExperimentalFoundationApi
9
+ import androidx.compose.foundation.background
5
10
  import androidx.compose.foundation.gestures.detectHorizontalDragGestures
6
11
  import androidx.compose.foundation.gestures.detectTapGestures
7
12
  import androidx.compose.foundation.layout.Arrangement
13
+ import androidx.compose.foundation.layout.Box
8
14
  import androidx.compose.foundation.layout.Column
9
15
  import androidx.compose.foundation.layout.Row
10
16
  import androidx.compose.foundation.layout.fillMaxSize
11
17
  import androidx.compose.foundation.layout.fillMaxWidth
18
+ import androidx.compose.foundation.layout.height
12
19
  import androidx.compose.foundation.layout.padding
20
+ import androidx.compose.foundation.layout.size
13
- import androidx.compose.foundation.rememberScrollState
21
+ import androidx.compose.foundation.layout.wrapContentSize
14
- import androidx.compose.foundation.verticalScroll
22
+ import androidx.compose.foundation.lazy.LazyColumn
23
+ import androidx.compose.foundation.lazy.items
24
+ import androidx.compose.foundation.shape.RoundedCornerShape
25
+ import androidx.compose.foundation.text.selection.DisableSelection
15
26
  import androidx.compose.material.icons.Icons
27
+ import androidx.compose.material.icons.filled.Close
28
+ import androidx.compose.material.icons.filled.FaceRetouchingNatural
29
+ import androidx.compose.material.icons.filled.FormatBold
30
+ import androidx.compose.material.icons.filled.FormatLineSpacing
31
+ import androidx.compose.material.icons.filled.FormatSize
16
32
  import androidx.compose.material.icons.outlined.MoreVert
17
33
  import androidx.compose.material.icons.outlined.Share
34
+ import androidx.compose.material3.ExperimentalMaterial3Api
35
+ import androidx.compose.material3.HorizontalDivider
18
36
  import androidx.compose.material3.Icon
19
37
  import androidx.compose.material3.IconButton
20
38
  import androidx.compose.material3.MaterialTheme
39
+ import androidx.compose.material3.ModalBottomSheet
21
40
  import androidx.compose.material3.Scaffold
22
41
  import androidx.compose.material3.Surface
23
42
  import androidx.compose.material3.Text
43
+ import androidx.compose.material3.rememberModalBottomSheetState
24
44
  import androidx.compose.runtime.Composable
25
45
  import androidx.compose.runtime.getValue
26
46
  import androidx.compose.runtime.mutableFloatStateOf
47
+ import androidx.compose.runtime.mutableIntStateOf
27
48
  import androidx.compose.runtime.mutableStateOf
28
49
  import androidx.compose.runtime.remember
29
50
  import androidx.compose.runtime.rememberCoroutineScope
@@ -37,16 +58,21 @@ import androidx.compose.ui.input.pointer.pointerInput
37
58
  import androidx.compose.ui.layout.boundsInWindow
38
59
  import androidx.compose.ui.layout.onGloballyPositioned
39
60
  import androidx.compose.ui.platform.LocalContext
61
+ import androidx.compose.ui.res.painterResource
40
62
  import androidx.compose.ui.text.SpanStyle
41
63
  import androidx.compose.ui.text.TextStyle
42
64
  import androidx.compose.ui.text.buildAnnotatedString
65
+ import androidx.compose.ui.text.font.FontFamily
43
66
  import androidx.compose.ui.text.font.FontWeight
44
67
  import androidx.compose.ui.text.withStyle
45
68
  import androidx.compose.ui.unit.dp
46
69
  import androidx.compose.ui.unit.sp
70
+ import androidx.datastore.preferences.core.edit
71
+ import androidx.datastore.preferences.core.intPreferencesKey
47
72
  import androidx.navigation.NavController
48
- import fontFamily
73
+ import convertVersesToSpeech
49
74
  import kotlinx.coroutines.Job
75
+ import kotlinx.coroutines.launch
50
76
  import kotlinx.serialization.Serializable
51
77
  import shareVerses
52
78
 
@@ -57,6 +83,23 @@ data class ChapterScreenProps(
57
83
  val chapterIndex: Int,
58
84
  )
59
85
 
86
+ val fontSizeDeltaKey = intPreferencesKey("fontSizeDelta");
87
+
88
+ suspend fun incrementFontSize(context: Context) {
89
+ context.dataStore.edit { settings ->
90
+ val currentCounterValue = settings[fontSizeDeltaKey] ?: 0
91
+ settings[fontSizeDeltaKey] = currentCounterValue + 1
92
+ }
93
+ }
94
+
95
+ suspend fun decrementFontSize(context: Context) {
96
+ context.dataStore.edit { settings ->
97
+ val currentCounterValue = settings[fontSizeDeltaKey] ?: 0
98
+ settings[fontSizeDeltaKey] = currentCounterValue - 1
99
+ }
100
+ }
101
+
102
+ @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
60
103
  @SuppressLint("MutableCollectionMutableState")
61
104
  @Composable
62
105
  fun ChapterScreen(
@@ -66,7 +109,17 @@ fun ChapterScreen(
66
109
  navController: NavController,
67
110
  openDrawer: (MenuType, Int) -> Job,
68
111
  ) {
69
- val context = LocalContext.current;
112
+ val context = LocalContext.current
113
+ val prefs = PreferencesManager(context)
114
+ var fontType by remember { mutableStateOf(prefs.getFontType()) }
115
+ var fontSizeDelta by remember { mutableIntStateOf(prefs.getFontSize()) }
116
+ var boldEnabled by remember { mutableStateOf(prefs.getBold()) }
117
+ val fontFamily = when (fontType) {
118
+ FontType.Sans -> FontFamily.SansSerif
119
+ FontType.Serif -> FontFamily.Serif
120
+ FontType.Mono -> FontFamily.Monospace
121
+ }
122
+ val boldWeight = if (boldEnabled) FontWeight.W700 else FontWeight.W400
70
123
  val scope = rememberCoroutineScope()
71
124
  var selectedVerseBounds: Rect by remember { mutableStateOf(Rect.Zero) }
72
125
  var selectedVerses by rememberSaveable {
@@ -80,42 +133,336 @@ fun ChapterScreen(
80
133
  Scaffold(
81
134
  modifier = Modifier.fillMaxSize(),
82
135
  ) { innerPadding ->
83
- // if (selectedVerses.isNotEmpty()) {
84
- // Box(
85
- // Modifier
86
- // .zIndex(99f)
87
- // .offset {
88
- // IntOffset(
89
- // selectedVerseBounds.centerLeft.x.toInt() + 400,
90
- // selectedVerseBounds.centerLeft.y.toInt() + 300,
91
- // )
92
- // }
93
- // ) {
94
- // Surface(
95
- // modifier = Modifier
96
- // .width(200.dp)
97
- // .height(60.dp)
98
- // .border(
99
- // 1.dp,
100
- // Color.Black,
101
- // RoundedCornerShape(0, 0, 0, 0),
102
- // ),
103
- // ) {
104
- // Text(
105
- // modifier = Modifier
106
- // .fillMaxWidth(),
107
- // textAlign = TextAlign.Center,
108
- // text = "Bottom app bar",
109
- // )
110
- // }
111
- // }
112
- // }
113
- Column(
136
+ val sheetState = rememberModalBottomSheetState()
137
+ var showBottomSheet by rememberSaveable { mutableStateOf(false) }
138
+ val showSheet = {
139
+ showBottomSheet = true
140
+ }
141
+ val closeSheet = {
142
+ showBottomSheet = false
143
+ }
144
+ if (showBottomSheet) {
145
+ ModalBottomSheet(
146
+ onDismissRequest = {
147
+ showBottomSheet = false
148
+ },
149
+ sheetState = sheetState
150
+ ) {
151
+ Column(
152
+ modifier = Modifier
153
+ .fillMaxSize()
154
+ .padding(horizontal = 16.dp),
155
+ ) {
156
+ Row(
157
+ modifier = Modifier.fillMaxWidth(),
158
+ horizontalArrangement = Arrangement.SpaceBetween,
159
+ verticalAlignment = Alignment.CenterVertically,
160
+ ) {
161
+ Text(
162
+ text = "Text Settings",
163
+ fontSize = 20.sp,
164
+ fontWeight = FontWeight.W500
165
+ )
166
+ Row(horizontalArrangement = Arrangement.End) {
167
+ IconButton(onClick = {
168
+ scope.launch {
169
+ closeSheet()
170
+ }
171
+ }) {
172
+ Icon(Icons.Filled.Close, "Close")
173
+ }
174
+ }
175
+ }
176
+ HorizontalDivider()
177
+ Row(
178
+ modifier = Modifier
179
+ .fillMaxWidth()
180
+ .padding(top = 16.dp),
181
+ horizontalArrangement = Arrangement.SpaceBetween,
182
+ verticalAlignment = Alignment.CenterVertically,
183
+ ) {
184
+ Surface(
185
+ shape = RoundedCornerShape(8.dp),
186
+ modifier = Modifier
187
+ .fillMaxWidth()
188
+ .height(60.dp)
189
+ .padding(end = 16.dp)
190
+ .weight(1f),
191
+ onClick = {
192
+ fontSizeDelta -= 1
193
+ prefs.setFontSize(fontSizeDelta)
194
+ }
195
+ ) {
196
+ Column(
197
+ modifier = Modifier
198
+ .background(Color(0xFFFAFAFA)),
199
+ verticalArrangement = Arrangement.Center,
200
+ horizontalAlignment = Alignment.CenterHorizontally
201
+ ) {
202
+ Icon(
203
+ imageVector = Icons.Filled.FormatSize,
204
+ contentDescription = "Bold",
205
+ modifier = Modifier.size(14.dp),
206
+ )
207
+ }
208
+ }
209
+ Surface(
210
+ shape = RoundedCornerShape(8.dp),
211
+ modifier = Modifier
212
+ .fillMaxWidth()
213
+ .height(60.dp)
214
+ .padding(end = 16.dp)
215
+ .weight(1f),
216
+ onClick = {
217
+ fontSizeDelta += 1
218
+ prefs.setFontSize(fontSizeDelta)
219
+ }
220
+ ) {
221
+ Column(
222
+ modifier = Modifier
223
+ .background(Color(0xFFFAFAFA)),
224
+ verticalArrangement = Arrangement.Center,
225
+ horizontalAlignment = Alignment.CenterHorizontally
226
+ ) {
227
+ Icon(
228
+ imageVector = Icons.Filled.FormatSize,
229
+ contentDescription = "Bold"
230
+ )
231
+ }
232
+ }
233
+ Surface(
234
+ shape = RoundedCornerShape(8.dp),
235
+ modifier = Modifier
236
+ .fillMaxWidth()
237
+ .height(60.dp)
238
+ .padding(end = 16.dp)
239
+ .weight(1f),
240
+ onClick = {
241
+ boldEnabled = !boldEnabled
242
+ prefs.setBold(boldEnabled)
243
+ }
244
+ ) {
245
+ Column(
246
+ modifier = Modifier
247
+ .background(Color(0xFFFAFAFA)),
248
+ verticalArrangement = Arrangement.Center,
249
+ horizontalAlignment = Alignment.CenterHorizontally
250
+ ) {
251
+ Icon(
252
+ imageVector = Icons.Filled.FormatBold,
253
+ contentDescription = "Bold"
254
+ )
255
+ }
256
+ }
257
+ Surface(
258
+ shape = RoundedCornerShape(8.dp),
259
+ modifier = Modifier
260
+ .fillMaxWidth()
261
+ .height(60.dp)
262
+ .padding(end = 16.dp)
263
+ .weight(1f),
264
+ onClick = {}
265
+ ) {
266
+ Column(
267
+ modifier = Modifier
268
+ .background(Color(0xFFFAFAFA)),
269
+ verticalArrangement = Arrangement.Center,
270
+ horizontalAlignment = Alignment.CenterHorizontally
271
+ ) {
272
+ Icon(
273
+ imageVector = Icons.Filled.FormatLineSpacing,
274
+ contentDescription = "Line Spacing"
275
+ )
276
+ }
277
+ }
278
+ }
279
+ Row(
280
+ modifier = Modifier
281
+ .fillMaxWidth()
282
+ .padding(top = 16.dp),
283
+ horizontalArrangement = Arrangement.SpaceBetween,
284
+ verticalAlignment = Alignment.CenterVertically,
285
+ ) {
286
+ Surface(
287
+ shape = RoundedCornerShape(8.dp),
288
+ modifier = Modifier
289
+ .fillMaxWidth()
290
+ .height(60.dp)
291
+ .padding(end = 16.dp)
292
+ .weight(1f),
293
+ onClick = {
294
+ fontType = FontType.Sans
295
+ prefs.setFontType(fontType)
296
+ }
297
+ ) {
298
+ Column(
299
+ modifier = Modifier
300
+ .background(Color(0xFFFAFAFA)),
301
+ verticalArrangement = Arrangement.Center,
302
+ horizontalAlignment = Alignment.CenterHorizontally
303
+ ) {
304
+ Text(
305
+ text = "Sans",
306
+ style = TextStyle(
307
+ fontSize = 18.sp,
308
+ fontWeight = FontWeight.Medium,
309
+ )
310
+ )
311
+ }
312
+ }
313
+ Surface(
314
+ shape = RoundedCornerShape(8.dp),
315
+ modifier = Modifier
316
+ .fillMaxWidth()
317
+ .height(60.dp)
318
+ .padding(end = 16.dp)
319
+ .weight(1f),
320
+ onClick = {
321
+ fontType = FontType.Serif
322
+ prefs.setFontType(fontType)
323
+ }
324
+ ) {
325
+ Column(
326
+ modifier = Modifier
327
+ .background(Color(0xFFFAFAFA)),
328
+ verticalArrangement = Arrangement.Center,
329
+ horizontalAlignment = Alignment.CenterHorizontally
330
+ ) {
331
+ Text(
332
+ text = "Serif",
333
+ style = TextStyle(
334
+ fontSize = 18.sp,
335
+ fontWeight = FontWeight.Medium,
336
+ )
337
+ )
338
+ }
339
+ }
340
+ Surface(
341
+ shape = RoundedCornerShape(8.dp),
342
+ modifier = Modifier
343
+ .fillMaxWidth()
344
+ .height(60.dp)
345
+ .padding(end = 16.dp)
346
+ .weight(1f),
347
+ onClick = {
348
+ fontType = FontType.Mono
349
+ prefs.setFontType(fontType)
350
+ }
351
+ ) {
352
+ Column(
353
+ modifier = Modifier
354
+ .background(Color(0xFFFAFAFA)),
355
+ verticalArrangement = Arrangement.Center,
356
+ horizontalAlignment = Alignment.CenterHorizontally
357
+ ) {
358
+ Text(
359
+ text = "Mono",
360
+ style = TextStyle(
361
+ fontSize = 18.sp,
362
+ fontWeight = FontWeight.Medium,
363
+ )
364
+ )
365
+ }
366
+ }
367
+ }
368
+ Row(
369
+ modifier = Modifier
370
+ .fillMaxWidth()
371
+ .padding(top = 16.dp),
372
+ horizontalArrangement = Arrangement.SpaceBetween,
373
+ verticalAlignment = Alignment.CenterVertically,
374
+ ) {
375
+ // #72abbf on active
376
+ // #ebe0c7 on yellow
377
+ // #424547 on dark
378
+ Surface(
379
+ shape = RoundedCornerShape(8.dp),
380
+ modifier = Modifier
381
+ .fillMaxWidth()
382
+ .height(80.dp)
383
+ .padding(end = 16.dp)
384
+ .weight(1f),
385
+ onClick = {}
386
+ ) {
387
+ Icon(
388
+ painter = painterResource(id = R.drawable.text_theme),
389
+ contentDescription = "Light",
390
+ tint = Color(0xFF424547),
391
+ modifier = Modifier
392
+ .background(Color.White)
393
+ .padding(8.dp)
394
+ )
395
+ }
396
+ Surface(
397
+ shape = RoundedCornerShape(8.dp),
398
+ modifier = Modifier
399
+ .fillMaxWidth()
400
+ .height(80.dp)
401
+ .padding(end = 16.dp)
402
+ .weight(1f),
403
+ onClick = {}
404
+ ) {
405
+ Icon(
406
+ painter = painterResource(id = R.drawable.text_theme),
407
+ contentDescription = "Warm",
408
+ tint = Color(0xFF424547),
409
+ modifier = Modifier
410
+ .background(Color(0xFFe5e0d1))
411
+ .padding(8.dp)
412
+ )
413
+ }
414
+ Surface(
415
+ shape = RoundedCornerShape(8.dp),
416
+ modifier = Modifier
417
+ .fillMaxWidth()
418
+ .height(80.dp)
419
+ .padding(end = 16.dp)
420
+ .weight(1f),
421
+ onClick = {}
422
+ ) {
423
+ Icon(
424
+ painter = painterResource(id = R.drawable.text_theme),
425
+ contentDescription = "Dark",
426
+ tint = Color(0xFFd3d7da),
427
+ modifier = Modifier
428
+ .background(Color(0xFF2c2e30))
429
+ .padding(8.dp)
430
+ )
431
+ }
432
+ Surface(
433
+ shape = RoundedCornerShape(8.dp),
434
+ modifier = Modifier
435
+ .fillMaxWidth()
436
+ .height(80.dp)
437
+ .padding(end = 16.dp)
438
+ .weight(1f),
439
+ onClick = {}
440
+ ) {
441
+ Column(
442
+ modifier = Modifier
443
+ .background(Color(0xFFFAFAFA)),
444
+ verticalArrangement = Arrangement.Center,
445
+ horizontalAlignment = Alignment.CenterHorizontally
446
+ ) {
447
+ Text(
448
+ text = "Auto",
449
+ style = TextStyle(
450
+ fontSize = 18.sp,
451
+ fontWeight = FontWeight.Medium,
452
+ )
453
+ )
454
+ }
455
+ }
456
+ }
457
+ }
458
+ }
459
+ }
460
+ LazyColumn(
461
+ // verticalArrangement = Arrangement.spacedBy(4.dp),
114
462
  modifier = Modifier
115
463
  .fillMaxSize()
116
464
  .padding(innerPadding)
117
465
  .padding(horizontal = 16.dp)
118
- .verticalScroll(rememberScrollState())
119
466
  .pointerInput(Unit) {
120
467
  detectHorizontalDragGestures(
121
468
  onDragEnd = {
@@ -156,74 +503,91 @@ fun ChapterScreen(
156
503
  )
157
504
  }
158
505
  ) {
159
- Row(
160
- modifier = Modifier.fillMaxWidth(),
506
+ stickyHeader {
161
- horizontalArrangement = Arrangement.Start,
162
- verticalAlignment = Alignment.CenterVertically,
163
- ) {
164
507
  Row(
508
+ modifier = Modifier
509
+ .fillMaxWidth()
510
+ .background(Color.White),
165
511
  horizontalArrangement = Arrangement.Start,
512
+ verticalAlignment = Alignment.CenterVertically,
166
513
  ) {
514
+ Row(
515
+ horizontalArrangement = Arrangement.Start,
516
+ ) {
167
- Surface(onClick = { openDrawer(MenuType.Book, bookIndex) }) {
517
+ Surface(onClick = { openDrawer(MenuType.Book, bookIndex) }) {
168
- Text(
518
+ Text(
169
- Verse.bookNames[bookIndex], style = TextStyle(
519
+ Verse.bookNames[bookIndex], style = TextStyle(
170
- fontSize = 22.sp,
520
+ fontSize = 22.sp,
171
- fontWeight = FontWeight.W500,
521
+ fontWeight = FontWeight.W500,
172
- color = Color.Black,
522
+ color = Color.Black,
523
+ )
173
524
  )
174
- )
175
525
 
176
- }
526
+ }
177
- Surface(onClick = { openDrawer(MenuType.Chapter, bookIndex) }) {
527
+ Surface(onClick = { openDrawer(MenuType.Chapter, bookIndex) }) {
178
- Text(
528
+ Text(
179
- "${chapterIndex + 1}", style = TextStyle(
529
+ "${chapterIndex + 1}", style = TextStyle(
180
- fontSize = 22.sp,
530
+ fontSize = 22.sp,
181
- fontWeight = FontWeight.W500,
531
+ fontWeight = FontWeight.W500,
182
- color = Color.Black,
532
+ color = Color.Black,
533
+ )
183
534
  )
184
- )
185
- }
186
- }
187
- Row(
188
- modifier = Modifier.fillMaxWidth(),
189
- horizontalArrangement = Arrangement.End,
190
- ) {
191
- if (selectedVerses.isNotEmpty()) {
192
- IconButton(onClick = {
193
- shareVerses(context, selectedVerses)
194
- selectedVerses = listOf()
195
- }) {
196
- Icon(Icons.Outlined.Share, "Share")
197
535
  }
198
536
  }
537
+ Row(
538
+ modifier = Modifier.fillMaxWidth(),
539
+ horizontalArrangement = Arrangement.End,
540
+ ) {
541
+ if (selectedVerses.isNotEmpty()) {
199
- IconButton(onClick = {
542
+ IconButton(onClick = {
200
- // scope.launch {
543
+ scope.launch {
544
+ convertVersesToSpeech(
545
+ scope,
201
- // convertVersesToSpeech(scope, selectedVerses.sortedBy { it.verseIndex })
546
+ selectedVerses.sortedBy { it.verseIndex })
547
+ }.invokeOnCompletion {
202
- // }
548
+ selectedVerses = listOf()
549
+ }
203
- }) {
550
+ }) {
551
+ Icon(Icons.Filled.FaceRetouchingNatural, "Share")
552
+ }
553
+ IconButton(onClick = {
554
+ shareVerses(context, selectedVerses)
555
+ selectedVerses = listOf()
556
+ }) {
557
+ Icon(Icons.Outlined.Share, "Share")
558
+ }
559
+ }
560
+ Box(modifier = Modifier.wrapContentSize(Alignment.TopEnd)) {
561
+ IconButton(onClick = {
562
+ showSheet()
563
+ }) {
204
- Icon(Icons.Outlined.MoreVert, "Close")
564
+ Icon(Icons.Outlined.MoreVert, "More")
565
+ }
566
+ }
205
567
  }
206
568
  }
207
569
  }
208
- chapterVerses.map { v ->
570
+ items(chapterVerses) { v ->
571
+ if (v.heading.isNotEmpty()) {
572
+ DisableSelection {
573
+ Text(
574
+ modifier = Modifier.padding(
575
+ top = if (v.verseIndex != 0) 12.dp else 0.dp,
576
+ bottom = 12.dp
577
+ ),
578
+ style = TextStyle(
579
+ fontFamily = fontFamily,
580
+ fontSize = (16 + fontSizeDelta).sp,
581
+ fontWeight = FontWeight.W700,
582
+ color = Color.Black,
583
+ ),
584
+ text = v.heading.replace("<br>", "\n\n"),
585
+ )
586
+ }
587
+ }
209
588
  val isSelected = selectedVerses.contains(v);
210
589
  val background =
211
590
  if (isSelected) Color(0xFFEEEEEE) else MaterialTheme.colorScheme.background
212
- if (v.heading.isNotEmpty()) {
213
- Text(
214
- modifier = Modifier.padding(
215
- top = if (v.verseIndex != 0) 12.dp else 0.dp,
216
- bottom = 12.dp
217
- ),
218
- style = TextStyle(
219
- fontFamily = fontFamily,
220
- fontSize = 16.sp,
221
- fontWeight = FontWeight.W700,
222
- color = Color.Black,
223
- ),
224
- text = v.heading.replace("<br>", "\n\n"),
225
- )
226
- }
227
591
  Text(
228
592
  modifier = Modifier
229
593
  .padding(bottom = 16.dp)
@@ -250,15 +614,15 @@ fun ChapterScreen(
250
614
  background = background,
251
615
  fontFamily = fontFamily,
252
616
  color = Color.Black,
253
- fontWeight = FontWeight.W400,
617
+ fontWeight = boldWeight,
254
- fontSize = 16.sp,
618
+ fontSize = (16 + fontSizeDelta).sp,
255
- lineHeight = 22.sp,
619
+ lineHeight = (22 + fontSizeDelta).sp,
256
620
  letterSpacing = 0.sp,
257
621
  ),
258
622
  text = buildAnnotatedString {
259
623
  withStyle(
260
624
  style = SpanStyle(
261
- fontSize = 13.sp,
625
+ fontSize = (13 + fontSizeDelta).sp,
262
626
  color = Color(0xFF9A1111),
263
627
  fontWeight = FontWeight.W700,
264
628
  )
app/src/main/java/dev/pyrossh/onlyBible/Drawer.kt CHANGED
@@ -7,7 +7,6 @@ import androidx.compose.foundation.background
7
7
  import androidx.compose.foundation.gestures.detectTapGestures
8
8
  import androidx.compose.foundation.interaction.MutableInteractionSource
9
9
  import androidx.compose.foundation.layout.Arrangement
10
- import androidx.compose.foundation.layout.Box
11
10
  import androidx.compose.foundation.layout.BoxWithConstraints
12
11
  import androidx.compose.foundation.layout.Column
13
12
  import androidx.compose.foundation.layout.PaddingValues
@@ -67,40 +66,6 @@ fun shortName(name: String): String {
67
66
  return "${name[0].uppercase()}${name.substring(1, 3).lowercase()}"
68
67
  }
69
68
 
70
- @Composable
71
- fun NonlazyGrid(
72
- columns: Int,
73
- itemCount: Int,
74
- modifier: Modifier = Modifier,
75
- content: @Composable() (Int) -> Unit
76
- ) {
77
- Column(modifier = modifier) {
78
- var rows = (itemCount / columns)
79
- if (itemCount.mod(columns) > 0) {
80
- rows += 1
81
- }
82
-
83
- for (rowId in 0 until rows) {
84
- val firstIndex = rowId * columns
85
-
86
- Row {
87
- for (columnId in 0 until columns) {
88
- val index = firstIndex + columnId
89
- Box(
90
- modifier = Modifier
91
- .fillMaxWidth()
92
- .weight(1f)
93
- ) {
94
- if (index < itemCount) {
95
- content(index)
96
- }
97
- }
98
- }
99
- }
100
- }
101
- }
102
- }
103
-
104
69
  @SuppressLint("UnrememberedMutableInteractionSource")
105
70
  @Composable
106
71
  fun DropDownSample() {
app/src/main/java/dev/pyrossh/onlyBible/Grid.kt ADDED
@@ -0,0 +1,42 @@
1
+ package dev.pyrossh.onlyBible
2
+
3
+ import androidx.compose.foundation.layout.Box
4
+ import androidx.compose.foundation.layout.Column
5
+ import androidx.compose.foundation.layout.Row
6
+ import androidx.compose.foundation.layout.fillMaxWidth
7
+ import androidx.compose.runtime.Composable
8
+ import androidx.compose.ui.Modifier
9
+
10
+ @Composable
11
+ fun Grid(
12
+ columns: Int,
13
+ itemCount: Int,
14
+ modifier: Modifier = Modifier,
15
+ content: @Composable() (Int) -> Unit
16
+ ) {
17
+ Column(modifier = modifier) {
18
+ var rows = (itemCount / columns)
19
+ if (itemCount.mod(columns) > 0) {
20
+ rows += 1
21
+ }
22
+
23
+ for (rowId in 0 until rows) {
24
+ val firstIndex = rowId * columns
25
+
26
+ Row {
27
+ for (columnId in 0 until columns) {
28
+ val index = firstIndex + columnId
29
+ Box(
30
+ modifier = Modifier
31
+ .fillMaxWidth()
32
+ .weight(1f)
33
+ ) {
34
+ if (index < itemCount) {
35
+ content(index)
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
app/src/main/java/dev/pyrossh/onlyBible/PreferencesManager.kt ADDED
@@ -0,0 +1,44 @@
1
+ import android.content.Context
2
+ import android.content.SharedPreferences
3
+
4
+ enum class FontType {
5
+ Sans,
6
+ Serif,
7
+ Mono
8
+ }
9
+
10
+ class PreferencesManager(context: Context) {
11
+ private val sharedPreferences: SharedPreferences =
12
+ context.getSharedPreferences("settings", Context.MODE_PRIVATE)
13
+
14
+ fun getFontSize(): Int {
15
+ return sharedPreferences.getInt("fontSizeDelta", 0)
16
+ }
17
+
18
+ fun setFontSize(v: Int) {
19
+ val editor = sharedPreferences.edit()
20
+ editor.putInt("fontSizeDelta", v)
21
+ editor.apply()
22
+ }
23
+
24
+ fun getBold(): Boolean {
25
+ return sharedPreferences.getBoolean("bold", false)
26
+ }
27
+
28
+ fun setBold(v: Boolean) {
29
+ val editor = sharedPreferences.edit()
30
+ editor.putBoolean("bold", v)
31
+ editor.apply()
32
+ }
33
+
34
+ fun getFontType(): FontType {
35
+ val ft = sharedPreferences.getString("fontType", FontType.Sans.name) ?: FontType.Sans.name
36
+ return FontType.valueOf(ft)
37
+ }
38
+
39
+ fun setFontType(v: FontType) {
40
+ val editor = sharedPreferences.edit()
41
+ editor.putString("fontType", v.name)
42
+ editor.apply()
43
+ }
44
+ }
app/src/main/java/dev/pyrossh/onlyBible/Utils.kt CHANGED
@@ -9,7 +9,6 @@ import kotlinx.coroutines.delay
9
9
  import kotlinx.coroutines.withContext
10
10
  import java.util.concurrent.Future
11
11
 
12
-
13
12
  val speechService = SpeechSynthesizer(
14
13
  SpeechConfig.fromSubscription(
15
14
  BuildConfig.subscriptionKey,
app/src/main/java/dev/pyrossh/onlyBible/ui/theme/Font.kt CHANGED
@@ -9,8 +9,6 @@ val provider = GoogleFont.Provider(
9
9
  certificates = R.array.com_google_android_gms_fonts_certs
10
10
  )
11
11
 
12
- val fontName = GoogleFont("Roboto")
13
-
14
- val fontFamily = FontFamily(
12
+ val RobotoFamily = FontFamily(
15
- Font(googleFont = fontName, fontProvider = provider)
13
+ Font(googleFont = GoogleFont("Roboto"), fontProvider = provider)
16
14
  )
app/src/main/res/drawable/cross_2.xml ADDED
@@ -0,0 +1,34 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
2
+ android:viewportWidth="108"
3
+ android:viewportHeight="108"
4
+ android:width="108dp"
5
+ android:height="108dp">
6
+ <group
7
+ android:scaleX="2.45144"
8
+ android:scaleY="1.819395"
9
+ android:translateX="-86.61852"
10
+ android:translateY="-54.24037">
11
+ <group
12
+ android:scaleX="0.2188043"
13
+ android:scaleY="0.1900782"
14
+ android:translateX="1.347705"
15
+ android:translateY="10.8325">
16
+ <path
17
+ android:pathData="M279.273 412.444L279.273 203.421 341.333 203.421 341.333 156.875 279.273 156.875 279.273 99.556 232.727 99.556 232.727 156.875 170.667 156.875 170.667 203.421 232.727 203.421 232.727 412.444Z"
18
+ android:fillColor="#FFD15D"
19
+ android:strokeColor="#000000"
20
+ android:strokeWidth="1" />
21
+ </group>
22
+ <group
23
+ android:scaleX="0.2188043"
24
+ android:scaleY="0.1900782"
25
+ android:translateX="1.347705"
26
+ android:translateY="10.8325">
27
+ <path
28
+ android:pathData="M279.273 99.556L256 99.556 256 412.444 279.273 412.444 279.273 203.421 341.333 203.421 341.333 156.875 279.273 156.875Z"
29
+ android:fillColor="#F9B54C"
30
+ android:strokeColor="#000000"
31
+ android:strokeWidth="1" />
32
+ </group>
33
+ </group>
34
+ </vector>
app/src/main/res/drawable/ic_launcher_background.xml CHANGED
@@ -5,6 +5,6 @@
5
5
  android:viewportWidth="108"
6
6
  android:viewportHeight="108">
7
7
  <path
8
- android:fillColor="#AA504B"
8
+ android:fillColor="#292928"
9
9
  android:pathData="M0,0h108v108h-108z" />
10
10
  </vector>
app/src/main/res/drawable/ic_launcher_foreground.xml CHANGED
@@ -1,17 +1,34 @@
1
1
  <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
- xmlns:aapt="http://schemas.android.com/aapt"
3
2
  android:width="108dp"
4
3
  android:height="108dp"
5
4
  android:viewportWidth="108"
6
5
  android:viewportHeight="108">
6
+ <group
7
- <group android:scaleX="0.8"
7
+ android:scaleX="2.05144"
8
- android:scaleY="0.8"
8
+ android:scaleY="1.219395"
9
- android:translateX="36"
9
+ android:translateX="-65.61852"
10
- android:translateY="24">
10
+ android:translateY="-20">
11
+ <group
12
+ android:scaleX="0.2188043"
13
+ android:scaleY="0.1900782"
14
+ android:translateX="1.347705"
15
+ android:translateY="10.8325">
11
16
  <path
12
- android:pathData="M42.82,15.776L29.298,15.776L29.298,2.254C29.298,1.009 28.289,0 27.044,0L18.03,0C16.785,0 15.776,1.009 15.776,2.254L15.776,15.776L2.254,15.776C1.009,15.776 0,16.785 0,18.03L0,27.044C0,28.289 1.009,29.298 2.254,29.298L15.776,29.298L15.776,69.865C15.776,71.109 16.785,72.118 18.03,72.118L27.044,72.118C28.289,72.118 29.298,71.109 29.298,69.865L29.298,29.298L42.82,29.298C44.065,29.298 45.074,28.289 45.074,27.044L45.074,18.03C45.074,16.785 44.065,15.776 42.82,15.776Z"
13
- android:fillColor="#FFB441"
14
- android:fillType="nonZero"
15
- android:strokeColor="#00000000"/>
17
+ android:fillColor="#FFD15D"
18
+ android:pathData="M279.273 412.444L279.273 203.421 341.333 203.421 341.333 156.875 279.273 156.875 279.273 99.556 232.727 99.556 232.727 156.875 170.667 156.875 170.667 203.421 232.727 203.421 232.727 412.444Z"
19
+ android:strokeWidth="1"
20
+ android:strokeColor="#000000" />
21
+ </group>
22
+ <group
23
+ android:scaleX="0.2188043"
24
+ android:scaleY="0.1900782"
25
+ android:translateX="1.347705"
26
+ android:translateY="10.8325">
27
+ <path
28
+ android:fillColor="#F9B54C"
29
+ android:pathData="M279.273 99.556L256 99.556 256 412.444 279.273 412.444 279.273 203.421 341.333 203.421 341.333 156.875 279.273 156.875Z"
30
+ android:strokeWidth="1"
31
+ android:strokeColor="#000000" />
32
+ </group>
16
33
  </group>
17
34
  </vector>
app/src/main/res/drawable/text_theme.xml ADDED
@@ -0,0 +1,29 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="43dp"
3
+ android:height="56dp"
4
+ android:viewportWidth="43"
5
+ android:viewportHeight="56">
6
+ <path
7
+ android:pathData="M22,12L40,12"
8
+ android:strokeWidth="1.25"
9
+ android:fillColor="#00000000"
10
+ android:strokeColor="#5E6266"/>
11
+ <path
12
+ android:pathData="M3,24H40"
13
+ android:strokeWidth="1.25"
14
+ android:fillColor="#00000000"
15
+ android:strokeColor="#5E6266"/>
16
+ <path
17
+ android:pathData="M3,36H40"
18
+ android:strokeWidth="1.25"
19
+ android:fillColor="#00000000"
20
+ android:strokeColor="#5E6266"/>
21
+ <path
22
+ android:pathData="M3,48H40"
23
+ android:strokeWidth="1.25"
24
+ android:fillColor="#00000000"
25
+ android:strokeColor="#5E6266"/>
26
+ <path
27
+ android:pathData="M13.06,14.96H11V16H16.6V14.96H14.92L10.48,2.86H9.08L4.32,14.96H2.92V16H7.3V14.96H5.54L6.92,11.3H11.76L13.06,14.96ZM9.4,4.82H9.46L11.42,10.36H7.28L9.4,4.82Z"
28
+ android:fillColor="#5E6266"/>
29
+ </vector>
gradle/libs.versions.toml CHANGED
@@ -1,7 +1,8 @@
1
1
  [versions]
2
2
  accompanistSystemuicontroller = "0.27.0"
3
- agp = "8.4.1"
3
+ agp = "8.4.2"
4
4
  clientSdk = "1.34.0"
5
+ datastorePreferences = "1.1.1"
5
6
  foundation = "1.6.7"
6
7
  kotlin = "2.0.0"
7
8
  kotlinxCoroutinesCore = "1.9.0-RC"
@@ -13,6 +14,7 @@ espressoCore = "3.5.1"
13
14
  lifecycleRuntimeKtx = "2.8.1"
14
15
  activityCompose = "1.9.0"
15
16
  composeBom = "2024.05.00"
17
+ materialIconsExtended = "1.6.8"
16
18
  navigationFragmentKtx = "2.7.7"
17
19
  secretsGradlePlugin = "2.0.1"
18
20
  uiTextGoogleFonts = "1.6.7"
@@ -21,7 +23,9 @@ uiUtilAndroid = "1.6.7"
21
23
  [libraries]
22
24
  accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanistSystemuicontroller" }
23
25
  androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
26
+ androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
24
27
  androidx-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "foundation" }
28
+ androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "materialIconsExtended" }
25
29
  androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationFragmentKtx" }
26
30
  androidx-navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigationFragmentKtx" }
27
31
  androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigationFragmentKtx" }