feat: update backend OCR parser, web app, mobile app camera/preview UI, tests, and documentation with sample images
This commit is contained in:
1 parent
aa3233e411
commit
bdb3a49742
71 files changed
+3360
-764
No files matched your search
@@ -1,12 +1,79 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
class AppConfig {
|
||||
// API Configuration
|
||||
static const String apiBaseUrl = 'http://192.168.80.84:3000/api/v1';
|
||||
// ─── API Configuration ────────────────────────────────────────────────────
|
||||
//
|
||||
// Dual-Mode Configuration:
|
||||
// - If public ngrok is running and active, the app will use it automatically.
|
||||
// - If ngrok is down/inactive or unreachable, it falls back to the LAN/Local URL.
|
||||
//
|
||||
|
||||
// LAN / WiFi / Emulator URL (port 8000 = nginx gateway)
|
||||
// - Physical Device on same Wi-Fi: use 'http://192.168.70.7:8000/api/v1'
|
||||
// - Android Emulator: use 'http://10.0.2.2:8000/api/v1'
|
||||
// - iOS Simulator: use 'http://localhost:8000/api/v1'
|
||||
static const String _lanBaseUrl = 'http://192.168.70.7:8000/api/v1';
|
||||
|
||||
// Ngrok public tunnel URL (update ini setiap ngrok di-restart)
|
||||
static const String _ngrokBaseUrl = 'https://unlocated-waylon-potently.ngrok-free.dev/api/v1';
|
||||
|
||||
// Dynamic Base URL determined at startup
|
||||
static String apiBaseUrl = _lanBaseUrl;
|
||||
|
||||
/// Dynamic URL resolver: Checks if the Ngrok tunnel is active.
|
||||
/// If it returns a valid response (not 502/503/504), we use Ngrok.
|
||||
/// Otherwise, we fall back to the LAN/Local base URL.
|
||||
static Future<void> initializeApiBaseUrl() async {
|
||||
final client = HttpClient();
|
||||
client.connectionTimeout = const Duration(seconds: 2);
|
||||
try {
|
||||
debugPrint('AppConfig: Checking public Ngrok tunnel at $_ngrokBaseUrl/auth/login...');
|
||||
final uri = Uri.parse('$_ngrokBaseUrl/auth/login');
|
||||
final request = await client.postUrl(uri);
|
||||
|
||||
// Add headers to bypass the ngrok browser warning page
|
||||
request.headers.add('ngrok-skip-browser-warning', 'true');
|
||||
request.headers.contentType = ContentType.json;
|
||||
request.write('{}');
|
||||
|
||||
final response = await request.close();
|
||||
|
||||
final contentType = response.headers.contentType?.mimeType ?? '';
|
||||
final ngrokErrorCode = response.headers.value('ngrok-error-code');
|
||||
|
||||
debugPrint('AppConfig: Ngrok response status: ${response.statusCode}, Content-Type: $contentType, Ngrok-Error-Code: $ngrokErrorCode');
|
||||
|
||||
// An active tunnel connected to our backend:
|
||||
// 1. Should not return an ngrok-error-code header.
|
||||
// 2. The response content-type should be JSON (our login API returns JSON).
|
||||
// 3. Status code should not be 502, 503, or 504.
|
||||
if (ngrokErrorCode == null &&
|
||||
contentType.contains('json') &&
|
||||
response.statusCode != 502 &&
|
||||
response.statusCode != 503 &&
|
||||
response.statusCode != 504) {
|
||||
apiBaseUrl = _ngrokBaseUrl;
|
||||
debugPrint('AppConfig: Ngrok tunnel is ACTIVE and backend responded. API Base URL: $apiBaseUrl');
|
||||
return;
|
||||
} else {
|
||||
debugPrint('AppConfig: Ngrok is offline, inactive, or returned an error page.');
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('AppConfig: Ngrok connection failed or timed out: $e');
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
apiBaseUrl = _lanBaseUrl;
|
||||
debugPrint('AppConfig: Using Local/LAN API Base URL: $apiBaseUrl');
|
||||
}
|
||||
|
||||
static const String loginEndpoint = '/auth/login';
|
||||
static const String uploadDocumentEndpoint = '/documents/upload';
|
||||
static const String fetchDocumentsEndpoint = '/documents';
|
||||
|
||||
|
||||
// App Constants
|
||||
static const String appName = 'Prima Mart Scanner';
|
||||
|
||||
Reference in new issue
Block a user