~repos /only-bible-app
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.
89a99c6d
—
pyrossh 2 years ago
Fix various issues
- lib/l10n/app_en.arb +1 -0
- lib/l10n/app_kn.arb +1 -0
- lib/models.dart +1 -4
- lib/providers/app_model.dart +158 -58
- lib/providers/chapter_view_model.dart +2 -122
- lib/screens/chapter_select_screen.dart +1 -11
- lib/screens/chapter_view_screen.dart +0 -1
- lib/theme.dart +2 -2
- lib/utils.dart +14 -0
- lib/widgets/actions_sheet.dart +28 -57
- lib/widgets/highlight_button.dart +1 -1
- lib/widgets/highlight_sheet.dart +49 -0
- lib/widgets/note_sheet.dart +7 -2
- lib/widgets/settings_sheet.dart +32 -40
- lib/widgets/verses_view.dart +3 -3
lib/l10n/app_en.arb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"hasAudio": "false",
|
|
2
3
|
"languageTitle": "English",
|
|
3
4
|
"localeLanguageTitle": "English",
|
|
4
5
|
"oldTestamentTitle": "Old Testament",
|
lib/l10n/app_kn.arb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"hasAudio": "true",
|
|
2
3
|
"languageTitle": "Kannada",
|
|
3
4
|
"localeLanguageTitle": "ಕನ್ನಡ",
|
|
4
5
|
"oldTestamentTitle": "ಹಳೆಯ ಒಡಂಬಡಿಕೆ",
|
lib/models.dart
CHANGED
|
@@ -3,17 +3,14 @@ import "package:only_bible_app/providers/app_model.dart";
|
|
|
3
3
|
|
|
4
4
|
class Bible {
|
|
5
5
|
final String name;
|
|
6
|
-
final bool hasAudio;
|
|
7
6
|
List<Book> books = [];
|
|
8
7
|
|
|
9
8
|
Bible({
|
|
10
9
|
required this.name,
|
|
11
|
-
required this.hasAudio,
|
|
12
10
|
});
|
|
13
11
|
|
|
14
12
|
Bible.withBooks({
|
|
15
13
|
required this.name,
|
|
16
|
-
required this.hasAudio,
|
|
17
14
|
required this.books,
|
|
18
15
|
});
|
|
19
16
|
|
|
@@ -50,7 +47,7 @@ class Book {
|
|
|
50
47
|
String shortName(BuildContext context) {
|
|
51
48
|
final name = this.name(context);
|
|
52
49
|
if (name[0] == "1" || name[0] == "2" || name[0] == "3") {
|
|
53
|
-
return "${name[0]}${name[2].toUpperCase()}${name.substring(3,
|
|
50
|
+
return "${name[0]}${name[2].toUpperCase()}${name.substring(3, 4).toLowerCase()}";
|
|
54
51
|
}
|
|
55
52
|
return "${name[0].toUpperCase()}${name.substring(1, 3).toLowerCase()}";
|
|
56
53
|
}
|
lib/providers/app_model.dart
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
// import "package:firebase_performance/firebase_performance.dart";
|
|
2
|
+
import "dart:developer";
|
|
3
|
+
import "package:firebase_crashlytics/firebase_crashlytics.dart";
|
|
4
|
+
import "package:firebase_storage/firebase_storage.dart";
|
|
5
|
+
import "package:just_audio/just_audio.dart";
|
|
6
|
+
import "package:only_bible_app/dialog.dart";
|
|
7
|
+
import "package:only_bible_app/screens/chapter_view_screen.dart";
|
|
8
|
+
import "package:share_plus/share_plus.dart";
|
|
2
9
|
import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
|
3
|
-
import "package:flutter/services.dart";
|
|
4
10
|
import "package:flutter/material.dart";
|
|
11
|
+
import "package:flutter/services.dart";
|
|
5
12
|
import "package:only_bible_app/screens/bible_select_screen.dart";
|
|
6
13
|
import "package:only_bible_app/screens/book_select_screen.dart";
|
|
7
14
|
import "package:only_bible_app/models.dart";
|
|
8
15
|
import "package:only_bible_app/widgets/actions_sheet.dart";
|
|
9
|
-
import "package:only_bible_app/widgets/
|
|
16
|
+
import "package:only_bible_app/widgets/highlight_sheet.dart";
|
|
10
17
|
import "package:only_bible_app/widgets/scaffold_markdown.dart";
|
|
11
18
|
import "package:only_bible_app/widgets/note_sheet.dart";
|
|
12
19
|
import "package:only_bible_app/widgets/settings_sheet.dart";
|
|
13
20
|
import "package:package_info_plus/package_info_plus.dart";
|
|
14
21
|
import "package:provider/provider.dart";
|
|
15
|
-
import "package:share_plus/share_plus.dart";
|
|
16
22
|
import "package:shared_preferences/shared_preferences.dart";
|
|
17
23
|
import "package:get_storage/get_storage.dart";
|
|
18
24
|
import "package:only_bible_app/utils.dart";
|
|
@@ -34,7 +40,10 @@ class AppModel extends ChangeNotifier {
|
|
|
34
40
|
bool fontBold = false;
|
|
35
41
|
double textScaleFactor = 0;
|
|
36
42
|
bool actionsShown = false;
|
|
37
|
-
bool
|
|
43
|
+
bool highlightsShown = false;
|
|
44
|
+
final player = AudioPlayer();
|
|
45
|
+
bool isPlaying = false;
|
|
46
|
+
final List<Verse> selectedVerses = [];
|
|
38
47
|
final TextEditingController noteTextController = TextEditingController();
|
|
39
48
|
List<HistoryFrame> history = [];
|
|
40
49
|
final box = GetStorage("only-bible-app-backup");
|
|
@@ -87,7 +96,6 @@ class AppModel extends ChangeNotifier {
|
|
|
87
96
|
// }
|
|
88
97
|
return Bible.withBooks(
|
|
89
98
|
name: name,
|
|
90
|
-
hasAudio: true,
|
|
91
99
|
books: books,
|
|
92
100
|
);
|
|
93
101
|
}
|
|
@@ -164,6 +172,10 @@ class AppModel extends ChangeNotifier {
|
|
|
164
172
|
];
|
|
165
173
|
}
|
|
166
174
|
|
|
175
|
+
hasAudio(BuildContext context) {
|
|
176
|
+
return context.l10n.hasAudio == "true";
|
|
177
|
+
}
|
|
178
|
+
|
|
167
179
|
changeBible(BuildContext context) {
|
|
168
180
|
Navigator.of(context).pushReplacement(
|
|
169
181
|
createNoTransitionPageRoute(
|
|
@@ -197,6 +209,36 @@ class AppModel extends ChangeNotifier {
|
|
|
197
209
|
);
|
|
198
210
|
}
|
|
199
211
|
|
|
212
|
+
clearEvents(
|
|
213
|
+
BuildContext context,
|
|
214
|
+
) {
|
|
215
|
+
if (isPlaying) {
|
|
216
|
+
pause();
|
|
217
|
+
}
|
|
218
|
+
clearSelections();
|
|
219
|
+
hideActions(context);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
pushBookChapter(BuildContext context, int book, int chapter, TextDirection? dir) {
|
|
223
|
+
clearEvents(context);
|
|
224
|
+
Navigator.of(context).push(
|
|
225
|
+
createSlideRoute(
|
|
226
|
+
context: context,
|
|
227
|
+
slideDir: dir,
|
|
228
|
+
page: ChapterViewScreen(book: book, chapter: chapter),
|
|
229
|
+
),
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
replaceBookChapter(BuildContext context, int book, int chapter) {
|
|
234
|
+
clearEvents(context);
|
|
235
|
+
Navigator.of(context).pushReplacement(
|
|
236
|
+
createNoTransitionPageRoute(
|
|
237
|
+
ChapterViewScreen(book: book, chapter: chapter),
|
|
238
|
+
),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
200
242
|
toggleDarkMode() {
|
|
201
243
|
darkMode = !darkMode;
|
|
202
244
|
updateStatusBar();
|
|
@@ -286,6 +328,24 @@ class AppModel extends ChangeNotifier {
|
|
|
286
328
|
}
|
|
287
329
|
}
|
|
288
330
|
|
|
331
|
+
showHighlights(BuildContext context) {
|
|
332
|
+
highlightsShown = true;
|
|
333
|
+
Scaffold.of(context).showBottomSheet(
|
|
334
|
+
enableDrag: false,
|
|
335
|
+
clipBehavior: Clip.antiAliasWithSaveLayer,
|
|
336
|
+
(context) => const HighlightSheet(),
|
|
337
|
+
);
|
|
338
|
+
notifyListeners();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
hideHighlights(BuildContext context) {
|
|
342
|
+
if (highlightsShown) {
|
|
343
|
+
highlightsShown = false;
|
|
344
|
+
Navigator.of(context).pop();
|
|
345
|
+
notifyListeners();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
289
349
|
bool hasNote(Verse v) {
|
|
290
350
|
return box.hasData("${v.book}:${v.chapter}:${v.index}:note");
|
|
291
351
|
}
|
|
@@ -308,11 +368,10 @@ class AppModel extends ChangeNotifier {
|
|
|
308
368
|
final note = noteTextController.text;
|
|
309
369
|
box.write("${v.book}:${v.chapter}:${v.index}:note", note);
|
|
310
370
|
box.save();
|
|
311
|
-
// Close the bottom sheet
|
|
312
|
-
// if (!mounted) return;
|
|
313
|
-
// Navigator.of(context).pop();
|
|
314
|
-
notifyListeners();
|
|
315
371
|
hideNoteField(context);
|
|
372
|
+
clearSelections();
|
|
373
|
+
hideActions(context);
|
|
374
|
+
notifyListeners();
|
|
316
375
|
}
|
|
317
376
|
|
|
318
377
|
deleteNote(BuildContext context, Verse v) {
|
|
@@ -359,55 +418,6 @@ class AppModel extends ChangeNotifier {
|
|
|
359
418
|
box.save();
|
|
360
419
|
}
|
|
361
420
|
|
|
362
|
-
void showHighlightMenu(BuildContext context, List<Verse> verses, Offset position) {
|
|
363
|
-
hideHighlightMenu(context);
|
|
364
|
-
highlightMenuShown = true;
|
|
365
|
-
final overlay = Overlay.of(context).context.findRenderObject();
|
|
366
|
-
onTap(c) => setHighlight(context, verses, c);
|
|
367
|
-
|
|
368
|
-
showMenu(
|
|
369
|
-
context: context,
|
|
370
|
-
position: RelativeRect.fromRect(
|
|
371
|
-
Rect.fromLTWH(position.dx, position.dy + 30, 100, 100),
|
|
372
|
-
Rect.fromLTWH(0, 0, overlay!.paintBounds.size.width, overlay.paintBounds.size.height),
|
|
373
|
-
),
|
|
374
|
-
items: [
|
|
375
|
-
PopupMenuItem(
|
|
376
|
-
child: Row(
|
|
377
|
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
378
|
-
children: [
|
|
379
|
-
HighlightButton(
|
|
380
|
-
color: const Color(0xFFDAEFFE),
|
|
381
|
-
onColorSelected: onTap,
|
|
382
|
-
),
|
|
383
|
-
HighlightButton(
|
|
384
|
-
color: const Color(0xFFFFFBB1),
|
|
385
|
-
onColorSelected: onTap,
|
|
386
|
-
),
|
|
387
|
-
HighlightButton(
|
|
388
|
-
color: const Color(0xFFFFDEF3),
|
|
389
|
-
onColorSelected: onTap,
|
|
390
|
-
),
|
|
391
|
-
HighlightButton(
|
|
392
|
-
color: const Color(0xFFE6FCC3),
|
|
393
|
-
onColorSelected: onTap,
|
|
394
|
-
),
|
|
395
|
-
HighlightButton(
|
|
396
|
-
color: const Color(0xFFEADDFF),
|
|
397
|
-
onColorSelected: onTap,
|
|
398
|
-
),
|
|
399
|
-
],
|
|
400
|
-
),
|
|
401
|
-
),
|
|
402
|
-
]);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
void hideHighlightMenu(BuildContext context) {
|
|
406
|
-
if (highlightMenuShown) {
|
|
407
|
-
Navigator.of(context).pop();
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
421
|
void shareAppLink(BuildContext context) {
|
|
412
422
|
if (isAndroid()) {
|
|
413
423
|
Share.share(
|
|
@@ -450,4 +460,94 @@ class AppModel extends ChangeNotifier {
|
|
|
450
460
|
),
|
|
451
461
|
);
|
|
452
462
|
}
|
|
463
|
+
|
|
464
|
+
bool hasSelectedVerses() {
|
|
465
|
+
return selectedVerses.isNotEmpty;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
void clearSelections() {
|
|
469
|
+
selectedVerses.clear();
|
|
470
|
+
notifyListeners();
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
void removeSelectedHighlights(BuildContext context) {
|
|
474
|
+
AppModel.ofEvent(context).removeHighlight(context, selectedVerses);
|
|
475
|
+
selectedVerses.clear();
|
|
476
|
+
AppModel.ofEvent(context).hideActions(context);
|
|
477
|
+
notifyListeners();
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
void closeActions(BuildContext context) {
|
|
481
|
+
selectedVerses.clear();
|
|
482
|
+
AppModel.ofEvent(context).hideActions(context);
|
|
483
|
+
notifyListeners();
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
bool isVerseSelected(Verse v) {
|
|
487
|
+
return selectedVerses.any((el) => el.index == v.index);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
bool isVerseHighlighted(BuildContext context) {
|
|
491
|
+
// box.read("${book}:${chapter}:${verse}", "color");
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
void onVerseSelected(BuildContext context, Verse v) {
|
|
496
|
+
if (selectedVerses.isEmpty) {
|
|
497
|
+
AppModel.ofEvent(context).showActions(context);
|
|
498
|
+
}
|
|
499
|
+
if (isVerseSelected(v)) {
|
|
500
|
+
selectedVerses.removeWhere((it) => it.index == v.index);
|
|
501
|
+
} else {
|
|
502
|
+
selectedVerses.add(v);
|
|
503
|
+
}
|
|
504
|
+
if (selectedVerses.isEmpty) {
|
|
505
|
+
AppModel.ofEvent(context).hideActions(context);
|
|
506
|
+
}
|
|
507
|
+
notifyListeners();
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
void shareVerses(BuildContext context) {
|
|
511
|
+
final name = bible.books[selectedVerses.first.book].name;
|
|
512
|
+
final chapter = selectedVerses.first.chapter + 1;
|
|
513
|
+
final title = "$name $chapter: ${selectedVerses.map((e) => e.index + 1).join(", ")}";
|
|
514
|
+
final text = selectedVerses.map((e) => e.text).join("\n");
|
|
515
|
+
Share.share("$title\n$text", subject: title);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
pause() async {
|
|
519
|
+
await player.pause();
|
|
520
|
+
isPlaying = false;
|
|
521
|
+
notifyListeners();
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
onPlay(BuildContext context) async {
|
|
525
|
+
if (isPlaying) {
|
|
526
|
+
pause();
|
|
527
|
+
} else {
|
|
528
|
+
isPlaying = true;
|
|
529
|
+
notifyListeners();
|
|
530
|
+
// add locks todo
|
|
531
|
+
for (final v in selectedVerses) {
|
|
532
|
+
final bibleName = bible.name;
|
|
533
|
+
final book = (v.book + 1).toString().padLeft(2, "0");
|
|
534
|
+
final chapter = (v.chapter + 1).toString().padLeft(3, "0");
|
|
535
|
+
final verseNo = (v.index + 1).toString().padLeft(3, "0");
|
|
536
|
+
final pathname = "$bibleName/$book-$chapter-$verseNo.mp3";
|
|
537
|
+
try {
|
|
538
|
+
final url = await FirebaseStorage.instance.ref(pathname).getDownloadURL();
|
|
539
|
+
await player.setUrl(url);
|
|
540
|
+
await player.play();
|
|
541
|
+
await player.stop();
|
|
542
|
+
} catch (err) {
|
|
543
|
+
log("Could not play audio", name: "play", error: (err.toString(), pathname));
|
|
544
|
+
FirebaseCrashlytics.instance.recordFlutterError(FlutterErrorDetails(exception: (err.toString(), pathname)));
|
|
545
|
+
showError(context, "Could not play audio");
|
|
546
|
+
return;
|
|
547
|
+
} finally {
|
|
548
|
+
pause();
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
453
553
|
}
|
lib/providers/chapter_view_model.dart
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import "dart:developer";
|
|
2
|
-
import "package:firebase_crashlytics/firebase_crashlytics.dart";
|
|
3
|
-
import "package:firebase_storage/firebase_storage.dart";
|
|
4
|
-
import "package:flutter/services.dart";
|
|
5
1
|
import "package:flutter/material.dart";
|
|
6
|
-
import "package:just_audio/just_audio.dart";
|
|
7
2
|
import "package:only_bible_app/screens/chapter_view_screen.dart";
|
|
8
|
-
import "package:only_bible_app/dialog.dart";
|
|
9
3
|
import "package:only_bible_app/models.dart";
|
|
10
4
|
import "package:provider/provider.dart";
|
|
11
|
-
import "package:share_plus/share_plus.dart";
|
|
12
5
|
import "package:shared_preferences/shared_preferences.dart";
|
|
13
6
|
import "package:only_bible_app/utils.dart";
|
|
14
7
|
import "package:only_bible_app/providers/app_model.dart";
|
|
@@ -16,9 +9,6 @@ import "package:only_bible_app/providers/app_model.dart";
|
|
|
16
9
|
class ChapterViewModel extends ChangeNotifier {
|
|
17
10
|
final int book;
|
|
18
11
|
final int chapter;
|
|
19
|
-
final List<Verse> selectedVerses;
|
|
20
|
-
final player = AudioPlayer();
|
|
21
|
-
bool isPlaying = false;
|
|
22
12
|
|
|
23
13
|
static ChapterViewModel of(BuildContext context) {
|
|
24
14
|
return Provider.of(context, listen: true);
|
|
@@ -38,7 +28,7 @@ class ChapterViewModel extends ChangeNotifier {
|
|
|
38
28
|
return AppModel.of(context).bible.books[model.book].chapters[model.chapter];
|
|
39
29
|
}
|
|
40
30
|
|
|
41
|
-
ChapterViewModel({required this.book, required this.chapter
|
|
31
|
+
ChapterViewModel({required this.book, required this.chapter}) {
|
|
42
32
|
save(book, chapter);
|
|
43
33
|
}
|
|
44
34
|
|
|
@@ -49,17 +39,7 @@ class ChapterViewModel extends ChangeNotifier {
|
|
|
49
39
|
}
|
|
50
40
|
|
|
51
41
|
navigateBookChapter(BuildContext context, int book, int chapter, TextDirection? dir) {
|
|
52
|
-
if (isPlaying) {
|
|
53
|
-
pause();
|
|
54
|
-
}
|
|
55
|
-
AppModel.ofEvent(context).hideActions(context);
|
|
56
|
-
Navigator.of(context).push(
|
|
57
|
-
createSlideRoute(
|
|
58
|
-
context: context,
|
|
59
|
-
slideDir: dir,
|
|
60
|
-
|
|
42
|
+
context.appEvent.pushBookChapter(context, book, chapter, dir);
|
|
61
|
-
),
|
|
62
|
-
);
|
|
63
43
|
}
|
|
64
44
|
|
|
65
45
|
onNext(BuildContext context, int book, int chapter) {
|
|
@@ -91,104 +71,4 @@ class ChapterViewModel extends ChangeNotifier {
|
|
|
91
71
|
}
|
|
92
72
|
}
|
|
93
73
|
}
|
|
94
|
-
|
|
95
|
-
bool hasSelectedVerses() {
|
|
96
|
-
return selectedVerses.isNotEmpty;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
void clearSelections(BuildContext context) {
|
|
100
|
-
AppModel.ofEvent(context).removeHighlight(context, selectedVerses);
|
|
101
|
-
selectedVerses.clear();
|
|
102
|
-
AppModel.ofEvent(context).hideActions(context);
|
|
103
|
-
notifyListeners();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
void closeActions(BuildContext context) {
|
|
107
|
-
selectedVerses.clear();
|
|
108
|
-
AppModel.ofEvent(context).hideActions(context);
|
|
109
|
-
notifyListeners();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
bool isVerseSelected(Verse v) {
|
|
113
|
-
return selectedVerses.any((el) => el.index == v.index);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
bool isVerseHighlighted(BuildContext context) {
|
|
117
|
-
// box.read("${book}:${chapter}:${verse}", "color");
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
void onVerseSelected(BuildContext context, Verse v) {
|
|
122
|
-
if (selectedVerses.isEmpty) {
|
|
123
|
-
AppModel.ofEvent(context).showActions(context);
|
|
124
|
-
}
|
|
125
|
-
if (isVerseSelected(v)) {
|
|
126
|
-
selectedVerses.removeWhere((it) => it.index == v.index);
|
|
127
|
-
} else {
|
|
128
|
-
selectedVerses.add(v);
|
|
129
|
-
}
|
|
130
|
-
if (selectedVerses.isEmpty) {
|
|
131
|
-
AppModel.ofEvent(context).hideActions(context);
|
|
132
|
-
}
|
|
133
|
-
notifyListeners();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
void copyVerses() {
|
|
137
|
-
final text = selectedVerses.map((e) => e.text).join("\n");
|
|
138
|
-
Clipboard.setData(ClipboardData(text: text));
|
|
139
|
-
// maybe close the action menu or show a snackbar on iOS (android already does this)
|
|
140
|
-
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Copied to clipboard")));
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
void shareVerses(BuildContext context) {
|
|
144
|
-
final bible = AppModel.ofEvent(context).bible;
|
|
145
|
-
final name = bible.books[selectedVerses.first.book].name;
|
|
146
|
-
final chapter = selectedVerses.first.chapter + 1;
|
|
147
|
-
final title = "$name $chapter: ${selectedVerses.map((e) => e.index + 1).join(", ")}";
|
|
148
|
-
final text = selectedVerses.map((e) => e.text).join("\n");
|
|
149
|
-
Share.share("$title\n$text", subject: title);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
pause() async {
|
|
153
|
-
await player.pause();
|
|
154
|
-
isPlaying = false;
|
|
155
|
-
notifyListeners();
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
onPlay(BuildContext context) async {
|
|
159
|
-
final bible = AppModel.ofEvent(context).bible;
|
|
160
|
-
if (!bible.hasAudio) {
|
|
161
|
-
showError(
|
|
162
|
-
context,
|
|
163
|
-
"This Bible doesn't support audio. Currently audio is only available for the Kannada Bible.",
|
|
164
|
-
);
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
if (isPlaying) {
|
|
168
|
-
pause();
|
|
169
|
-
} else {
|
|
170
|
-
isPlaying = true;
|
|
171
|
-
notifyListeners();
|
|
172
|
-
for (final v in selectedVerses) {
|
|
173
|
-
final bibleName = bible.name;
|
|
174
|
-
final book = (v.book + 1).toString().padLeft(2, "0");
|
|
175
|
-
final chapter = (v.chapter + 1).toString().padLeft(3, "0");
|
|
176
|
-
final verseNo = (v.index + 1).toString().padLeft(3, "0");
|
|
177
|
-
final pathname = "$bibleName/$book-$chapter-$verseNo.mp3";
|
|
178
|
-
try {
|
|
179
|
-
final url = await FirebaseStorage.instance.ref(pathname).getDownloadURL();
|
|
180
|
-
await player.setUrl(url);
|
|
181
|
-
await player.play();
|
|
182
|
-
await player.stop();
|
|
183
|
-
} catch (err) {
|
|
184
|
-
log("Could not play audio", name: "play", error: (err.toString(), pathname));
|
|
185
|
-
FirebaseCrashlytics.instance.recordFlutterError(FlutterErrorDetails(exception: (err.toString(), pathname)));
|
|
186
|
-
showError(context, "Could not play audio");
|
|
187
|
-
return;
|
|
188
|
-
} finally {
|
|
189
|
-
pause();
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
74
|
}
|
lib/screens/chapter_select_screen.dart
CHANGED
|
@@ -4,7 +4,6 @@ import "package:only_bible_app/utils.dart";
|
|
|
4
4
|
import "package:only_bible_app/widgets/scaffold_menu.dart";
|
|
5
5
|
import "package:only_bible_app/widgets/sliver_tile_grid.dart";
|
|
6
6
|
import "package:only_bible_app/widgets/sliver_heading.dart";
|
|
7
|
-
import "package:only_bible_app/screens/chapter_view_screen.dart";
|
|
8
7
|
|
|
9
8
|
class ChapterSelectScreen extends StatelessWidget {
|
|
10
9
|
final Book book;
|
|
@@ -12,15 +11,6 @@ class ChapterSelectScreen extends StatelessWidget {
|
|
|
12
11
|
|
|
13
12
|
const ChapterSelectScreen({super.key, required this.selectedBookIndex, required this.book});
|
|
14
13
|
|
|
15
|
-
// TODO: move this to app and allow to pause
|
|
16
|
-
onChapterSelected(BuildContext context, int index) {
|
|
17
|
-
Navigator.of(context).pushReplacement(
|
|
18
|
-
createNoTransitionPageRoute(
|
|
19
|
-
ChapterViewScreen(book: selectedBookIndex, chapter: index),
|
|
20
|
-
),
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
14
|
@override
|
|
25
15
|
Widget build(BuildContext context) {
|
|
26
16
|
return ScaffoldMenu(
|
|
@@ -32,7 +22,7 @@ class ChapterSelectScreen extends StatelessWidget {
|
|
|
32
22
|
children: List.generate(book.chapters.length, (index) {
|
|
33
23
|
return TextButton(
|
|
34
24
|
child: Text("${index + 1}"),
|
|
35
|
-
onPressed: () =>
|
|
25
|
+
onPressed: () => context.appEvent.replaceBookChapter(context, selectedBookIndex, index),
|
|
36
26
|
);
|
|
37
27
|
}),
|
|
38
28
|
),
|
lib/screens/chapter_view_screen.dart
CHANGED
|
@@ -36,7 +36,6 @@ class ChapterViewScreen extends StatelessWidget {
|
|
|
36
36
|
create: (_) => ChapterViewModel(
|
|
37
37
|
book: book,
|
|
38
38
|
chapter: chapter,
|
|
39
|
-
selectedVerses: [],
|
|
40
39
|
),
|
|
41
40
|
child: Scaffold(
|
|
42
41
|
appBar: isDesktop ? null : const ChapterAppBar(),
|
lib/theme.dart
CHANGED
|
@@ -42,8 +42,8 @@ final lightTheme = ThemeData(
|
|
|
42
42
|
// selectionColor: const Color(0xAAF8D0DC),
|
|
43
43
|
// ),
|
|
44
44
|
inputDecorationTheme: const InputDecorationTheme(
|
|
45
|
-
focusColor: Colors.
|
|
45
|
+
focusColor: Colors.transparent,
|
|
46
|
-
hoverColor: Colors.
|
|
46
|
+
hoverColor: Colors.transparent,
|
|
47
47
|
activeIndicatorBorder: BorderSide(
|
|
48
48
|
color: Colors.black,
|
|
49
49
|
),
|
lib/utils.dart
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
import "dart:convert";
|
|
2
2
|
import "package:only_bible_app/dialog.dart";
|
|
3
|
+
import "package:only_bible_app/providers/app_model.dart";
|
|
4
|
+
import "package:only_bible_app/providers/chapter_view_model.dart";
|
|
3
5
|
import "package:url_launcher/url_launcher.dart";
|
|
4
6
|
import "package:flutter/foundation.dart" show defaultTargetPlatform, TargetPlatform;
|
|
5
7
|
import "package:flutter/material.dart";
|
|
6
8
|
import "package:flutter/services.dart";
|
|
7
9
|
import "package:only_bible_app/models.dart";
|
|
10
|
+
import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
|
11
|
+
import "package:provider/provider.dart";
|
|
8
12
|
|
|
9
13
|
extension MyIterable<E> on Iterable<E> {
|
|
10
14
|
Iterable<E> sortedBy(Comparable Function(E e) key) =>
|
|
11
15
|
toList()..sort((a, b) => key(a).compareTo(key(b)));
|
|
12
16
|
}
|
|
13
17
|
|
|
18
|
+
extension AppContext on BuildContext {
|
|
19
|
+
ThemeData get theme => Theme.of(this);
|
|
20
|
+
AppLocalizations get l10n => app.engTitles ? lookupAppLocalizations(const Locale("en")) : AppLocalizations.of(this)!;
|
|
21
|
+
AppModel get app => Provider.of(this, listen: true);
|
|
22
|
+
AppModel get appEvent => Provider.of(this, listen: false);
|
|
23
|
+
ChapterViewModel get chapter => Provider.of(this, listen: true);
|
|
24
|
+
ChapterViewModel get chapterEvent => Provider.of(this, listen: false);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
14
28
|
bool isDesktop() {
|
|
15
29
|
return defaultTargetPlatform == TargetPlatform.macOS ||
|
|
16
30
|
defaultTargetPlatform == TargetPlatform.windows ||
|
lib/widgets/actions_sheet.dart
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
+
import "package:only_bible_app/dialog.dart";
|
|
2
3
|
import "package:only_bible_app/providers/app_model.dart";
|
|
3
|
-
import "package:only_bible_app/providers/chapter_view_model.dart";
|
|
4
4
|
import "package:only_bible_app/utils.dart";
|
|
5
|
-
import "package:only_bible_app/widgets/highlight_button.dart";
|
|
6
5
|
import "package:only_bible_app/widgets/icon_button_text.dart";
|
|
7
6
|
|
|
8
7
|
class ActionsSheet extends StatelessWidget {
|
|
@@ -12,101 +11,73 @@ class ActionsSheet extends StatelessWidget {
|
|
|
12
11
|
Widget build(BuildContext context) {
|
|
13
12
|
final app = AppModel.of(context);
|
|
14
13
|
final isDesktop = isWide(context);
|
|
15
|
-
final
|
|
14
|
+
final height = isDesktop || isIOS() ? 92.0 : 70.0;
|
|
16
15
|
final iconColor = app.darkMode ? Colors.white.withOpacity(0.9) : Colors.black.withOpacity(0.9);
|
|
17
16
|
final bodySmall = Theme.of(context).textTheme.bodySmall;
|
|
18
|
-
final model = ChapterViewModel.of(context);
|
|
19
|
-
final audioIcon =
|
|
17
|
+
final audioIcon = app.isPlaying ? Icons.pause_circle_outline : Icons.play_circle_outline;
|
|
20
|
-
final audioText =
|
|
18
|
+
final audioText = app.isPlaying ? "Pause" : "Play";
|
|
21
|
-
final
|
|
19
|
+
final audioEnabled = app.hasAudio(context);
|
|
22
|
-
onHighlight(Color c) {
|
|
23
|
-
final verses = ChapterViewModel.ofEvent(context).selectedVerses;
|
|
24
|
-
app.setHighlight(context, verses, c);
|
|
25
|
-
model.closeActions(context);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
;
|
|
29
20
|
return Container(
|
|
30
|
-
height:
|
|
21
|
+
height: height,
|
|
31
|
-
? 150
|
|
32
|
-
: isDesktop
|
|
33
|
-
? 95
|
|
34
|
-
: isIOS()
|
|
35
|
-
? 100
|
|
36
|
-
: 70,
|
|
37
22
|
color: Theme.of(context).colorScheme.background,
|
|
38
23
|
padding: EdgeInsets.only(left: 20, right: 20, top: isDesktop ? 10 : 10, bottom: 20),
|
|
39
24
|
child: Column(
|
|
40
|
-
mainAxisAlignment:
|
|
25
|
+
mainAxisAlignment: MainAxisAlignment.start,
|
|
41
26
|
children: [
|
|
42
|
-
if (highlightRowEnabled)
|
|
43
|
-
Row(
|
|
44
|
-
mainAxisAlignment: MainAxisAlignment.end,
|
|
45
|
-
children: [
|
|
46
|
-
HighlightButton(
|
|
47
|
-
color: const Color(0xFFDAEFFE),
|
|
48
|
-
onColorSelected: onHighlight,
|
|
49
|
-
),
|
|
50
|
-
HighlightButton(
|
|
51
|
-
color: const Color(0xFFFFFBB1),
|
|
52
|
-
onColorSelected: onHighlight,
|
|
53
|
-
),
|
|
54
|
-
HighlightButton(
|
|
55
|
-
color: const Color(0xFFFFDEF3),
|
|
56
|
-
onColorSelected: onHighlight,
|
|
57
|
-
),
|
|
58
|
-
HighlightButton(
|
|
59
|
-
color: const Color(0xFFE6FCC3),
|
|
60
|
-
onColorSelected: onHighlight,
|
|
61
|
-
),
|
|
62
|
-
],
|
|
63
|
-
),
|
|
64
|
-
// const Padding(padding: EdgeInsets.only(top: 10)),
|
|
65
27
|
Row(
|
|
66
28
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
67
29
|
children: [
|
|
68
30
|
IconButtonText(
|
|
69
31
|
leading: IconButton(
|
|
70
32
|
padding: EdgeInsets.zero,
|
|
71
|
-
onPressed: () =>
|
|
33
|
+
onPressed: () => context.appEvent.removeSelectedHighlights(context),
|
|
72
|
-
icon: Icon(Icons.cancel_outlined, size:
|
|
34
|
+
icon: Icon(Icons.cancel_outlined, size: 28, color: iconColor),
|
|
73
35
|
),
|
|
74
36
|
trailing: Text("Clear", style: bodySmall),
|
|
75
37
|
),
|
|
76
38
|
IconButtonText(
|
|
77
39
|
leading: IconButton(
|
|
78
40
|
padding: EdgeInsets.zero,
|
|
79
|
-
onPressed:
|
|
41
|
+
onPressed: () => context.appEvent.showHighlights(context),
|
|
80
|
-
icon: Icon(Icons.
|
|
42
|
+
icon: Icon(Icons.border_color_outlined, size: 28, color: iconColor),
|
|
81
43
|
),
|
|
82
|
-
trailing: Text("
|
|
44
|
+
trailing: Text("Highlight", style: bodySmall),
|
|
83
45
|
),
|
|
84
46
|
IconButtonText(
|
|
85
47
|
leading: IconButton(
|
|
86
48
|
padding: EdgeInsets.zero,
|
|
49
|
+
onPressed: () {
|
|
50
|
+
if (audioEnabled) {
|
|
87
|
-
|
|
51
|
+
context.appEvent.onPlay(context);
|
|
52
|
+
} else {
|
|
53
|
+
showError(
|
|
54
|
+
context,
|
|
55
|
+
"This Bible doesn't support audio. Currently audio is only available for the Kannada Bible.",
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
88
|
-
icon: Icon(audioIcon, size: 34
|
|
59
|
+
icon: Icon(audioIcon, size: 34, color: audioEnabled ? iconColor : Colors.grey),
|
|
89
60
|
),
|
|
90
61
|
trailing: Text(
|
|
91
62
|
audioText,
|
|
92
63
|
style: bodySmall!.copyWith(
|
|
93
|
-
color:
|
|
64
|
+
color: audioEnabled ? bodySmall.color : Colors.grey,
|
|
94
65
|
),
|
|
95
66
|
),
|
|
96
67
|
),
|
|
97
68
|
IconButtonText(
|
|
98
69
|
leading: IconButton(
|
|
99
70
|
padding: EdgeInsets.zero,
|
|
100
|
-
onPressed: () =>
|
|
71
|
+
onPressed: () => context.appEvent.showNoteField(context, context.appEvent.selectedVerses.first),
|
|
101
|
-
icon: Icon(Icons.post_add_outlined, size:
|
|
72
|
+
icon: Icon(Icons.post_add_outlined, size: 34, color: iconColor),
|
|
102
73
|
),
|
|
103
74
|
trailing: Text("Note", style: bodySmall),
|
|
104
75
|
),
|
|
105
76
|
IconButtonText(
|
|
106
77
|
leading: IconButton(
|
|
107
78
|
padding: EdgeInsets.zero,
|
|
108
|
-
onPressed: () =>
|
|
79
|
+
onPressed: () => context.appEvent.shareVerses(context),
|
|
109
|
-
icon: Icon(Icons.share_outlined, size:
|
|
80
|
+
icon: Icon(Icons.share_outlined, size: 34, color: iconColor),
|
|
110
81
|
),
|
|
111
82
|
trailing: Text("Share", style: bodySmall),
|
|
112
83
|
),
|
lib/widgets/highlight_button.dart
CHANGED
|
@@ -16,7 +16,7 @@ class HighlightButton extends StatelessWidget {
|
|
|
16
16
|
color: color.withOpacity(1),
|
|
17
17
|
shape: BoxShape.circle,
|
|
18
18
|
),
|
|
19
|
-
child: const SizedBox(width:
|
|
19
|
+
child: const SizedBox(width: 45, height: 45),
|
|
20
20
|
),
|
|
21
21
|
);
|
|
22
22
|
}
|
lib/widgets/highlight_sheet.dart
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import "package:flutter/material.dart";
|
|
2
|
+
import "package:only_bible_app/utils.dart";
|
|
3
|
+
import "package:only_bible_app/widgets/highlight_button.dart";
|
|
4
|
+
|
|
5
|
+
class HighlightSheet extends StatelessWidget {
|
|
6
|
+
const HighlightSheet({super.key});
|
|
7
|
+
|
|
8
|
+
@override
|
|
9
|
+
Widget build(BuildContext context) {
|
|
10
|
+
final isDesktop = isWide(context);
|
|
11
|
+
final height = isDesktop || isIOS() ? 100.0 : 70.0;
|
|
12
|
+
onHighlight(Color c) {
|
|
13
|
+
final verses = context.appEvent.selectedVerses;
|
|
14
|
+
context.appEvent.setHighlight(context, verses, c);
|
|
15
|
+
context.appEvent.closeActions(context);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return Container(
|
|
19
|
+
height: height,
|
|
20
|
+
color: Theme.of(context).colorScheme.background,
|
|
21
|
+
padding: EdgeInsets.only(left: 20, right: 20, top: isDesktop ? 10 : 10, bottom: 30),
|
|
22
|
+
child: Row(
|
|
23
|
+
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
24
|
+
children: [
|
|
25
|
+
HighlightButton(
|
|
26
|
+
color: const Color(0xFFDAEFFE),
|
|
27
|
+
onColorSelected: onHighlight,
|
|
28
|
+
),
|
|
29
|
+
HighlightButton(
|
|
30
|
+
color: const Color(0xFFFFFBB1),
|
|
31
|
+
onColorSelected: onHighlight,
|
|
32
|
+
),
|
|
33
|
+
HighlightButton(
|
|
34
|
+
color: const Color(0xFFFFDEF3),
|
|
35
|
+
onColorSelected: onHighlight,
|
|
36
|
+
),
|
|
37
|
+
HighlightButton(
|
|
38
|
+
color: const Color(0xFFE6FCC3),
|
|
39
|
+
onColorSelected: onHighlight,
|
|
40
|
+
),
|
|
41
|
+
HighlightButton(
|
|
42
|
+
color: const Color(0xFFAACCAA),
|
|
43
|
+
onColorSelected: onHighlight,
|
|
44
|
+
),
|
|
45
|
+
],
|
|
46
|
+
),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
lib/widgets/note_sheet.dart
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import "package:only_bible_app/models.dart";
|
|
3
3
|
import "package:only_bible_app/providers/app_model.dart";
|
|
4
|
+
import "package:only_bible_app/utils.dart";
|
|
4
5
|
import "package:only_bible_app/widgets/modal_button.dart";
|
|
5
6
|
|
|
6
7
|
class NoteSheet extends StatelessWidget {
|
|
@@ -24,7 +25,7 @@ class NoteSheet extends StatelessWidget {
|
|
|
24
25
|
Padding(
|
|
25
26
|
padding: const EdgeInsets.only(bottom: 5, left: 15),
|
|
26
27
|
child: Text(
|
|
27
|
-
"Note on ${app.bible.books[verse.book].name} ${verse.chapter + 1}:${verse.index + 1}",
|
|
28
|
+
"Note on ${app.bible.books[verse.book].name(context)} ${verse.chapter + 1}:${verse.index + 1}",
|
|
28
29
|
style: Theme.of(context).textTheme.headlineMedium,
|
|
29
30
|
),
|
|
30
31
|
),
|
|
@@ -57,7 +58,11 @@ class NoteSheet extends StatelessWidget {
|
|
|
57
58
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
58
59
|
children: [
|
|
59
60
|
ModalButton(
|
|
61
|
+
onPressed: () {
|
|
60
|
-
|
|
62
|
+
context.appEvent.saveNote(context, verse);
|
|
63
|
+
// context.chapterEvent.clearSelections();
|
|
64
|
+
// context.appEvent.hideActions(context);
|
|
65
|
+
},
|
|
61
66
|
icon: Icons.save_outlined,
|
|
62
67
|
label: "Save",
|
|
63
68
|
),
|
lib/widgets/settings_sheet.dart
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
-
import "package:only_bible_app/providers/app_model.dart";
|
|
3
2
|
import "package:only_bible_app/utils.dart";
|
|
4
3
|
import "package:settings_ui/settings_ui.dart";
|
|
5
4
|
|
|
@@ -8,9 +7,6 @@ class SettingsSheet extends StatelessWidget {
|
|
|
8
7
|
|
|
9
8
|
@override
|
|
10
9
|
Widget build(BuildContext context) {
|
|
11
|
-
final app = AppModel.of(context);
|
|
12
|
-
final localizations = AppModel.getLocalizations(context);
|
|
13
|
-
final iconColor = Theme.of(context).textTheme.bodyMedium!.color;
|
|
14
10
|
return SettingsList(
|
|
15
11
|
contentPadding: EdgeInsets.zero,
|
|
16
12
|
platform: DevicePlatform.iOS,
|
|
@@ -22,26 +18,26 @@ class SettingsSheet extends StatelessWidget {
|
|
|
22
18
|
),
|
|
23
19
|
sections: [
|
|
24
20
|
SettingsSection(
|
|
25
|
-
title: Text(
|
|
21
|
+
title: Text(context.l10n.settingsTitle, style: context.theme.textTheme.headlineMedium),
|
|
26
22
|
margin: const EdgeInsetsDirectional.symmetric(horizontal: 20),
|
|
27
23
|
tiles: [
|
|
28
24
|
SettingsTile.navigation(
|
|
29
25
|
leading: const Icon(Icons.book_outlined, color: Colors.blueAccent),
|
|
30
|
-
title: Text(
|
|
26
|
+
title: Text(context.l10n.bibleTitle),
|
|
31
|
-
value: Text(app.bible.name),
|
|
27
|
+
value: Text(context.app.bible.name),
|
|
32
|
-
onPressed: app.changeBible,
|
|
28
|
+
onPressed: context.app.changeBible,
|
|
33
29
|
),
|
|
34
30
|
SettingsTile.navigation(
|
|
35
31
|
leading: const Icon(Icons.color_lens_outlined, color: Colors.pink),
|
|
36
|
-
title: Text(
|
|
32
|
+
title: Text(context.l10n.themeTitle),
|
|
37
33
|
trailing: ToggleButtons(
|
|
38
34
|
onPressed: (int index) {
|
|
39
|
-
|
|
35
|
+
context.appEvent.toggleDarkMode();
|
|
40
36
|
},
|
|
41
37
|
highlightColor: Colors.transparent,
|
|
42
38
|
borderColor: Colors.grey,
|
|
43
39
|
borderRadius: const BorderRadius.all(Radius.circular(25)),
|
|
44
|
-
selectedColor: app.darkMode ? Colors.lightBlue.shade300 : Colors.yellowAccent.shade700,
|
|
40
|
+
selectedColor: context.app.darkMode ? Colors.lightBlue.shade300 : Colors.yellowAccent.shade700,
|
|
45
41
|
selectedBorderColor: Colors.grey,
|
|
46
42
|
color: Colors.grey,
|
|
47
43
|
fillColor: Colors.transparent,
|
|
@@ -49,7 +45,7 @@ class SettingsSheet extends StatelessWidget {
|
|
|
49
45
|
minHeight: 36.0,
|
|
50
46
|
minWidth: 50.0,
|
|
51
47
|
),
|
|
52
|
-
isSelected: [!app.darkMode, app.darkMode],
|
|
48
|
+
isSelected: [!context.app.darkMode, context.app.darkMode],
|
|
53
49
|
children: const [
|
|
54
50
|
Icon(Icons.light_mode),
|
|
55
51
|
Icon(Icons.dark_mode),
|
|
@@ -57,63 +53,59 @@ class SettingsSheet extends StatelessWidget {
|
|
|
57
53
|
),
|
|
58
54
|
),
|
|
59
55
|
SettingsTile(
|
|
60
|
-
title: Text(
|
|
56
|
+
title: Text(context.l10n.incrementFontTitle),
|
|
61
|
-
leading: Icon(Icons.font_download, color:
|
|
57
|
+
leading: Icon(Icons.font_download, color: context.theme.colorScheme.onBackground),
|
|
62
58
|
trailing: IconButton(
|
|
63
|
-
onPressed:
|
|
59
|
+
onPressed: context.appEvent.increaseFont,
|
|
64
60
|
icon: const Icon(Icons.add_circle_outline, size: 32, color: Colors.redAccent),
|
|
65
61
|
),
|
|
66
62
|
),
|
|
67
63
|
SettingsTile(
|
|
68
|
-
title: Text(
|
|
64
|
+
title: Text(context.l10n.decrementFontTitle),
|
|
69
|
-
leading: Icon(Icons.font_download, color:
|
|
65
|
+
leading: Icon(Icons.font_download, color: context.theme.colorScheme.onBackground),
|
|
70
66
|
trailing: IconButton(
|
|
71
|
-
onPressed:
|
|
67
|
+
onPressed: context.appEvent.decreaseFont,
|
|
72
68
|
icon: const Icon(Icons.remove_circle_outline, size: 32, color: Colors.blueAccent),
|
|
73
69
|
),
|
|
74
70
|
),
|
|
75
71
|
SettingsTile.switchTile(
|
|
76
|
-
onToggle: (value) {
|
|
77
|
-
app.toggleBold();
|
|
78
|
-
},
|
|
79
|
-
initialValue: app.fontBold,
|
|
72
|
+
initialValue: context.app.fontBold,
|
|
80
|
-
leading: Icon(Icons.format_bold, color:
|
|
73
|
+
leading: Icon(Icons.format_bold, color: context.theme.colorScheme.onBackground),
|
|
81
|
-
title: Text(
|
|
74
|
+
title: Text(context.l10n.boldFontTitle),
|
|
75
|
+
onToggle: (value) => context.appEvent.toggleBold(),
|
|
82
76
|
),
|
|
83
77
|
SettingsTile.switchTile(
|
|
84
|
-
onToggle: (value) {
|
|
85
|
-
app.toggleEngBookNames();
|
|
86
|
-
},
|
|
87
|
-
initialValue: app.engTitles,
|
|
78
|
+
initialValue: context.app.engTitles,
|
|
88
|
-
leading: Icon(Icons.abc, color:
|
|
79
|
+
leading: Icon(Icons.abc, color: context.theme.colorScheme.onBackground),
|
|
89
|
-
title: Text(
|
|
80
|
+
title: Text(context.l10n.engTitles),
|
|
81
|
+
onToggle: (value) => context.appEvent.toggleEngBookNames(),
|
|
90
82
|
),
|
|
91
83
|
],
|
|
92
84
|
),
|
|
93
85
|
SettingsSection(
|
|
94
|
-
|
|
86
|
+
title: Text(context.l10n.aboutUsTitle, style: context.theme.textTheme.headlineMedium),
|
|
95
87
|
margin: const EdgeInsetsDirectional.symmetric(horizontal: 20, vertical: 20),
|
|
96
88
|
tiles: [
|
|
97
89
|
SettingsTile.navigation(
|
|
98
90
|
leading: const Icon(Icons.policy_outlined, color: Colors.brown),
|
|
99
|
-
title: Text(
|
|
91
|
+
title: Text(context.l10n.privacyPolicyTitle),
|
|
100
|
-
onPressed:
|
|
92
|
+
onPressed: context.appEvent.showPrivacyPolicy,
|
|
101
93
|
),
|
|
102
94
|
SettingsTile.navigation(
|
|
103
95
|
leading: const Icon(Icons.share_outlined, color: Colors.blueAccent),
|
|
104
|
-
title: Text(
|
|
96
|
+
title: Text(context.l10n.shareAppTitle),
|
|
105
|
-
onPressed:
|
|
97
|
+
onPressed: context.appEvent.shareAppLink,
|
|
106
98
|
),
|
|
107
99
|
if (!isDesktop()) // TODO: mabe support OSx if we release in that store
|
|
108
100
|
SettingsTile.navigation(
|
|
109
101
|
leading: Icon(Icons.star, color: Colors.yellowAccent.shade700),
|
|
110
|
-
title: Text(
|
|
102
|
+
title: Text(context.l10n.rateAppTitle),
|
|
111
|
-
onPressed:
|
|
103
|
+
onPressed: context.appEvent.rateApp,
|
|
112
104
|
),
|
|
113
105
|
SettingsTile.navigation(
|
|
114
|
-
leading: Icon(Icons.info_outline, color:
|
|
106
|
+
leading: Icon(Icons.info_outline, color: context.theme.colorScheme.onBackground),
|
|
115
|
-
title: Text(
|
|
107
|
+
title: Text(context.l10n.aboutUsTitle),
|
|
116
|
-
onPressed:
|
|
108
|
+
onPressed: context.appEvent.showAboutUs,
|
|
117
109
|
),
|
|
118
110
|
],
|
|
119
111
|
),
|
lib/widgets/verses_view.dart
CHANGED
|
@@ -3,7 +3,7 @@ import "package:flutter/material.dart";
|
|
|
3
3
|
import "package:flutter_swipe_detector/flutter_swipe_detector.dart";
|
|
4
4
|
import "package:only_bible_app/providers/app_model.dart";
|
|
5
5
|
import "package:only_bible_app/providers/chapter_view_model.dart";
|
|
6
|
-
import "package:
|
|
6
|
+
import "package:only_bible_app/utils.dart";
|
|
7
7
|
|
|
8
8
|
class VersesView extends StatelessWidget {
|
|
9
9
|
const VersesView({super.key});
|
|
@@ -75,7 +75,7 @@ class VersesView extends StatelessWidget {
|
|
|
75
75
|
),
|
|
76
76
|
TextSpan(
|
|
77
77
|
text: "${v.text}\n",
|
|
78
|
-
style: context.
|
|
78
|
+
style: context.app.isVerseSelected(v)
|
|
79
79
|
? TextStyle(
|
|
80
80
|
backgroundColor: app.darkMode ? Colors.grey.shade800 : Colors.grey.shade200,
|
|
81
81
|
)
|
|
@@ -84,7 +84,7 @@ class VersesView extends StatelessWidget {
|
|
|
84
84
|
),
|
|
85
85
|
recognizer: TapGestureRecognizer()
|
|
86
86
|
..onTap = () {
|
|
87
|
-
|
|
87
|
+
context.appEvent.onVerseSelected(context, v);
|
|
88
88
|
// AppModel.ofEvent(context).showHighlightMenu(context, v, details.globalPosition);
|
|
89
89
|
},
|
|
90
90
|
),
|