2023-09-08 11:50:21 +02:00
|
|
|
import 'dart:io';
|
|
|
|
|
|
|
|
import 'package:dio/dio.dart';
|
|
|
|
import 'package:flutter_tesseract_ocr/flutter_tesseract_ocr.dart';
|
|
|
|
import 'package:prasule/main.dart';
|
|
|
|
|
2023-12-29 21:39:54 +01:00
|
|
|
/// Used for communication with my repo mirror
|
|
|
|
///
|
|
|
|
/// Downloads Tessdata for OCR
|
2023-09-08 11:50:21 +02:00
|
|
|
class TessdataApi {
|
|
|
|
static final Dio _client = Dio(
|
|
|
|
BaseOptions(
|
|
|
|
validateStatus: (status) => true,
|
2024-01-09 23:03:23 +01:00
|
|
|
headers: {"User-Agent": "prasule/1.0.0"},
|
2023-09-08 11:50:21 +02:00
|
|
|
),
|
|
|
|
);
|
2023-12-29 21:39:54 +01:00
|
|
|
|
|
|
|
/// Gets available languages from the repo
|
2023-09-08 11:50:21 +02:00
|
|
|
static Future<List<String>> getAvailableData() async {
|
2024-01-09 23:03:23 +01:00
|
|
|
final res = await _client.get<List<dynamic>>(
|
2023-12-29 21:39:54 +01:00
|
|
|
"https://git.mnau.xyz/api/v1/repos/hernik/tessdata_fast/contents",
|
|
|
|
options: Options(headers: {"Accept": "application/json"}),
|
|
|
|
);
|
2023-09-08 11:50:21 +02:00
|
|
|
if ((res.statusCode ?? 500) > 399) {
|
|
|
|
return Future.error("The server returned status code ${res.statusCode}");
|
|
|
|
}
|
2024-01-09 23:03:23 +01:00
|
|
|
final data = List<Map<String, dynamic>>.from(res.data ?? []);
|
2023-09-08 11:50:21 +02:00
|
|
|
final dataFiles = <String>[];
|
2024-01-09 23:03:23 +01:00
|
|
|
for (final file in data) {
|
2023-12-29 21:39:54 +01:00
|
|
|
if (!(file["name"] as String).endsWith(".traineddata")) continue;
|
|
|
|
dataFiles.add((file["name"] as String).replaceAll(".traineddata", ""));
|
2023-09-08 11:50:21 +02:00
|
|
|
}
|
|
|
|
return dataFiles;
|
|
|
|
}
|
|
|
|
|
2023-12-29 21:39:54 +01:00
|
|
|
/// Deletes data from device
|
2023-09-08 11:50:21 +02:00
|
|
|
static Future<void> deleteData(String name) async {
|
2023-12-29 21:39:54 +01:00
|
|
|
final dataDir = Directory(await FlutterTesseractOcr.getTessdataPath());
|
2023-10-05 17:47:20 +02:00
|
|
|
if (!dataDir.existsSync()) {
|
|
|
|
dataDir.createSync();
|
|
|
|
}
|
2023-12-29 21:39:54 +01:00
|
|
|
final dataFile = File("${dataDir.path}/$name.traineddata");
|
2023-09-08 11:50:21 +02:00
|
|
|
if (!dataFile.existsSync()) return;
|
|
|
|
dataFile.deleteSync();
|
|
|
|
}
|
|
|
|
|
2023-12-29 21:39:54 +01:00
|
|
|
/// Finds existing data on the device
|
2023-10-05 17:47:20 +02:00
|
|
|
static Future<List<String>> getDownloadedData() async {
|
2023-12-29 21:39:54 +01:00
|
|
|
final tessDir = Directory(await FlutterTesseractOcr.getTessdataPath());
|
2023-10-05 17:47:20 +02:00
|
|
|
if (!tessDir.existsSync()) {
|
|
|
|
tessDir.createSync();
|
|
|
|
}
|
|
|
|
return tessDir
|
|
|
|
.listSync()
|
|
|
|
.where((element) => element.path.endsWith(".traineddata"))
|
|
|
|
.map<String>((e) => e.path.split("/").last)
|
|
|
|
.toList();
|
|
|
|
}
|
2023-09-08 11:50:21 +02:00
|
|
|
|
2023-12-29 21:39:54 +01:00
|
|
|
/// Downloads data from the repo to the device
|
|
|
|
static Future<void> downloadData(
|
|
|
|
String isoCode, {
|
|
|
|
void Function(int, int)? callback,
|
|
|
|
}) async {
|
|
|
|
final tessDir = Directory(await FlutterTesseractOcr.getTessdataPath());
|
2023-10-05 17:47:20 +02:00
|
|
|
if (!tessDir.existsSync()) {
|
|
|
|
tessDir.createSync();
|
|
|
|
}
|
2023-12-29 21:39:54 +01:00
|
|
|
final file = File("${tessDir.path}/$isoCode.traineddata");
|
2023-09-08 11:50:21 +02:00
|
|
|
if (file.existsSync()) return; // TODO: maybe ask to redownload?
|
2023-12-29 21:39:54 +01:00
|
|
|
final res = await _client.get<List<int>>(
|
|
|
|
"https://git.mnau.xyz/hernik/tessdata_fast/raw/branch/main/$isoCode.traineddata",
|
|
|
|
options: Options(responseType: ResponseType.bytes),
|
|
|
|
onReceiveProgress: callback,
|
|
|
|
);
|
2023-09-08 11:50:21 +02:00
|
|
|
if ((res.statusCode ?? 500) > 399) {
|
|
|
|
return Future.error("The server returned status code ${res.statusCode}");
|
|
|
|
}
|
|
|
|
try {
|
2023-12-29 21:39:54 +01:00
|
|
|
file.openSync(mode: FileMode.write)
|
|
|
|
..writeFromSync(res.data!)
|
|
|
|
..closeSync();
|
2023-09-08 11:50:21 +02:00
|
|
|
} catch (e) {
|
|
|
|
logger.e(e);
|
|
|
|
return Future.error("Could not complete writing file");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|