~repos /only-bible-app
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.
334dbbac
—
pyrossh 2 years ago
dart format/fix
- bible_app/README.md +6 -0
- bible_app/analysis_options.yaml +13 -2
- bible_app/integration_test/home_screen_test.dart +0 -1
- bible_app/lib/components/book_selector.dart +15 -12
- bible_app/lib/components/books_list.dart +18 -15
- bible_app/lib/components/chapters_list.dart +8 -7
- bible_app/lib/components/header.dart +20 -9
- bible_app/lib/components/menu.dart +45 -41
- bible_app/lib/components/play_button.dart +6 -5
- bible_app/lib/components/shell.dart +2 -6
- bible_app/lib/components/side_menu_page.dart +2 -2
- bible_app/lib/components/sidebar.dart +66 -62
- bible_app/lib/components/tile.dart +1 -1
- bible_app/lib/components/verse_view.dart +27 -24
- bible_app/lib/main.dart +28 -27
- bible_app/lib/models/book.dart +6 -5
- bible_app/lib/routes/home_screen.dart +3 -3
- bible_app/lib/state.dart +18 -14
- bible_app/pubspec.yaml +1 -1
- bible_app/test/widget_test.dart +0 -1
bible_app/README.md
CHANGED
|
@@ -6,4 +6,10 @@ A new Flutter project.
|
|
|
6
6
|
|
|
7
7
|
```agsl
|
|
8
8
|
brew install fluttter
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Lint
|
|
12
|
+
```agsl
|
|
13
|
+
dart fix --apply
|
|
14
|
+
dart format lib
|
|
9
15
|
```
|
bible_app/analysis_options.yaml
CHANGED
|
@@ -21,8 +21,19 @@ linter:
|
|
|
21
21
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
|
22
22
|
# producing the lint.
|
|
23
23
|
rules:
|
|
24
|
+
- always_use_package_imports
|
|
25
|
+
- avoid_relative_lib_imports
|
|
26
|
+
- avoid_type_to_string
|
|
27
|
+
- require_trailing_commas
|
|
28
|
+
- sized_box_for_whitespace
|
|
29
|
+
- sort_child_properties_last
|
|
30
|
+
- use_colored_box
|
|
31
|
+
- use_decorated_box
|
|
24
|
-
|
|
32
|
+
- use_function_type_syntax_for_parameters
|
|
25
|
-
|
|
33
|
+
- use_named_constants
|
|
34
|
+
- use_string_buffers
|
|
35
|
+
- secure_pubspec_urls
|
|
36
|
+
- sort_pub_dependencies
|
|
26
37
|
|
|
27
38
|
# Additional information about this file can be found at
|
|
28
39
|
# https://dart.dev/guides/language/analysis-options
|
bible_app/integration_test/home_screen_test.dart
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import 'package:flutter_test/flutter_test.dart';
|
|
2
2
|
import 'package:integration_test/integration_test.dart';
|
|
3
|
-
import 'package:only_bible_app/main.dart';
|
|
4
3
|
|
|
5
4
|
void main() {
|
|
6
5
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
bible_app/lib/components/book_selector.dart
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import 'package:go_router/go_router.dart';
|
|
3
|
-
import 'books_list.dart';
|
|
3
|
+
import 'package:only_bible_app/components/books_list.dart';
|
|
4
|
-
import 'chapters_list.dart';
|
|
4
|
+
import 'package:only_bible_app/components/chapters_list.dart';
|
|
5
|
-
import '
|
|
5
|
+
import 'package:only_bible_app/state.dart';
|
|
6
6
|
|
|
7
7
|
class BookSelector extends StatefulWidget {
|
|
8
8
|
const BookSelector({super.key});
|
|
@@ -40,9 +40,10 @@ class BookSelectorState extends State<BookSelector> {
|
|
|
40
40
|
return Container(
|
|
41
41
|
margin: const EdgeInsets.only(top: 15, left: 20),
|
|
42
42
|
child: ChaptersList(
|
|
43
|
-
|
|
43
|
+
title: book.name,
|
|
44
|
-
|
|
44
|
+
length: book.chapters.length,
|
|
45
|
-
|
|
45
|
+
onTap: onChapterSelected,
|
|
46
|
+
),
|
|
46
47
|
);
|
|
47
48
|
}
|
|
48
49
|
final oldTestament =
|
|
@@ -54,16 +55,18 @@ class BookSelectorState extends State<BookSelector> {
|
|
|
54
55
|
child: ListView(
|
|
55
56
|
children: [
|
|
56
57
|
BooksList(
|
|
57
|
-
|
|
58
|
+
title: "Old Testament",
|
|
58
|
-
|
|
59
|
+
books: oldTestament,
|
|
59
|
-
|
|
60
|
+
onTap: onBookSelected,
|
|
61
|
+
),
|
|
60
62
|
Container(
|
|
61
63
|
margin: const EdgeInsets.only(bottom: 10),
|
|
62
64
|
),
|
|
63
65
|
BooksList(
|
|
64
|
-
|
|
66
|
+
title: "New Testament",
|
|
65
|
-
|
|
67
|
+
books: newTestament,
|
|
66
|
-
|
|
68
|
+
onTap: onBookSelected,
|
|
69
|
+
),
|
|
67
70
|
],
|
|
68
71
|
),
|
|
69
72
|
);
|
bible_app/lib/components/books_list.dart
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
-
import
|
|
2
|
+
import 'package:only_bible_app/state.dart';
|
|
3
|
-
import
|
|
3
|
+
import 'package:only_bible_app/components/tile.dart';
|
|
4
|
-
import
|
|
4
|
+
import 'package:only_bible_app/models/book.dart';
|
|
5
5
|
|
|
6
6
|
class BooksList extends StatelessWidget {
|
|
7
7
|
final String title;
|
|
8
8
|
final List<Book> books;
|
|
9
9
|
final Function(int) onTap;
|
|
10
10
|
|
|
11
|
-
const BooksList(
|
|
11
|
+
const BooksList({
|
|
12
|
-
|
|
12
|
+
super.key,
|
|
13
|
-
|
|
13
|
+
required this.title,
|
|
14
|
-
|
|
14
|
+
required this.books,
|
|
15
|
-
|
|
15
|
+
required this.onTap,
|
|
16
|
+
});
|
|
16
17
|
|
|
17
18
|
@override
|
|
18
19
|
Widget build(BuildContext context) {
|
|
@@ -24,13 +25,15 @@ class BooksList extends StatelessWidget {
|
|
|
24
25
|
child: Text(title, style: theme.value.titleText),
|
|
25
26
|
),
|
|
26
27
|
Wrap(
|
|
27
|
-
children: List.of(
|
|
28
|
+
children: List.of(
|
|
29
|
+
books.map((book) {
|
|
28
|
-
|
|
30
|
+
final name = book.shortName();
|
|
29
|
-
|
|
31
|
+
return Tile(
|
|
30
|
-
|
|
32
|
+
name: name,
|
|
31
|
-
|
|
33
|
+
onPressed: () => onTap(book.index),
|
|
32
|
-
|
|
34
|
+
);
|
|
33
|
-
|
|
35
|
+
}),
|
|
36
|
+
),
|
|
34
37
|
),
|
|
35
38
|
],
|
|
36
39
|
);
|
bible_app/lib/components/chapters_list.dart
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
-
import '
|
|
2
|
+
import 'package:only_bible_app/state.dart';
|
|
3
|
-
import 'tile.dart';
|
|
3
|
+
import 'package:only_bible_app/components/tile.dart';
|
|
4
4
|
|
|
5
5
|
class ChaptersList extends StatelessWidget {
|
|
6
6
|
final String title;
|
|
7
7
|
final int length;
|
|
8
8
|
final Function(int) onTap;
|
|
9
9
|
|
|
10
|
-
const ChaptersList(
|
|
10
|
+
const ChaptersList({
|
|
11
|
-
|
|
11
|
+
super.key,
|
|
12
|
-
|
|
12
|
+
required this.title,
|
|
13
|
-
|
|
13
|
+
required this.length,
|
|
14
|
-
|
|
14
|
+
required this.onTap,
|
|
15
|
+
});
|
|
15
16
|
|
|
16
17
|
@override
|
|
17
18
|
Widget build(BuildContext context) {
|
bible_app/lib/components/header.dart
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
+
import 'package:only_bible_app/components/play_button.dart';
|
|
3
|
+
import 'package:only_bible_app/components/side_menu_page.dart';
|
|
2
|
-
import
|
|
4
|
+
import 'package:only_bible_app/components/menu.dart';
|
|
3
|
-
import "./play_button.dart";
|
|
4
|
-
import "./side_menu_page.dart";
|
|
5
|
-
import "./menu.dart";
|
|
6
|
-
import '
|
|
5
|
+
import 'package:only_bible_app/models/book.dart';
|
|
7
|
-
import
|
|
6
|
+
import 'package:only_bible_app/state.dart';
|
|
8
7
|
|
|
9
8
|
class Header extends StatelessWidget {
|
|
10
9
|
final int book;
|
|
11
10
|
final int chapter;
|
|
12
11
|
final List<Verse> verses;
|
|
13
12
|
|
|
13
|
+
const Header({
|
|
14
|
+
super.key,
|
|
15
|
+
required this.book,
|
|
14
|
-
|
|
16
|
+
required this.chapter,
|
|
17
|
+
required this.verses,
|
|
18
|
+
});
|
|
15
19
|
|
|
16
20
|
@override
|
|
17
21
|
Widget build(BuildContext context) {
|
|
@@ -32,8 +36,15 @@ class Header extends StatelessWidget {
|
|
|
32
36
|
padding: EdgeInsets.zero,
|
|
33
37
|
foregroundColor: const Color(0xFF9A1111),
|
|
34
38
|
),
|
|
39
|
+
label: Icon(
|
|
40
|
+
Icons.expand_more,
|
|
41
|
+
size: 28,
|
|
35
|
-
|
|
42
|
+
color: theme.value.headerText.color,
|
|
43
|
+
),
|
|
44
|
+
icon: Text(
|
|
36
|
-
|
|
45
|
+
"${selectedBible.value[book].name} ${chapter + 1}",
|
|
46
|
+
style: theme.value.headerText,
|
|
47
|
+
),
|
|
37
48
|
onPressed: () {
|
|
38
49
|
Navigator.of(context).push(SideMenuPage());
|
|
39
50
|
},
|
bible_app/lib/components/menu.dart
CHANGED
|
@@ -10,46 +10,50 @@ class Menu extends StatelessWidget {
|
|
|
10
10
|
final moreIcon = isWide(context) ? Icons.more_vert : Icons.more_vert;
|
|
11
11
|
const spacing = 25.0;
|
|
12
12
|
return PopupMenuButton(
|
|
13
|
-
|
|
13
|
+
constraints: const BoxConstraints.tightFor(width: 80),
|
|
14
|
-
|
|
14
|
+
icon: Icon(moreIcon, size: 28),
|
|
15
|
-
|
|
15
|
+
offset: const Offset(0.0, 60),
|
|
16
|
-
|
|
16
|
+
itemBuilder: (BuildContext itemContext) {
|
|
17
|
-
|
|
17
|
+
final modeIcon = darkMode.reactiveValue(itemContext)
|
|
18
|
-
|
|
18
|
+
? Icons.dark_mode
|
|
19
|
-
|
|
19
|
+
: Icons.light_mode;
|
|
20
|
-
|
|
20
|
+
final boldColor =
|
|
21
|
-
|
|
21
|
+
fontBold.reactiveValue(itemContext) ? Colors.red : Colors.grey;
|
|
22
|
-
|
|
22
|
+
return [
|
|
23
|
-
|
|
23
|
+
PopupMenuItem(
|
|
24
|
-
|
|
24
|
+
value: 1,
|
|
25
|
-
|
|
25
|
+
child: Column(
|
|
26
|
-
|
|
26
|
+
crossAxisAlignment: CrossAxisAlignment.center,
|
|
27
|
-
|
|
27
|
+
mainAxisAlignment: MainAxisAlignment.center,
|
|
28
|
-
|
|
28
|
+
children: [
|
|
29
|
-
|
|
29
|
+
IconButton(
|
|
30
|
-
|
|
30
|
+
icon: Icon(modeIcon, color: Colors.black, size: 28),
|
|
31
|
-
|
|
31
|
+
onPressed: toggleMode,
|
|
32
|
-
|
|
32
|
+
),
|
|
33
|
-
|
|
33
|
+
Container(margin: const EdgeInsets.only(top: spacing)),
|
|
34
|
-
|
|
34
|
+
IconButton(
|
|
35
|
-
|
|
35
|
+
icon: Icon(Icons.format_bold, color: boldColor, size: 28),
|
|
36
|
-
|
|
36
|
+
onPressed: toggleBold,
|
|
37
|
-
|
|
37
|
+
),
|
|
38
|
-
|
|
38
|
+
Container(margin: const EdgeInsets.only(top: spacing)),
|
|
39
|
-
|
|
39
|
+
const IconButton(
|
|
40
|
-
icon:
|
|
41
|
-
|
|
40
|
+
icon: Icon(Icons.add_circle, color: Colors.black, size: 28),
|
|
42
|
-
|
|
41
|
+
onPressed: increaseFont,
|
|
43
|
-
|
|
42
|
+
),
|
|
44
|
-
|
|
43
|
+
Container(margin: const EdgeInsets.only(top: spacing)),
|
|
45
|
-
|
|
44
|
+
const IconButton(
|
|
45
|
+
icon: Icon(
|
|
46
|
-
|
|
46
|
+
Icons.remove_circle,
|
|
47
|
-
|
|
47
|
+
color: Colors.black,
|
|
48
|
+
size: 28,
|
|
49
|
+
),
|
|
48
|
-
|
|
50
|
+
onPressed: decreaseFont,
|
|
49
|
-
|
|
51
|
+
),
|
|
50
|
-
|
|
52
|
+
],
|
|
51
|
-
|
|
53
|
+
),
|
|
54
|
+
),
|
|
52
|
-
|
|
55
|
+
];
|
|
56
|
+
},
|
|
53
|
-
|
|
57
|
+
);
|
|
54
58
|
}
|
|
55
59
|
}
|
bible_app/lib/components/play_button.dart
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import "package:flutter_reactive_value/flutter_reactive_value.dart";
|
|
3
|
-
import
|
|
3
|
+
import 'package:only_bible_app/state.dart';
|
|
4
4
|
|
|
5
5
|
class PlayButton extends StatelessWidget {
|
|
6
6
|
const PlayButton({super.key});
|
|
@@ -11,9 +11,10 @@ class PlayButton extends StatelessWidget {
|
|
|
11
11
|
? Icons.pause_circle_filled
|
|
12
12
|
: Icons.play_circle_fill;
|
|
13
13
|
return IconButton(
|
|
14
|
-
|
|
14
|
+
icon: Icon(icon, size: 28),
|
|
15
|
-
|
|
15
|
+
onPressed: () {
|
|
16
|
-
|
|
16
|
+
onPlay(context);
|
|
17
|
+
},
|
|
17
|
-
|
|
18
|
+
);
|
|
18
19
|
}
|
|
19
20
|
}
|
bible_app/lib/components/shell.dart
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import 'package:flutter_reactive_value/flutter_reactive_value.dart';
|
|
2
1
|
import 'package:go_router/go_router.dart';
|
|
3
2
|
import "package:flutter/material.dart";
|
|
4
|
-
import 'package:flutter/services.dart';
|
|
5
3
|
import 'package:one_context/one_context.dart';
|
|
4
|
+
import 'package:only_bible_app/state.dart';
|
|
6
|
-
import 'package:only_bible_app/components/
|
|
5
|
+
import 'package:only_bible_app/components/sidebar.dart';
|
|
7
|
-
import '../models/theme.dart';
|
|
8
|
-
import '../state.dart';
|
|
9
|
-
import "sidebar.dart";
|
|
10
6
|
|
|
11
7
|
class Shell extends ShellRoute {
|
|
12
8
|
Shell({required super.routes});
|
bible_app/lib/components/side_menu_page.dart
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
-
import
|
|
2
|
+
import 'package:only_bible_app/components/book_selector.dart';
|
|
3
|
-
import
|
|
3
|
+
import 'package:only_bible_app/state.dart';
|
|
4
4
|
|
|
5
5
|
class SideMenuPage extends ModalRoute<void> {
|
|
6
6
|
@override
|
bible_app/lib/components/sidebar.dart
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import 'package:only_bible_app/state.dart';
|
|
4
4
|
|
|
5
5
|
class Sidebar extends StatelessWidget {
|
|
6
6
|
const Sidebar({super.key});
|
|
@@ -9,42 +9,43 @@ class Sidebar extends StatelessWidget {
|
|
|
9
9
|
Widget build(BuildContext context) {
|
|
10
10
|
final height = MediaQuery.of(context).size.height;
|
|
11
11
|
return Container(
|
|
12
|
-
|
|
12
|
+
color: const Color(0xFF4C2323),
|
|
13
|
-
|
|
13
|
+
child: Stack(
|
|
14
|
-
|
|
14
|
+
children: [
|
|
15
|
-
|
|
15
|
+
Positioned(
|
|
16
|
-
|
|
16
|
+
left: 0.0,
|
|
17
|
-
|
|
17
|
+
top: 0.0,
|
|
18
|
-
|
|
18
|
+
child: Container(
|
|
19
|
-
|
|
19
|
+
width: 40.0,
|
|
20
|
-
height: height,
|
|
21
|
-
decoration: const BoxDecoration(color: Color(0xFF3C1B1C)),
|
|
22
|
-
),
|
|
23
|
-
),
|
|
24
|
-
const Belt(top: 80),
|
|
25
|
-
Belt(top: height - 120),
|
|
26
|
-
const Bookmark(),
|
|
27
|
-
SizedBox(
|
|
28
|
-
width: 250,
|
|
29
20
|
height: height,
|
|
21
|
+
decoration: const BoxDecoration(color: Color(0xFF3C1B1C)),
|
|
22
|
+
),
|
|
23
|
+
),
|
|
24
|
+
const Belt(top: 80),
|
|
25
|
+
Belt(top: height - 120),
|
|
26
|
+
const Bookmark(),
|
|
27
|
+
SizedBox(
|
|
28
|
+
width: 250,
|
|
29
|
+
height: height,
|
|
30
|
-
|
|
30
|
+
child: Container(
|
|
31
|
-
|
|
31
|
+
margin: const EdgeInsets.only(bottom: 50),
|
|
32
|
-
|
|
32
|
+
child: Column(
|
|
33
|
-
|
|
33
|
+
mainAxisAlignment: MainAxisAlignment.center,
|
|
34
|
-
|
|
34
|
+
crossAxisAlignment: CrossAxisAlignment.center,
|
|
35
|
-
|
|
35
|
+
children: [
|
|
36
|
-
|
|
36
|
+
Flexible(
|
|
37
|
-
|
|
37
|
+
child: Text("KANNADA", style: theme.value.logoText),
|
|
38
|
-
|
|
38
|
+
),
|
|
39
|
-
|
|
39
|
+
Flexible(
|
|
40
|
-
|
|
40
|
+
child: Text("BIBLE", style: theme.value.logoText),
|
|
41
|
-
|
|
41
|
+
),
|
|
42
|
-
|
|
42
|
+
],
|
|
43
|
-
),
|
|
44
43
|
),
|
|
45
44
|
),
|
|
45
|
+
),
|
|
46
|
-
|
|
46
|
+
],
|
|
47
|
+
),
|
|
47
|
-
|
|
48
|
+
);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -65,10 +66,11 @@ class TrianglePainter extends CustomPainter {
|
|
|
65
66
|
path.lineTo(-15, 30);
|
|
66
67
|
path.close();
|
|
67
68
|
canvas.drawPath(
|
|
68
|
-
|
|
69
|
+
path,
|
|
69
|
-
|
|
70
|
+
Paint()
|
|
70
|
-
|
|
71
|
+
..color = color
|
|
71
|
-
|
|
72
|
+
..style = PaintingStyle.fill,
|
|
73
|
+
);
|
|
72
74
|
|
|
73
75
|
canvas.save();
|
|
74
76
|
canvas.restore();
|
|
@@ -86,28 +88,29 @@ class Bookmark extends StatelessWidget {
|
|
|
86
88
|
@override
|
|
87
89
|
Widget build(BuildContext context) {
|
|
88
90
|
return Positioned(
|
|
89
|
-
|
|
91
|
+
left: 70.0,
|
|
90
|
-
|
|
92
|
+
top: 0.0,
|
|
91
|
-
|
|
93
|
+
child: Column(
|
|
92
|
-
|
|
94
|
+
children: [
|
|
93
|
-
|
|
95
|
+
Container(
|
|
94
|
-
|
|
96
|
+
width: 30.0,
|
|
95
|
-
|
|
97
|
+
height: 80.0,
|
|
96
|
-
|
|
98
|
+
decoration: BoxDecoration(
|
|
97
|
-
|
|
99
|
+
color: theme.value.secondaryColor,
|
|
98
|
-
|
|
100
|
+
borderRadius: const BorderRadius.only(
|
|
99
|
-
|
|
101
|
+
topLeft: Radius.circular(4),
|
|
100
|
-
|
|
102
|
+
topRight: Radius.circular(4),
|
|
101
|
-
),
|
|
102
103
|
),
|
|
103
104
|
),
|
|
105
|
+
),
|
|
104
|
-
|
|
106
|
+
CustomPaint(
|
|
105
|
-
|
|
107
|
+
painter: TrianglePainter(
|
|
106
|
-
|
|
108
|
+
color: theme.value.secondaryColor,
|
|
107
|
-
),
|
|
108
109
|
),
|
|
110
|
+
),
|
|
109
|
-
|
|
111
|
+
],
|
|
112
|
+
),
|
|
110
|
-
|
|
113
|
+
);
|
|
111
114
|
}
|
|
112
115
|
}
|
|
113
116
|
|
|
@@ -125,11 +128,12 @@ class Belt extends StatelessWidget {
|
|
|
125
128
|
width: 60.0,
|
|
126
129
|
height: 30.0,
|
|
127
130
|
decoration: const BoxDecoration(
|
|
128
|
-
|
|
131
|
+
borderRadius: BorderRadius.only(
|
|
129
|
-
|
|
132
|
+
bottomRight: Radius.circular(25),
|
|
130
|
-
|
|
133
|
+
topRight: Radius.circular(25),
|
|
131
|
-
|
|
134
|
+
),
|
|
132
|
-
|
|
135
|
+
color: Color(0xFF7F3D3C),
|
|
136
|
+
),
|
|
133
137
|
),
|
|
134
138
|
);
|
|
135
139
|
}
|
bible_app/lib/components/tile.dart
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import 'package:flutter/material.dart';
|
|
2
2
|
|
|
3
|
-
import '
|
|
3
|
+
import 'package:only_bible_app/state.dart';
|
|
4
4
|
|
|
5
5
|
class Tile extends StatelessWidget {
|
|
6
6
|
final String name;
|
bible_app/lib/components/verse_view.dart
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import "package:flutter_reactive_value/flutter_reactive_value.dart";
|
|
3
|
-
import
|
|
3
|
+
import 'package:only_bible_app/state.dart';
|
|
4
4
|
|
|
5
5
|
class VerseText extends StatelessWidget {
|
|
6
6
|
final int index;
|
|
@@ -20,30 +20,33 @@ class VerseText extends StatelessWidget {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
return MouseRegion(
|
|
23
|
-
|
|
23
|
+
cursor: SystemMouseCursors.click,
|
|
24
|
-
|
|
24
|
+
child: GestureDetector(
|
|
25
|
-
|
|
25
|
+
onTap: onTap,
|
|
26
|
-
|
|
26
|
+
child: DecoratedBox(
|
|
27
|
-
|
|
27
|
+
decoration: BoxDecoration(
|
|
28
|
-
|
|
28
|
+
color: selected ? theme.value.highlightColor : Colors.white,
|
|
29
|
-
|
|
29
|
+
),
|
|
30
|
-
|
|
30
|
+
child: Row(
|
|
31
|
-
|
|
31
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
32
|
-
|
|
32
|
+
children: [
|
|
33
|
-
|
|
33
|
+
Container(
|
|
34
|
-
|
|
34
|
+
margin: const EdgeInsets.only(right: 4),
|
|
35
|
-
|
|
35
|
+
child: Transform.translate(
|
|
36
|
-
|
|
36
|
+
offset: const Offset(0, 2),
|
|
37
|
-
|
|
37
|
+
child: Text("${index + 1}", style: theme.value.labelText),
|
|
38
|
-
|
|
38
|
+
),
|
|
39
|
+
),
|
|
40
|
+
Flexible(
|
|
41
|
+
child: Text(
|
|
42
|
+
text,
|
|
43
|
+
style: TextStyle(fontSize: bodySize, fontWeight: weight),
|
|
39
44
|
),
|
|
40
|
-
Flexible(
|
|
41
|
-
child: Text(text,
|
|
42
|
-
style: TextStyle(fontSize: bodySize, fontWeight: weight)),
|
|
43
|
-
|
|
45
|
+
)
|
|
44
|
-
|
|
46
|
+
],
|
|
45
|
-
),
|
|
46
47
|
),
|
|
48
|
+
),
|
|
49
|
+
),
|
|
47
|
-
|
|
50
|
+
);
|
|
48
51
|
}
|
|
49
52
|
}
|
bible_app/lib/main.dart
CHANGED
|
@@ -3,10 +3,9 @@ import 'package:flutter_persistent_value_notifier/flutter_persistent_value_notif
|
|
|
3
3
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
|
4
4
|
import 'package:go_router/go_router.dart';
|
|
5
5
|
import 'package:one_context/one_context.dart';
|
|
6
|
-
import 'package:only_bible_app/
|
|
6
|
+
import 'package:only_bible_app/components/shell.dart';
|
|
7
|
+
import 'package:only_bible_app/routes/home_screen.dart';
|
|
7
|
-
import '
|
|
8
|
+
import 'package:only_bible_app/state.dart';
|
|
8
|
-
import 'routes/home_screen.dart';
|
|
9
|
-
import 'state.dart';
|
|
10
9
|
|
|
11
10
|
void main() async {
|
|
12
11
|
WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
|
@@ -14,30 +13,32 @@ void main() async {
|
|
|
14
13
|
await initPersistentValueNotifier();
|
|
15
14
|
await loadBible();
|
|
16
15
|
await updateStatusBar();
|
|
16
|
+
runApp(
|
|
17
|
-
|
|
17
|
+
MaterialApp.router(
|
|
18
|
-
|
|
18
|
+
debugShowCheckedModeBanner: false,
|
|
19
|
-
|
|
19
|
+
builder: OneContext().builder,
|
|
20
|
-
|
|
20
|
+
theme: ThemeData(
|
|
21
|
-
|
|
21
|
+
visualDensity: VisualDensity.adaptivePlatformDensity,
|
|
22
|
-
|
|
22
|
+
),
|
|
23
|
-
|
|
23
|
+
routerConfig: GoRouter(
|
|
24
|
-
|
|
24
|
+
debugLogDiagnostics: true,
|
|
25
|
-
|
|
25
|
+
initialLocation:
|
|
26
|
-
|
|
26
|
+
"/${selectedBible.value[bookIndex.value].name}/${chapterIndex.value}",
|
|
27
|
-
|
|
27
|
+
routes: [
|
|
28
|
-
|
|
28
|
+
Shell(
|
|
29
|
-
|
|
29
|
+
routes: [
|
|
30
|
-
|
|
30
|
+
GoRouteData.$route(
|
|
31
|
-
|
|
31
|
+
path: '/:book/:chapter',
|
|
32
|
-
|
|
32
|
+
factory: (GoRouterState state) => HomeScreen(
|
|
33
|
-
|
|
33
|
+
book: state.pathParameters['book']!,
|
|
34
|
-
|
|
34
|
+
chapter: int.parse(state.pathParameters['chapter']!),
|
|
35
|
+
),
|
|
35
36
|
),
|
|
37
|
+
],
|
|
36
|
-
|
|
38
|
+
),
|
|
37
|
-
|
|
39
|
+
],
|
|
38
|
-
|
|
40
|
+
),
|
|
39
|
-
],
|
|
40
41
|
),
|
|
41
|
-
)
|
|
42
|
+
);
|
|
42
43
|
FlutterNativeSplash.remove();
|
|
43
44
|
}
|
bible_app/lib/models/book.dart
CHANGED
|
@@ -4,11 +4,12 @@ class Book {
|
|
|
4
4
|
final String localeName;
|
|
5
5
|
final List<Chapter> chapters;
|
|
6
6
|
|
|
7
|
-
const Book(
|
|
7
|
+
const Book({
|
|
8
|
-
|
|
8
|
+
required this.index,
|
|
9
|
-
|
|
9
|
+
required this.name,
|
|
10
|
-
|
|
10
|
+
required this.localeName,
|
|
11
|
-
|
|
11
|
+
required this.chapters,
|
|
12
|
+
});
|
|
12
13
|
|
|
13
14
|
bool isOldTestament() => index < 39;
|
|
14
15
|
|
bible_app/lib/routes/home_screen.dart
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import 'package:go_router/go_router.dart';
|
|
3
|
-
import '
|
|
3
|
+
import 'package:only_bible_app/components/header.dart';
|
|
4
|
-
import '
|
|
4
|
+
import 'package:only_bible_app/components/verse_view.dart';
|
|
5
|
-
import '
|
|
5
|
+
import 'package:only_bible_app/state.dart';
|
|
6
6
|
|
|
7
7
|
class HomeScreen extends GoRouteData {
|
|
8
8
|
final String book;
|
bible_app/lib/state.dart
CHANGED
|
@@ -5,11 +5,9 @@ import 'package:flutter/material.dart';
|
|
|
5
5
|
import 'package:flutter_persistent_value_notifier/flutter_persistent_value_notifier.dart';
|
|
6
6
|
import 'package:flutter_reactive_value/flutter_reactive_value.dart';
|
|
7
7
|
import 'package:just_audio/just_audio.dart';
|
|
8
|
-
import 'package:one_context/one_context.dart';
|
|
9
|
-
import 'package:only_bible_app/components/play_button.dart';
|
|
10
8
|
import 'package:only_bible_app/utils/dialog.dart';
|
|
11
|
-
import 'models/book.dart';
|
|
9
|
+
import 'package:only_bible_app/models/book.dart';
|
|
12
|
-
import 'models/theme.dart';
|
|
10
|
+
import 'package:only_bible_app/models/theme.dart';
|
|
13
11
|
|
|
14
12
|
final darkMode = PersistentValueNotifier<bool>(
|
|
15
13
|
sharedPreferencesKey: 'darkMode',
|
|
@@ -86,7 +84,7 @@ getBibleFromAsset(String file) async {
|
|
|
86
84
|
getBibleFromText(String text) {
|
|
87
85
|
final List<Book> books = [];
|
|
88
86
|
final items = text.split("\n").map((line) => line.split("|"));
|
|
89
|
-
|
|
87
|
+
for (var item in items) {
|
|
90
88
|
var book = int.parse(item[0]);
|
|
91
89
|
var chapter = int.parse(item[1]);
|
|
92
90
|
var verse = item[3];
|
|
@@ -97,20 +95,25 @@ getBibleFromText(String text) {
|
|
|
97
95
|
end = double.parse(item[5]);
|
|
98
96
|
}
|
|
99
97
|
if (books.length - 1 < book) {
|
|
100
|
-
books.add(
|
|
98
|
+
books.add(
|
|
99
|
+
Book(
|
|
101
100
|
index: book,
|
|
102
101
|
name: bookNames[book],
|
|
103
102
|
localeName: bookNames[book],
|
|
104
|
-
chapters: []
|
|
103
|
+
chapters: [],
|
|
104
|
+
),
|
|
105
|
+
);
|
|
105
106
|
}
|
|
106
107
|
if (books[book].chapters.length < chapter) {
|
|
107
|
-
books[book].chapters.add(Chapter(verses: []));
|
|
108
|
+
books[book].chapters.add(const Chapter(verses: []));
|
|
108
109
|
}
|
|
109
|
-
books[book].chapters[chapter - 1].verses.add(
|
|
110
|
+
books[book].chapters[chapter - 1].verses.add(
|
|
111
|
+
Verse(
|
|
110
|
-
|
|
112
|
+
text: verse,
|
|
111
|
-
|
|
113
|
+
audioRange: TimeRange(start: start, end: end),
|
|
114
|
+
),
|
|
112
|
-
)
|
|
115
|
+
);
|
|
113
|
-
}
|
|
116
|
+
}
|
|
114
117
|
return books;
|
|
115
118
|
}
|
|
116
119
|
|
|
@@ -124,7 +127,8 @@ onPlay(BuildContext context) async {
|
|
|
124
127
|
.map((it) => verses[it]);
|
|
125
128
|
final player = AudioPlayer();
|
|
126
129
|
player.setUrl(
|
|
127
|
-
|
|
130
|
+
"https://github.com/pyrossh/bible-app/raw/master/public/audio/output.mp3",
|
|
131
|
+
);
|
|
128
132
|
// player.setUrl("asset:output.mp3");
|
|
129
133
|
if (isPlaying.value) {
|
|
130
134
|
await player.pause();
|
bible_app/pubspec.yaml
CHANGED
|
@@ -10,8 +10,8 @@ dependencies:
|
|
|
10
10
|
flutter:
|
|
11
11
|
sdk: flutter
|
|
12
12
|
path_provider: ^2.0.15
|
|
13
|
-
flutter_reactive_value: ^1.0.4
|
|
14
13
|
flutter_persistent_value_notifier: ^1.0.2
|
|
14
|
+
flutter_reactive_value: ^1.0.4
|
|
15
15
|
just_audio: ^0.9.34
|
|
16
16
|
go_router: ^10.0.0
|
|
17
17
|
shared_preferences: ^2.2.0
|
bible_app/test/widget_test.dart
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import 'package:flutter/material.dart';
|
|
2
2
|
import 'package:flutter_test/flutter_test.dart';
|
|
3
|
-
import 'package:only_bible_app/main.dart';
|
|
4
3
|
|
|
5
4
|
void main() {
|
|
6
5
|
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|