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 createState() => _ListDetailScreenState(); } class _ListDetailScreenState extends State { 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( "http://localhost/$base", ), // agar path relatif seperti img1/* jalan mimeType: 'text/html', encoding: 'utf-8', ); }, 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")), ); } }