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.

266 lines
8.1 KiB
Dart

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:isekai_wiki/components/isekai_nav_bar.dart';
import 'package:isekai_wiki/components/isekai_page_scaffold.dart';
import 'package:isekai_wiki/models/user.dart';
import 'package:isekai_wiki/pages/about.dart';
import 'package:isekai_wiki/pages/settings/list.dart';
import 'package:isekai_wiki/styles.dart';
import 'package:isekai_wiki/utils/dialog.dart';
import '../components/dummy_icon.dart';
import '../components/follow_scale.dart';
class OwnProfileController extends GetxController {
late UserController uc;
@override
void onInit() {
super.onInit();
uc = Get.find<UserController>();
}
Future<void> handleUserClick() {
if (uc.isLoggedIn) {
} else {
if (uc.authProcessing.isFalse) {
handleStartAuth();
return Future.delayed(const Duration(milliseconds: 100));
}
}
return Future.value();
}
Future<void> handleStartAuth() async {
await uc.startAuthFlow();
}
Future<void> handleLogoutClick() async {
if (await confirm(
Get.overlayContext!,
"你想要退出登录吗?",
title: "退出登录",
positiveText: "确定",
isDanger: true,
)) {
handleLogout();
}
}
Future<void> handleLogout() async {
await uc.logout();
}
Future<void> handleSettingsClick(BuildContext context) async {
await Navigator.of(context, rootNavigator: false).push(
CupertinoPageRoute(
title: "设置",
builder: (_) => const SettingsListPage(),
),
);
}
Future<void> handleAboutClick(BuildContext context) async {
await Navigator.of(context, rootNavigator: false).push(
CupertinoPageRoute(
title: "关于",
builder: (_) => const AboutPage(),
),
);
}
}
class OwnProfileTab extends StatelessWidget {
const OwnProfileTab({super.key});
Widget _buildUserAvatar(UserController uc, {double size = 64}) {
return Obx(() {
var avatarUrl = uc.getAvatar(128);
if (avatarUrl != null && avatarUrl.isNotEmpty) {
return ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(size / 2)),
child: CachedNetworkImage(
width: size,
height: size,
placeholder: (_, __) => const CupertinoActivityIndicator(radius: 12),
imageUrl: avatarUrl,
fit: BoxFit.cover,
),
);
} else {
return DummyIcon(
color: CupertinoColors.systemGrey,
icon: CupertinoIcons.person_fill,
size: size,
rounded: true,
);
}
});
}
Widget _buildUserSection(BuildContext context, OwnProfileController c) {
var uc = Get.find<UserController>();
return FollowTextScale(
child: Obx(
() => CupertinoListSection.insetGrouped(
backgroundColor: CupertinoTheme.of(context).scaffoldBackgroundColor,
dividerMargin: uc.isLoggedIn ? 14 : double.infinity,
children: <Widget>[
Obx(
() => CupertinoListTile.notched(
title: uc.isLoggedIn
? Text(uc.displayName, style: Styles.listTileLargeTitle)
: const Text('登录/注册', style: Styles.listTileLargeTitle),
subtitle: uc.isLoggedIn
? Text("@${uc.userName.value}", style: Styles.listTileSubTitle)
: null,
padding: const EdgeInsets.only(left: 6, right: 14, top: 0, bottom: 0),
leading: _buildUserAvatar(uc),
leadingSize: 80,
leadingToTitle: 4,
trailing: uc.authProcessing.value
? const Padding(
padding: EdgeInsets.only(right: 5),
child: CupertinoActivityIndicator(
radius: 12,
),
)
: const CupertinoListTileChevron(),
onTap: c.handleUserClick,
),
),
AnimatedSize(
duration: const Duration(milliseconds: 250),
curve: Curves.easeInOut,
child: SizedBox(
height: uc.isLoggedIn ? null : 0,
child: CupertinoListTile.notched(
title: const Text('退出登录'),
leading: const DummyIcon(
color: CupertinoColors.systemRed,
icon: CupertinoIcons.arrow_right_square,
),
trailing: const CupertinoListTileChevron(),
onTap: c.handleLogoutClick,
),
),
),
],
),
),
);
}
Widget _buildArticleListsSection(BuildContext context, OwnProfileController c) {
return FollowTextScale(
child: CupertinoListSection.insetGrouped(
backgroundColor: CupertinoTheme.of(context).scaffoldBackgroundColor,
children: <CupertinoListTile>[
CupertinoListTile.notched(
title: const Text('收藏'),
leading: const DummyIcon(
color: CupertinoColors.systemYellow,
icon: CupertinoIcons.star_fill,
),
trailing: const CupertinoListTileChevron(),
onTap: () {},
),
CupertinoListTile.notched(
title: const Text('阅读历史'),
leading: const DummyIcon(
color: CupertinoColors.systemBlue,
icon: CupertinoIcons.time_solid,
),
trailing: const CupertinoListTileChevron(),
onTap: () {},
),
CupertinoListTile.notched(
title: const Text('贡献'),
leading: const DummyIcon(
color: CupertinoColors.systemOrange,
icon: CupertinoIcons.create,
),
trailing: const CupertinoListTileChevron(),
onTap: () {},
),
],
));
}
Widget _buildSettingsSection(BuildContext context, OwnProfileController c) {
return FollowTextScale(
child: CupertinoListSection.insetGrouped(
backgroundColor: CupertinoTheme.of(context).scaffoldBackgroundColor,
children: <CupertinoListTile>[
CupertinoListTile.notched(
title: const Text('设置'),
leading: const DummyIcon(
color: CupertinoColors.systemGrey,
icon: CupertinoIcons.settings,
),
trailing: const CupertinoListTileChevron(),
onTap: () async {
await c.handleSettingsClick(context);
},
),
CupertinoListTile.notched(
title: const Text('关于'),
leading: const DummyIcon(
color: CupertinoColors.systemBlue,
icon: CupertinoIcons.info,
),
trailing: const CupertinoListTileChevron(),
onTap: () async {
await c.handleAboutClick(context);
},
),
if (kDebugMode)
CupertinoListTile.notched(
title: const Text('内部浏览器测试'),
leading: const DummyIcon(
color: CupertinoColors.systemBlue,
icon: CupertinoIcons.airplane,
),
trailing: const CupertinoListTileChevron(),
onTap: () async {},
),
],
));
}
SliverChildListDelegate _buildSliverChildBuilderDelegate(
BuildContext context, OwnProfileController c) {
return SliverChildListDelegate([
_buildUserSection(context, c),
_buildArticleListsSection(context, c),
_buildSettingsSection(context, c),
]);
}
@override
Widget build(BuildContext context) {
var c = Get.put(OwnProfileController());
return IsekaiPageScaffold(
child: CustomScrollView(
slivers: <Widget>[
const IsekaiSliverNavigationBar(
largeTitle: Text('我的'),
),
SliverSafeArea(
top: false,
minimum: const EdgeInsets.only(top: 4),
sliver: SliverList(
delegate: _buildSliverChildBuilderDelegate(context, c),
),
)
],
),
);
}
}