将页面模式从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:shared_preferences/shared_preferences.dart';
|
||||
|
||||
typedef VoidFutureCallback = Future<void> Function();
|
||||
typedef BoolFutureCallback = Future<bool> Function();
|
||||
|
||||
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 String wikiLang = "zh-cn";
|
||||
|
||||
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