将页面模式从Flutter渲染改为Webview渲染
parent
fcd6df92f8
commit
949752dbd1
@ -0,0 +1 @@
|
|||||||
|
class MWApiParse {}
|
@ -0,0 +1,147 @@
|
|||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'parse.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class MWParseCategoryInfo {
|
||||||
|
String sortkey;
|
||||||
|
String category;
|
||||||
|
|
||||||
|
MWParseCategoryInfo({
|
||||||
|
this.sortkey = "",
|
||||||
|
this.category = "",
|
||||||
|
});
|
||||||
|
|
||||||
|
factory MWParseCategoryInfo.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$MWParseCategoryInfoFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$MWParseCategoryInfoToJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class MWParseLangLinkInfo {
|
||||||
|
String lang;
|
||||||
|
String url;
|
||||||
|
String langname;
|
||||||
|
String autonym;
|
||||||
|
String title;
|
||||||
|
|
||||||
|
MWParseLangLinkInfo({
|
||||||
|
this.lang = "",
|
||||||
|
this.url = "",
|
||||||
|
this.langname = "",
|
||||||
|
this.autonym = "",
|
||||||
|
this.title = "",
|
||||||
|
});
|
||||||
|
|
||||||
|
factory MWParseLangLinkInfo.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$MWParseLangLinkInfoFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$MWParseLangLinkInfoToJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class MWParsePageLinkInfo {
|
||||||
|
int ns;
|
||||||
|
String title;
|
||||||
|
bool exists;
|
||||||
|
|
||||||
|
MWParsePageLinkInfo({
|
||||||
|
this.ns = -1,
|
||||||
|
this.title = "",
|
||||||
|
this.exists = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory MWParsePageLinkInfo.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$MWParsePageLinkInfoFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$MWParsePageLinkInfoToJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class MWParseSectionInfo {
|
||||||
|
int toclevel;
|
||||||
|
int level;
|
||||||
|
String line;
|
||||||
|
String number;
|
||||||
|
String index;
|
||||||
|
String fromtitle;
|
||||||
|
int? byteoffset;
|
||||||
|
String anchor;
|
||||||
|
|
||||||
|
MWParseSectionInfo({
|
||||||
|
this.toclevel = -1,
|
||||||
|
this.level = -1,
|
||||||
|
this.line = "",
|
||||||
|
this.number = "",
|
||||||
|
this.index = "",
|
||||||
|
this.fromtitle = "",
|
||||||
|
this.byteoffset,
|
||||||
|
this.anchor = "",
|
||||||
|
});
|
||||||
|
|
||||||
|
factory MWParseSectionInfo.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$MWParseSectionInfoFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$MWParseSectionInfoToJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class MWParseInfo {
|
||||||
|
String title;
|
||||||
|
int pageid;
|
||||||
|
int revid;
|
||||||
|
String text;
|
||||||
|
List<MWParseLangLinkInfo> langlink;
|
||||||
|
List<MWParseCategoryInfo> categories;
|
||||||
|
List<MWParsePageLinkInfo> links;
|
||||||
|
List<MWParsePageLinkInfo> templates;
|
||||||
|
List<String> images;
|
||||||
|
List<String> externallinks;
|
||||||
|
List<MWParseSectionInfo> sections;
|
||||||
|
bool showtoc;
|
||||||
|
String displaytitle;
|
||||||
|
List<String> modules;
|
||||||
|
List<String> modulescripts;
|
||||||
|
List<String> modulestyles;
|
||||||
|
Map<String, dynamic> jsconfigvars;
|
||||||
|
Map<String, dynamic> iwlinks;
|
||||||
|
Map<String, dynamic> properties;
|
||||||
|
|
||||||
|
MWParseInfo({
|
||||||
|
this.title = "",
|
||||||
|
this.pageid = -1,
|
||||||
|
this.revid = -1,
|
||||||
|
this.text = "",
|
||||||
|
this.langlink = const [],
|
||||||
|
this.categories = const [],
|
||||||
|
this.links = const [],
|
||||||
|
this.templates = const [],
|
||||||
|
this.images = const [],
|
||||||
|
this.externallinks = const [],
|
||||||
|
this.sections = const [],
|
||||||
|
this.showtoc = true,
|
||||||
|
this.displaytitle = "",
|
||||||
|
this.modules = const [],
|
||||||
|
this.modulescripts = const [],
|
||||||
|
this.modulestyles = const [],
|
||||||
|
this.jsconfigvars = const {},
|
||||||
|
this.iwlinks = const {},
|
||||||
|
this.properties = const {},
|
||||||
|
});
|
||||||
|
|
||||||
|
factory MWParseInfo.fromJson(Map<String, dynamic> json) => _$MWParseInfoFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$MWParseInfoToJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class MWParseResponse {
|
||||||
|
MWParseInfo parse;
|
||||||
|
|
||||||
|
MWParseResponse({required this.parse});
|
||||||
|
|
||||||
|
factory MWParseResponse.fromJson(Map<String, dynamic> json) => _$MWParseResponseFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$MWParseResponseToJson(this);
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'parse.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
MWParseCategoryInfo _$MWParseCategoryInfoFromJson(Map<String, dynamic> json) =>
|
||||||
|
MWParseCategoryInfo(
|
||||||
|
sortkey: json['sortkey'] as String? ?? "",
|
||||||
|
category: json['category'] as String? ?? "",
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$MWParseCategoryInfoToJson(
|
||||||
|
MWParseCategoryInfo instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'sortkey': instance.sortkey,
|
||||||
|
'category': instance.category,
|
||||||
|
};
|
||||||
|
|
||||||
|
MWParseLangLinkInfo _$MWParseLangLinkInfoFromJson(Map<String, dynamic> json) =>
|
||||||
|
MWParseLangLinkInfo(
|
||||||
|
lang: json['lang'] as String? ?? "",
|
||||||
|
url: json['url'] as String? ?? "",
|
||||||
|
langname: json['langname'] as String? ?? "",
|
||||||
|
autonym: json['autonym'] as String? ?? "",
|
||||||
|
title: json['title'] as String? ?? "",
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$MWParseLangLinkInfoToJson(
|
||||||
|
MWParseLangLinkInfo instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'lang': instance.lang,
|
||||||
|
'url': instance.url,
|
||||||
|
'langname': instance.langname,
|
||||||
|
'autonym': instance.autonym,
|
||||||
|
'title': instance.title,
|
||||||
|
};
|
||||||
|
|
||||||
|
MWParsePageLinkInfo _$MWParsePageLinkInfoFromJson(Map<String, dynamic> json) =>
|
||||||
|
MWParsePageLinkInfo(
|
||||||
|
ns: json['ns'] as int? ?? -1,
|
||||||
|
title: json['title'] as String? ?? "",
|
||||||
|
exists: json['exists'] as bool? ?? false,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$MWParsePageLinkInfoToJson(
|
||||||
|
MWParsePageLinkInfo instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'ns': instance.ns,
|
||||||
|
'title': instance.title,
|
||||||
|
'exists': instance.exists,
|
||||||
|
};
|
||||||
|
|
||||||
|
MWParseSectionInfo _$MWParseSectionInfoFromJson(Map<String, dynamic> json) =>
|
||||||
|
MWParseSectionInfo(
|
||||||
|
toclevel: json['toclevel'] as int? ?? -1,
|
||||||
|
level: json['level'] as int? ?? -1,
|
||||||
|
line: json['line'] as String? ?? "",
|
||||||
|
number: json['number'] as String? ?? "",
|
||||||
|
index: json['index'] as String? ?? "",
|
||||||
|
fromtitle: json['fromtitle'] as String? ?? "",
|
||||||
|
byteoffset: json['byteoffset'] as int?,
|
||||||
|
anchor: json['anchor'] as String? ?? "",
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$MWParseSectionInfoToJson(MWParseSectionInfo instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'toclevel': instance.toclevel,
|
||||||
|
'level': instance.level,
|
||||||
|
'line': instance.line,
|
||||||
|
'number': instance.number,
|
||||||
|
'index': instance.index,
|
||||||
|
'fromtitle': instance.fromtitle,
|
||||||
|
'byteoffset': instance.byteoffset,
|
||||||
|
'anchor': instance.anchor,
|
||||||
|
};
|
||||||
|
|
||||||
|
MWParseInfo _$MWParseInfoFromJson(Map<String, dynamic> json) => MWParseInfo(
|
||||||
|
title: json['title'] as String? ?? "",
|
||||||
|
pageid: json['pageid'] as int? ?? -1,
|
||||||
|
revid: json['revid'] as int? ?? -1,
|
||||||
|
text: json['text'] as String? ?? "",
|
||||||
|
langlink: (json['langlink'] as List<dynamic>?)
|
||||||
|
?.map((e) =>
|
||||||
|
MWParseLangLinkInfo.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
categories: (json['categories'] as List<dynamic>?)
|
||||||
|
?.map((e) =>
|
||||||
|
MWParseCategoryInfo.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
links: (json['links'] as List<dynamic>?)
|
||||||
|
?.map((e) =>
|
||||||
|
MWParsePageLinkInfo.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
templates: (json['templates'] as List<dynamic>?)
|
||||||
|
?.map((e) =>
|
||||||
|
MWParsePageLinkInfo.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
images: (json['images'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
externallinks: (json['externallinks'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
sections: (json['sections'] as List<dynamic>?)
|
||||||
|
?.map(
|
||||||
|
(e) => MWParseSectionInfo.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
showtoc: json['showtoc'] as bool? ?? true,
|
||||||
|
displaytitle: json['displaytitle'] as String? ?? "",
|
||||||
|
modules: (json['modules'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
modulescripts: (json['modulescripts'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
modulestyles: (json['modulestyles'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
jsconfigvars: json['jsconfigvars'] as Map<String, dynamic>? ?? const {},
|
||||||
|
iwlinks: json['iwlinks'] as Map<String, dynamic>? ?? const {},
|
||||||
|
properties: json['properties'] as Map<String, dynamic>? ?? const {},
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$MWParseInfoToJson(MWParseInfo instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'title': instance.title,
|
||||||
|
'pageid': instance.pageid,
|
||||||
|
'revid': instance.revid,
|
||||||
|
'text': instance.text,
|
||||||
|
'langlink': instance.langlink,
|
||||||
|
'categories': instance.categories,
|
||||||
|
'links': instance.links,
|
||||||
|
'templates': instance.templates,
|
||||||
|
'images': instance.images,
|
||||||
|
'externallinks': instance.externallinks,
|
||||||
|
'sections': instance.sections,
|
||||||
|
'showtoc': instance.showtoc,
|
||||||
|
'displaytitle': instance.displaytitle,
|
||||||
|
'modules': instance.modules,
|
||||||
|
'modulescripts': instance.modulescripts,
|
||||||
|
'modulestyles': instance.modulestyles,
|
||||||
|
'jsconfigvars': instance.jsconfigvars,
|
||||||
|
'iwlinks': instance.iwlinks,
|
||||||
|
'properties': instance.properties,
|
||||||
|
};
|
||||||
|
|
||||||
|
MWParseResponse _$MWParseResponseFromJson(Map<String, dynamic> json) =>
|
||||||
|
MWParseResponse(
|
||||||
|
parse: MWParseInfo.fromJson(json['parse'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$MWParseResponseToJson(MWParseResponse instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'parse': instance.parse,
|
||||||
|
};
|
@ -0,0 +1,25 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
class SafeAreaBuilder extends StatelessWidget {
|
||||||
|
final Widget Function(BuildContext context, EdgeInsets padding) builder;
|
||||||
|
final bool maintainBottomViewPadding;
|
||||||
|
|
||||||
|
const SafeAreaBuilder({
|
||||||
|
super.key,
|
||||||
|
required this.builder,
|
||||||
|
this.maintainBottomViewPadding = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
assert(debugCheckHasMediaQuery(context));
|
||||||
|
final MediaQueryData data = MediaQuery.of(context);
|
||||||
|
EdgeInsets padding = data.padding;
|
||||||
|
// Bottom padding has been consumed - i.e. by the keyboard
|
||||||
|
if (maintainBottomViewPadding) {
|
||||||
|
padding = padding.copyWith(bottom: data.viewPadding.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder(context, padding);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
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 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),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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<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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,25 @@
|
|||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
typedef VoidFutureCallback = Future<void> Function();
|
typedef VoidFutureCallback = Future<void> Function();
|
||||||
typedef BoolFutureCallback = Future<bool> Function();
|
typedef BoolFutureCallback = Future<bool> Function();
|
||||||
|
|
||||||
class Global {
|
class Global {
|
||||||
static String isekaiWikiHomeUrl = "https://www.isekai.cn/";
|
static const String wikiApiUrl = "https://www.isekai.cn/api.php";
|
||||||
|
|
||||||
|
static String wikiHomeUrl = "https://www.isekai.cn/";
|
||||||
|
|
||||||
|
static String restfulApiUrl = "https://www.isekai.cn/api/rest_v1";
|
||||||
|
|
||||||
|
static String pageUrl = "https://www.isekai.cn/index.php?title={{title}}";
|
||||||
|
|
||||||
|
static const String renderThemeFallback = "vector";
|
||||||
|
|
||||||
static PackageInfo? packageInfo;
|
static PackageInfo? packageInfo;
|
||||||
|
|
||||||
static String wikiLang = "zh-cn";
|
static String wikiLang = "zh-cn";
|
||||||
|
|
||||||
static String? webOrigin;
|
static String? webOrigin;
|
||||||
|
|
||||||
|
static SharedPreferences? sharedPreferences;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../global.dart';
|
||||||
|
|
||||||
|
part 'settings.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class AppSettings {
|
||||||
|
bool? betaPageRender;
|
||||||
|
|
||||||
|
AppSettings({this.betaPageRender});
|
||||||
|
|
||||||
|
factory AppSettings.fromJson(Map<String, dynamic> json) => _$AppSettingsFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$AppSettingsToJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppSettingsController extends GetxController {
|
||||||
|
bool _ignoreSave = false;
|
||||||
|
|
||||||
|
var betaPageRender = false.obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
super.onInit();
|
||||||
|
|
||||||
|
loadFromStorage();
|
||||||
|
|
||||||
|
everAll([betaPageRender], (_) {
|
||||||
|
saveToStorage();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 从本地存储读取
|
||||||
|
Future<void> loadFromStorage() async {
|
||||||
|
try {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
var settingsJson = prefs.getString("settings");
|
||||||
|
if (settingsJson == null) return;
|
||||||
|
|
||||||
|
var settingsObject = jsonDecode(settingsJson);
|
||||||
|
if (settingsObject == null) return;
|
||||||
|
|
||||||
|
var settingsData = AppSettings.fromJson(settingsObject);
|
||||||
|
|
||||||
|
_ignoreSave = true;
|
||||||
|
betaPageRender.value = settingsData.betaPageRender ?? betaPageRender.value;
|
||||||
|
_ignoreSave = false;
|
||||||
|
} catch (ex) {
|
||||||
|
if (kDebugMode) {
|
||||||
|
print(ex);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_ignoreSave = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 保存到本地存储
|
||||||
|
void saveToStorage() {
|
||||||
|
if (_ignoreSave) return;
|
||||||
|
|
||||||
|
final prefs = Global.sharedPreferences!;
|
||||||
|
|
||||||
|
var settingsData = AppSettings(betaPageRender: betaPageRender.value);
|
||||||
|
|
||||||
|
var settingsJson = jsonEncode(settingsData.toJson());
|
||||||
|
|
||||||
|
prefs.setString("settings", settingsJson);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'settings.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
AppSettings _$AppSettingsFromJson(Map<String, dynamic> json) => AppSettings(
|
||||||
|
betaPageRender: json['betaPageRender'] as bool?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$AppSettingsToJson(AppSettings instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'betaPageRender': instance.betaPageRender,
|
||||||
|
};
|
@ -0,0 +1,81 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../global.dart';
|
||||||
|
|
||||||
|
part 'site_config.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class SiteConfig {
|
||||||
|
List<String> moduleStyles;
|
||||||
|
List<String> moduleScripts;
|
||||||
|
String renderTheme;
|
||||||
|
|
||||||
|
SiteConfig({
|
||||||
|
this.moduleStyles = const [],
|
||||||
|
this.moduleScripts = const [],
|
||||||
|
this.renderTheme = Global.renderThemeFallback,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory SiteConfig.fromJson(Map<String, dynamic> json) => _$SiteConfigFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$SiteConfigToJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppSettingsController extends GetxController {
|
||||||
|
bool _ignoreSave = false;
|
||||||
|
|
||||||
|
var betaPageRender = false.obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
super.onInit();
|
||||||
|
|
||||||
|
loadFromStorage();
|
||||||
|
|
||||||
|
everAll([betaPageRender], (_) {
|
||||||
|
saveToStorage();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 从本地存储读取
|
||||||
|
Future<void> loadFromStorage() async {
|
||||||
|
try {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
var settingsJson = prefs.getString("siteConfigCache");
|
||||||
|
if (settingsJson == null) return;
|
||||||
|
|
||||||
|
var settingsObject = jsonDecode(settingsJson);
|
||||||
|
if (settingsObject == null) return;
|
||||||
|
|
||||||
|
var settingsData = SiteConfig.fromJson(settingsObject);
|
||||||
|
|
||||||
|
_ignoreSave = true;
|
||||||
|
// betaPageRender.value = settingsData.betaPageRender ?? betaPageRender.value;
|
||||||
|
_ignoreSave = false;
|
||||||
|
} catch (ex) {
|
||||||
|
if (kDebugMode) {
|
||||||
|
print(ex);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_ignoreSave = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 保存到本地存储
|
||||||
|
void saveToStorage() {
|
||||||
|
if (_ignoreSave) return;
|
||||||
|
|
||||||
|
final prefs = Global.sharedPreferences!;
|
||||||
|
|
||||||
|
var settingsData = SiteConfig();
|
||||||
|
|
||||||
|
var settingsJson = jsonEncode(settingsData.toJson());
|
||||||
|
|
||||||
|
prefs.setString("siteConfigCache", settingsJson);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'site_config.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
SiteConfig _$SiteConfigFromJson(Map<String, dynamic> json) => SiteConfig(
|
||||||
|
moduleStyles: (json['moduleStyles'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
moduleScripts: (json['moduleScripts'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
renderTheme: json['renderTheme'] as String? ?? Global.renderThemeFallback,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SiteConfigToJson(SiteConfig instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'moduleStyles': instance.moduleStyles,
|
||||||
|
'moduleScripts': instance.moduleScripts,
|
||||||
|
'renderTheme': instance.renderTheme,
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue