fix:对比原型增加功能交互
This commit is contained in:
@@ -1,10 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
|
||||
import '../../data/api/report_data_source.dart';
|
||||
import '../../theme/app_icons.dart';
|
||||
import '../../data/content_providers.dart';
|
||||
import '../../data/models/models.dart';
|
||||
import '../../data/providers.dart';
|
||||
import '../../data/state/app_interaction_state.dart';
|
||||
import '../../routing/app_routes.dart';
|
||||
import '../../theme/app_icons.dart';
|
||||
import '../../theme/yanting_text.dart';
|
||||
import '../../theme/yanting_tokens.dart';
|
||||
import '../../widgets/app_buttons.dart';
|
||||
@@ -12,15 +17,34 @@ import '../../widgets/app_card.dart';
|
||||
import '../../widgets/page_header.dart';
|
||||
import '../../widgets/sheets.dart';
|
||||
import '../../widgets/states.dart';
|
||||
import '../shared/report_card_widget.dart';
|
||||
|
||||
class ProfilePage extends StatelessWidget {
|
||||
class ProfilePage extends ConsumerWidget {
|
||||
const ProfilePage({required this.dataSource, super.key});
|
||||
|
||||
final ReportDataSource dataSource;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final colors = ShadTheme.of(context).colorScheme;
|
||||
final auth = ref.watch(authControllerProvider);
|
||||
final profile = ref.watch(profileControllerProvider);
|
||||
final historySnapshot = ref.watch(profileHistoryReportsProvider);
|
||||
final favoriteSnapshot = ref.watch(profileFavoriteReportsProvider);
|
||||
final savedListenSnapshot = ref.watch(profileSavedListenReportsProvider);
|
||||
final historyCount = historySnapshot.maybeWhen(
|
||||
data: (items) => items.length,
|
||||
orElse: () => profile.history.length,
|
||||
);
|
||||
final favoriteCount = favoriteSnapshot.maybeWhen(
|
||||
data: (items) => items.length,
|
||||
orElse: () => profile.favorites.length,
|
||||
);
|
||||
final savedListenCount = savedListenSnapshot.maybeWhen(
|
||||
data: (items) => items.length,
|
||||
orElse: () => profile.savedListens.length,
|
||||
);
|
||||
|
||||
return ListView(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
YantingSpacing.screenX,
|
||||
@@ -46,7 +70,7 @@ class ProfilePage extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'未登录',
|
||||
auth.loggedIn ? '已登录' : '未登录',
|
||||
style: YantingText.cardTitle.copyWith(
|
||||
fontSize: 18,
|
||||
color: colors.foreground,
|
||||
@@ -54,7 +78,7 @@ class ProfilePage extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
'登录后同步收藏、历史和听单',
|
||||
auth.loggedIn ? '收藏、历史和听单已在本地同步' : '登录后同步收藏、历史和听单',
|
||||
style: YantingText.meta.copyWith(
|
||||
height: 1.5,
|
||||
color: colors.mutedForeground,
|
||||
@@ -68,9 +92,16 @@ class ProfilePage extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: YantingSpacing.x3),
|
||||
AppButton(
|
||||
label: '登录 / 注册',
|
||||
label: auth.loggedIn ? '退出登录' : '登录 / 注册',
|
||||
expand: true,
|
||||
onPressed: () => showLoginSheet(context),
|
||||
onPressed: auth.loggedIn
|
||||
? () => ref.read(authControllerProvider.notifier).logout()
|
||||
: () => showLoginSheet(
|
||||
context,
|
||||
reason: '登录后同步收藏、历史和听单',
|
||||
onPhoneLogin: () => _login(ref, LoginMethod.phone),
|
||||
onSecondaryLogin: () => _login(ref, LoginMethod.wechat),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
_MenuGroup(
|
||||
@@ -78,8 +109,43 @@ class ProfilePage extends StatelessWidget {
|
||||
_MenuRow(
|
||||
icon: AppIcons.history,
|
||||
title: '本地浏览记录',
|
||||
trailing: '0 条 · 本地临时',
|
||||
onTap: () => showAppToast(context, '历史同步接口待接入'),
|
||||
trailing: '$historyCount 条 · 本地临时',
|
||||
onTap: () => _showProfileListSheet(
|
||||
context,
|
||||
ref,
|
||||
title: '本地浏览记录',
|
||||
snapshot: historySnapshot,
|
||||
emptyTitle: '暂无本地浏览记录',
|
||||
emptyMessage: '打开研报详情或播放音频后会出现在这里',
|
||||
),
|
||||
),
|
||||
_MenuRow(
|
||||
icon: AppIcons.heart,
|
||||
title: '我的收藏',
|
||||
trailing: '$favoriteCount 条',
|
||||
onTap: () => _showLoginAwareList(
|
||||
context,
|
||||
ref,
|
||||
auth,
|
||||
title: '我的收藏',
|
||||
snapshot: favoriteSnapshot,
|
||||
emptyTitle: '暂无收藏',
|
||||
emptyMessage: '在研报详情页点击收藏后会出现在这里',
|
||||
),
|
||||
),
|
||||
_MenuRow(
|
||||
icon: AppIcons.headphones,
|
||||
title: '已存听单',
|
||||
trailing: '$savedListenCount 条',
|
||||
onTap: () => _showLoginAwareList(
|
||||
context,
|
||||
ref,
|
||||
auth,
|
||||
title: '已存听单',
|
||||
snapshot: savedListenSnapshot,
|
||||
emptyTitle: '暂无已存听单',
|
||||
emptyMessage: '在音频研报详情页保存听单后会出现在这里',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -94,19 +160,21 @@ class ProfilePage extends StatelessWidget {
|
||||
_MenuRow(
|
||||
icon: AppIcons.fileList,
|
||||
title: '用户协议',
|
||||
onTap: () => showOutboundSheet(context, title: '用户协议'),
|
||||
onTap: () =>
|
||||
_showOutbound(context, ref, 'user_agreement', '用户协议'),
|
||||
),
|
||||
_MenuRow(
|
||||
icon: AppIcons.shield,
|
||||
title: '隐私政策',
|
||||
onTap: () => showOutboundSheet(context, title: '隐私政策'),
|
||||
onTap: () =>
|
||||
_showOutbound(context, ref, 'privacy_policy', '隐私政策'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: YantingSpacing.x3),
|
||||
AppCard(
|
||||
color: colors.secondary,
|
||||
onTap: () => showOutboundSheet(context, title: '相关服务'),
|
||||
onTap: () => _showOutbound(context, ref, 'profile_services', '相关服务'),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -143,6 +211,109 @@ class ProfilePage extends StatelessWidget {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _login(WidgetRef ref, LoginMethod method) async {
|
||||
await ref.read(authControllerProvider.notifier).login(method);
|
||||
await ref.read(profileControllerProvider.notifier).refresh();
|
||||
}
|
||||
|
||||
void _showOutbound(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
String scene,
|
||||
String title,
|
||||
) {
|
||||
showOutboundSheet(
|
||||
context,
|
||||
title: title,
|
||||
onConfirm: () => ref
|
||||
.read(outboundRepositoryProvider)
|
||||
.recordOutbound(OutboundEvent(scene: scene)),
|
||||
);
|
||||
}
|
||||
|
||||
void _showLoginAwareList(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
AuthState auth, {
|
||||
required String title,
|
||||
required AsyncValue<List<ReportCardModel>> snapshot,
|
||||
required String emptyTitle,
|
||||
required String emptyMessage,
|
||||
}) {
|
||||
if (!auth.loggedIn) {
|
||||
showLoginSheet(
|
||||
context,
|
||||
reason: '登录后查看$title',
|
||||
onPhoneLogin: () => _login(ref, LoginMethod.phone),
|
||||
onSecondaryLogin: () => _login(ref, LoginMethod.wechat),
|
||||
);
|
||||
return;
|
||||
}
|
||||
_showProfileListSheet(
|
||||
context,
|
||||
ref,
|
||||
title: title,
|
||||
snapshot: snapshot,
|
||||
emptyTitle: emptyTitle,
|
||||
emptyMessage: emptyMessage,
|
||||
);
|
||||
}
|
||||
|
||||
void _showProfileListSheet(
|
||||
BuildContext context,
|
||||
WidgetRef ref, {
|
||||
required String title,
|
||||
required AsyncValue<List<ReportCardModel>> snapshot,
|
||||
required String emptyTitle,
|
||||
required String emptyMessage,
|
||||
}) {
|
||||
showShadSheet<void>(
|
||||
context: context,
|
||||
side: ShadSheetSide.bottom,
|
||||
builder: (sheetContext) => ShadSheet(
|
||||
title: Text(title),
|
||||
description: const Text('本地状态列表,真实同步接口后续接入。'),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: MediaQuery.sizeOf(sheetContext).height * 0.66,
|
||||
),
|
||||
child: snapshot.when(
|
||||
loading: () => const LoadingState(label: '正在加载列表'),
|
||||
error: (error, _) => ErrorState(message: error.toString()),
|
||||
data: (items) {
|
||||
if (items.isEmpty) {
|
||||
return EmptyState(
|
||||
title: emptyTitle,
|
||||
message: emptyMessage,
|
||||
icon: Icons.inbox_outlined,
|
||||
);
|
||||
}
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
itemCount: items.length,
|
||||
separatorBuilder: (_, _) =>
|
||||
const SizedBox(height: YantingSpacing.x3),
|
||||
itemBuilder: (_, index) {
|
||||
final report = items[index];
|
||||
return ReportCardWidget(
|
||||
report: report,
|
||||
onTap: () {
|
||||
Navigator.pop(sheetContext);
|
||||
ref
|
||||
.read(profileControllerProvider.notifier)
|
||||
.addHistory(report.id);
|
||||
openReportDetail(context, dataSource, report);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _MenuGroup extends StatelessWidget {
|
||||
|
||||
Reference in New Issue
Block a user