~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.
8120183d
—
pyrossh 2 years ago
Fix locale issues
- lib/app.dart +6 -4
- lib/main.dart +2 -4
- lib/models.dart +2 -2
- lib/providers/app_provider.dart +13 -82
- lib/screens/bible_select_screen.dart +19 -25
- lib/screens/book_select_screen.dart +3 -4
- lib/screens/chapter_view_screen.dart +2 -3
- lib/sheets/actions_sheet.dart +2 -6
- lib/sheets/highlight_sheet.dart +1 -2
- lib/theme.dart +2 -2
- lib/utils.dart +97 -14
- lib/widgets/chapter_app_bar.dart +1 -1
- lib/widgets/scaffold_menu.dart +5 -4
- lib/widgets/sliver_tile_grid.dart +2 -3
lib/app.dart
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
|
3
|
+
import "package:only_bible_app/screens/bible_select_screen.dart";
|
|
3
4
|
import "package:only_bible_app/screens/chapter_view_screen.dart";
|
|
4
5
|
import "package:only_bible_app/theme.dart";
|
|
5
6
|
import "package:only_bible_app/utils.dart";
|
|
6
7
|
import "package:only_bible_app/widgets/scaffold_markdown.dart";
|
|
7
8
|
|
|
8
9
|
class App extends StatelessWidget {
|
|
10
|
+
final bool firstOpen;
|
|
9
11
|
final int initialBook;
|
|
10
12
|
final int initialChapter;
|
|
11
13
|
|
|
12
|
-
const App({super.key, required this.initialBook, required this.initialChapter});
|
|
14
|
+
const App({super.key, required this.firstOpen, required this.initialBook, required this.initialChapter});
|
|
13
15
|
|
|
14
16
|
@override
|
|
15
17
|
Widget build(BuildContext context) {
|
|
16
18
|
return MaterialApp(
|
|
17
|
-
title: "Only Bible App",
|
|
18
|
-
|
|
19
|
+
onGenerateTitle: (context) => context.l10n.title,
|
|
19
20
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
20
21
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
21
22
|
debugShowCheckedModeBanner: false,
|
|
22
23
|
themeMode: context.app.darkMode ? ThemeMode.dark : ThemeMode.light,
|
|
23
24
|
theme: lightTheme,
|
|
24
25
|
darkTheme: darkTheme,
|
|
26
|
+
locale: context.app.locale,
|
|
25
27
|
// initialRoute: "",
|
|
26
28
|
routes: {
|
|
27
29
|
// TODO: maybe have a landing page
|
|
@@ -29,7 +31,7 @@ class App extends StatelessWidget {
|
|
|
29
31
|
"/privacy-policy": (context) => const ScaffoldMarkdown(title: "Privacy Policy", file: "privacy-policy.md"),
|
|
30
32
|
"/about-us": (context) => const ScaffoldMarkdown(title: "About Us", file: "about-us.md"),
|
|
31
33
|
},
|
|
32
|
-
home: ChapterViewScreen(book: initialBook, chapter: initialChapter),
|
|
34
|
+
home: firstOpen ? const BibleSelectScreen() : ChapterViewScreen(book: initialBook, chapter: initialChapter),
|
|
33
35
|
);
|
|
34
36
|
}
|
|
35
37
|
}
|
lib/main.dart
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
-
import "package:intl/intl.dart";
|
|
3
2
|
import "package:flutter/foundation.dart";
|
|
4
3
|
import "package:flutter_web_plugins/url_strategy.dart";
|
|
5
4
|
import "package:firebase_core/firebase_core.dart";
|
|
@@ -25,13 +24,12 @@ void main() async {
|
|
|
25
24
|
};
|
|
26
25
|
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
|
27
26
|
usePathUrlStrategy();
|
|
28
|
-
print(Intl.getCurrentLocale());
|
|
29
27
|
final model = AppProvider();
|
|
30
|
-
final (book, chapter) = await model.loadData();
|
|
28
|
+
final (firstOpen, book, chapter) = await model.loadData();
|
|
31
29
|
runApp(
|
|
32
30
|
ChangeNotifierProvider.value(
|
|
33
31
|
value: model,
|
|
34
|
-
child: App(initialBook: book, initialChapter: chapter),
|
|
32
|
+
child: App(firstOpen: firstOpen, initialBook: book, initialChapter: chapter),
|
|
35
33
|
),
|
|
36
34
|
);
|
|
37
35
|
FlutterNativeSplash.remove();
|
lib/models.dart
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
-
import "package:only_bible_app/
|
|
2
|
+
import "package:only_bible_app/utils.dart";
|
|
3
3
|
|
|
4
4
|
class Bible {
|
|
5
5
|
final String name;
|
|
@@ -37,7 +37,7 @@ class Book {
|
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
String name(BuildContext context) {
|
|
40
|
-
return
|
|
40
|
+
return context.bookNames[index];
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
bool isOldTestament() => index < 39;
|
lib/providers/app_provider.dart
CHANGED
|
@@ -7,7 +7,6 @@ import "package:only_bible_app/dialog.dart";
|
|
|
7
7
|
import "package:only_bible_app/screens/chapter_view_screen.dart";
|
|
8
8
|
import "package:only_bible_app/theme.dart";
|
|
9
9
|
import "package:share_plus/share_plus.dart";
|
|
10
|
-
import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
|
11
10
|
import "package:flutter/material.dart";
|
|
12
11
|
import "package:flutter/services.dart";
|
|
13
12
|
import "package:only_bible_app/screens/bible_select_screen.dart";
|
|
@@ -36,6 +35,7 @@ class AppProvider extends ChangeNotifier {
|
|
|
36
35
|
late PackageInfo packageInfo;
|
|
37
36
|
late Bible bible;
|
|
38
37
|
late Locale locale;
|
|
38
|
+
bool firstOpen = true;
|
|
39
39
|
bool engTitles = false;
|
|
40
40
|
bool darkMode = false;
|
|
41
41
|
bool fontBold = false;
|
|
@@ -57,24 +57,22 @@ class AppProvider extends ChangeNotifier {
|
|
|
57
57
|
return Provider.of(context, listen: false);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
static AppLocalizations getLocalizations(BuildContext context) {
|
|
61
|
-
return AppProvider.of(context).engTitles
|
|
62
|
-
? lookupAppLocalizations(const Locale("en"))
|
|
63
|
-
: AppLocalizations.of(context)!;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
60
|
save() async {
|
|
67
61
|
final prefs = await SharedPreferences.getInstance();
|
|
62
|
+
await prefs.setBool("firstOpen", firstOpen);
|
|
68
63
|
await prefs.setString("bibleName", bible.name);
|
|
64
|
+
await prefs.setBool("engTitles", engTitles);
|
|
69
65
|
await prefs.setBool("darkMode", darkMode);
|
|
70
66
|
await prefs.setBool("fontBold", fontBold);
|
|
71
67
|
await prefs.setDouble("textScaleFactor", textScaleFactor);
|
|
72
68
|
await prefs.setString("languageCode", locale.languageCode);
|
|
73
69
|
}
|
|
74
70
|
|
|
75
|
-
Future<(int, int)> loadData() async {
|
|
71
|
+
Future<(bool, int, int)> loadData() async {
|
|
76
72
|
packageInfo = await PackageInfo.fromPlatform();
|
|
77
73
|
final prefs = await SharedPreferences.getInstance();
|
|
74
|
+
engTitles = prefs.getBool("engTitles") ?? false;
|
|
75
|
+
firstOpen = prefs.getBool("firstOpen") ?? true;
|
|
78
76
|
darkMode = prefs.getBool("darkMode") ?? false;
|
|
79
77
|
fontBold = prefs.getBool("fontBold") ?? false;
|
|
80
78
|
textScaleFactor = prefs.getDouble("textScaleFactor") ?? 1;
|
|
@@ -84,7 +82,7 @@ class AppProvider extends ChangeNotifier {
|
|
|
84
82
|
final book = prefs.getInt("book") ?? 0;
|
|
85
83
|
final chapter = prefs.getInt("chapter") ?? 0;
|
|
86
84
|
updateStatusBar();
|
|
87
|
-
return (book, chapter);
|
|
85
|
+
return (firstOpen, book, chapter);
|
|
88
86
|
}
|
|
89
87
|
|
|
90
88
|
Future<Bible> loadBible(String name) async {
|
|
@@ -103,78 +101,6 @@ class AppProvider extends ChangeNotifier {
|
|
|
103
101
|
);
|
|
104
102
|
}
|
|
105
103
|
|
|
106
|
-
List<String> getBookNames(BuildContext context) {
|
|
107
|
-
final l = getLocalizations(context);
|
|
108
|
-
return [
|
|
109
|
-
l.genesis,
|
|
110
|
-
l.exodus,
|
|
111
|
-
l.leviticus,
|
|
112
|
-
l.numbers,
|
|
113
|
-
l.deuteronomy,
|
|
114
|
-
l.joshua,
|
|
115
|
-
l.judges,
|
|
116
|
-
l.ruth,
|
|
117
|
-
l.firstSamuel,
|
|
118
|
-
l.secondSamuel,
|
|
119
|
-
l.firstKings,
|
|
120
|
-
l.secondKings,
|
|
121
|
-
l.firstChronicles,
|
|
122
|
-
l.secondChronicles,
|
|
123
|
-
l.ezra,
|
|
124
|
-
l.nehemiah,
|
|
125
|
-
l.esther,
|
|
126
|
-
l.job,
|
|
127
|
-
l.psalms,
|
|
128
|
-
l.proverbs,
|
|
129
|
-
l.ecclesiastes,
|
|
130
|
-
l.song_of_solomon,
|
|
131
|
-
l.isaiah,
|
|
132
|
-
l.jeremiah,
|
|
133
|
-
l.lamentations,
|
|
134
|
-
l.ezekiel,
|
|
135
|
-
l.daniel,
|
|
136
|
-
l.hosea,
|
|
137
|
-
l.joel,
|
|
138
|
-
l.amos,
|
|
139
|
-
l.obadiah,
|
|
140
|
-
l.jonah,
|
|
141
|
-
l.micah,
|
|
142
|
-
l.nahum,
|
|
143
|
-
l.habakkuk,
|
|
144
|
-
l.zephaniah,
|
|
145
|
-
l.haggai,
|
|
146
|
-
l.zechariah,
|
|
147
|
-
l.malachi,
|
|
148
|
-
l.matthew,
|
|
149
|
-
l.mark,
|
|
150
|
-
l.luke,
|
|
151
|
-
l.john,
|
|
152
|
-
l.acts,
|
|
153
|
-
l.romans,
|
|
154
|
-
l.firstCorinthians,
|
|
155
|
-
l.secondCorinthians,
|
|
156
|
-
l.galatians,
|
|
157
|
-
l.ephesians,
|
|
158
|
-
l.philippians,
|
|
159
|
-
l.colossians,
|
|
160
|
-
l.firstThessalonians,
|
|
161
|
-
l.secondThessalonians,
|
|
162
|
-
l.firstTimothy,
|
|
163
|
-
l.secondTimothy,
|
|
164
|
-
l.titus,
|
|
165
|
-
l.philemon,
|
|
166
|
-
l.hebrews,
|
|
167
|
-
l.james,
|
|
168
|
-
l.firstPeter,
|
|
169
|
-
l.secondPeter,
|
|
170
|
-
l.firstJohn,
|
|
171
|
-
l.secondJohn,
|
|
172
|
-
l.thirdJohn,
|
|
173
|
-
l.jude,
|
|
174
|
-
l.revelation,
|
|
175
|
-
];
|
|
176
|
-
}
|
|
177
|
-
|
|
178
104
|
hasAudio(BuildContext context) {
|
|
179
105
|
return context.l10n.hasAudio == "true";
|
|
180
106
|
}
|
|
@@ -240,6 +166,11 @@ class AppProvider extends ChangeNotifier {
|
|
|
240
166
|
);
|
|
241
167
|
}
|
|
242
168
|
|
|
169
|
+
updateFirstOpen() {
|
|
170
|
+
firstOpen = false;
|
|
171
|
+
save();
|
|
172
|
+
}
|
|
173
|
+
|
|
243
174
|
toggleDarkMode() {
|
|
244
175
|
darkMode = !darkMode;
|
|
245
176
|
updateStatusBar();
|
|
@@ -554,7 +485,7 @@ class AppProvider extends ChangeNotifier {
|
|
|
554
485
|
log("Could not play audio", name: "play", error: (err.toString(), pathname));
|
|
555
486
|
FirebaseCrashlytics.instance.recordFlutterError(FlutterErrorDetails(exception: (err.toString(), pathname)));
|
|
556
487
|
if (context.mounted) {
|
|
557
|
-
showError(context,
|
|
488
|
+
showError(context, context.l10n.audioError);
|
|
558
489
|
}
|
|
559
490
|
return;
|
|
560
491
|
} finally {
|
lib/screens/bible_select_screen.dart
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
-
import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
|
3
2
|
import "package:only_bible_app/providers/app_provider.dart";
|
|
4
3
|
import "package:only_bible_app/utils.dart";
|
|
5
4
|
import "package:only_bible_app/widgets/scaffold_menu.dart";
|
|
@@ -11,37 +10,32 @@ class BibleSelectScreen extends StatelessWidget {
|
|
|
11
10
|
|
|
12
11
|
@override
|
|
13
12
|
Widget build(BuildContext context) {
|
|
14
|
-
final locales = AppLocalizations.supportedLocales.sortedBy((e) => e.languageCode);
|
|
15
13
|
return ScaffoldMenu(
|
|
16
14
|
child: CustomScrollView(
|
|
17
15
|
physics: const BouncingScrollPhysics(),
|
|
18
16
|
slivers: [
|
|
19
|
-
SliverHeading(title: context.l10n.bibleSelectTitle, showClose:
|
|
17
|
+
SliverHeading(title: context.l10n.bibleSelectTitle, showClose: !context.app.firstOpen),
|
|
20
18
|
SliverTileGrid(
|
|
21
19
|
listType: ListType.large,
|
|
22
20
|
children: List.of(
|
|
23
|
-
locales.map((l) {
|
|
24
|
-
|
|
21
|
+
context.supportedLocalizations.map((l) {
|
|
25
|
-
context: context,
|
|
26
|
-
locale: Locale(l.languageCode),
|
|
27
|
-
child: Builder(
|
|
28
|
-
builder: (context) {
|
|
29
|
-
final bibleName = context.l10n.languageTitle;
|
|
30
|
-
|
|
22
|
+
return TextButton(
|
|
31
|
-
|
|
23
|
+
child: Text(l.languageTitle),
|
|
32
|
-
|
|
24
|
+
// child: Column(
|
|
33
|
-
|
|
25
|
+
// children: [
|
|
34
|
-
|
|
26
|
+
// Text(l.name),
|
|
35
|
-
|
|
27
|
+
// // Text("(${l.localName})"),
|
|
36
|
-
|
|
28
|
+
// ],
|
|
37
|
-
|
|
29
|
+
// ),
|
|
38
|
-
|
|
30
|
+
onPressed: () {
|
|
39
|
-
|
|
31
|
+
AppProvider.ofEvent(context).updateCurrentBible(context, Locale(l.localeName), l.languageTitle);
|
|
32
|
+
if (context.appEvent.firstOpen) {
|
|
33
|
+
context.appEvent.updateFirstOpen();
|
|
34
|
+
context.appEvent.pushBookChapter(context, 0, 0, null);
|
|
35
|
+
} else {
|
|
40
|
-
|
|
36
|
+
Navigator.of(context).pop();
|
|
37
|
+
}
|
|
41
|
-
|
|
38
|
+
},
|
|
42
|
-
);
|
|
43
|
-
},
|
|
44
|
-
),
|
|
45
39
|
);
|
|
46
40
|
}),
|
|
47
41
|
),
|
lib/screens/book_select_screen.dart
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
|
-
import "package:only_bible_app/
|
|
2
|
+
import "package:only_bible_app/utils.dart";
|
|
3
3
|
import "package:only_bible_app/widgets/scaffold_menu.dart";
|
|
4
4
|
import "package:only_bible_app/screens/chapter_select_screen.dart";
|
|
5
5
|
import "package:only_bible_app/widgets/sliver_heading.dart";
|
|
@@ -27,12 +27,11 @@ class BookSelectScreen extends StatelessWidget {
|
|
|
27
27
|
|
|
28
28
|
@override
|
|
29
29
|
Widget build(BuildContext context) {
|
|
30
|
-
final localizations = AppProvider.getLocalizations(context);
|
|
31
30
|
return ScaffoldMenu(
|
|
32
31
|
child: CustomScrollView(
|
|
33
32
|
physics: const BouncingScrollPhysics(),
|
|
34
33
|
slivers: [
|
|
35
|
-
SliverHeading(title:
|
|
34
|
+
SliverHeading(title: context.l10n.oldTestamentTitle, showClose: true),
|
|
36
35
|
SliverTileGrid(
|
|
37
36
|
children: List.of(
|
|
38
37
|
bible.getOldBooks().map((book) {
|
|
@@ -43,7 +42,7 @@ class BookSelectScreen extends StatelessWidget {
|
|
|
43
42
|
}),
|
|
44
43
|
),
|
|
45
44
|
),
|
|
46
|
-
SliverHeading(title:
|
|
45
|
+
SliverHeading(title: context.l10n.newTestamentTitle, top: 30, bottom: 20),
|
|
47
46
|
SliverTileGrid(
|
|
48
47
|
children: List.of(
|
|
49
48
|
bible.getNewBooks().map((book) {
|
lib/screens/chapter_view_screen.dart
CHANGED
|
@@ -31,17 +31,16 @@ class ChapterViewScreen extends StatelessWidget {
|
|
|
31
31
|
// );
|
|
32
32
|
// },
|
|
33
33
|
// ),
|
|
34
|
-
final isDesktop = isWide(context);
|
|
35
34
|
return ChangeNotifierProvider(
|
|
36
35
|
create: (_) => ChapterProvider(
|
|
37
36
|
book: book,
|
|
38
37
|
chapter: chapter,
|
|
39
38
|
),
|
|
40
39
|
child: Scaffold(
|
|
41
|
-
appBar:
|
|
40
|
+
appBar: context.isWide ? null : const ChapterAppBar(),
|
|
42
41
|
backgroundColor: Theme.of(context).colorScheme.background,
|
|
43
42
|
body: SafeArea(
|
|
44
|
-
child:
|
|
43
|
+
child: context.isWide
|
|
45
44
|
? const Row(
|
|
46
45
|
children: [
|
|
47
46
|
Sidebar(),
|
lib/sheets/actions_sheet.dart
CHANGED
|
@@ -9,7 +9,6 @@ class ActionsSheet extends StatelessWidget {
|
|
|
9
9
|
@override
|
|
10
10
|
Widget build(BuildContext context) {
|
|
11
11
|
final app = AppProvider.of(context);
|
|
12
|
-
final isDesktop = isWide(context);
|
|
13
12
|
final bottom = isIOS() ? 20.0 : 0.0;
|
|
14
13
|
final height = isIOS() ? 100.0 : 65.0;
|
|
15
14
|
final iconColor = app.darkMode ? Colors.white.withOpacity(0.9) : Colors.black.withOpacity(0.9);
|
|
@@ -20,7 +19,7 @@ class ActionsSheet extends StatelessWidget {
|
|
|
20
19
|
color: Theme.of(context).colorScheme.background,
|
|
21
20
|
padding: EdgeInsets.only(left: 20, right: 20, bottom: bottom),
|
|
22
21
|
child: Row(
|
|
23
|
-
mainAxisAlignment:
|
|
22
|
+
mainAxisAlignment: context.isWide ? MainAxisAlignment.spaceEvenly : MainAxisAlignment.spaceBetween,
|
|
24
23
|
children: [
|
|
25
24
|
IconButton(
|
|
26
25
|
padding: EdgeInsets.zero,
|
|
@@ -38,10 +37,7 @@ class ActionsSheet extends StatelessWidget {
|
|
|
38
37
|
if (audioEnabled) {
|
|
39
38
|
context.appEvent.onPlay(context);
|
|
40
39
|
} else {
|
|
41
|
-
showError(
|
|
42
|
-
context,
|
|
43
|
-
|
|
40
|
+
showError(context, context.l10n.audioNotAvailable);
|
|
44
|
-
);
|
|
45
41
|
}
|
|
46
42
|
},
|
|
47
43
|
icon: Icon(audioIcon, size: 34, color: audioEnabled ? iconColor : Colors.grey),
|
lib/sheets/highlight_sheet.dart
CHANGED
|
@@ -8,7 +8,6 @@ class HighlightSheet extends StatelessWidget {
|
|
|
8
8
|
|
|
9
9
|
@override
|
|
10
10
|
Widget build(BuildContext context) {
|
|
11
|
-
final isDesktop = isWide(context);
|
|
12
11
|
final bottom = isIOS() ? 20.0 : 0.0;
|
|
13
12
|
final height = isIOS() ? 100.0 : 65.0;
|
|
14
13
|
final iconColor = context.app.darkMode ? Colors.white.withOpacity(0.9) : Colors.black.withOpacity(0.9);
|
|
@@ -23,7 +22,7 @@ class HighlightSheet extends StatelessWidget {
|
|
|
23
22
|
color: context.theme.colorScheme.background,
|
|
24
23
|
padding: EdgeInsets.only(left: 20, right: 20, bottom: bottom),
|
|
25
24
|
child: Row(
|
|
26
|
-
mainAxisAlignment:
|
|
25
|
+
mainAxisAlignment: context.isWide ? MainAxisAlignment.spaceEvenly : MainAxisAlignment.spaceBetween,
|
|
27
26
|
children: [
|
|
28
27
|
IconButton(
|
|
29
28
|
padding: EdgeInsets.zero,
|
lib/theme.dart
CHANGED
|
@@ -65,8 +65,8 @@ final lightTheme = ThemeData(
|
|
|
65
65
|
),
|
|
66
66
|
appBarTheme: AppBarTheme(
|
|
67
67
|
backgroundColor: lightColorScheme.background,
|
|
68
|
+
foregroundColor: lightColorScheme.onBackground,
|
|
68
69
|
elevation: 1,
|
|
69
|
-
foregroundColor: lightColorScheme.primary,
|
|
70
70
|
),
|
|
71
71
|
bottomSheetTheme: const BottomSheetThemeData(
|
|
72
72
|
elevation: 10,
|
|
@@ -188,7 +188,7 @@ final darkTheme = lightTheme.copyWith(
|
|
|
188
188
|
shadowColor: Colors.white,
|
|
189
189
|
appBarTheme: AppBarTheme(
|
|
190
190
|
backgroundColor: darkColorScheme.background,
|
|
191
|
-
foregroundColor: darkColorScheme.
|
|
191
|
+
foregroundColor: darkColorScheme.onBackground,
|
|
192
192
|
elevation: 1,
|
|
193
193
|
),
|
|
194
194
|
bottomSheetTheme: lightTheme.bottomSheetTheme.copyWith(
|
lib/utils.dart
CHANGED
|
@@ -11,19 +11,110 @@ import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
|
|
11
11
|
import "package:provider/provider.dart";
|
|
12
12
|
|
|
13
13
|
extension MyIterable<E> on Iterable<E> {
|
|
14
|
-
Iterable<E> sortedBy(Comparable Function(E e) key) =>
|
|
14
|
+
Iterable<E> sortedBy(Comparable Function(E e) key) => toList()..sort((a, b) => key(a).compareTo(key(b)));
|
|
15
|
-
toList()..sort((a, b) => key(a).compareTo(key(b)));
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
extension AppContext on BuildContext {
|
|
19
18
|
ThemeData get theme => Theme.of(this);
|
|
19
|
+
|
|
20
|
-
AppLocalizations get l10n => app.engTitles
|
|
20
|
+
AppLocalizations get l10n => app.engTitles && app.locale.languageCode != "en"
|
|
21
|
+
? lookupAppLocalizations(const Locale("en"))
|
|
22
|
+
: AppLocalizations.of(this)!;
|
|
23
|
+
|
|
21
24
|
AppProvider get app => Provider.of(this, listen: true);
|
|
25
|
+
|
|
22
26
|
AppProvider get appEvent => Provider.of(this, listen: false);
|
|
27
|
+
|
|
23
28
|
ChapterProvider get chapter => Provider.of(this, listen: true);
|
|
29
|
+
|
|
24
30
|
ChapterProvider get chapterEvent => Provider.of(this, listen: false);
|
|
25
|
-
}
|
|
26
31
|
|
|
32
|
+
bool get isWide {
|
|
33
|
+
if (defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
final width = MediaQuery.of(this).size.width;
|
|
37
|
+
return width > 700;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
List<AppLocalizations> get supportedLocalizations {
|
|
41
|
+
return AppLocalizations.supportedLocales
|
|
42
|
+
.sortedBy((e) => e.languageCode)
|
|
43
|
+
.map((e) => lookupAppLocalizations(e))
|
|
44
|
+
.toList();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
List<String> get bookNames {
|
|
48
|
+
return [
|
|
49
|
+
l10n.genesis,
|
|
50
|
+
l10n.exodus,
|
|
51
|
+
l10n.leviticus,
|
|
52
|
+
l10n.numbers,
|
|
53
|
+
l10n.deuteronomy,
|
|
54
|
+
l10n.joshua,
|
|
55
|
+
l10n.judges,
|
|
56
|
+
l10n.ruth,
|
|
57
|
+
l10n.firstSamuel,
|
|
58
|
+
l10n.secondSamuel,
|
|
59
|
+
l10n.firstKings,
|
|
60
|
+
l10n.secondKings,
|
|
61
|
+
l10n.firstChronicles,
|
|
62
|
+
l10n.secondChronicles,
|
|
63
|
+
l10n.ezra,
|
|
64
|
+
l10n.nehemiah,
|
|
65
|
+
l10n.esther,
|
|
66
|
+
l10n.job,
|
|
67
|
+
l10n.psalms,
|
|
68
|
+
l10n.proverbs,
|
|
69
|
+
l10n.ecclesiastes,
|
|
70
|
+
l10n.song_of_solomon,
|
|
71
|
+
l10n.isaiah,
|
|
72
|
+
l10n.jeremiah,
|
|
73
|
+
l10n.lamentations,
|
|
74
|
+
l10n.ezekiel,
|
|
75
|
+
l10n.daniel,
|
|
76
|
+
l10n.hosea,
|
|
77
|
+
l10n.joel,
|
|
78
|
+
l10n.amos,
|
|
79
|
+
l10n.obadiah,
|
|
80
|
+
l10n.jonah,
|
|
81
|
+
l10n.micah,
|
|
82
|
+
l10n.nahum,
|
|
83
|
+
l10n.habakkuk,
|
|
84
|
+
l10n.zephaniah,
|
|
85
|
+
l10n.haggai,
|
|
86
|
+
l10n.zechariah,
|
|
87
|
+
l10n.malachi,
|
|
88
|
+
l10n.matthew,
|
|
89
|
+
l10n.mark,
|
|
90
|
+
l10n.luke,
|
|
91
|
+
l10n.john,
|
|
92
|
+
l10n.acts,
|
|
93
|
+
l10n.romans,
|
|
94
|
+
l10n.firstCorinthians,
|
|
95
|
+
l10n.secondCorinthians,
|
|
96
|
+
l10n.galatians,
|
|
97
|
+
l10n.ephesians,
|
|
98
|
+
l10n.philippians,
|
|
99
|
+
l10n.colossians,
|
|
100
|
+
l10n.firstThessalonians,
|
|
101
|
+
l10n.secondThessalonians,
|
|
102
|
+
l10n.firstTimothy,
|
|
103
|
+
l10n.secondTimothy,
|
|
104
|
+
l10n.titus,
|
|
105
|
+
l10n.philemon,
|
|
106
|
+
l10n.hebrews,
|
|
107
|
+
l10n.james,
|
|
108
|
+
l10n.firstPeter,
|
|
109
|
+
l10n.secondPeter,
|
|
110
|
+
l10n.firstJohn,
|
|
111
|
+
l10n.secondJohn,
|
|
112
|
+
l10n.thirdJohn,
|
|
113
|
+
l10n.jude,
|
|
114
|
+
l10n.revelation,
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
27
118
|
|
|
28
119
|
bool isDesktop() {
|
|
29
120
|
return defaultTargetPlatform == TargetPlatform.macOS ||
|
|
@@ -39,14 +130,6 @@ bool isAndroid() {
|
|
|
39
130
|
return defaultTargetPlatform == TargetPlatform.android;
|
|
40
131
|
}
|
|
41
132
|
|
|
42
|
-
bool isWide(BuildContext context) {
|
|
43
|
-
if (defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS) {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
final width = MediaQuery.of(context).size.width;
|
|
47
|
-
return width > 700;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
133
|
createNoTransitionPageRoute(Widget page) {
|
|
51
134
|
return PageRouteBuilder(
|
|
52
135
|
opaque: false,
|
|
@@ -57,7 +140,7 @@ createNoTransitionPageRoute(Widget page) {
|
|
|
57
140
|
}
|
|
58
141
|
|
|
59
142
|
createSlideRoute({required BuildContext context, TextDirection? slideDir, required Widget page}) {
|
|
60
|
-
if (
|
|
143
|
+
if (context.isWide || slideDir == null) {
|
|
61
144
|
return PageRouteBuilder(
|
|
62
145
|
pageBuilder: (context, _, __) {
|
|
63
146
|
return page;
|
|
@@ -93,5 +176,5 @@ openUrl(BuildContext context, String url) async {
|
|
|
93
176
|
}
|
|
94
177
|
}
|
|
95
178
|
if (!context.mounted) return;
|
|
96
|
-
showError(context,
|
|
179
|
+
showError(context, context.l10n.urlError);
|
|
97
180
|
}
|
lib/widgets/chapter_app_bar.dart
CHANGED
|
@@ -17,7 +17,7 @@ class ChapterAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
|
17
17
|
final model = ChapterProvider.of(context);
|
|
18
18
|
final selectedBook = app.bible.books[model.book];
|
|
19
19
|
final bookName = selectedBook.name(context);
|
|
20
|
-
final isDesktop =
|
|
20
|
+
final isDesktop = context.isWide;
|
|
21
21
|
return SafeArea(
|
|
22
22
|
child: Container(
|
|
23
23
|
padding: EdgeInsets.only(left: 18, right: 5, top: isDesktop ? 5 : 0),
|
lib/widgets/scaffold_menu.dart
CHANGED
|
@@ -10,15 +10,16 @@ class ScaffoldMenu extends StatelessWidget {
|
|
|
10
10
|
@override
|
|
11
11
|
Widget build(BuildContext context) {
|
|
12
12
|
final pageWidth = MediaQuery.of(context).size.width;
|
|
13
|
+
final isWide = context.isWide && !context.app.firstOpen;
|
|
13
14
|
return Scaffold(
|
|
14
|
-
backgroundColor: Colors.transparent,
|
|
15
|
+
backgroundColor: isWide ? Colors.transparent : context.theme.colorScheme.background,
|
|
15
16
|
body: SafeArea(
|
|
16
17
|
child: Container(
|
|
17
18
|
color: Colors.black.withOpacity(0.7),
|
|
18
|
-
margin: EdgeInsets.only(left: isWide
|
|
19
|
+
margin: EdgeInsets.only(left: isWide ? 250 : 0),
|
|
19
20
|
child: Container(
|
|
20
|
-
color: backgroundColor ??
|
|
21
|
+
color: backgroundColor ?? context.theme.colorScheme.background,
|
|
21
|
-
margin: EdgeInsets.only(right: isWide
|
|
22
|
+
margin: EdgeInsets.only(right: isWide ? pageWidth - 750 : 0),
|
|
22
23
|
child: child,
|
|
23
24
|
),
|
|
24
25
|
),
|
lib/widgets/sliver_tile_grid.dart
CHANGED
|
@@ -32,15 +32,14 @@ class SliverTileGrid extends StatelessWidget {
|
|
|
32
32
|
|
|
33
33
|
@override
|
|
34
34
|
Widget build(BuildContext context) {
|
|
35
|
-
final isDesktop = isWide(context);
|
|
36
|
-
final spacing =
|
|
35
|
+
final spacing = context.isWide ? 16.0 : 12.0;
|
|
37
36
|
return SliverPadding(
|
|
38
37
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
|
39
38
|
sliver: SliverGrid.count(
|
|
40
39
|
crossAxisCount: listType.crossAxisCount(),
|
|
41
40
|
crossAxisSpacing: spacing,
|
|
42
41
|
mainAxisSpacing: spacing,
|
|
43
|
-
childAspectRatio: listType.childAspectRatio(
|
|
42
|
+
childAspectRatio: listType.childAspectRatio(context.isWide),
|
|
44
43
|
children: children,
|
|
45
44
|
),
|
|
46
45
|
);
|