FreekakeApp/lib/screen/pustaka/list_detail_screen.dart
2025-07-07 17:31:26 +07:00

134 lines
5.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'dart:convert';
class ListDetailScreen extends StatefulWidget {
final String title;
final String? filepath;
const ListDetailScreen({super.key, required this.title, this.filepath});
@override
State<ListDetailScreen> createState() => _ListDetailScreenState();
}
class _ListDetailScreenState extends State<ListDetailScreen> {
late InAppWebViewController _webViewController;
@override
Widget build(BuildContext context) {
String _getMimeType(String path) {
if (path.endsWith('.png')) return 'image/png';
if (path.endsWith('.jpg') || path.endsWith('.jpeg')) return 'image/jpeg';
if (path.endsWith('.svg')) return 'image/svg+xml';
if (path.endsWith('.html')) return 'text/html';
if (path.endsWith('.css')) return 'text/css';
if (path.endsWith('.js')) return 'application/javascript';
return 'application/octet-stream';
}
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body:
widget.filepath != null
? InAppWebView(
initialUrlRequest: URLRequest(url: WebUri("about:blank")),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
javaScriptEnabled: true,
allowFileAccessFromFileURLs: true,
allowUniversalAccessFromFileURLs: true,
),
),
onWebViewCreated: (controller) async {
_webViewController = controller;
final html = await rootBundle.loadString(widget.filepath!);
final base = widget.filepath!.substring(
0,
widget.filepath!.lastIndexOf('/') + 1,
);
await controller.loadData(
data: html,
baseUrl: WebUri(
"file:///android_asset/flutter_assets/$base",
), // agar path relatif seperti img1/* jalan
mimeType: 'text/html',
encoding: 'utf-8',
);
debugPrint("http://localhost/$base");
debugPrint("file:///android_asset/flutter_assets/$base");
},
onLoadStop: (controller, url) async {
debugPrint("🚀 onLoadStop called. URL: $url");
var result = await controller.evaluateJavascript(
source: """
(() => {
const board = document.getElementById('game-board');
const hasRender = typeof renderGrid === 'function';
return { hasRender, boardExists: board !== null };
})();
""",
);
debugPrint("📊 Evaluated JS result: $result");
final jsCheck = await controller.evaluateJavascript(
source: """
typeof renderGrid === 'function' &&
document.querySelector('#game-board') !== null
""",
);
debugPrint(
"Apakah renderGrid tersedia dan board muncul? => $jsCheck",
);
final imageLoaded = await controller.evaluateJavascript(
source: """
Array.from(document.images).every(img => img.complete)
""",
);
debugPrint("Semua gambar berhasil dimuat? => $imageLoaded");
},
// (Opsional) tangkap log dari JS
onConsoleMessage: (controller, consoleMessage) {
debugPrint("📢 JS Console: ${consoleMessage.message}");
},
shouldInterceptRequest: (controller, request) async {
final url = request.url;
if (url == null || url.host != 'localhost') return null;
try {
// Strip "http://localhost/" from the path
final path = url.path.replaceFirst('/', '');
final asset = await rootBundle.load(path);
final mimeType = _getMimeType(path);
return WebResourceResponse(
contentType: mimeType,
data: asset.buffer.asUint8List(),
statusCode: 200,
reasonPhrase: 'OK',
);
} catch (e) {
print("⚠️ Asset not found: ${url.path} -> $e");
return WebResourceResponse(
contentType: 'text/plain',
data: Uint8List.fromList(utf8.encode('404 Not Found')),
statusCode: 404,
reasonPhrase: 'Not Found',
);
}
},
)
: const Center(child: Text("Tidak ada file HTML")),
);
}
}