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.

230 lines
6.9 KiB
Dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:isekai_wiki/api/mw/list.dart';
import 'package:isekai_wiki/api/mw/mw_api.dart';
import 'package:isekai_wiki/api/response/page_info.dart';
import 'package:isekai_wiki/components/responsive_pair.dart';
import 'package:isekai_wiki/components/isekai_nav_bar.dart';
import 'package:isekai_wiki/components/isekai_page_scaffold.dart';
import 'package:isekai_wiki/global.dart';
import 'package:isekai_wiki/reactive/reactive.dart';
import 'package:isekai_wiki/utils/dialog.dart';
import 'package:isekai_wiki/utils/error.dart';
class WikiInfoPageController extends GetxController {
var pageTitle = "".obs;
var pageId = 0.obs;
var pageInfo = Rx<PageInfo?>(null);
var loadingPageInfo = true.obs;
@override
void onInit() {
super.onInit();
Future.delayed(const Duration(milliseconds: 150)).then((_) {
loadPageInfo();
});
}
Future<void> loadPageInfo() async {
if (pageTitle.isNotEmpty || pageId.value != 0) {
try {
// 加载页面信息
loadingPageInfo.value = true;
MWResponse<List<PageInfo>> pageInfoRes;
if (pageId.value != 0) {
pageInfoRes = await MWApiList.getPageInfoList(pageids: [
pageId.value
], prop: [
"info",
"pageimages",
"pageviews"
], extraParams: {
"inprop":
"url|protection|watched|watchers|visitingwatchers|displaytitle",
});
} else {
pageInfoRes =
await MWApiList.getPageInfoList(titles: [pageTitle.value]);
}
if (pageInfoRes.data.isEmpty) {
throw MWApiErrorException(code: 'no-page', info: "页面信息丢失");
}
pageInfo.value = pageInfoRes.data[0];
pageId.value = pageInfo.value!.pageid;
pageTitle.value = pageInfo.value!.title;
} catch (err, stack) {
alert(Get.overlayContext!, ErrorUtils.getErrorMessage(err),
title: "错误");
if (kDebugMode) {
print("Exception in page: $err");
stack.printError();
}
} finally {
loadingPageInfo.value = false;
}
} else {
alert(Get.overlayContext!, "页面不存在");
}
}
}
class WikiInfoPage extends StatefulWidget {
final String? targetPage;
final int? targetPageId;
const WikiInfoPage({super.key, this.targetPage, this.targetPageId});
@override
State<StatefulWidget> createState() => _WikiInfoPageState();
}
class _WikiInfoPageState extends ReactiveState<WikiInfoPage> {
WikiInfoPageController c = WikiInfoPageController();
@override
void initState() {
super.initState();
Get.put(c);
}
@override
void dispose() {
super.dispose();
Get.delete<WikiInfoPageController>();
}
@override
void receiveProps() {
c.pageId.value = widget.targetPageId ?? 0;
c.pageTitle.value = widget.targetPage ?? "";
}
Widget buildLoading(BuildContext context) {
return CupertinoListSection.insetGrouped(
header: Text("基本信息"),
backgroundColor: CupertinoTheme.of(context).scaffoldBackgroundColor,
children: <CupertinoListTile>[
CupertinoListTile.notched(
title: Center(
child: CupertinoActivityIndicator(
radius: 10 * MediaQuery.of(context).textScaleFactor),
),
),
],
);
}
CupertinoListTile buildPageInfo(
BuildContext context, String label, dynamic value,
{VoidFutureCallback? onTap}) {
final Locale appLocale = Localizations.localeOf(context);
var valueStr = "未知";
if (value is String) {
valueStr = value;
}
if (value is int) {
valueStr =
NumberFormat.decimalPattern(appLocale.toLanguageTag()).format(value);
} else if (value is double) {
var pattern = NumberFormat.decimalPattern(appLocale.toLanguageTag());
pattern.maximumFractionDigits = 2;
valueStr = pattern.format(value);
} else if (value is DateTime) {
// ignore: prefer_interpolation_to_compose_strings
valueStr = DateFormat.yMMMd(appLocale.toLanguageTag()).format(value) +
" " +
DateFormat.Hms(appLocale.toLanguageTag()).format(value);
}
return CupertinoListTile.notched(
padding: const EdgeInsetsDirectional.fromSTEB(20.0, 10.0, 14.0, 10.0),
title: SizedBox(
width: MediaQuery.of(context).size.width,
child: ResponsivePair(
children: [
Text(label),
Text(
valueStr,
style: TextStyle(
color: CupertinoColors.systemGrey2.resolveFrom(context)),
),
],
),
),
trailing: onTap != null
? const Padding(
padding: EdgeInsets.only(left: 8),
child: CupertinoListTileChevron(),
)
: null,
onTap: onTap,
);
}
int? getPageViews(Map<DateTime, int?>? pageViews) {
if (pageViews == null) return null;
int validData = 0;
int visitSum = 0;
pageViews.forEach((key, value) {
if (value != null) {
validData++;
visitSum += value;
}
});
return validData != 0 ? visitSum : null;
}
Widget buildPageInfoList(BuildContext context) {
var pageInfo = c.pageInfo.value;
return Column(
children: [
CupertinoListSection.insetGrouped(
additionalDividerMargin: 6,
header: const Text("基本信息"),
backgroundColor: CupertinoTheme.of(context).scaffoldBackgroundColor,
children: <CupertinoListTile>[
buildPageInfo(context, "页面标题", pageInfo?.title),
buildPageInfo(context, "显示标题", pageInfo?.mainTitle),
buildPageInfo(context, "页面长度(字节)", pageInfo?.length),
buildPageInfo(context, "页面ID", pageInfo?.pageid),
buildPageInfo(context, "页面内容语言", pageInfo?.pagelanguage),
buildPageInfo(context, "页面内容类型", pageInfo?.contentmodel),
buildPageInfo(context, "收藏者数", pageInfo?.watchers),
buildPageInfo(context, "更新后已查看的收藏者", pageInfo?.visitingwatchers),
buildPageInfo(context, "最后修改于", pageInfo?.updatedTime),
buildPageInfo(context, "该页面的子页面数", null),
buildPageInfo(
context, "过去30天的页面访问量", getPageViews(pageInfo?.pageviews)),
],
),
],
);
}
@override
Widget render(BuildContext context) {
return IsekaiPageScaffold(
navigationBar: const IsekaiNavigationBar(
middle: Text("页面信息"),
),
child: SafeArea(
child: ListView(
children: [
Obx(() => c.loadingPageInfo.value
? buildLoading(context)
: buildPageInfoList(context))
],
),
),
);
}
}