You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
4.2 KiB
Dart

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.siteConfig.baseUrl),
);
}
});
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.siteConfig.baseUrl),
);
}
void onPageCommitVisible(InAppWebViewController controller, Uri? uri) {
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<StatefulWidget> createState() {
return _WikiParserState();
}
}
class _WikiParserState extends ReactiveState<WikiPageParser> {
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: <Widget>[
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<AppSettingsController>();
return Obx(() => sc.betaPageRender.value ? _buildRender() : _buildWebview());
}
}