~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.
e015ba68
—
pyrossh 2 years ago
fix transitions
- lib/app.dart +23 -2
- lib/components/book_selector.dart +1 -1
- lib/components/header.dart +43 -46
- lib/components/shell.dart +0 -31
- lib/routes/home_screen.dart +47 -23
- lib/state.dart +19 -12
lib/app.dart
CHANGED
|
@@ -2,9 +2,9 @@ import 'package:flutter/material.dart';
|
|
|
2
2
|
import 'package:flutter_reactive_value/flutter_reactive_value.dart';
|
|
3
3
|
import 'package:go_router/go_router.dart';
|
|
4
4
|
import 'package:one_context/one_context.dart';
|
|
5
|
-
import 'package:only_bible_app/components/shell.dart';
|
|
6
5
|
import 'package:only_bible_app/routes/home_screen.dart';
|
|
7
6
|
import 'package:only_bible_app/state.dart';
|
|
7
|
+
import 'package:only_bible_app/components/sidebar.dart';
|
|
8
8
|
|
|
9
9
|
class App extends StatelessWidget {
|
|
10
10
|
const App({super.key});
|
|
@@ -116,7 +116,28 @@ class App extends StatelessWidget {
|
|
|
116
116
|
debugLogDiagnostics: true,
|
|
117
117
|
initialLocation: "/${selectedBible.value[bookIndex.value].name}/${chapterIndex.value}",
|
|
118
118
|
routes: [
|
|
119
|
-
|
|
119
|
+
ShellRoute(
|
|
120
|
+
builder: (context, state, child) {
|
|
121
|
+
if (isWide(context)) {
|
|
122
|
+
return Scaffold(
|
|
123
|
+
backgroundColor: Theme.of(context).colorScheme.background,
|
|
124
|
+
body: Row(
|
|
125
|
+
children: [
|
|
126
|
+
const Sidebar(),
|
|
127
|
+
Flexible(
|
|
128
|
+
child: child,
|
|
129
|
+
),
|
|
130
|
+
],
|
|
131
|
+
),
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return Scaffold(
|
|
135
|
+
backgroundColor: Theme.of(context).colorScheme.background,
|
|
136
|
+
body: SafeArea(
|
|
137
|
+
child: child,
|
|
138
|
+
),
|
|
139
|
+
);
|
|
140
|
+
},
|
|
120
141
|
routes: [
|
|
121
142
|
GoRouteData.$route(
|
|
122
143
|
path: '/:book/:chapter',
|
lib/components/book_selector.dart
CHANGED
|
@@ -29,7 +29,7 @@ class BookSelectorState extends State<BookSelector> {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
onChapterSelected(int index) {
|
|
32
|
-
navigateBookChapter(context, bookIndex, index);
|
|
32
|
+
navigateBookChapter(context, bookIndex, index, true);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
@override
|
lib/components/header.dart
CHANGED
|
@@ -14,53 +14,50 @@ class Header extends StatelessWidget {
|
|
|
14
14
|
final chapter = chapterIndex.reactiveValue(context);
|
|
15
15
|
final selectedBook = selectedBible.value[book];
|
|
16
16
|
return Container(
|
|
17
|
-
|
|
17
|
+
padding: EdgeInsets.only(
|
|
18
|
+
left: 20,
|
|
19
|
+
right: 20,
|
|
18
|
-
|
|
20
|
+
top: isWide(context) ? 10 : 0,
|
|
19
|
-
bottom: isWide(context) ? 10 : 0,
|
|
20
|
-
),
|
|
21
|
-
decoration: BoxDecoration(
|
|
22
|
-
border: Border(
|
|
23
|
-
bottom: BorderSide(
|
|
24
|
-
width: 1.5,
|
|
25
|
-
color: Theme.of(context).dividerColor,
|
|
26
|
-
),
|
|
27
21
|
),
|
|
22
|
+
child: Column(
|
|
23
|
+
children: [
|
|
24
|
+
Row(
|
|
25
|
+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
26
|
+
crossAxisAlignment: CrossAxisAlignment.center,
|
|
27
|
+
children: [
|
|
28
|
+
TextButton.icon(
|
|
29
|
+
style: TextButton.styleFrom(
|
|
30
|
+
padding: EdgeInsets.zero,
|
|
31
|
+
backgroundColor: Theme.of(context).colorScheme.background,
|
|
32
|
+
elevation: 0,
|
|
28
|
-
|
|
33
|
+
),
|
|
29
|
-
|
|
34
|
+
label: Icon(
|
|
35
|
+
Icons.expand_more,
|
|
36
|
+
size: 28,
|
|
37
|
+
color: Theme.of(context).textTheme.headlineMedium!.color,
|
|
38
|
+
),
|
|
39
|
+
icon: Text(
|
|
40
|
+
"${selectedBook.name} ${chapter + 1}",
|
|
41
|
+
style: Theme.of(context).textTheme.headlineMedium,
|
|
42
|
+
),
|
|
43
|
+
onPressed: () {
|
|
44
|
+
Navigator.of(context).push(SideMenuPage());
|
|
45
|
+
},
|
|
46
|
+
),
|
|
47
|
+
Row(
|
|
30
|
-
|
|
48
|
+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
31
|
-
crossAxisAlignment: CrossAxisAlignment.center,
|
|
32
|
-
|
|
49
|
+
children: [
|
|
33
|
-
|
|
50
|
+
Container(
|
|
51
|
+
margin: EdgeInsets.only(right: isWide(context) ? 10 : 8),
|
|
34
|
-
|
|
52
|
+
child: const PlayButton(),
|
|
35
|
-
|
|
53
|
+
),
|
|
36
|
-
backgroundColor: Theme.of(context).colorScheme.background,
|
|
37
|
-
|
|
54
|
+
const Menu(),
|
|
55
|
+
],
|
|
56
|
+
),
|
|
57
|
+
],
|
|
38
58
|
),
|
|
39
|
-
label: Icon(
|
|
40
|
-
Icons.expand_more,
|
|
41
|
-
size: 28,
|
|
42
|
-
color: Theme.of(context).textTheme.headlineMedium!.color,
|
|
43
|
-
),
|
|
44
|
-
icon: Text(
|
|
45
|
-
"${selectedBook.name} ${chapter + 1}",
|
|
46
|
-
style: Theme.of(context).textTheme.headlineMedium,
|
|
47
|
-
),
|
|
48
|
-
onPressed: () {
|
|
49
|
-
Navigator.of(context).push(SideMenuPage());
|
|
50
|
-
},
|
|
51
|
-
),
|
|
52
|
-
Row(
|
|
53
|
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
54
|
-
children: [
|
|
55
|
-
Container(
|
|
56
|
-
|
|
59
|
+
const Divider(thickness: 1.5, endIndent: 10),
|
|
57
|
-
child: const PlayButton(),
|
|
58
|
-
),
|
|
59
|
-
const Menu(),
|
|
60
|
-
|
|
60
|
+
],
|
|
61
|
-
),
|
|
62
|
-
],
|
|
63
|
-
),
|
|
64
|
-
|
|
61
|
+
));
|
|
65
62
|
}
|
|
66
63
|
}
|
lib/components/shell.dart
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import 'package:go_router/go_router.dart';
|
|
2
|
-
import "package:flutter/material.dart";
|
|
3
|
-
import 'package:one_context/one_context.dart';
|
|
4
|
-
import 'package:only_bible_app/state.dart';
|
|
5
|
-
import 'package:only_bible_app/components/sidebar.dart';
|
|
6
|
-
|
|
7
|
-
class Shell extends ShellRoute {
|
|
8
|
-
Shell({required super.routes});
|
|
9
|
-
|
|
10
|
-
@override
|
|
11
|
-
GlobalKey<NavigatorState> get navigatorKey => OneContext().key;
|
|
12
|
-
|
|
13
|
-
@override
|
|
14
|
-
ShellRouteBuilder? get builder => (context, state, child) {
|
|
15
|
-
return Scaffold(
|
|
16
|
-
backgroundColor: Theme.of(context).colorScheme.background,
|
|
17
|
-
body: SafeArea(
|
|
18
|
-
child: isWide(context)
|
|
19
|
-
? Row(
|
|
20
|
-
children: [
|
|
21
|
-
const Sidebar(),
|
|
22
|
-
Flexible(
|
|
23
|
-
child: child,
|
|
24
|
-
),
|
|
25
|
-
],
|
|
26
|
-
)
|
|
27
|
-
: child,
|
|
28
|
-
),
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
}
|
lib/routes/home_screen.dart
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import 'package:flutter_swipe_detector/flutter_swipe_detector.dart';
|
|
3
3
|
import 'package:go_router/go_router.dart';
|
|
4
|
+
import 'package:only_bible_app/components/header.dart';
|
|
4
5
|
import 'package:only_bible_app/components/verse_view.dart';
|
|
5
6
|
import 'package:only_bible_app/state.dart';
|
|
6
7
|
|
|
@@ -14,8 +15,9 @@ class HomeScreen extends GoRouteData {
|
|
|
14
15
|
|
|
15
16
|
@override
|
|
16
17
|
Page buildPage(BuildContext context, GoRouterState state) {
|
|
17
|
-
|
|
18
|
+
if (slideTextDir.value == null) {
|
|
18
|
-
|
|
19
|
+
return NoTransitionPage(child: Home(book: book, chapter: chapter));
|
|
20
|
+
}
|
|
19
21
|
return CustomTransitionPage(
|
|
20
22
|
barrierDismissible: false,
|
|
21
23
|
barrierColor: Theme.of(context).colorScheme.background,
|
|
@@ -29,29 +31,51 @@ class HomeScreen extends GoRouteData {
|
|
|
29
31
|
child: child,
|
|
30
32
|
);
|
|
31
33
|
},
|
|
34
|
+
child: Home(book: book, chapter: chapter),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
class Home extends StatelessWidget {
|
|
40
|
+
final String book;
|
|
41
|
+
final int chapter;
|
|
42
|
+
|
|
43
|
+
const Home({required this.book, required this.chapter});
|
|
44
|
+
|
|
45
|
+
@override
|
|
46
|
+
Widget build(BuildContext context) {
|
|
47
|
+
final selectedBook = selectedBible.value.firstWhere((it) => book == it.name);
|
|
48
|
+
final verses = selectedBook.chapters[chapter].verses;
|
|
32
|
-
|
|
49
|
+
return SwipeDetector(
|
|
33
|
-
|
|
50
|
+
onSwipeLeft: (offset) {
|
|
34
|
-
|
|
51
|
+
onNext(context);
|
|
35
|
-
|
|
52
|
+
},
|
|
36
|
-
|
|
53
|
+
onSwipeRight: (offset) {
|
|
37
|
-
|
|
54
|
+
onPrevious(context);
|
|
38
|
-
|
|
55
|
+
},
|
|
56
|
+
child: Column(
|
|
57
|
+
children: [
|
|
58
|
+
const Header(),
|
|
59
|
+
Flexible(
|
|
39
|
-
|
|
60
|
+
child: SelectionArea(
|
|
40
|
-
|
|
61
|
+
child: ListView.builder(
|
|
41
|
-
|
|
62
|
+
padding: const EdgeInsets.only(
|
|
42
|
-
|
|
63
|
+
left: 20,
|
|
43
|
-
|
|
64
|
+
right: 20,
|
|
65
|
+
bottom: 20,
|
|
66
|
+
),
|
|
67
|
+
itemCount: verses.length,
|
|
68
|
+
itemBuilder: (BuildContext context, int index) {
|
|
69
|
+
final v = verses[index];
|
|
70
|
+
return Container(
|
|
71
|
+
margin: const EdgeInsets.symmetric(vertical: 6),
|
|
72
|
+
child: VerseText(index: index, text: v.text),
|
|
73
|
+
);
|
|
74
|
+
},
|
|
75
|
+
),
|
|
44
76
|
),
|
|
45
|
-
itemCount: verses.length,
|
|
46
|
-
itemBuilder: (BuildContext context, int index) {
|
|
47
|
-
final v = verses[index];
|
|
48
|
-
return Container(
|
|
49
|
-
margin: const EdgeInsets.symmetric(vertical: 6),
|
|
50
|
-
child: VerseText(index: index, text: v.text),
|
|
51
|
-
);
|
|
52
|
-
},
|
|
53
77
|
),
|
|
54
|
-
|
|
78
|
+
],
|
|
55
79
|
),
|
|
56
80
|
);
|
|
57
81
|
}
|
lib/state.dart
CHANGED
|
@@ -37,7 +37,7 @@ final chapterIndex = PersistentValueNotifier<int>(
|
|
|
37
37
|
initialValue: 0,
|
|
38
38
|
);
|
|
39
39
|
|
|
40
|
-
final slideTextDir = ValueNotifier<TextDirection>(
|
|
40
|
+
final slideTextDir = ValueNotifier<TextDirection?>(null);
|
|
41
41
|
final selectedBible = ValueNotifier<List<Book>>([]);
|
|
42
42
|
final selectedVerses = ValueNotifier([]);
|
|
43
43
|
final isPlaying = ValueNotifier(false);
|
|
@@ -71,8 +71,8 @@ decreaseFont() {
|
|
|
71
71
|
updateStatusBar() {
|
|
72
72
|
if (darkMode.value) {
|
|
73
73
|
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
|
74
|
-
systemNavigationBarColor:
|
|
74
|
+
systemNavigationBarColor: Color(0xFF1F1F22),
|
|
75
|
-
statusBarColor:
|
|
75
|
+
statusBarColor: Color(0xFF1F1F22),
|
|
76
76
|
systemNavigationBarIconBrightness: Brightness.light,
|
|
77
77
|
statusBarIconBrightness: Brightness.light,
|
|
78
78
|
));
|
|
@@ -86,23 +86,31 @@ updateStatusBar() {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
navigateBookChapter(BuildContext context, int book, int chapter) {
|
|
89
|
+
navigateBookChapter(BuildContext context, int book, int chapter, bool noAnim) {
|
|
90
|
+
if (isWide(context) || noAnim) {
|
|
91
|
+
slideTextDir.value = null;
|
|
92
|
+
} else {
|
|
93
|
+
slideTextDir.value = bookIndex.value > book || chapterIndex.value > chapter ? TextDirection.rtl : TextDirection.ltr;
|
|
94
|
+
print(slideTextDir.value);
|
|
95
|
+
}
|
|
90
96
|
bookIndex.value = book;
|
|
91
97
|
chapterIndex.value = chapter;
|
|
92
98
|
context.push("/${selectedBible.value[book].name}/$chapter");
|
|
99
|
+
// Use this or use navigatorKey once header moves scaffold
|
|
100
|
+
// if (!isWide(context)) {
|
|
93
|
-
context.pop();
|
|
101
|
+
// context.pop();
|
|
102
|
+
// }
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
onNext(BuildContext context) {
|
|
97
106
|
final selectedBook = selectedBible.value[bookIndex.value];
|
|
98
107
|
final chapter = chapterIndex.value;
|
|
99
|
-
slideTextDir.value = TextDirection.ltr;
|
|
100
108
|
if (selectedBook.chapters.length > chapter + 1) {
|
|
101
|
-
navigateBookChapter(context, selectedBook.index, chapter + 1);
|
|
109
|
+
navigateBookChapter(context, selectedBook.index, chapter + 1, false);
|
|
102
110
|
} else {
|
|
103
111
|
if (selectedBook.index + 1 < selectedBible.value.length) {
|
|
104
112
|
final nextBook = selectedBible.value[selectedBook.index + 1];
|
|
105
|
-
navigateBookChapter(context, nextBook.index, 0);
|
|
113
|
+
navigateBookChapter(context, nextBook.index, 0, false);
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
116
|
}
|
|
@@ -110,13 +118,12 @@ onNext(BuildContext context) {
|
|
|
110
118
|
onPrevious(BuildContext context) {
|
|
111
119
|
final selectedBook = selectedBible.value[bookIndex.value];
|
|
112
120
|
final chapter = chapterIndex.value;
|
|
113
|
-
slideTextDir.value = TextDirection.rtl;
|
|
114
121
|
if (chapter - 1 >= 0) {
|
|
115
|
-
navigateBookChapter(context, selectedBook.index, chapter - 1);
|
|
122
|
+
navigateBookChapter(context, selectedBook.index, chapter - 1, false);
|
|
116
123
|
} else {
|
|
117
124
|
if (selectedBook.index - 1 >= 0) {
|
|
118
125
|
final prevBook = selectedBible.value[selectedBook.index - 1];
|
|
119
|
-
navigateBookChapter(context, prevBook.index, prevBook.chapters.length - 1);
|
|
126
|
+
navigateBookChapter(context, prevBook.index, prevBook.chapters.length - 1, false);
|
|
120
127
|
}
|
|
121
128
|
}
|
|
122
129
|
}
|
|
@@ -210,4 +217,4 @@ onVerseSelected(int i) {
|
|
|
210
217
|
} else {
|
|
211
218
|
selectedVerses.value = [...selectedVerses.value, i];
|
|
212
219
|
}
|
|
213
|
-
}
|
|
220
|
+
}
|