~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.
ceccb000
—
pyrossh 2 years ago
Improve popup menu
- README.md +6 -0
- lib/app.dart +2 -0
- lib/models.dart +214 -76
- lib/state.dart +10 -7
- lib/widgets/header.dart +4 -9
- lib/widgets/menu.dart +61 -38
- macos/Flutter/GeneratedPluginRegistrant.swift +2 -0
- macos/Podfile.lock +29 -0
- pubspec.lock +24 -0
- pubspec.yaml +1 -0
- scripts/build/.last_build_id +0 -1
- scripts/generate_audio.dart +1 -4
README.md
CHANGED
|
@@ -43,8 +43,14 @@ firebase deploy
|
|
|
43
43
|
## Web
|
|
44
44
|
```agsl
|
|
45
45
|
https://only-bible-app.web.app
|
|
46
|
+
https://only-bible-app.firebaseapp.com/
|
|
46
47
|
https://onlybible.app
|
|
47
48
|
```
|
|
48
49
|
|
|
50
|
+
## Sync audio files
|
|
51
|
+
```agsl
|
|
52
|
+
gsutil -m cp -r scripts/audio/Kannada gs://only-bible-app.appspot.com/
|
|
53
|
+
```
|
|
54
|
+
|
|
49
55
|
Note:
|
|
50
56
|
> For crashanalytics to work in dev/debug mode in macos this has to be set DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
lib/app.dart
CHANGED
|
@@ -15,6 +15,8 @@ class App extends StatelessWidget {
|
|
|
15
15
|
final model = AppModel.of(context);
|
|
16
16
|
return MaterialApp(
|
|
17
17
|
title: "Only Bible App",
|
|
18
|
+
// onGenerateTitle: (context) =>
|
|
19
|
+
// DemoLocalizations.of(context).title,
|
|
18
20
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
19
21
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
20
22
|
debugShowCheckedModeBanner: false,
|
lib/models.dart
CHANGED
|
@@ -66,74 +66,212 @@ class TimeRange {
|
|
|
66
66
|
const TimeRange({required this.start, required this.end});
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const bookNames =
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
69
|
+
const bookNames = <String, List<String>>{
|
|
70
|
+
"en": [
|
|
71
|
+
"Genesis",
|
|
72
|
+
"Exodus",
|
|
73
|
+
"Leviticus",
|
|
74
|
+
"Numbers",
|
|
75
|
+
"Deuteronomy",
|
|
76
|
+
"Joshua",
|
|
77
|
+
"Judges",
|
|
78
|
+
"Ruth",
|
|
79
|
+
"1 Samuel",
|
|
80
|
+
"2 Samuel",
|
|
81
|
+
"1 Kings",
|
|
82
|
+
"2 Kings",
|
|
83
|
+
"1 Chronicles",
|
|
84
|
+
"2 Chronicles",
|
|
85
|
+
"Ezra",
|
|
86
|
+
"Nehemiah",
|
|
87
|
+
"Esther",
|
|
88
|
+
"Job",
|
|
89
|
+
"Psalms",
|
|
90
|
+
"Proverbs",
|
|
91
|
+
"Ecclesiastes",
|
|
92
|
+
"Song of Solomon",
|
|
93
|
+
"Isaiah",
|
|
94
|
+
"Jeremiah",
|
|
95
|
+
"Lamentations",
|
|
96
|
+
"Ezekiel",
|
|
97
|
+
"Daniel",
|
|
98
|
+
"Hosea",
|
|
99
|
+
"Joel",
|
|
100
|
+
"Amos",
|
|
101
|
+
"Obadiah",
|
|
102
|
+
"Jonah",
|
|
103
|
+
"Micah",
|
|
104
|
+
"Nahum",
|
|
105
|
+
"Habakkuk",
|
|
106
|
+
"Zephaniah",
|
|
107
|
+
"Haggai",
|
|
108
|
+
"Zechariah",
|
|
109
|
+
"Malachi",
|
|
110
|
+
"Matthew",
|
|
111
|
+
"Mark",
|
|
112
|
+
"Luke",
|
|
113
|
+
"John",
|
|
114
|
+
"Acts",
|
|
115
|
+
"Romans",
|
|
116
|
+
"1 Corinthians",
|
|
117
|
+
"2 Corinthians",
|
|
118
|
+
"Galatians",
|
|
119
|
+
"Ephesians",
|
|
120
|
+
"Philippians",
|
|
121
|
+
"Colossians",
|
|
122
|
+
"1 Thessalonians",
|
|
123
|
+
"2 Thessalonians",
|
|
124
|
+
"1 Timothy",
|
|
125
|
+
"2 Timothy",
|
|
126
|
+
"Titus",
|
|
127
|
+
"Philemon",
|
|
128
|
+
"Hebrews",
|
|
129
|
+
"James",
|
|
130
|
+
"1 Peter",
|
|
131
|
+
"2 Peter",
|
|
132
|
+
"1 John",
|
|
133
|
+
"2 John",
|
|
134
|
+
"3 John",
|
|
135
|
+
"Jude",
|
|
136
|
+
"Revelation"
|
|
137
|
+
],
|
|
138
|
+
"kn": [
|
|
139
|
+
"ಆದಿಕಾಂಡ",
|
|
140
|
+
"ವಿಮೋಚನಕಾಂಡ",
|
|
141
|
+
"ಯಾಜಕಕಾಂಡ",
|
|
142
|
+
"ಅರಣ್ಯಕಾಂಡ",
|
|
143
|
+
"ಧರ್ಮೋಪದೇಶಕಾಂಡ",
|
|
144
|
+
"ಯೆಹೋಶುವ",
|
|
145
|
+
"ನ್ಯಾಯಸ್ಥಾಪಕರು",
|
|
146
|
+
"ರೂತಳು",
|
|
147
|
+
"1 ಸಮುವೇಲನು",
|
|
148
|
+
"2 ಸಮುವೇಲನು",
|
|
149
|
+
"1 ಅರಸುಗಳು",
|
|
150
|
+
"2 ಅರಸುಗಳು",
|
|
151
|
+
"1 ಪೂರ್ವಕಾಲವೃತ್ತಾ",
|
|
152
|
+
"2 ಪೂರ್ವಕಾಲವೃತ್ತಾ",
|
|
153
|
+
"ಎಜ್ರನು",
|
|
154
|
+
"ನೆಹೆಮಿಯ",
|
|
155
|
+
"ಎಸ್ತೇರಳು",
|
|
156
|
+
"ಯೋಬನು",
|
|
157
|
+
"ಕೀರ್ತನೆಗಳು",
|
|
158
|
+
"ಙ್ಞಾನೋಕ್ತಿಗಳು",
|
|
159
|
+
"ಪ್ರಸಂಗಿ",
|
|
160
|
+
"ಪರಮ ಗೀತ",
|
|
161
|
+
"ಯೆಶಾಯ",
|
|
162
|
+
"ಯೆರೆಮಿಯ",
|
|
163
|
+
"ಪ್ರಲಾಪಗಳು",
|
|
164
|
+
"ಯೆಹೆಜ್ಕೇಲನು",
|
|
165
|
+
"ದಾನಿಯೇಲನು",
|
|
166
|
+
"ಹೋಶೇ",
|
|
167
|
+
"ಯೋವೇಲ",
|
|
168
|
+
"ಆಮೋಸ",
|
|
169
|
+
"ಓಬದ್ಯ",
|
|
170
|
+
"ಯೋನ",
|
|
171
|
+
"ಮಿಕ",
|
|
172
|
+
"ನಹೂಮ",
|
|
173
|
+
"ಹಬಕ್ಕೂಕ್ಕ",
|
|
174
|
+
"ಚೆಫನ್ಯ",
|
|
175
|
+
"ಹಗ್ಗಾಯ",
|
|
176
|
+
"ಜೆಕರ್ಯ",
|
|
177
|
+
"ಮಲಾಕಿಯ",
|
|
178
|
+
"ಮತ್ತಾಯನು",
|
|
179
|
+
"ಮಾರ್ಕನು",
|
|
180
|
+
"ಲೂಕನು",
|
|
181
|
+
"ಯೋಹಾನನು",
|
|
182
|
+
"ಅಪೊಸ್ತಲರ ಕೃತ್ಯಗ",
|
|
183
|
+
"ರೋಮಾಪುರದವರಿಗೆ",
|
|
184
|
+
"1 ಕೊರಿಂಥದವರಿಗೆ",
|
|
185
|
+
"2 ಕೊರಿಂಥದವರಿಗೆ",
|
|
186
|
+
"ಗಲಾತ್ಯದವರಿಗೆ",
|
|
187
|
+
"ಎಫೆಸದವರಿಗೆ",
|
|
188
|
+
"ಫಿಲಿಪ್ಪಿಯವರಿಗೆ",
|
|
189
|
+
"ಕೊಲೊಸ್ಸೆಯವರಿಗೆ",
|
|
190
|
+
"1 ಥೆಸಲೊನೀಕದವರಿಗೆ",
|
|
191
|
+
"2 ಥೆಸಲೊನೀಕದವರಿಗೆ",
|
|
192
|
+
"1 ತಿಮೊಥೆಯನಿಗೆ",
|
|
193
|
+
"2 ತಿಮೊಥೆಯನಿಗೆ",
|
|
194
|
+
"ತೀತನಿಗೆ",
|
|
195
|
+
"ಫಿಲೆಮೋನನಿಗೆ",
|
|
196
|
+
"ಇಬ್ರಿಯರಿಗೆ",
|
|
197
|
+
"ಯಾಕೋಬನು",
|
|
198
|
+
"1 ಪೇತ್ರನು",
|
|
199
|
+
"2 ಪೇತ್ರನು",
|
|
200
|
+
"1 ಯೋಹಾನನು",
|
|
201
|
+
"2 ಯೋಹಾನನು",
|
|
202
|
+
"3 ಯೋಹಾನನು",
|
|
203
|
+
"ಯೂದನು",
|
|
204
|
+
"ಪ್ರಕಟನೆ"
|
|
205
|
+
],
|
|
206
|
+
"ne": [
|
|
207
|
+
"उत्पत्ति",
|
|
208
|
+
"प्रस्थान ",
|
|
209
|
+
"लेवी",
|
|
210
|
+
"गन्ती",
|
|
211
|
+
"व्यवस्था",
|
|
212
|
+
"यहोशू",
|
|
213
|
+
"न्यायकर्ता",
|
|
214
|
+
"रूथ",
|
|
215
|
+
"1 शमूएल",
|
|
216
|
+
"2 शमूएल",
|
|
217
|
+
"1 राजा",
|
|
218
|
+
"2 राजा",
|
|
219
|
+
"1 इतिहास",
|
|
220
|
+
"2 इतिहास",
|
|
221
|
+
"एज्रा",
|
|
222
|
+
"नहेम्याह",
|
|
223
|
+
"एस्तर",
|
|
224
|
+
"अय्यूब",
|
|
225
|
+
"भजनसंग्रह",
|
|
226
|
+
"हितोपदेश",
|
|
227
|
+
"उपदेशक",
|
|
228
|
+
"श्रेष्ठगीत",
|
|
229
|
+
"यशैया",
|
|
230
|
+
"यर्मिया",
|
|
231
|
+
"विलाप",
|
|
232
|
+
"इजकिएल",
|
|
233
|
+
"दानियल",
|
|
234
|
+
"होशे",
|
|
235
|
+
"योएल",
|
|
236
|
+
"आमोस",
|
|
237
|
+
"ओबदिया",
|
|
238
|
+
"योना",
|
|
239
|
+
"मीका",
|
|
240
|
+
"नहूम",
|
|
241
|
+
"हबकूक",
|
|
242
|
+
"सपन्याह",
|
|
243
|
+
"हाग्गै",
|
|
244
|
+
"जकरिया",
|
|
245
|
+
"मलाकी",
|
|
246
|
+
"मत्ती",
|
|
247
|
+
"मर्कूस",
|
|
248
|
+
"लूका",
|
|
249
|
+
"यूहन्ना",
|
|
250
|
+
"प्रेरित",
|
|
251
|
+
"रोमी",
|
|
252
|
+
"1 कोरिन्थी",
|
|
253
|
+
"2 कोरिन्थी",
|
|
254
|
+
"गलाती",
|
|
255
|
+
"एफिसी",
|
|
256
|
+
"फिलिप्पी",
|
|
257
|
+
"कलस्सी",
|
|
258
|
+
"1 थिस्सलोनिकी",
|
|
259
|
+
"2 थिस्सलोनिकी",
|
|
260
|
+
"1 तिमोथी",
|
|
261
|
+
"2 तिमोथी",
|
|
262
|
+
"तीतस",
|
|
263
|
+
"फिलेमोन",
|
|
264
|
+
"हिब्रू",
|
|
265
|
+
"याकूब",
|
|
266
|
+
"1 पत्रुस",
|
|
267
|
+
"2 पत्रुस",
|
|
268
|
+
"1 यूहन्ना",
|
|
269
|
+
"2 यूहन्ना",
|
|
270
|
+
"3 यूहन्ना",
|
|
271
|
+
"यहूदा",
|
|
272
|
+
"प्रकाश",
|
|
273
|
+
]
|
|
274
|
+
};
|
|
137
275
|
|
|
138
276
|
final bibles = [
|
|
139
277
|
Bible(id: 1, name: "KJV"),
|
|
@@ -149,7 +287,7 @@ final bibles = [
|
|
|
149
287
|
Bible(id: 11, name: "Bengali"),
|
|
150
288
|
];
|
|
151
289
|
|
|
152
|
-
List<Book> getBibleFromText(String text) {
|
|
290
|
+
List<Book> getBibleFromText(String languageCode, String text) {
|
|
153
291
|
final List<Book> books = [];
|
|
154
292
|
final lines = text.split("\n");
|
|
155
293
|
for (var (index, line) in lines.indexed) {
|
|
@@ -171,7 +309,7 @@ List<Book> getBibleFromText(String text) {
|
|
|
171
309
|
books.add(
|
|
172
310
|
Book(
|
|
173
311
|
index: book - 1,
|
|
174
|
-
name: bookNames[book-1],
|
|
312
|
+
name: bookNames[languageCode]![book - 1],
|
|
175
313
|
chapters: [],
|
|
176
314
|
),
|
|
177
315
|
);
|
|
@@ -181,11 +319,11 @@ List<Book> getBibleFromText(String text) {
|
|
|
181
319
|
books[book - 1].chapters.add(Chapter(verses: []));
|
|
182
320
|
}
|
|
183
321
|
books[book - 1].chapters[chapter - 1].verses.add(
|
|
184
|
-
|
|
322
|
+
Verse(
|
|
185
|
-
|
|
323
|
+
text: verseText,
|
|
186
|
-
|
|
324
|
+
audioRange: TimeRange(start: start, end: end),
|
|
187
|
-
|
|
325
|
+
),
|
|
188
|
-
|
|
326
|
+
);
|
|
189
327
|
}
|
|
190
328
|
return books;
|
|
191
|
-
}
|
|
329
|
+
}
|
lib/state.dart
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import "dart:convert";
|
|
2
2
|
import "dart:developer";
|
|
3
3
|
import "package:firebase_crashlytics/firebase_crashlytics.dart";
|
|
4
|
+
import "package:firebase_storage/firebase_storage.dart";
|
|
4
5
|
// import "package:firebase_performance/firebase_performance.dart";
|
|
5
6
|
import "package:flutter/foundation.dart" show defaultTargetPlatform, TargetPlatform;
|
|
6
7
|
import "package:flutter/services.dart";
|
|
@@ -14,6 +15,7 @@ import "package:provider/provider.dart";
|
|
|
14
15
|
import "package:shared_preferences/shared_preferences.dart";
|
|
15
16
|
|
|
16
17
|
class AppModel extends ChangeNotifier {
|
|
18
|
+
String languageCode = "en";
|
|
17
19
|
Bible bible = bibles.first;
|
|
18
20
|
bool darkMode = false;
|
|
19
21
|
bool fontBold = false;
|
|
@@ -56,7 +58,7 @@ class AppModel extends ChangeNotifier {
|
|
|
56
58
|
// customTrace = FirebasePerformance.instance.newTrace("loadBible");
|
|
57
59
|
// await customTrace.start();
|
|
58
60
|
// }
|
|
59
|
-
final books = await getBibleFromAsset(selectedBible.name);
|
|
61
|
+
final books = await getBibleFromAsset(languageCode, selectedBible.name);
|
|
60
62
|
// if (!isDesktop()) {
|
|
61
63
|
// await customTrace.stop();
|
|
62
64
|
// }
|
|
@@ -222,14 +224,15 @@ class ChapterViewModel extends ChangeNotifier {
|
|
|
222
224
|
final book = (model.book + 1).toString().padLeft(2, "0");
|
|
223
225
|
final chapter = (model.chapter + 1).toString().padLeft(3, "0");
|
|
224
226
|
final verse = (v + 1).toString().padLeft(3, "0");
|
|
225
|
-
final
|
|
227
|
+
final pathname = "$bibleName/$book-$chapter-$verse.mp3";
|
|
226
228
|
try {
|
|
229
|
+
final url = await FirebaseStorage.instance.ref(pathname).getDownloadURL();
|
|
227
230
|
await player.setUrl(url);
|
|
228
231
|
await player.play();
|
|
229
232
|
await player.stop();
|
|
230
|
-
}
|
|
233
|
+
} catch (err) {
|
|
231
|
-
log("Could not play audio", name: "play", error: (err.toString(),
|
|
234
|
+
log("Could not play audio", name: "play", error: (err.toString(), pathname));
|
|
232
|
-
FirebaseCrashlytics.instance.recordFlutterError(FlutterErrorDetails(exception: (err.toString(),
|
|
235
|
+
FirebaseCrashlytics.instance.recordFlutterError(FlutterErrorDetails(exception: (err.toString(), pathname)));
|
|
233
236
|
showError(context, "Could not play audio");
|
|
234
237
|
return;
|
|
235
238
|
} finally {
|
|
@@ -292,7 +295,7 @@ createSlideRoute({required BuildContext context, TextDirection? slideDir, requir
|
|
|
292
295
|
);
|
|
293
296
|
}
|
|
294
297
|
|
|
295
|
-
getBibleFromAsset(String file) async {
|
|
298
|
+
getBibleFromAsset(String languageCode, String file) async {
|
|
296
299
|
final bytes = await rootBundle.load("assets/bibles/$file.txt");
|
|
297
|
-
return getBibleFromText(utf8.decode(bytes.buffer.asUint8List(), allowMalformed: false));
|
|
300
|
+
return getBibleFromText(languageCode, utf8.decode(bytes.buffer.asUint8List(), allowMalformed: false));
|
|
298
301
|
}
|
lib/widgets/header.dart
CHANGED
|
@@ -14,6 +14,8 @@ class Header extends StatelessWidget {
|
|
|
14
14
|
final model = ChapterViewModel.of(context);
|
|
15
15
|
final selectedBook = selectedBible.books[model.book];
|
|
16
16
|
final isDesktop = isWide(context);
|
|
17
|
+
final bookName = selectedBook.name;
|
|
18
|
+
// Localizations.localeOf(context).languageCode
|
|
17
19
|
return Container(
|
|
18
20
|
padding: EdgeInsets.only(
|
|
19
21
|
left: 20,
|
|
@@ -39,7 +41,7 @@ class Header extends StatelessWidget {
|
|
|
39
41
|
color: Theme.of(context).textTheme.headlineMedium!.color,
|
|
40
42
|
),
|
|
41
43
|
icon: Text(
|
|
42
|
-
"$
|
|
44
|
+
"$bookName ${model.chapter + 1}",
|
|
43
45
|
style: Theme.of(context).textTheme.headlineMedium,
|
|
44
46
|
),
|
|
45
47
|
onPressed: () {
|
|
@@ -67,14 +69,7 @@ class Header extends StatelessWidget {
|
|
|
67
69
|
),
|
|
68
70
|
child: Text(selectedBible.name),
|
|
69
71
|
onPressed: () {
|
|
70
|
-
Navigator.of(context).push(
|
|
71
|
-
PageRouteBuilder(
|
|
72
|
-
opaque: false,
|
|
73
|
-
transitionDuration: Duration.zero,
|
|
74
|
-
reverseTransitionDuration: Duration.zero,
|
|
75
|
-
|
|
72
|
+
Navigator.of(context).push(createNoTransitionPageRoute(const BibleSelectScreen()));
|
|
76
|
-
),
|
|
77
|
-
);
|
|
78
73
|
},
|
|
79
74
|
),
|
|
80
75
|
),
|
lib/widgets/menu.dart
CHANGED
|
@@ -1,53 +1,76 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import "package:only_bible_app/state.dart";
|
|
3
|
+
import "package:only_bible_app/screens/bible_select_screen.dart";
|
|
3
4
|
|
|
4
5
|
class Menu extends StatelessWidget {
|
|
5
6
|
const Menu({super.key});
|
|
6
7
|
|
|
7
8
|
@override
|
|
8
9
|
Widget build(BuildContext context) {
|
|
10
|
+
final isDesktop = isWide(context);
|
|
11
|
+
final model = AppModel.of(context);
|
|
9
|
-
final
|
|
12
|
+
final modeIcon = model.darkMode ? Icons.dark_mode : Icons.light_mode;
|
|
10
|
-
const spacing = 25.0;
|
|
11
13
|
return PopupMenuButton(
|
|
12
|
-
constraints: const BoxConstraints.tightFor(width: 90),
|
|
13
|
-
icon: Icon(
|
|
14
|
+
icon: const Icon(Icons.more_vert, size: 28),
|
|
14
|
-
offset: const Offset(0.0,
|
|
15
|
+
offset: const Offset(0.0, 50),
|
|
16
|
+
onSelected: (int v) {
|
|
17
|
+
if (v == 1) {
|
|
18
|
+
Navigator.of(context).push(createNoTransitionPageRoute(const BibleSelectScreen()));
|
|
19
|
+
}
|
|
20
|
+
if (v == 2) {
|
|
21
|
+
model.toggleMode();
|
|
22
|
+
}
|
|
23
|
+
if (v == 3) {
|
|
24
|
+
model.toggleBold();
|
|
25
|
+
}
|
|
26
|
+
if (v == 4) {
|
|
27
|
+
model.increaseFont();
|
|
28
|
+
}
|
|
29
|
+
if (v == 5) {
|
|
30
|
+
model.decreaseFont();
|
|
31
|
+
}
|
|
32
|
+
},
|
|
15
33
|
itemBuilder: (BuildContext itemContext) {
|
|
16
34
|
return [
|
|
35
|
+
if (!isDesktop)
|
|
36
|
+
PopupMenuItem(
|
|
37
|
+
value: 1,
|
|
38
|
+
child: Container(
|
|
39
|
+
alignment: Alignment.center,
|
|
40
|
+
margin: const EdgeInsets.symmetric(vertical: 15),
|
|
41
|
+
child: const Icon(Icons.abc, size: 28),
|
|
42
|
+
),
|
|
43
|
+
),
|
|
44
|
+
PopupMenuItem(
|
|
45
|
+
value: 2,
|
|
46
|
+
child: Container(
|
|
47
|
+
alignment: Alignment.center,
|
|
48
|
+
margin: const EdgeInsets.symmetric(vertical: 15),
|
|
49
|
+
child: Icon(modeIcon, size: 28),
|
|
50
|
+
),
|
|
51
|
+
),
|
|
52
|
+
PopupMenuItem(
|
|
53
|
+
value: 3,
|
|
54
|
+
child: Container(
|
|
55
|
+
alignment: Alignment.center,
|
|
56
|
+
margin: const EdgeInsets.symmetric(vertical: 15),
|
|
57
|
+
child: const Icon(Icons.format_bold, size: 28),
|
|
58
|
+
),
|
|
59
|
+
),
|
|
60
|
+
PopupMenuItem(
|
|
61
|
+
value: 4,
|
|
62
|
+
child: Container(
|
|
63
|
+
alignment: Alignment.center,
|
|
64
|
+
margin: const EdgeInsets.symmetric(vertical: 15),
|
|
65
|
+
child: const Icon(Icons.add_circle, size: 28),
|
|
66
|
+
),
|
|
67
|
+
),
|
|
17
68
|
PopupMenuItem(
|
|
18
|
-
value:
|
|
69
|
+
value: 5,
|
|
19
|
-
child:
|
|
70
|
+
child: Container(
|
|
20
|
-
builder: (BuildContext menuContext, StateSetter setState) {
|
|
21
|
-
final model = AppModel.of(context);
|
|
22
|
-
final modeIcon = model.darkMode ? Icons.dark_mode : Icons.light_mode;
|
|
23
|
-
final boldColor = model.fontBold ? Colors.red : Colors.grey;
|
|
24
|
-
return Column(
|
|
25
|
-
crossAxisAlignment: CrossAxisAlignment.center,
|
|
26
|
-
|
|
71
|
+
alignment: Alignment.center,
|
|
27
|
-
children: [
|
|
28
|
-
IconButton(
|
|
29
|
-
icon: Icon(modeIcon, size: 28),
|
|
30
|
-
onPressed: model.toggleMode,
|
|
31
|
-
),
|
|
32
|
-
|
|
72
|
+
margin: const EdgeInsets.symmetric(vertical: 15),
|
|
33
|
-
// TODO: figure out bold active/inactive color
|
|
34
|
-
IconButton(
|
|
35
|
-
icon: const Icon(Icons.format_bold, size: 28),
|
|
36
|
-
onPressed: model.toggleBold,
|
|
37
|
-
),
|
|
38
|
-
Container(margin: const EdgeInsets.only(top: spacing)),
|
|
39
|
-
IconButton(
|
|
40
|
-
icon: const Icon(Icons.add_circle, size: 28),
|
|
41
|
-
onPressed: model.increaseFont,
|
|
42
|
-
),
|
|
43
|
-
Container(margin: const EdgeInsets.only(top: spacing)),
|
|
44
|
-
IconButton(
|
|
45
|
-
|
|
73
|
+
child: const Icon(Icons.remove_circle, size: 28),
|
|
46
|
-
onPressed: model.decreaseFont,
|
|
47
|
-
),
|
|
48
|
-
],
|
|
49
|
-
);
|
|
50
|
-
},
|
|
51
74
|
),
|
|
52
75
|
),
|
|
53
76
|
];
|
macos/Flutter/GeneratedPluginRegistrant.swift
CHANGED
|
@@ -8,6 +8,7 @@ import Foundation
|
|
|
8
8
|
import audio_session
|
|
9
9
|
import firebase_core
|
|
10
10
|
import firebase_crashlytics
|
|
11
|
+
import firebase_storage
|
|
11
12
|
import just_audio
|
|
12
13
|
import path_provider_foundation
|
|
13
14
|
import shared_preferences_foundation
|
|
@@ -16,6 +17,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|
|
16
17
|
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
|
17
18
|
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
|
18
19
|
FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin"))
|
|
20
|
+
FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin"))
|
|
19
21
|
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
|
|
20
22
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
|
21
23
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
macos/Podfile.lock
CHANGED
|
@@ -6,6 +6,9 @@ PODS:
|
|
|
6
6
|
- Firebase/Crashlytics (10.12.0):
|
|
7
7
|
- Firebase/CoreOnly
|
|
8
8
|
- FirebaseCrashlytics (~> 10.12.0)
|
|
9
|
+
- Firebase/Storage (10.12.0):
|
|
10
|
+
- Firebase/CoreOnly
|
|
11
|
+
- FirebaseStorage (~> 10.12.0)
|
|
9
12
|
- firebase_core (2.15.0):
|
|
10
13
|
- Firebase/CoreOnly (~> 10.12.0)
|
|
11
14
|
- FlutterMacOS
|
|
@@ -14,6 +17,13 @@ PODS:
|
|
|
14
17
|
- Firebase/Crashlytics (~> 10.12.0)
|
|
15
18
|
- firebase_core
|
|
16
19
|
- FlutterMacOS
|
|
20
|
+
- firebase_storage (11.2.5):
|
|
21
|
+
- Firebase/CoreOnly (~> 10.12.0)
|
|
22
|
+
- Firebase/Storage (~> 10.12.0)
|
|
23
|
+
- firebase_core
|
|
24
|
+
- FlutterMacOS
|
|
25
|
+
- FirebaseAppCheckInterop (10.13.0)
|
|
26
|
+
- FirebaseAuthInterop (10.13.0)
|
|
17
27
|
- FirebaseCore (10.12.0):
|
|
18
28
|
- FirebaseCoreInternal (~> 10.0)
|
|
19
29
|
- GoogleUtilities/Environment (~> 7.8)
|
|
@@ -43,6 +53,12 @@ PODS:
|
|
|
43
53
|
- GoogleUtilities/Environment (~> 7.10)
|
|
44
54
|
- nanopb (< 2.30910.0, >= 2.30908.0)
|
|
45
55
|
- PromisesSwift (~> 2.1)
|
|
56
|
+
- FirebaseStorage (10.12.0):
|
|
57
|
+
- FirebaseAppCheckInterop (~> 10.0)
|
|
58
|
+
- FirebaseAuthInterop (~> 10.0)
|
|
59
|
+
- FirebaseCore (~> 10.0)
|
|
60
|
+
- FirebaseCoreExtension (~> 10.0)
|
|
61
|
+
- GTMSessionFetcher/Core (< 4.0, >= 2.1)
|
|
46
62
|
- FlutterMacOS (1.0.0)
|
|
47
63
|
- GoogleDataTransport (9.2.5):
|
|
48
64
|
- GoogleUtilities/Environment (~> 7.7)
|
|
@@ -55,6 +71,7 @@ PODS:
|
|
|
55
71
|
- "GoogleUtilities/NSData+zlib (7.11.5)"
|
|
56
72
|
- GoogleUtilities/UserDefaults (7.11.5):
|
|
57
73
|
- GoogleUtilities/Logger
|
|
74
|
+
- GTMSessionFetcher/Core (3.1.1)
|
|
58
75
|
- just_audio (0.0.1):
|
|
59
76
|
- FlutterMacOS
|
|
60
77
|
- nanopb (2.30909.0):
|
|
@@ -76,6 +93,7 @@ DEPENDENCIES:
|
|
|
76
93
|
- audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`)
|
|
77
94
|
- firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`)
|
|
78
95
|
- firebase_crashlytics (from `Flutter/ephemeral/.symlinks/plugins/firebase_crashlytics/macos`)
|
|
96
|
+
- firebase_storage (from `Flutter/ephemeral/.symlinks/plugins/firebase_storage/macos`)
|
|
79
97
|
- FlutterMacOS (from `Flutter/ephemeral`)
|
|
80
98
|
- just_audio (from `Flutter/ephemeral/.symlinks/plugins/just_audio/macos`)
|
|
81
99
|
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
|
@@ -84,14 +102,18 @@ DEPENDENCIES:
|
|
|
84
102
|
SPEC REPOS:
|
|
85
103
|
trunk:
|
|
86
104
|
- Firebase
|
|
105
|
+
- FirebaseAppCheckInterop
|
|
106
|
+
- FirebaseAuthInterop
|
|
87
107
|
- FirebaseCore
|
|
88
108
|
- FirebaseCoreExtension
|
|
89
109
|
- FirebaseCoreInternal
|
|
90
110
|
- FirebaseCrashlytics
|
|
91
111
|
- FirebaseInstallations
|
|
92
112
|
- FirebaseSessions
|
|
113
|
+
- FirebaseStorage
|
|
93
114
|
- GoogleDataTransport
|
|
94
115
|
- GoogleUtilities
|
|
116
|
+
- GTMSessionFetcher
|
|
95
117
|
- nanopb
|
|
96
118
|
- PromisesObjC
|
|
97
119
|
- PromisesSwift
|
|
@@ -103,6 +125,8 @@ EXTERNAL SOURCES:
|
|
|
103
125
|
:path: Flutter/ephemeral/.symlinks/plugins/firebase_core/macos
|
|
104
126
|
firebase_crashlytics:
|
|
105
127
|
:path: Flutter/ephemeral/.symlinks/plugins/firebase_crashlytics/macos
|
|
128
|
+
firebase_storage:
|
|
129
|
+
:path: Flutter/ephemeral/.symlinks/plugins/firebase_storage/macos
|
|
106
130
|
FlutterMacOS:
|
|
107
131
|
:path: Flutter/ephemeral
|
|
108
132
|
just_audio:
|
|
@@ -117,15 +141,20 @@ SPEC CHECKSUMS:
|
|
|
117
141
|
Firebase: 07150e75d142fb9399f6777fa56a187b17f833a0
|
|
118
142
|
firebase_core: ff59797157ca9adda4440071643761b41fcd03b3
|
|
119
143
|
firebase_crashlytics: 223f1e85437fa85822439e51db3cd0be7dd35b23
|
|
144
|
+
firebase_storage: d873afdc6a0b5307ffa2bb4a5ca9282cb0b922f3
|
|
145
|
+
FirebaseAppCheckInterop: 5e12dc623d443dedffcde9c6f3ed41510125d8ef
|
|
146
|
+
FirebaseAuthInterop: 74875bde5d15636522a8fe98beb561df7a54db58
|
|
120
147
|
FirebaseCore: f86a1394906b97ac445ae49c92552a9425831bed
|
|
121
148
|
FirebaseCoreExtension: ce60f9db46d83944cf444664d6d587474128eeca
|
|
122
149
|
FirebaseCoreInternal: b342e37cd4f5b4454ec34308f073420e7920858e
|
|
123
150
|
FirebaseCrashlytics: c4d111b7430c49744c74bcc6346ea00868661ac8
|
|
124
151
|
FirebaseInstallations: b28af1b9f997f1a799efe818c94695a3728c352f
|
|
125
152
|
FirebaseSessions: 991fb4c20b3505eef125f7cbfa20a5b5b189c2a4
|
|
153
|
+
FirebaseStorage: 1d7ca8c8953fc61ccacaa7c612696b5402968a0d
|
|
126
154
|
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
|
127
155
|
GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2
|
|
128
156
|
GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084
|
|
157
|
+
GTMSessionFetcher: e8647203b65cee28c5f73d0f473d096653945e72
|
|
129
158
|
just_audio: 9b67ca7b97c61cfc9784ea23cd8cc55eb226d489
|
|
130
159
|
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
|
|
131
160
|
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
pubspec.lock
CHANGED
|
@@ -313,6 +313,30 @@ packages:
|
|
|
313
313
|
url: "https://pub.dev"
|
|
314
314
|
source: hosted
|
|
315
315
|
version: "0.1.4+4"
|
|
316
|
+
firebase_storage:
|
|
317
|
+
dependency: "direct main"
|
|
318
|
+
description:
|
|
319
|
+
name: firebase_storage
|
|
320
|
+
sha256: "4b747005aee0c611242cdd553f58795f51e1567d2dfd4f75692fac3f67c8c336"
|
|
321
|
+
url: "https://pub.dev"
|
|
322
|
+
source: hosted
|
|
323
|
+
version: "11.2.5"
|
|
324
|
+
firebase_storage_platform_interface:
|
|
325
|
+
dependency: transitive
|
|
326
|
+
description:
|
|
327
|
+
name: firebase_storage_platform_interface
|
|
328
|
+
sha256: c77c7b6b7d283280993c81ea8ac95552b2ae521a7bb46a95181c1482e62d1633
|
|
329
|
+
url: "https://pub.dev"
|
|
330
|
+
source: hosted
|
|
331
|
+
version: "4.4.4"
|
|
332
|
+
firebase_storage_web:
|
|
333
|
+
dependency: transitive
|
|
334
|
+
description:
|
|
335
|
+
name: firebase_storage_web
|
|
336
|
+
sha256: "6906245579f1af225e43df0395c9d9631cb3135cbfa3521a839196d3383bb89a"
|
|
337
|
+
url: "https://pub.dev"
|
|
338
|
+
source: hosted
|
|
339
|
+
version: "3.6.5"
|
|
316
340
|
fixnum:
|
|
317
341
|
dependency: transitive
|
|
318
342
|
description:
|
pubspec.yaml
CHANGED
|
@@ -22,6 +22,7 @@ dependencies:
|
|
|
22
22
|
provider: ^6.0.5
|
|
23
23
|
firebase_crashlytics: ^3.3.4
|
|
24
24
|
firebase_performance: ^0.9.2+4
|
|
25
|
+
firebase_storage: ^11.2.5
|
|
25
26
|
|
|
26
27
|
dev_dependencies:
|
|
27
28
|
flutter_test:
|
scripts/build/.last_build_id
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
d99b6d880707949ca952db50a1399779
|
scripts/generate_audio.dart
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "dart:io";
|
|
2
|
-
import
|
|
2
|
+
import "package:flutter_azure_tts/flutter_azure_tts.dart";
|
|
3
3
|
|
|
4
4
|
Future<void> convertText(Voice v, String fileName, String text) async {
|
|
5
5
|
final ttsResponse = await AzureTts.getTts(TtsParams(
|
|
@@ -42,9 +42,6 @@ void main() async {
|
|
|
42
42
|
continue;
|
|
43
43
|
}
|
|
44
44
|
await convertText(voice, outputFilename, verseText);
|
|
45
|
-
if (chapter == "002") {
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
45
|
}
|
|
49
46
|
print("finished");
|
|
50
47
|
}
|