~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.


3386df20 pyrossh

2 years ago
unify desktop interface
lib/{utils/dialog.dart → dialog.dart} RENAMED
File without changes
lib/screens/chapter_view_screen.dart CHANGED
@@ -1,6 +1,5 @@
1
1
  import "package:flutter/material.dart";
2
2
  import "package:only_bible_app/widgets/chapter_app_bar.dart";
3
- import "package:only_bible_app/widgets/header.dart";
4
3
  import "package:only_bible_app/state.dart";
5
4
  import "package:only_bible_app/widgets/sidebar.dart";
6
5
  import "package:only_bible_app/widgets/verses_view.dart";
@@ -49,7 +48,11 @@ class ChapterViewScreen extends StatelessWidget {
49
48
  Flexible(
50
49
  child: Column(
51
50
  children: [
52
- Header(),
51
+ ChapterAppBar(),
52
+ Padding(
53
+ padding: EdgeInsets.only(bottom: 10),
54
+ child: Divider(height: 5, indent: 20, endIndent: 20, thickness: 1.5),
55
+ ),
53
56
  Flexible(
54
57
  child: VersesView(),
55
58
  ),
lib/state.dart CHANGED
@@ -9,13 +9,21 @@ import "package:flutter/services.dart";
9
9
  import "package:flutter/material.dart";
10
10
  import "package:just_audio/just_audio.dart";
11
11
  import "package:only_bible_app/screens/chapter_view_screen.dart";
12
- import "package:only_bible_app/utils/dialog.dart";
12
+ import 'package:only_bible_app/dialog.dart';
13
13
  import "package:only_bible_app/models.dart";
14
14
  import "package:only_bible_app/widgets/actions_sheet.dart";
15
15
  import "package:only_bible_app/widgets/settings_sheet.dart";
16
16
  import "package:provider/provider.dart";
17
17
  import "package:shared_preferences/shared_preferences.dart";
18
18
 
19
+ class HistoryFrame {
20
+ final int book;
21
+ final int chapter;
22
+ final int? verse;
23
+
24
+ const HistoryFrame({required this.book, required this.chapter, this.verse});
25
+ }
26
+
19
27
  class AppModel extends ChangeNotifier {
20
28
  String languageCode = "en";
21
29
  Bible bible = bibles.first;
@@ -23,6 +31,7 @@ class AppModel extends ChangeNotifier {
23
31
  bool fontBold = false;
24
32
  double textScaleFactor = 0;
25
33
  bool actionsShown = false;
34
+ List<HistoryFrame> history = [];
26
35
 
27
36
  static AppModel of(BuildContext context) {
28
37
  return Provider.of(context, listen: true);
@@ -215,7 +224,11 @@ class ChapterViewModel extends ChangeNotifier {
215
224
  final selectedBible = AppModel.ofEvent(context).bible;
216
225
  final selectedBook = selectedBible.books[book];
217
226
  if (chapter - 1 >= 0) {
227
+ // if (Navigator.of(context).canPop()) {
228
+ // Navigator.of(context).pop();
229
+ // } else {
218
230
  navigateBookChapter(context, selectedBook.index, chapter - 1, TextDirection.rtl);
231
+ // }
219
232
  } else {
220
233
  if (selectedBook.index - 1 >= 0) {
221
234
  final prevBook = selectedBible.books[selectedBook.index - 1];
@@ -233,20 +246,16 @@ class ChapterViewModel extends ChangeNotifier {
233
246
  }
234
247
 
235
248
  void onVerseSelected(BuildContext context, int i) {
236
- if (!isWide(context)) {
237
- if (selectedVerses.isEmpty) {
249
+ if (selectedVerses.isEmpty) {
238
- AppModel.ofEvent(context).showActions(context);
250
+ AppModel.ofEvent(context).showActions(context);
239
- }
240
251
  }
241
252
  if (selectedVerses.contains(i)) {
242
253
  selectedVerses.remove(i);
243
254
  } else {
244
255
  selectedVerses.add(i);
245
256
  }
246
- if (!isWide(context)) {
247
- if (selectedVerses.isEmpty) {
257
+ if (selectedVerses.isEmpty) {
248
- AppModel.ofEvent(context).hideActions(context);
258
+ AppModel.ofEvent(context).hideActions(context);
249
- }
250
259
  }
251
260
  notifyListeners();
252
261
  }
lib/widgets/actions_sheet.dart CHANGED
@@ -14,38 +14,40 @@ class ActionsSheet extends StatelessWidget {
14
14
  final model = ChapterViewModel.of(context);
15
15
  final audioIcon = model.isPlaying ? Icons.pause_circle_outline : Icons.play_circle_outline;
16
16
  final audioText = model.isPlaying ? "Pause" : "Play";
17
+ final isDesktop = isWide(context);
17
18
  return Container(
18
- height: 160,
19
+ height: isDesktop ? 80 : 160,
19
20
  color: Theme.of(context).colorScheme.background,
20
21
  padding: EdgeInsets.only(bottom: isIOS() ? 20 : 0, left: 20, right: 20, top: 10),
21
22
  child: Column(
22
23
  mainAxisAlignment: MainAxisAlignment.spaceAround,
23
24
  children: [
25
+ if (!isDesktop)
24
- Row(
26
+ Row(
25
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
27
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
26
- children: [
28
+ children: [
27
- HighlightButton(
29
+ HighlightButton(
28
- color: const Color(0xFFDAEFFE),
30
+ color: const Color(0xFFDAEFFE),
29
- onTap: () {},
31
+ onTap: () {},
30
- ),
32
+ ),
31
- HighlightButton(
33
+ HighlightButton(
32
- color: const Color(0xFFFFFBB1),
34
+ color: const Color(0xFFFFFBB1),
33
- onTap: () {},
35
+ onTap: () {},
34
- ),
36
+ ),
35
- HighlightButton(
37
+ HighlightButton(
36
- color: const Color(0xFFFFDEF3),
38
+ color: const Color(0xFFFFDEF3),
37
- onTap: () {},
39
+ onTap: () {},
38
- ),
40
+ ),
39
- HighlightButton(
41
+ HighlightButton(
40
- color: const Color(0xFFE6FCC3),
42
+ color: const Color(0xFFE6FCC3),
41
- onTap: () {},
43
+ onTap: () {},
42
- ),
44
+ ),
43
- HighlightButton(
45
+ HighlightButton(
44
- color: const Color(0xFFEADDFF),
46
+ color: const Color(0xFFEADDFF),
45
- onTap: () {},
47
+ onTap: () {},
46
- ),
48
+ ),
47
- ],
49
+ ],
48
- ),
50
+ ),
49
51
  // const Padding(padding: EdgeInsets.only(top: 10)),
50
52
  Row(
51
53
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
lib/widgets/chapter_app_bar.dart CHANGED
@@ -1,7 +1,6 @@
1
1
  import "package:flutter/material.dart";
2
2
  import "package:only_bible_app/screens/book_select_screen.dart";
3
3
  import "package:only_bible_app/state.dart";
4
- import "package:only_bible_app/widgets/more_button.dart";
5
4
 
6
5
  class ChapterAppBar extends StatelessWidget implements PreferredSizeWidget {
7
6
  const ChapterAppBar({super.key});
@@ -16,8 +15,8 @@ class ChapterAppBar extends StatelessWidget implements PreferredSizeWidget {
16
15
  final selectedBook = selectedBible.books[model.book];
17
16
  final bookName = selectedBook.name;
18
17
  return SafeArea(
19
- child: Padding(
18
+ child: Container(
20
- padding: const EdgeInsets.only(left: 18, right: 5, bottom: 0),
19
+ padding: const EdgeInsets.only(left: 18, right: 5),
21
20
  child: Row(
22
21
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
23
22
  children: [
@@ -45,7 +44,11 @@ class ChapterAppBar extends StatelessWidget implements PreferredSizeWidget {
45
44
  ],
46
45
  ),
47
46
  ),
48
- const MoreButton(),
47
+ IconButton(
48
+ padding: EdgeInsets.zero,
49
+ onPressed: () => AppModel.ofEvent(context).showSettings(context),
50
+ icon: const Icon(Icons.more_vert, size: 24),
51
+ ),
49
52
  ],
50
53
  ),
51
54
  ),
lib/widgets/header.dart DELETED
@@ -1,91 +0,0 @@
1
- import "package:flutter/material.dart";
2
- import "package:only_bible_app/screens/bible_select_screen.dart";
3
- import "package:only_bible_app/screens/book_select_screen.dart";
4
- import "package:only_bible_app/widgets/play_button.dart";
5
- import "package:only_bible_app/widgets/menu.dart";
6
- import "package:only_bible_app/state.dart";
7
-
8
- class Header extends StatelessWidget {
9
- const Header({super.key});
10
-
11
- @override
12
- Widget build(BuildContext context) {
13
- final selectedBible = AppModel.of(context).bible;
14
- final model = ChapterViewModel.of(context);
15
- final selectedBook = selectedBible.books[model.book];
16
- final bookName = selectedBook.name;
17
- final isDesktop = isWide(context);
18
- // Localizations.localeOf(context).languageCode
19
- return Container(
20
- padding: EdgeInsets.only(
21
- left: 20,
22
- right: 20,
23
- top: isWide(context) ? 10 : 0,
24
- bottom: 0,
25
- ),
26
- child: Column(
27
- children: [
28
- Row(
29
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
30
- crossAxisAlignment: CrossAxisAlignment.center,
31
- children: [
32
- TextButton.icon(
33
- style: TextButton.styleFrom(
34
- padding: EdgeInsets.zero,
35
- backgroundColor: Theme.of(context).colorScheme.background,
36
- elevation: 0,
37
- ),
38
- label: Icon(
39
- Icons.expand_more,
40
- size: 28,
41
- color: Theme.of(context).textTheme.headlineMedium!.color,
42
- ),
43
- icon: Text(
44
- "$bookName ${model.chapter + 1}",
45
- style: Theme.of(context).textTheme.headlineMedium,
46
- ),
47
- onPressed: () {
48
- Navigator.of(context).push(
49
- createNoTransitionPageRoute(
50
- BookSelectScreen(bible: selectedBible),
51
- ),
52
- );
53
- },
54
- ),
55
- // TODO: show this in more menu in mobile
56
- Row(
57
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
58
- children: [
59
- if (isDesktop)
60
- Container(
61
- margin: EdgeInsets.only(right: isWide(context) ? 10 : 8),
62
- child: TextButton(
63
- style: TextButton.styleFrom(
64
- padding: const EdgeInsets.symmetric(horizontal: 20),
65
- ),
66
- child: Text(selectedBible.name),
67
- onPressed: () {
68
- Navigator.of(context).push(
69
- createNoTransitionPageRoute(
70
- const BibleSelectScreen(),
71
- ),
72
- );
73
- },
74
- ),
75
- ),
76
- if (isDesktop)
77
- Container(
78
- margin: EdgeInsets.only(right: isWide(context) ? 10 : 8),
79
- child: const PlayButton(),
80
- ),
81
- const Menu(),
82
- ],
83
- ),
84
- ],
85
- ),
86
- Divider(height: isDesktop ? 10 : 0, endIndent: 10, thickness: isDesktop ? 1.5 : 1),
87
- ],
88
- ),
89
- );
90
- }
91
- }
lib/widgets/menu.dart DELETED
@@ -1,92 +0,0 @@
1
- import "package:flutter/material.dart";
2
- import "package:only_bible_app/state.dart";
3
- import "package:only_bible_app/screens/bible_select_screen.dart";
4
-
5
- class Menu extends StatelessWidget {
6
- const Menu({super.key});
7
-
8
- @override
9
- Widget build(BuildContext context) {
10
- final isDesktop = isWide(context);
11
- final model = AppModel.of(context);
12
- final modeIcon = model.darkMode ? Icons.dark_mode : Icons.light_mode;
13
- final boldColor = model.fontBold ? Theme.of(context).shadowColor : Colors.grey;
14
- return PopupMenuButton(
15
- padding: EdgeInsets.zero,
16
- icon: Icon(Icons.more_vert, size: isDesktop ? 28 : 22),
17
- offset: Offset(0.0, isDesktop ? 60 : 30),
18
- onSelected: (int v) {
19
- if (v == 1) {
20
- Navigator.of(context).push(
21
- createNoTransitionPageRoute(
22
- const BibleSelectScreen(),
23
- ),
24
- );
25
- }
26
- if (v == 2) {
27
- model.toggleMode();
28
- }
29
- if (v == 3) {
30
- model.toggleBold();
31
- }
32
- if (v == 4) {
33
- model.increaseFont();
34
- }
35
- if (v == 5) {
36
- model.decreaseFont();
37
- }
38
- },
39
- itemBuilder: (BuildContext itemContext) {
40
- return [
41
- if (!isDesktop)
42
- PopupMenuItem(
43
- value: 1,
44
- child: Container(
45
- alignment: Alignment.center,
46
- margin: const EdgeInsets.symmetric(vertical: 15),
47
- child: Text(
48
- model.bible.shortName(),
49
- style: const TextStyle(
50
- fontSize: 18,
51
- fontWeight: FontWeight.bold,
52
- ),
53
- ),
54
- ),
55
- ),
56
- PopupMenuItem(
57
- value: 2,
58
- child: Container(
59
- alignment: Alignment.center,
60
- margin: const EdgeInsets.symmetric(vertical: 15),
61
- child: Icon(modeIcon, size: 28),
62
- ),
63
- ),
64
- PopupMenuItem(
65
- value: 3,
66
- child: Container(
67
- alignment: Alignment.center,
68
- margin: const EdgeInsets.symmetric(vertical: 15),
69
- child: Icon(Icons.format_bold, size: 28, color: boldColor),
70
- ),
71
- ),
72
- PopupMenuItem(
73
- value: 4,
74
- child: Container(
75
- alignment: Alignment.center,
76
- margin: const EdgeInsets.symmetric(vertical: 15),
77
- child: const Icon(Icons.add_circle, size: 28),
78
- ),
79
- ),
80
- PopupMenuItem(
81
- value: 5,
82
- child: Container(
83
- alignment: Alignment.center,
84
- margin: const EdgeInsets.symmetric(vertical: 15),
85
- child: const Icon(Icons.remove_circle, size: 28),
86
- ),
87
- ),
88
- ];
89
- },
90
- );
91
- }
92
- }
lib/widgets/play_button.dart DELETED
@@ -1,20 +0,0 @@
1
- import "package:flutter/material.dart";
2
- import "package:only_bible_app/state.dart";
3
-
4
- class PlayButton extends StatelessWidget {
5
- const PlayButton({super.key});
6
-
7
- @override
8
- Widget build(BuildContext context) {
9
- final model = ChapterViewModel.of(context);
10
- final icon = model.isPlaying ? Icons.pause_circle_filled : Icons.play_circle_fill;
11
- final size = isWide(context) ? 28.0 : 42.0;
12
-
13
- return IconButton(
14
- icon: Icon(icon, size: size),
15
- onPressed: () {
16
- model.onPlay(context);
17
- },
18
- );
19
- }
20
- }
lib/widgets/tile.dart DELETED
@@ -1,23 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:only_bible_app/state.dart';
3
-
4
- class Tile extends StatelessWidget {
5
- final String name;
6
- final VoidCallback onPressed;
7
-
8
- const Tile({super.key, required this.name, required this.onPressed});
9
-
10
- @override
11
- Widget build(BuildContext context) {
12
- final availableWidth = MediaQuery.of(context).size.width - 40; // width - margin
13
- return Container(
14
- width: isWide(context) ? 60 : (availableWidth/5).round() - 13,
15
- height: isWide(context) ? 60 : 40,
16
- margin: const EdgeInsets.only(right: 16, bottom: 16),
17
- child: TextButton(
18
- onPressed: onPressed,
19
- child: Text(name),
20
- ),
21
- );
22
- }
23
- }