import "package:http/http.dart" as http;
import "package:flutter/services.dart";
import "package:package_info_plus/package_info_plus.dart";
import "package:flutter/foundation.dart" show TargetPlatform, defaultTargetPlatform, kDebugMode;
import "package:flutter/material.dart";
import "package:flutter_azure_tts/flutter_azure_tts.dart";
import "package:only_bible_app/env.dart";
import "package:only_bible_app/gen/bible.gen.dart";
export "package:only_bible_app/bible_data.dart";
extension BibleExt on Bible {
List<Book> getOldBooks() {
return books!.where((it) => it.index < 39).toList();
List<Book> getNewBooks() {
return books!.where((it) => it.index >= 39).toList();
extension BookExt on Book {
String shortName(String name) {
if (name[0] == "1" || name[0] == "2" || name[0] == "3") {
return "${name[0]}${name[2].toUpperCase()}${name.substring(3, 4).toLowerCase()}";
return "${name[0].toUpperCase()}${name.substring(1, 3).toLowerCase()}";
extension IterableUtils<E> on Iterable<E> {
Iterable<E> sortedBy(Comparable Function(E e) key) => toList()..sort((a, b) => key(a).compareTo(key(b)));
Iterable<E> removeBy(bool Function(E e) key) => toList()..removeWhere(key);
Iterable<E> addBy(E e) => toList()..add(e);
extension AppContext on BuildContext {
ThemeData get theme => Theme.of(this);
return defaultTargetPlatform == TargetPlatform.iOS;
return defaultTargetPlatform == TargetPlatform.android;
Future<Uint8List> convertText(String langCode, String text) async {
final ttsResponse = await FlutterAzureTts.getTts(
sampleRateHertz: AudioOutputFormat.audio48khz96kBitrateMonoMp3,
audioFormat: AudioOutputFormat.audio48khz96kBitrateMonoMp3,
return ttsResponse.audio.buffer.asUint8List();
Future<Bible> loadBible(String name) async {
final data = await rootBundle.load("assets/bibles/$name.bin.gz");
final decompressed = gzip.decode(data.buffer.asUint8List());
return Bible(decompressed);
Future<void> recordError(String message, StackTrace? stack) async {
final packageInfo = await PackageInfo.fromPlatform();
print("ERROR: $message");
print("ERROR STACK: ${stack.toString()}");
final url = Uri.https("api.resend.com", "/emails");
final response = await http.post(
"Authorization": "Bearer ${Env.resendApiKey}",
"Content-Type": "application/json",
"subject": "Error Stack trace",
<p><strong>OS:</strong>$defaultTargetPlatform</p>
<p><strong>App Version:</strong>${packageInfo.version}</p>
<p><strong>App Build Number:</strong>${packageInfo.buildSignature}</p>
<p><strong>Error:</strong>$message</p>
<p><strong>StackTrace:</strong>${stack?.toString()}</p>
if (response.statusCode == 200) {
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");