import 'package:flutter/cupertino.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:get/get.dart'; import 'package:isekai_wiki/global.dart'; import 'package:isekai_wiki/models/settings.dart'; import 'package:isekai_wiki/reactive/reactive.dart'; import 'package:isekai_wiki/styles.dart'; class WikiPageParserController extends GetxController { InAppWebViewController? webviewCotroller; var contentHtml = "".obs; var safeAreaPadding = const EdgeInsets.all(0).obs; var textZoom = 100.obs; var loading = true.obs; @override void onInit() { super.onInit(); ever(contentHtml, (_) { loading.value = true; if (contentHtml.value.isNotEmpty) { webviewCotroller?.loadData( data: contentHtml.value, baseUrl: Uri.parse(Global.wikiHomeUrl), ); } }); ever(textZoom, (_) { webviewCotroller?.setOptions( options: InAppWebViewGroupOptions( android: AndroidInAppWebViewOptions(textZoom: textZoom.value), ), ); }); } void onWebViewCreated(InAppWebViewController controller) { webviewCotroller = controller; webviewCotroller?.loadData( data: contentHtml.value, baseUrl: Uri.parse(Global.wikiHomeUrl), ); } void onPageCommitVisible(InAppWebViewController controller, Uri? uri) { debugPrint("loaded"); controller.injectCSSCode(source: """ body { padding-top: ${safeAreaPadding.value.top}px; padding-bottom: ${safeAreaPadding.value.bottom}px; padding-left: ${safeAreaPadding.value.left}px; padding-right: ${safeAreaPadding.value.right}px; } """); controller.evaluateJavascript(source: """ var metaEl = document.createElement("meta"); metaEl.name = "viewport"; metaEl.content = "width=device-width, initial-scale=1.0, user-scalable=yes, minimum-scale=0.25, maximum-scale=5.0"; document.head.appendChild(metaEl); """); if (contentHtml.value.isNotEmpty) { Future.delayed(const Duration(milliseconds: 100)).then((value) { loading.value = false; }); } } } class WikiPageParser extends StatefulWidget { final String? contentHtml; final EdgeInsets? padding; const WikiPageParser({super.key, this.contentHtml, this.padding}); @override State createState() { return _WikiParserState(); } } class _WikiParserState extends ReactiveState { var c = WikiPageParserController(); @override void initState() { super.initState(); c = Get.put(c); } @override void receiveProps() { c.contentHtml.value = widget.contentHtml ?? ""; c.safeAreaPadding.value = widget.padding ?? const EdgeInsets.all(0); c.textZoom.value = (MediaQuery.of(Get.context!).textScaleFactor * 100).round(); } Widget _buildRender() { return ListView( children: [ Container( color: Styles.panelBackgroundColor, child: SafeArea( top: false, bottom: false, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Html( data: c.contentHtml.value, ), ], ), ), ), ), ], ); } Widget _buildWebview() { return Obx( () => Stack( children: [ Opacity( opacity: c.loading.value ? 0 : 1, child: InAppWebView( onWebViewCreated: c.onWebViewCreated, onPageCommitVisible: c.onPageCommitVisible, initialOptions: InAppWebViewGroupOptions( android: AndroidInAppWebViewOptions( textZoom: c.textZoom.value, ), ), ), ), if (c.loading.value) const Center( child: CupertinoActivityIndicator(radius: 20), ), ], ), ); } @override Widget build(BuildContext context) { var sc = Get.find(); return Obx( () => sc.betaPageRender.value ? _buildRender() : _buildWebview()); } }