完成初次打开加载配置文件

main
落雨楓 2 years ago
parent f5c9dd9720
commit 81d402bba7

Before

Width:  |  Height:  |  Size: 744 KiB

After

Width:  |  Height:  |  Size: 744 KiB

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="{{lang}}">
<head>
<meta charset="utf-8">
<meta lang="{{lang}}">
<title>{{title}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, minimum-scale=0.25, maximum-scale=5.0">
{{scripts}}
</head>
<body class="mediawiki mobileapp ltr sitedir-ltr mw-hide-empty-elt action-view skin--responsive {{bodyClassName}}">
<div id="content" class="mw-body">
{{content}}
</div>
</body>
</html>

@ -72,8 +72,6 @@ class MWResponse<T> {
}
class MWApi {
static Uri apiBaseUri = Uri.parse(Global.wikiApiUrl);
static Future<MWResponse<Map<String, dynamic>>> get(String action,
{Map<String, dynamic>? params}) async {
Map<String, String> paramsStr =
@ -90,6 +88,7 @@ class MWApi {
var resText = "";
try {
var apiBaseUri = Uri.parse(Global.siteConfig.apiUrl);
resText = await BaseApi.get(apiBaseUri, search: paramsStr);
} on DioError catch (err) {
if (err.type == DioErrorType.response) {
@ -133,6 +132,8 @@ class MWApi {
params["token"] = await getToken(type: withToken);
}
var apiBaseUri = Uri.parse(Global.siteConfig.apiUrl);
resText = await BaseApi.post(apiBaseUri, data: params);
} on DioError catch (err) {
if (err.type == DioErrorType.response) {

@ -3,7 +3,7 @@ import 'package:isekai_wiki/global.dart';
class RestbaseApi {
static Uri getUri(String endpoint, {Map<String, dynamic>? search}) {
String url = Global.restfulApiUrl;
String url = Global.siteConfig.restfulApiUrl;
if (url.endsWith("/")) {
url = url.substring(0, url.length - 1);
}

@ -1,8 +1,10 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:get/get.dart';
import 'package:isekai_wiki/global.dart';
import 'package:isekai_wiki/models/settings.dart';
import 'package:isekai_wiki/models/site_config.dart';
import 'package:isekai_wiki/models/user.dart';
import 'package:isekai_wiki/pages/welcome_page.dart';
import 'models/model.dart';
@ -33,9 +35,13 @@ class IsekaiWikiApp extends StatelessWidget {
textTheme: Styles.defaultTextTheme,
scaffoldBackgroundColor: Styles.themePageBackgroundColor),
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
DefaultMaterialLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('zh', 'CN'),
Locale('en'),
],
initialBinding: InitialBinding(),
home: _buildApp(context),

@ -0,0 +1,146 @@
import 'package:flutter/cupertino.dart';
import 'dart:ui' as ui show TextHeightBehavior;
class IsekaiText extends StatelessWidget {
const IsekaiText(
this.data, {
super.key,
this.style,
this.strutStyle,
this.textAlign,
this.textDirection,
this.locale,
this.softWrap,
this.overflow,
this.textScaleFactor,
this.maxLines,
this.semanticsLabel,
this.textWidthBasis,
this.textHeightBehavior,
this.selectionColor,
});
/// The text to display.
///
/// This will be null if a [textSpan] is provided instead.
final String data;
/// If non-null, the style to use for this text.
///
/// If the style's "inherit" property is true, the style will be merged with
/// the closest enclosing [DefaultTextStyle]. Otherwise, the style will
/// replace the closest enclosing [DefaultTextStyle].
final TextStyle? style;
/// {@macro flutter.painting.textPainter.strutStyle}
final StrutStyle? strutStyle;
/// How the text should be aligned horizontally.
final TextAlign? textAlign;
/// The directionality of the text.
///
/// This decides how [textAlign] values like [TextAlign.start] and
/// [TextAlign.end] are interpreted.
///
/// This is also used to disambiguate how to render bidirectional text. For
/// example, if the [data] is an English phrase followed by a Hebrew phrase,
/// in a [TextDirection.ltr] context the English phrase will be on the left
/// and the Hebrew phrase to its right, while in a [TextDirection.rtl]
/// context, the English phrase will be on the right and the Hebrew phrase on
/// its left.
///
/// Defaults to the ambient [Directionality], if any.
final TextDirection? textDirection;
/// Used to select a font when the same Unicode character can
/// be rendered differently, depending on the locale.
///
/// It's rarely necessary to set this property. By default its value
/// is inherited from the enclosing app with `Localizations.localeOf(context)`.
///
/// See [RenderParagraph.locale] for more information.
final Locale? locale;
/// Whether the text should break at soft line breaks.
///
/// If false, the glyphs in the text will be positioned as if there was unlimited horizontal space.
final bool? softWrap;
/// How visual overflow should be handled.
///
/// If this is null [TextStyle.overflow] will be used, otherwise the value
/// from the nearest [DefaultTextStyle] ancestor will be used.
final TextOverflow? overflow;
/// The number of font pixels for each logical pixel.
///
/// For example, if the text scale factor is 1.5, text will be 50% larger than
/// the specified font size.
///
/// The value given to the constructor as textScaleFactor. If null, will
/// use the [MediaQueryData.textScaleFactor] obtained from the ambient
/// [MediaQuery], or 1.0 if there is no [MediaQuery] in scope.
final double? textScaleFactor;
/// An optional maximum number of lines for the text to span, wrapping if necessary.
/// If the text exceeds the given number of lines, it will be truncated according
/// to [overflow].
///
/// If this is 1, text will not wrap. Otherwise, text will be wrapped at the
/// edge of the box.
///
/// If this is null, but there is an ambient [DefaultTextStyle] that specifies
/// an explicit number for its [DefaultTextStyle.maxLines], then the
/// [DefaultTextStyle] value will take precedence. You can use a [RichText]
/// widget directly to entirely override the [DefaultTextStyle].
final int? maxLines;
/// {@template flutter.widgets.Text.semanticsLabel}
/// An alternative semantics label for this text.
///
/// If present, the semantics of this widget will contain this value instead
/// of the actual text. This will overwrite any of the semantics labels applied
/// directly to the [TextSpan]s.
///
/// This is useful for replacing abbreviations or shorthands with the full
/// text value:
///
/// ```dart
/// Text(r'$$', semanticsLabel: 'Double dollars')
/// ```
/// {@endtemplate}
final String? semanticsLabel;
/// {@macro flutter.painting.textPainter.textWidthBasis}
final TextWidthBasis? textWidthBasis;
/// {@macro dart.ui.textHeightBehavior}
final ui.TextHeightBehavior? textHeightBehavior;
/// The color to use when painting the selection.
final Color? selectionColor;
@override
Widget build(BuildContext context) {
var strutStyleFixed = strutStyle;
if (style?.fontSize != null) {}
return Text(
data,
style: style,
strutStyle: strutStyleFixed,
textAlign: textAlign,
textDirection: textDirection,
locale: locale,
softWrap: softWrap,
overflow: overflow,
textScaleFactor: textScaleFactor,
maxLines: maxLines,
semanticsLabel: semanticsLabel,
textWidthBasis: textWidthBasis,
textHeightBehavior: textHeightBehavior,
selectionColor: selectionColor,
);
}
}

@ -115,7 +115,6 @@ class _PageCardState extends ReactiveState<PageCard> {
@override
void initState() {
super.initState();
Get.put(c);
}
@override

@ -26,7 +26,7 @@ class WikiPageParserController extends GetxController {
if (contentHtml.value.isNotEmpty) {
webviewCotroller?.loadData(
data: contentHtml.value,
baseUrl: Uri.parse(Global.wikiHomeUrl),
baseUrl: Uri.parse(Global.siteConfig.baseUrl),
);
}
});
@ -45,12 +45,11 @@ class WikiPageParserController extends GetxController {
webviewCotroller?.loadData(
data: contentHtml.value,
baseUrl: Uri.parse(Global.wikiHomeUrl),
baseUrl: Uri.parse(Global.siteConfig.baseUrl),
);
}
void onPageCommitVisible(InAppWebViewController controller, Uri? uri) {
debugPrint("loaded");
controller.injectCSSCode(source: """
body {
padding-top: ${safeAreaPadding.value.top}px;
@ -99,8 +98,7 @@ class _WikiParserState extends ReactiveState<WikiPageParser> {
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();
c.textZoom.value = (MediaQuery.of(Get.context!).textScaleFactor * 100).round();
}
Widget _buildRender() {
@ -156,7 +154,6 @@ class _WikiParserState extends ReactiveState<WikiPageParser> {
@override
Widget build(BuildContext context) {
var sc = Get.find<AppSettingsController>();
return Obx(
() => sc.betaPageRender.value ? _buildRender() : _buildWebview());
return Obx(() => sc.betaPageRender.value ? _buildRender() : _buildWebview());
}
}

@ -1,3 +1,4 @@
import 'package:isekai_wiki/models/site_config.dart';
import 'package:package_info_plus/package_info_plus.dart';
typedef VoidFutureCallback = Future<void> Function();
@ -11,15 +12,9 @@ class Global {
static const String privacyPolicyUrl =
"https://www.isekai.cn/%E5%BC%82%E4%B8%96%E7%95%8C%E7%99%BE%E7%A7%91:%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96";
static const String siteConfigUrl = "https://www.isekai.cn/app/config.json";
static const String siteConfigUrl = "https://www.isekai.cn/mugenapp/config.json";
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/{{title}}";
static SiteConfig siteConfig = SiteConfig();
static const String renderThemeFallback = "vector";

@ -7,6 +7,7 @@ import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:isekai_wiki/global.dart';
import 'package:isekai_wiki/models/lifecycle.dart';
import 'package:isekai_wiki/models/site_config.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'app.dart';
@ -61,10 +62,11 @@ Future<void> postInit() async {
}
Future<void> main() async {
Get.put(LifeCycleController());
await init();
Get.put(LifeCycleController());
Get.put(SiteConfigController());
runApp(const IsekaiWikiApp());
postInit();

@ -1,6 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:isekai_wiki/global.dart';
import 'package:isekai_wiki/models/user.dart';
class LifeCycleController extends SuperController {
@ -11,15 +11,21 @@ class LifeCycleController extends SuperController {
void onInactive() {}
@override
void onPaused() {
debugPrint("onPause");
}
void onPaused() {}
@override
void onResumed() {
debugPrint("onResume");
if (Global.isAppActive) {
try {
var uc = Get.find<UserController>();
uc.attemptFinishAuth();
} catch (err, stack) {
if (kDebugMode) {
print("error on attemptFinishAuth: $err");
stack.printError();
}
}
}
}
}

@ -16,26 +16,58 @@ class SiteConfig {
List<String> moduleScripts;
String renderTheme;
String baseUrl;
String indexUrl;
String apiUrl;
String resourceLoaderUrl;
String restfulApiUrl;
String pageUrlTemplate;
SiteConfig({
this.moduleStyles = const [],
this.moduleScripts = const [],
this.renderTheme = Global.renderThemeFallback,
this.baseUrl = "",
this.indexUrl = "",
this.apiUrl = "",
this.resourceLoaderUrl = "",
this.restfulApiUrl = "",
this.pageUrlTemplate = "",
});
factory SiteConfig.fromJson(Map<String, dynamic> json) =>
_$SiteConfigFromJson(json);
factory SiteConfig.fromJson(Map<String, dynamic> json) => _$SiteConfigFromJson(json);
Map<String, dynamic> toJson() => _$SiteConfigToJson(this);
void fillUrl() {
if (indexUrl.isEmpty) {
indexUrl = "$baseUrl/index.php";
}
if (apiUrl.isEmpty) {
apiUrl = "$baseUrl/api.php";
}
class AppSettingsController extends GetxController {
if (resourceLoaderUrl.isEmpty) {
resourceLoaderUrl = "$baseUrl/load.php";
}
if (pageUrlTemplate.isEmpty) {
pageUrlTemplate = "$baseUrl/index.php?title={{title}}";
}
}
bool get restfulApiAvailable {
return restfulApiUrl.isNotEmpty;
}
}
class SiteConfigController extends GetxController {
bool _ignoreSave = false;
bool isAppActive = false;
List<String> moduleStyles = [];
List<String> moduleScripts = [];
String renderTheme = Global.renderThemeFallback;
var config = Rx<SiteConfig>(SiteConfig());
@override
void onInit() {
@ -85,21 +117,16 @@ class AppSettingsController extends GetxController {
final storage = GetStorage();
var siteConfigData = SiteConfig(
moduleScripts: moduleScripts,
moduleStyles: moduleStyles,
renderTheme: renderTheme,
);
var siteConfigJson = jsonEncode(siteConfigData.toJson());
var siteConfigJson = jsonEncode(config.value);
storage.write("siteConfigCache", siteConfigJson);
storage.write("appActive", isAppActive);
}
void loadFromEntity(SiteConfig siteConfigData) {
moduleScripts = siteConfigData.moduleScripts;
moduleStyles = siteConfigData.moduleStyles;
renderTheme = siteConfigData.renderTheme;
config.value = siteConfigData;
Global.siteConfig = config.value;
}
Future<void> loadFromRemote() async {
@ -108,5 +135,8 @@ class AppSettingsController extends GetxController {
var siteConfigData = SiteConfig.fromJson(resMap);
loadFromEntity(siteConfigData);
isAppActive = true;
saveToStorage();
}
}

@ -11,7 +11,7 @@ import '../styles.dart';
class AboutPageController extends GetxController {
Future<void> handleMainPageLinkClick() async {
openUrl(Global.wikiHomeUrl);
openUrl(Global.siteConfig.indexUrl);
}
}

@ -1,14 +1,19 @@
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:isekai_wiki/components/isekai_page_scaffold.dart';
import 'package:isekai_wiki/global.dart';
import 'package:isekai_wiki/models/site_config.dart';
import 'package:isekai_wiki/pages/tab_page.dart';
import 'package:isekai_wiki/utils/dialog.dart';
import 'package:roundcheckbox/roundcheckbox.dart';
import '../utils/error.dart';
class WelcomePageController extends GetxController {
var isLoading = false.obs;
@ -17,11 +22,96 @@ class WelcomePageController extends GetxController {
void handleClickPolicyLink() {
openUrl(Global.privacyPolicyUrl, inApp: false);
}
Future<void> handleClickContinue() async {
isLoading.value = true;
var siteConfig = Get.find<SiteConfigController>();
try {
await showLoading(Get.overlayContext!, callback: () async {
await siteConfig.loadFromRemote();
});
//
Navigator.of(Get.context!).pushReplacement(
CupertinoPageRoute(
builder: (_) => const IsekaiWikiTabsPage(),
),
);
} catch (err, stack) {
alert(Get.overlayContext!, ErrorUtils.getErrorMessage(err), title: "错误");
if (kDebugMode) {
print("Exception in logout: $err");
stack.printError();
}
}
isLoading.value = false;
}
}
class WelcomePage extends StatelessWidget {
const WelcomePage({super.key});
@override
Widget build(BuildContext context) {
var c = Get.put(WelcomePageController());
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: IsekaiPageScaffold(
backgroundColor: CupertinoColors.white,
child: Stack(
fit: StackFit.expand,
children: [
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: ExactAssetImage('assets/images/title.png'),
fit: BoxFit.cover,
),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
decoration: BoxDecoration(color: Colors.black.withOpacity(0.4)),
),
),
),
SafeArea(
child: OrientationBuilder(
builder: (context, orientation) => Padding(
padding: orientation == Orientation.portrait
? const EdgeInsets.only(top: 48, right: 20, bottom: 32, left: 20)
: const EdgeInsets.symmetric(horizontal: 20, vertical: 32),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
flex: 0,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 8),
child: _buildSiteTitle(context, c),
),
),
],
),
const SizedBox(height: 36),
_buildActions(context, c),
],
),
),
),
),
],
),
),
);
}
Widget _buildSiteTitle(BuildContext context, WelcomePageController c) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -30,8 +120,7 @@ class WelcomePage extends StatelessWidget {
data: MediaQueryData(textScaleFactor: 1),
child: Text(
Global.siteTitle,
style: TextStyle(
fontSize: 48, color: Colors.white, fontWeight: FontWeight.bold),
style: TextStyle(fontSize: 48, color: Colors.white, fontWeight: FontWeight.bold),
),
),
Text(
@ -44,6 +133,7 @@ class WelcomePage extends StatelessWidget {
Widget _buildActions(BuildContext context, WelcomePageController c) {
var theme = CupertinoTheme.of(context);
var scaleFactor = MediaQuery.of(context).textScaleFactor;
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
@ -57,13 +147,18 @@ class WelcomePage extends StatelessWidget {
children: [
Obx(
() => RoundCheckBox(
size: 24,
size: 24 * scaleFactor,
isChecked: c.policyAccepted.value,
animationDuration: Duration.zero,
checkedColor: theme.primaryColor,
checkedWidget: Icon(
Icons.check,
color: Colors.white,
size: 18 * scaleFactor,
),
onTap: (checked) {
c.policyAccepted.value = checked ?? false;
},
animationDuration: Duration.zero,
checkedColor: theme.primaryColor,
),
),
const SizedBox(
@ -90,82 +185,11 @@ class WelcomePage extends StatelessWidget {
Obx(
() => CupertinoButton.filled(
disabledColor: theme.primaryColor.withOpacity(0.6),
onPressed: c.policyAccepted.value && !c.isLoading.value
? () {
c.isLoading.value = true;
Future.delayed(const Duration(seconds: 5)).then((value) {
c.isLoading.value = false;
});
}
: null,
onPressed: c.policyAccepted.value && !c.isLoading.value ? c.handleClickContinue : null,
child: const Text("继续"),
),
),
],
);
}
@override
Widget build(BuildContext context) {
var c = Get.put(WelcomePageController());
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: IsekaiPageScaffold(
backgroundColor: CupertinoColors.white,
child: Stack(
fit: StackFit.expand,
children: [
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: ExactAssetImage('images/title.png'),
fit: BoxFit.cover,
),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
decoration:
BoxDecoration(color: Colors.black.withOpacity(0.4)),
),
),
),
SafeArea(
child: OrientationBuilder(
builder: (context, orientation) => Padding(
padding: orientation == Orientation.portrait
? const EdgeInsets.only(
top: 32, right: 20, bottom: 32, left: 20)
: const EdgeInsets.symmetric(
horizontal: 20, vertical: 32),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
flex: 0,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 24, horizontal: 8),
child: _buildSiteTitle(context, c),
),
),
],
),
const SizedBox(height: 36),
_buildActions(context, c),
],
),
),
),
),
],
),
),
);
}
}

@ -6,24 +6,25 @@ abstract class Styles {
static bool isXs = false;
static const double defaultFontSize = 16;
static const CupertinoTextThemeData defaultTextTheme = CupertinoTextThemeData(
textStyle: TextStyle(
fontSize: 16,
fontSize: defaultFontSize,
fontFamilyFallback: [
"PingFang SC",
"Heiti SC",
"Noto Sans SC",
"Hei",
"Microsoft YaHei",
"Hei",
"SimHei",
],
color: CupertinoColors.label,
),
);
static const TextStyle navLargeTitleTextStyle = TextStyle(
fontWeight: FontWeight.normal,
fontSize: 32,
color: CupertinoColors.label,
inherit: false);
fontWeight: FontWeight.normal, fontSize: 32, color: CupertinoColors.label, inherit: false);
static const TextStyle productRowItemName = TextStyle(
color: Color.fromRGBO(0, 0, 0, 0.8),
@ -61,13 +62,14 @@ abstract class Styles {
static const TextStyle listTileLargeTitle = TextStyle(fontSize: 18);
static const TextStyle listTileSubTitle = TextStyle(fontSize: 16);
static const TextStyle loadingDialogTitle = TextStyle(fontSize: 18, fontWeight: FontWeight.w500);
static const Color websiteNavbarColor = Color.fromRGBO(33, 37, 41, 1);
static const Color themeMainColor = Color.fromRGBO(65, 147, 135, 1);
static const Color themeNavTitleColor = Color.fromRGBO(255, 255, 255, 1);
static const Color themeBottomColor = Color.fromRGBO(255, 255, 255, 1);
static const Color themePageBackgroundColor =
Color.fromRGBO(240, 240, 240, 1);
static const Color themePageBackgroundColor = Color.fromRGBO(240, 240, 240, 1);
static const Color themeNavSegmentTextColor = Color.fromRGBO(12, 12, 12, 1);
static const Color panelBackgroundColor = Color.fromRGBO(255, 255, 255, 1);
static const Color linkColor = CupertinoColors.link;

@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_web_browser/flutter_web_browser.dart';
import 'package:get/get.dart';
import 'package:isekai_wiki/global.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:url_launcher/url_launcher_string.dart';
@ -33,10 +34,7 @@ Future<void> alert(BuildContext context, String content, {String? title}) {
}
Future<bool> confirm(BuildContext context, String content,
{String? title,
String? positiveText,
String? negativeText,
bool isDanger = false}) {
{String? title, String? positiveText, String? negativeText, bool isDanger = false}) {
var c = Completer<bool>();
positiveText ??= "";
@ -94,3 +92,30 @@ Future<void> openUrl(String url, {bool inApp = false}) async {
//
launchUrlString(url, mode: LaunchMode.externalApplication);
}
Future<void> showLoading(BuildContext context,
{String? title, required VoidFutureCallback callback}) async {
title ??= "加载中";
showCupertinoDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: Row(
children: [
const CupertinoActivityIndicator(radius: 14),
const SizedBox(width: 20),
Text(title!),
],
),
actions: const [],
),
);
try {
var ret = await callback.call();
Navigator.of(Get.context!).pop();
return ret;
} catch (_) {
Navigator.of(Get.context!).pop();
rethrow;
}
}

File diff suppressed because it is too large Load Diff

@ -99,7 +99,8 @@ flutter:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
assets:
- images/title.png
- assets/images/title.png
- assets/tpl/wikiPage.html
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware

@ -1 +1 @@
/Users/hyperzlib/Projects/isekai_wiki_app/images
D:/Users/hyperzlib/Projects/isekai_wiki_app/images
Loading…
Cancel
Save