~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.
56c55f3c
—
pyrossh 2 years ago
add multiple audio
- .gitignore +1 -0
- integration_test/home_screen_test.dart +23 -28
- ios/Podfile.lock +0 -28
- lib/l10n/app_bn.arb +1 -1
- lib/l10n/app_en.arb +1 -1
- lib/l10n/app_gu.arb +1 -1
- lib/l10n/app_hi.arb +1 -1
- lib/l10n/app_kn.arb +1 -0
- lib/l10n/app_ml.arb +1 -1
- lib/l10n/app_ne.arb +1 -1
- lib/l10n/app_or.arb +1 -1
- lib/l10n/app_pa.arb +1 -1
- lib/l10n/app_ta.arb +1 -1
- lib/l10n/app_te.arb +1 -1
- lib/main.dart +8 -0
- lib/screens/chapter_select_screen.dart +0 -1
- lib/state.dart +31 -8
- lib/utils.dart +23 -1
- lib/widgets/chapter_app_bar.dart +1 -0
- macos/Flutter/GeneratedPluginRegistrant.swift +0 -2
- pubspec.lock +85 -29
- pubspec.yaml +4 -2
- readme.md +1 -7
- scripts/generate_audio.dart +0 -47
.gitignore
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*.log
|
|
4
4
|
*.pyc
|
|
5
5
|
*.swp
|
|
6
|
+
*.env
|
|
6
7
|
.DS_Store
|
|
7
8
|
.atom/
|
|
8
9
|
.buildlog/
|
integration_test/home_screen_test.dart
CHANGED
|
@@ -1,36 +1,31 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "package:flutter/material.dart";
|
|
2
|
-
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
|
3
|
-
import 'package:flutter_persistent_value_notifier/flutter_persistent_value_notifier.dart';
|
|
4
|
-
import
|
|
2
|
+
import "package:flutter_test/flutter_test.dart";
|
|
5
|
-
import
|
|
3
|
+
import "package:integration_test/integration_test.dart";
|
|
6
|
-
import
|
|
4
|
+
import "package:only_bible_app/main.dart" as app;
|
|
7
|
-
import
|
|
5
|
+
import "package:only_bible_app/state.dart";
|
|
8
6
|
|
|
9
7
|
void main() {
|
|
10
8
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
|
11
9
|
|
|
12
|
-
group(
|
|
10
|
+
group("Chapter View screen", () {
|
|
13
|
-
testWidgets(
|
|
11
|
+
testWidgets("should render", (tester) async {
|
|
14
|
-
WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
|
15
|
-
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
|
16
|
-
await initPersistentValueNotifier();
|
|
17
|
-
|
|
12
|
+
app.main();
|
|
18
|
-
await updateStatusBar();
|
|
19
|
-
await tester.pumpWidget(const App());
|
|
20
13
|
await tester.pumpAndSettle();
|
|
14
|
+
languageCode.value = "en";
|
|
21
|
-
|
|
15
|
+
bibleName.update!("English");
|
|
22
|
-
expect(find.text('Genesis 1'), findsOneWidget);
|
|
23
|
-
// // Finds the floating action button to tap on.
|
|
24
|
-
|
|
16
|
+
bibleCache.value = loadBible("English");
|
|
25
|
-
//
|
|
26
|
-
// // Emulate a tap on the floating action button.
|
|
27
|
-
// await tester.tap(fab);
|
|
28
|
-
//
|
|
29
|
-
// // Trigger a frame.
|
|
30
|
-
|
|
17
|
+
await tester.pumpAndSettle();
|
|
31
|
-
//
|
|
32
|
-
|
|
18
|
+
final bookTitle = find.byKey(const Key("bookTitle"));
|
|
19
|
+
await tester.ensureVisible(bookTitle);
|
|
20
|
+
await tester.tap(bookTitle);
|
|
21
|
+
await tester.pumpAndSettle();
|
|
22
|
+
|
|
33
|
-
|
|
23
|
+
await tester.ensureVisible(find.text("Old Testament"));
|
|
24
|
+
await tester.ensureVisible(find.text("New Testament"));
|
|
25
|
+
await tester.ensureVisible(find.byIcon(Icons.close));
|
|
26
|
+
await tester.tap(find.byIcon(Icons.close));
|
|
27
|
+
await tester.pumpAndSettle();
|
|
28
|
+
await tester.ensureVisible(bookTitle);
|
|
34
29
|
});
|
|
35
30
|
});
|
|
36
31
|
}
|
ios/Podfile.lock
CHANGED
|
@@ -9,9 +9,6 @@ PODS:
|
|
|
9
9
|
- Firebase/Performance (10.12.0):
|
|
10
10
|
- Firebase/CoreOnly
|
|
11
11
|
- FirebasePerformance (~> 10.12.0)
|
|
12
|
-
- Firebase/Storage (10.12.0):
|
|
13
|
-
- Firebase/CoreOnly
|
|
14
|
-
- FirebaseStorage (~> 10.12.0)
|
|
15
12
|
- firebase_core (2.15.0):
|
|
16
13
|
- Firebase/CoreOnly (= 10.12.0)
|
|
17
14
|
- Flutter
|
|
@@ -23,14 +20,8 @@ PODS:
|
|
|
23
20
|
- Firebase/Performance (= 10.12.0)
|
|
24
21
|
- firebase_core
|
|
25
22
|
- Flutter
|
|
26
|
-
- firebase_storage (11.2.5):
|
|
27
|
-
- Firebase/Storage (= 10.12.0)
|
|
28
|
-
- firebase_core
|
|
29
|
-
- Flutter
|
|
30
23
|
- FirebaseABTesting (10.13.0):
|
|
31
24
|
- FirebaseCore (~> 10.0)
|
|
32
|
-
- FirebaseAppCheckInterop (10.13.0)
|
|
33
|
-
- FirebaseAuthInterop (10.13.0)
|
|
34
25
|
- FirebaseCore (10.12.0):
|
|
35
26
|
- FirebaseCoreInternal (~> 10.0)
|
|
36
27
|
- GoogleUtilities/Environment (~> 7.8)
|
|
@@ -76,12 +67,6 @@ PODS:
|
|
|
76
67
|
- GoogleUtilities/Environment (~> 7.10)
|
|
77
68
|
- nanopb (< 2.30910.0, >= 2.30908.0)
|
|
78
69
|
- PromisesSwift (~> 2.1)
|
|
79
|
-
- FirebaseStorage (10.12.0):
|
|
80
|
-
- FirebaseAppCheckInterop (~> 10.0)
|
|
81
|
-
- FirebaseAuthInterop (~> 10.0)
|
|
82
|
-
- FirebaseCore (~> 10.0)
|
|
83
|
-
- FirebaseCoreExtension (~> 10.0)
|
|
84
|
-
- GTMSessionFetcher/Core (< 4.0, >= 2.1)
|
|
85
70
|
- Flutter (1.0.0)
|
|
86
71
|
- flutter_native_splash (0.0.1):
|
|
87
72
|
- Flutter
|
|
@@ -99,7 +84,6 @@ PODS:
|
|
|
99
84
|
- "GoogleUtilities/NSData+zlib (7.11.5)"
|
|
100
85
|
- GoogleUtilities/UserDefaults (7.11.5):
|
|
101
86
|
- GoogleUtilities/Logger
|
|
102
|
-
- GTMSessionFetcher/Core (3.1.1)
|
|
103
87
|
- integration_test (0.0.1):
|
|
104
88
|
- Flutter
|
|
105
89
|
- just_audio (0.0.1):
|
|
@@ -130,7 +114,6 @@ DEPENDENCIES:
|
|
|
130
114
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
|
131
115
|
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
|
132
116
|
- firebase_performance (from `.symlinks/plugins/firebase_performance/ios`)
|
|
133
|
-
- firebase_storage (from `.symlinks/plugins/firebase_storage/ios`)
|
|
134
117
|
- Flutter (from `Flutter`)
|
|
135
118
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
|
136
119
|
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
|
@@ -145,8 +128,6 @@ SPEC REPOS:
|
|
|
145
128
|
trunk:
|
|
146
129
|
- Firebase
|
|
147
130
|
- FirebaseABTesting
|
|
148
|
-
- FirebaseAppCheckInterop
|
|
149
|
-
- FirebaseAuthInterop
|
|
150
131
|
- FirebaseCore
|
|
151
132
|
- FirebaseCoreExtension
|
|
152
133
|
- FirebaseCoreInternal
|
|
@@ -155,10 +136,8 @@ SPEC REPOS:
|
|
|
155
136
|
- FirebasePerformance
|
|
156
137
|
- FirebaseRemoteConfig
|
|
157
138
|
- FirebaseSessions
|
|
158
|
-
- FirebaseStorage
|
|
159
139
|
- GoogleDataTransport
|
|
160
140
|
- GoogleUtilities
|
|
161
|
-
- GTMSessionFetcher
|
|
162
141
|
- nanopb
|
|
163
142
|
- PromisesObjC
|
|
164
143
|
- PromisesSwift
|
|
@@ -172,8 +151,6 @@ EXTERNAL SOURCES:
|
|
|
172
151
|
:path: ".symlinks/plugins/firebase_crashlytics/ios"
|
|
173
152
|
firebase_performance:
|
|
174
153
|
:path: ".symlinks/plugins/firebase_performance/ios"
|
|
175
|
-
firebase_storage:
|
|
176
|
-
:path: ".symlinks/plugins/firebase_storage/ios"
|
|
177
154
|
Flutter:
|
|
178
155
|
:path: Flutter
|
|
179
156
|
flutter_native_splash:
|
|
@@ -199,10 +176,7 @@ SPEC CHECKSUMS:
|
|
|
199
176
|
firebase_core: e477125798fc37cd4ab43ca6a8536bf7e0929c00
|
|
200
177
|
firebase_crashlytics: 6043ce85800f96e53f15ee5051f9cfad10cce73d
|
|
201
178
|
firebase_performance: 32e9164da8ae1cc69ee3edff231e2f020be9b6c2
|
|
202
|
-
firebase_storage: d5c1b95383db1230d9fed88c76cb257d8d1ec1d6
|
|
203
179
|
FirebaseABTesting: 86ac5a4fc749088bb4d55a1cbfb2c4cb42c6d5de
|
|
204
|
-
FirebaseAppCheckInterop: 5e12dc623d443dedffcde9c6f3ed41510125d8ef
|
|
205
|
-
FirebaseAuthInterop: 74875bde5d15636522a8fe98beb561df7a54db58
|
|
206
180
|
FirebaseCore: f86a1394906b97ac445ae49c92552a9425831bed
|
|
207
181
|
FirebaseCoreExtension: ce60f9db46d83944cf444664d6d587474128eeca
|
|
208
182
|
FirebaseCoreInternal: b342e37cd4f5b4454ec34308f073420e7920858e
|
|
@@ -211,12 +185,10 @@ SPEC CHECKSUMS:
|
|
|
211
185
|
FirebasePerformance: 1a63c51c9d14fc1190b0970d5aab96672cb0bce6
|
|
212
186
|
FirebaseRemoteConfig: 33e0dcf43899fbb4f8ef2d84200bf5f5e32eaf05
|
|
213
187
|
FirebaseSessions: 991fb4c20b3505eef125f7cbfa20a5b5b189c2a4
|
|
214
|
-
FirebaseStorage: 1d7ca8c8953fc61ccacaa7c612696b5402968a0d
|
|
215
188
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
|
216
189
|
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
|
217
190
|
GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2
|
|
218
191
|
GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084
|
|
219
|
-
GTMSessionFetcher: e8647203b65cee28c5f73d0f473d096653945e72
|
|
220
192
|
integration_test: 13825b8a9334a850581300559b8839134b124670
|
|
221
193
|
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
|
|
222
194
|
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
|
lib/l10n/app_bn.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "bn-IN-TanishaaNeural",
|
|
3
3
|
"title": "শুধুমাত্র বাইবেল অ্যাপ",
|
|
4
4
|
"languageTitle": "Bengali",
|
|
5
5
|
"localeLanguageTitle": "বাংলা",
|
lib/l10n/app_en.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "en-GB-RyanNeural",
|
|
3
3
|
"title": "Only Bible App",
|
|
4
4
|
"languageTitle": "English",
|
|
5
5
|
"localeLanguageTitle": "English",
|
lib/l10n/app_gu.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "gu-IN-DhwaniNeural",
|
|
3
3
|
"title": "ફક્ત બાઇબલ એપ્લિકેશન",
|
|
4
4
|
"languageTitle": "Gujarati",
|
|
5
5
|
"localeLanguageTitle": "ગુજરાતી",
|
lib/l10n/app_hi.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "hi-IN-SwaraNeural",
|
|
3
3
|
"title": "केवल बाइबिल ऐप",
|
|
4
4
|
"languageTitle": "Hindi",
|
|
5
5
|
"localeLanguageTitle": "हिंदी",
|
lib/l10n/app_kn.arb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"hasAudio": "true",
|
|
3
|
+
"audioVoice": "kn-IN-GaganNeural",
|
|
3
4
|
"title": "ಬೈಬಲ್ ಮಾತ್ರರ",
|
|
4
5
|
"languageTitle": "Kannada",
|
|
5
6
|
"localeLanguageTitle": "ಕನ್ನಡ",
|
lib/l10n/app_ml.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "ml-IN-SobhanaNeural",
|
|
3
3
|
"title": "ബൈബിൾ ആപ്പ് മാത്രം",
|
|
4
4
|
"languageTitle": "Malayalam",
|
|
5
5
|
"localeLanguageTitle": "മലയാളം",
|
lib/l10n/app_ne.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "ne-NP-HemkalaNeural",
|
|
3
3
|
"title": "केवल बाइबल एप",
|
|
4
4
|
"languageTitle": "Nepali",
|
|
5
5
|
"localeLanguageTitle": "नेपाली",
|
lib/l10n/app_or.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "",
|
|
3
3
|
"title": "କେବଳ ବାଇବଲ ଆପ୍ |",
|
|
4
4
|
"languageTitle": "Oriya",
|
|
5
5
|
"localeLanguageTitle": "ଓଡିଆ",
|
lib/l10n/app_pa.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "",
|
|
3
3
|
"title": "ਸਿਰਫ਼ ਬਾਈਬਲ ਐਪ",
|
|
4
4
|
"languageTitle": "Punjabi",
|
|
5
5
|
"localeLanguageTitle": "ਪੰਜਾਬੀ",
|
lib/l10n/app_ta.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "ta-IN-PallaviNeural",
|
|
3
3
|
"title": "பைபிள் ஆப் மட்டுமே",
|
|
4
4
|
"languageTitle": "Tamil",
|
|
5
5
|
"localeLanguageTitle": "தமிழ்",
|
lib/l10n/app_te.arb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"audioVoice": "te-IN-ShrutiNeural",
|
|
3
3
|
"title": "బైబిల్ యాప్ మాత్రమే",
|
|
4
4
|
"languageTitle": "Telugu",
|
|
5
5
|
"localeLanguageTitle": "తెలుగు",
|
lib/main.dart
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import "package:flutter/foundation.dart";
|
|
3
|
+
import "package:flutter_azure_tts/flutter_azure_tts.dart";
|
|
4
|
+
import "package:flutter_dotenv/flutter_dotenv.dart";
|
|
3
5
|
import "package:flutter_web_plugins/url_strategy.dart";
|
|
4
6
|
import "package:firebase_core/firebase_core.dart";
|
|
5
7
|
import "package:firebase_crashlytics/firebase_crashlytics.dart";
|
|
@@ -24,6 +26,12 @@ void main() async {
|
|
|
24
26
|
};
|
|
25
27
|
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
|
26
28
|
usePathUrlStrategy();
|
|
29
|
+
await dotenv.load(fileName: ".env");
|
|
30
|
+
AzureTts.init(
|
|
31
|
+
subscriptionKey: dotenv.get("TTS_SUBSCRIPTION_KEY"),
|
|
32
|
+
region: "centralindia",
|
|
33
|
+
withLogs: false,
|
|
34
|
+
);
|
|
27
35
|
await initState();
|
|
28
36
|
updateStatusBar(darkMode.value);
|
|
29
37
|
bibleCache.value = loadBible(bibleName.value);
|
lib/screens/chapter_select_screen.dart
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import "package:flutter/material.dart";
|
|
2
2
|
import "package:only_bible_app/models.dart";
|
|
3
3
|
import "package:only_bible_app/navigation.dart";
|
|
4
|
-
import "package:only_bible_app/utils.dart";
|
|
5
4
|
import "package:only_bible_app/widgets/scaffold_menu.dart";
|
|
6
5
|
import "package:only_bible_app/widgets/sliver_tile_grid.dart";
|
|
7
6
|
import "package:only_bible_app/widgets/sliver_heading.dart";
|
lib/state.dart
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
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";
|
|
5
4
|
import "package:flutter/material.dart";
|
|
6
5
|
import "package:flutter/services.dart";
|
|
7
6
|
import "package:get_storage/get_storage.dart";
|
|
@@ -62,6 +61,7 @@ final bibleCache = Atom<Future<Bible?>?>(
|
|
|
62
61
|
);
|
|
63
62
|
|
|
64
63
|
updateCurrentBible(BuildContext context, Locale l, String name) async {
|
|
64
|
+
hideActions(context);
|
|
65
65
|
languageCode.value = l.languageCode;
|
|
66
66
|
bibleName.update!(name);
|
|
67
67
|
bibleCache.value = loadBible(name);
|
|
@@ -77,6 +77,10 @@ Future<Bible> getBibleFromAsset(String file) async {
|
|
|
77
77
|
);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
// CachedValue(
|
|
81
|
+
// () => factorial(originalValue),
|
|
82
|
+
// ).withDependency(() => originalValue)
|
|
83
|
+
|
|
80
84
|
Future<Bible?> loadBible(String name) async {
|
|
81
85
|
print("loadBible ${name}");
|
|
82
86
|
return getBibleFromAsset(name).then((value) {
|
|
@@ -254,20 +258,39 @@ pause() async {
|
|
|
254
258
|
isPlaying.value = false;
|
|
255
259
|
}
|
|
256
260
|
|
|
261
|
+
class BufferAudioSource extends StreamAudioSource {
|
|
262
|
+
final Uint8List _buffer;
|
|
263
|
+
|
|
264
|
+
BufferAudioSource(this._buffer);
|
|
265
|
+
|
|
266
|
+
@override
|
|
267
|
+
Future<StreamAudioResponse> request([int? start, int? end]) {
|
|
268
|
+
start = start ?? 0;
|
|
269
|
+
end = end ?? _buffer.length;
|
|
270
|
+
|
|
271
|
+
return Future.value(
|
|
272
|
+
StreamAudioResponse(
|
|
273
|
+
sourceLength: _buffer.length,
|
|
274
|
+
contentLength: end - start,
|
|
275
|
+
offset: start,
|
|
276
|
+
contentType: "audio/mpeg",
|
|
277
|
+
stream: Stream.value(List<int>.from(_buffer.skip(start).take(end - start))),
|
|
278
|
+
),
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
257
283
|
onPlay(BuildContext context) async {
|
|
258
|
-
final versesToPlay = List.from(selectedVerses.value);
|
|
284
|
+
final versesToPlay = List<Verse>.from(selectedVerses.value);
|
|
259
285
|
if (isPlaying.value) {
|
|
260
286
|
pause();
|
|
261
287
|
} else {
|
|
262
288
|
isPlaying.value = true;
|
|
263
289
|
for (final v in versesToPlay) {
|
|
264
|
-
final book = (v.book + 1).toString().padLeft(2, "0");
|
|
265
|
-
final chapter = (v.chapter + 1).toString().padLeft(3, "0");
|
|
266
|
-
final verseNo = (v.index + 1).toString().padLeft(3, "0");
|
|
267
|
-
final pathname = "${bibleName.value}
|
|
290
|
+
final pathname = "${bibleName.value}|${v.book}|${v.chapter}|${v.index}";
|
|
268
291
|
try {
|
|
269
|
-
final
|
|
292
|
+
final list = await convertText(context.l.audioVoice, v.text);
|
|
270
|
-
await player.
|
|
293
|
+
await player.setAudioSource(BufferAudioSource(list));
|
|
271
294
|
await player.play();
|
|
272
295
|
await player.stop();
|
|
273
296
|
} catch (err) {
|
lib/utils.dart
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import "dart:typed_data";
|
|
1
2
|
import "package:only_bible_app/dialog.dart";
|
|
2
3
|
import "package:only_bible_app/state.dart";
|
|
3
4
|
import "package:url_launcher/url_launcher.dart";
|
|
4
5
|
import "package:flutter/foundation.dart" show defaultTargetPlatform, TargetPlatform;
|
|
5
6
|
import "package:flutter/material.dart";
|
|
6
7
|
import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
|
8
|
+
import "package:flutter_azure_tts/flutter_azure_tts.dart";
|
|
7
9
|
|
|
8
10
|
extension MyIterable<E> on Iterable<E> {
|
|
9
11
|
Iterable<E> sortedBy(Comparable Function(E e) key) => toList()..sort((a, b) => key(a).compareTo(key(b)));
|
|
@@ -20,7 +22,7 @@ extension AppContext on BuildContext {
|
|
|
20
22
|
? lookupAppLocalizations(const Locale("en"))
|
|
21
23
|
: AppLocalizations.of(this)!;
|
|
22
24
|
|
|
23
|
-
get hasAudio => l.
|
|
25
|
+
get hasAudio => l.audioVoice != "";
|
|
24
26
|
|
|
25
27
|
double get actionsHeight {
|
|
26
28
|
if (isIOS()) {
|
|
@@ -143,3 +145,23 @@ bool isIOS() {
|
|
|
143
145
|
bool isAndroid() {
|
|
144
146
|
return defaultTargetPlatform == TargetPlatform.android;
|
|
145
147
|
}
|
|
148
|
+
|
|
149
|
+
Future<Uint8List> convertText(String langCode, String text) async {
|
|
150
|
+
final ttsResponse = await AzureTts.getTts(TtsParams(
|
|
151
|
+
voice: Voice(
|
|
152
|
+
name: "",
|
|
153
|
+
displayName: "",
|
|
154
|
+
localName: "",
|
|
155
|
+
shortName: langCode,
|
|
156
|
+
gender: "",
|
|
157
|
+
locale: langCode,
|
|
158
|
+
sampleRateHertz: AudioOutputFormat.audio48khz96kBitrateMonoMp3,
|
|
159
|
+
voiceType: "",
|
|
160
|
+
status: "",
|
|
161
|
+
),
|
|
162
|
+
audioFormat: AudioOutputFormat.audio48khz96kBitrateMonoMp3,
|
|
163
|
+
rate: 0.90,
|
|
164
|
+
text: text,
|
|
165
|
+
));
|
|
166
|
+
return ttsResponse.audio.buffer.asUint8List();
|
|
167
|
+
}
|
lib/widgets/chapter_app_bar.dart
CHANGED
|
@@ -32,6 +32,7 @@ class ChapterAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
|
32
32
|
Text(
|
|
33
33
|
"$bookName ${chapter.index + 1}",
|
|
34
34
|
style: Theme.of(context).textTheme.headlineMedium,
|
|
35
|
+
key: const Key("bookTitle"),
|
|
35
36
|
),
|
|
36
37
|
Icon(
|
|
37
38
|
Icons.expand_more,
|
macos/Flutter/GeneratedPluginRegistrant.swift
CHANGED
|
@@ -8,7 +8,6 @@ import Foundation
|
|
|
8
8
|
import audio_session
|
|
9
9
|
import firebase_core
|
|
10
10
|
import firebase_crashlytics
|
|
11
|
-
import firebase_storage
|
|
12
11
|
import just_audio
|
|
13
12
|
import package_info_plus
|
|
14
13
|
import path_provider_foundation
|
|
@@ -20,7 +19,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|
|
20
19
|
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
|
21
20
|
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
|
22
21
|
FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin"))
|
|
23
|
-
FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin"))
|
|
24
22
|
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
|
|
25
23
|
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
|
26
24
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
pubspec.lock
CHANGED
|
@@ -5,10 +5,10 @@ packages:
|
|
|
5
5
|
dependency: transitive
|
|
6
6
|
description:
|
|
7
7
|
name: _fe_analyzer_shared
|
|
8
|
-
sha256:
|
|
8
|
+
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
|
|
9
9
|
url: "https://pub.dev"
|
|
10
10
|
source: hosted
|
|
11
|
-
version: "
|
|
11
|
+
version: "61.0.0"
|
|
12
12
|
_flutterfire_internals:
|
|
13
13
|
dependency: transitive
|
|
14
14
|
description:
|
|
@@ -21,10 +21,10 @@ packages:
|
|
|
21
21
|
dependency: transitive
|
|
22
22
|
description:
|
|
23
23
|
name: analyzer
|
|
24
|
-
sha256:
|
|
24
|
+
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
|
|
25
25
|
url: "https://pub.dev"
|
|
26
26
|
source: hosted
|
|
27
|
-
version: "
|
|
27
|
+
version: "5.13.0"
|
|
28
28
|
archive:
|
|
29
29
|
dependency: transitive
|
|
30
30
|
description:
|
|
@@ -185,6 +185,14 @@ packages:
|
|
|
185
185
|
url: "https://pub.dev"
|
|
186
186
|
source: hosted
|
|
187
187
|
version: "3.1.1"
|
|
188
|
+
coverage:
|
|
189
|
+
dependency: transitive
|
|
190
|
+
description:
|
|
191
|
+
name: coverage
|
|
192
|
+
sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097"
|
|
193
|
+
url: "https://pub.dev"
|
|
194
|
+
source: hosted
|
|
195
|
+
version: "1.6.3"
|
|
188
196
|
cross_file:
|
|
189
197
|
dependency: transitive
|
|
190
198
|
description:
|
|
@@ -321,30 +329,6 @@ packages:
|
|
|
321
329
|
url: "https://pub.dev"
|
|
322
330
|
source: hosted
|
|
323
331
|
version: "0.1.4+4"
|
|
324
|
-
firebase_storage:
|
|
325
|
-
dependency: "direct main"
|
|
326
|
-
description:
|
|
327
|
-
name: firebase_storage
|
|
328
|
-
sha256: "4b747005aee0c611242cdd553f58795f51e1567d2dfd4f75692fac3f67c8c336"
|
|
329
|
-
url: "https://pub.dev"
|
|
330
|
-
source: hosted
|
|
331
|
-
version: "11.2.5"
|
|
332
|
-
firebase_storage_platform_interface:
|
|
333
|
-
dependency: transitive
|
|
334
|
-
description:
|
|
335
|
-
name: firebase_storage_platform_interface
|
|
336
|
-
sha256: c77c7b6b7d283280993c81ea8ac95552b2ae521a7bb46a95181c1482e62d1633
|
|
337
|
-
url: "https://pub.dev"
|
|
338
|
-
source: hosted
|
|
339
|
-
version: "4.4.4"
|
|
340
|
-
firebase_storage_web:
|
|
341
|
-
dependency: transitive
|
|
342
|
-
description:
|
|
343
|
-
name: firebase_storage_web
|
|
344
|
-
sha256: "6906245579f1af225e43df0395c9d9631cb3135cbfa3521a839196d3383bb89a"
|
|
345
|
-
url: "https://pub.dev"
|
|
346
|
-
source: hosted
|
|
347
|
-
version: "3.6.5"
|
|
348
332
|
fixnum:
|
|
349
333
|
dependency: transitive
|
|
350
334
|
description:
|
|
@@ -359,13 +343,21 @@ packages:
|
|
|
359
343
|
source: sdk
|
|
360
344
|
version: "0.0.0"
|
|
361
345
|
flutter_azure_tts:
|
|
362
|
-
dependency: "direct
|
|
346
|
+
dependency: "direct main"
|
|
363
347
|
description:
|
|
364
348
|
name: flutter_azure_tts
|
|
365
349
|
sha256: c216a6b6b7c1b4f2217bb2ad7b6b5b6c3b4221d21309eab57ea1cad41e55949e
|
|
366
350
|
url: "https://pub.dev"
|
|
367
351
|
source: hosted
|
|
368
352
|
version: "0.1.6"
|
|
353
|
+
flutter_dotenv:
|
|
354
|
+
dependency: "direct main"
|
|
355
|
+
description:
|
|
356
|
+
name: flutter_dotenv
|
|
357
|
+
sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77"
|
|
358
|
+
url: "https://pub.dev"
|
|
359
|
+
source: hosted
|
|
360
|
+
version: "5.1.0"
|
|
369
361
|
flutter_driver:
|
|
370
362
|
dependency: transitive
|
|
371
363
|
description: flutter
|
|
@@ -628,6 +620,14 @@ packages:
|
|
|
628
620
|
url: "https://pub.dev"
|
|
629
621
|
source: hosted
|
|
630
622
|
version: "1.0.4"
|
|
623
|
+
node_preamble:
|
|
624
|
+
dependency: transitive
|
|
625
|
+
description:
|
|
626
|
+
name: node_preamble
|
|
627
|
+
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
|
628
|
+
url: "https://pub.dev"
|
|
629
|
+
source: hosted
|
|
630
|
+
version: "2.0.2"
|
|
631
631
|
package_config:
|
|
632
632
|
dependency: transitive
|
|
633
633
|
description:
|
|
@@ -868,6 +868,22 @@ packages:
|
|
|
868
868
|
url: "https://pub.dev"
|
|
869
869
|
source: hosted
|
|
870
870
|
version: "1.4.1"
|
|
871
|
+
shelf_packages_handler:
|
|
872
|
+
dependency: transitive
|
|
873
|
+
description:
|
|
874
|
+
name: shelf_packages_handler
|
|
875
|
+
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
|
876
|
+
url: "https://pub.dev"
|
|
877
|
+
source: hosted
|
|
878
|
+
version: "3.0.2"
|
|
879
|
+
shelf_static:
|
|
880
|
+
dependency: transitive
|
|
881
|
+
description:
|
|
882
|
+
name: shelf_static
|
|
883
|
+
sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e
|
|
884
|
+
url: "https://pub.dev"
|
|
885
|
+
source: hosted
|
|
886
|
+
version: "1.1.2"
|
|
871
887
|
shelf_web_socket:
|
|
872
888
|
dependency: transitive
|
|
873
889
|
description:
|
|
@@ -881,6 +897,22 @@ packages:
|
|
|
881
897
|
description: flutter
|
|
882
898
|
source: sdk
|
|
883
899
|
version: "0.0.99"
|
|
900
|
+
source_map_stack_trace:
|
|
901
|
+
dependency: transitive
|
|
902
|
+
description:
|
|
903
|
+
name: source_map_stack_trace
|
|
904
|
+
sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
|
|
905
|
+
url: "https://pub.dev"
|
|
906
|
+
source: hosted
|
|
907
|
+
version: "2.1.1"
|
|
908
|
+
source_maps:
|
|
909
|
+
dependency: transitive
|
|
910
|
+
description:
|
|
911
|
+
name: source_maps
|
|
912
|
+
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
|
|
913
|
+
url: "https://pub.dev"
|
|
914
|
+
source: hosted
|
|
915
|
+
version: "0.10.12"
|
|
884
916
|
source_span:
|
|
885
917
|
dependency: transitive
|
|
886
918
|
description:
|
|
@@ -937,6 +969,14 @@ packages:
|
|
|
937
969
|
url: "https://pub.dev"
|
|
938
970
|
source: hosted
|
|
939
971
|
version: "1.2.1"
|
|
972
|
+
test:
|
|
973
|
+
dependency: "direct dev"
|
|
974
|
+
description:
|
|
975
|
+
name: test
|
|
976
|
+
sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46"
|
|
977
|
+
url: "https://pub.dev"
|
|
978
|
+
source: hosted
|
|
979
|
+
version: "1.24.3"
|
|
940
980
|
test_api:
|
|
941
981
|
dependency: transitive
|
|
942
982
|
description:
|
|
@@ -945,6 +985,14 @@ packages:
|
|
|
945
985
|
url: "https://pub.dev"
|
|
946
986
|
source: hosted
|
|
947
987
|
version: "0.6.0"
|
|
988
|
+
test_core:
|
|
989
|
+
dependency: transitive
|
|
990
|
+
description:
|
|
991
|
+
name: test_core
|
|
992
|
+
sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e"
|
|
993
|
+
url: "https://pub.dev"
|
|
994
|
+
source: hosted
|
|
995
|
+
version: "0.5.3"
|
|
948
996
|
timing:
|
|
949
997
|
dependency: transitive
|
|
950
998
|
description:
|
|
@@ -1089,6 +1137,14 @@ packages:
|
|
|
1089
1137
|
url: "https://pub.dev"
|
|
1090
1138
|
source: hosted
|
|
1091
1139
|
version: "3.0.2"
|
|
1140
|
+
webkit_inspection_protocol:
|
|
1141
|
+
dependency: transitive
|
|
1142
|
+
description:
|
|
1143
|
+
name: webkit_inspection_protocol
|
|
1144
|
+
sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d"
|
|
1145
|
+
url: "https://pub.dev"
|
|
1146
|
+
source: hosted
|
|
1147
|
+
version: "1.2.0"
|
|
1092
1148
|
win32:
|
|
1093
1149
|
dependency: transitive
|
|
1094
1150
|
description:
|
pubspec.yaml
CHANGED
|
@@ -23,13 +23,14 @@ dependencies:
|
|
|
23
23
|
firebase_core: ^2.15.0
|
|
24
24
|
firebase_crashlytics: ^3.3.4
|
|
25
25
|
firebase_performance: ^0.9.2+4
|
|
26
|
-
firebase_storage: ^11.2.5
|
|
27
26
|
settings_ui: ^2.0.2
|
|
28
27
|
get_storage: ^2.1.1
|
|
29
28
|
share_plus: ^7.1.0
|
|
30
29
|
flutter_markdown: ^0.6.17+1
|
|
31
30
|
url_launcher: ^6.1.12
|
|
32
31
|
package_info_plus: ^4.1.0
|
|
32
|
+
flutter_azure_tts: ^0.1.6
|
|
33
|
+
flutter_dotenv: ^5.1.0
|
|
33
34
|
|
|
34
35
|
dev_dependencies:
|
|
35
36
|
flutter_test:
|
|
@@ -37,13 +38,14 @@ dev_dependencies:
|
|
|
37
38
|
integration_test:
|
|
38
39
|
sdk: flutter
|
|
39
40
|
flutter_lints: ^2.0.0
|
|
40
|
-
flutter_azure_tts: ^0.1.6
|
|
41
41
|
flutter_launcher_icons: ^0.13.1
|
|
42
|
+
test: ^1.24.3
|
|
42
43
|
|
|
43
44
|
flutter:
|
|
44
45
|
generate: true
|
|
45
46
|
uses-material-design: true
|
|
46
47
|
assets:
|
|
48
|
+
- .env
|
|
47
49
|
- assets/bibles/
|
|
48
50
|
- assets/fonts/
|
|
49
51
|
- assets/md/
|
readme.md
CHANGED
|
@@ -58,12 +58,6 @@ https://only-bible-app.firebaseapp.com/
|
|
|
58
58
|
https://onlybible.app
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
## Sync audio files
|
|
62
|
-
|
|
63
|
-
```agsl
|
|
64
|
-
gsutil -m cp -r scripts/audio/Kannada gs://only-bible-app.appspot.com/
|
|
65
|
-
```
|
|
66
|
-
|
|
67
61
|
Note:
|
|
68
62
|
> For crashanalytics to work in dev/debug mode in macos this has to be set DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
69
63
|
|
|
@@ -74,4 +68,4 @@ Note:
|
|
|
74
68
|
|
|
75
69
|
1. Figure out history
|
|
76
70
|
2. Add more text options compact/loose, line spacing
|
|
77
|
-
3. Backups (File, Google Drive)
|
|
71
|
+
3. Backups (File, Google Drive)
|
scripts/generate_audio.dart
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import "dart:io";
|
|
2
|
-
import "package:flutter_azure_tts/flutter_azure_tts.dart";
|
|
3
|
-
|
|
4
|
-
Future<void> convertText(Voice v, String fileName, String text) async {
|
|
5
|
-
final ttsResponse = await AzureTts.getTts(TtsParams(
|
|
6
|
-
voice: v,
|
|
7
|
-
audioFormat: AudioOutputFormat.audio48khz96kBitrateMonoMp3,
|
|
8
|
-
rate: 0.90,
|
|
9
|
-
text: text,
|
|
10
|
-
));
|
|
11
|
-
await File(fileName).writeAsBytes(ttsResponse.audio.buffer.asUint8List(), flush: true);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
void main() async {
|
|
15
|
-
print("starting");
|
|
16
|
-
AzureTts.init(subscriptionKey: Platform.environment["SUB_KEY"]!, region: "centralindia", withLogs: false);
|
|
17
|
-
final voice = Voice(
|
|
18
|
-
name: "",
|
|
19
|
-
displayName: "",
|
|
20
|
-
localName: "",
|
|
21
|
-
shortName: "ne-NP-HemkalaNeural",
|
|
22
|
-
gender: "",
|
|
23
|
-
locale: "ne-NP",
|
|
24
|
-
sampleRateHertz: AudioOutputFormat.audio48khz96kBitrateMonoMp3,
|
|
25
|
-
voiceType: "",
|
|
26
|
-
status: "",
|
|
27
|
-
);
|
|
28
|
-
final bibleTxt = await File("./assets/bibles/Nepali.txt").readAsString();
|
|
29
|
-
final lines = bibleTxt.split("\n");
|
|
30
|
-
for (final line in lines) {
|
|
31
|
-
if (line.isEmpty) {
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
final book = line.substring(0, 2);
|
|
35
|
-
final chapter = line.substring(3, 6);
|
|
36
|
-
final verseNo = line.substring(7, 10);
|
|
37
|
-
final verseText = line.substring(11);
|
|
38
|
-
print("$book-$chapter-$verseNo.mp3");
|
|
39
|
-
final outputFilename = "./scripts/audio/Nepali/$book-$chapter-$verseNo.mp3";
|
|
40
|
-
final outFile = File(outputFilename);
|
|
41
|
-
if (outFile.existsSync() && outFile.lengthSync() > 100) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
await convertText(voice, outputFilename, verseText);
|
|
45
|
-
}
|
|
46
|
-
print("finished");
|
|
47
|
-
}
|