mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: item
chore: clean up widgets Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget.dart';
|
||||
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/space_article/item.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/article/member_article_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/article/widget/item.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/article/member_article_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/article/widget/item.dart';
|
||||
import 'package:PiliPlus/utils/grid.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -50,11 +49,7 @@ class _MemberArticleState extends State<MemberArticle>
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverGrid(
|
||||
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
mainAxisSpacing: 2,
|
||||
maxCrossAxisExtent: Grid.mediumCardWidth * 2,
|
||||
childAspectRatio: StyleString.aspectRatio * 2.2,
|
||||
),
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (index == loadingState.response!.length - 1) {
|
||||
@@ -59,27 +59,36 @@ class MemberArticleItem extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item.title?.isNotEmpty == true) ...[
|
||||
Text(
|
||||
item.title!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
Expanded(
|
||||
child: Text(
|
||||
item.title!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.fontSize,
|
||||
height: 1.42,
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
Text(
|
||||
'${item.publishTimeText}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
value: item.stats?.view ?? 0,
|
||||
size: 'medium',
|
||||
goto: 'picture',
|
||||
textColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
@@ -87,7 +96,6 @@ class MemberArticleItem extends StatelessWidget {
|
||||
StatView(
|
||||
context: context,
|
||||
goto: 'reply',
|
||||
size: 'medium',
|
||||
value: item.stats?.reply ?? 0,
|
||||
textColor: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
@@ -4,7 +4,7 @@ import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/space_archive/item.dart';
|
||||
import 'package:PiliPlus/pages/bangumi/widgets/bangumi_card_v_member_home.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/bangumi/member_bangumi_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/bangumi/member_bangumi_ctr.dart';
|
||||
import 'package:PiliPlus/utils/grid.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -3,9 +3,9 @@ import 'package:PiliPlus/http/member.dart';
|
||||
import 'package:PiliPlus/models/space_archive/data.dart';
|
||||
import 'package:PiliPlus/models/space_archive/item.dart';
|
||||
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/member_contribute.dart'
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/member_contribute.dart'
|
||||
show ContributeType;
|
||||
import 'package:PiliPlus/pages/member/new/controller.dart';
|
||||
import 'package:PiliPlus/pages/member/controller.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/models/space/data.dart' as space;
|
||||
|
||||
@@ -3,8 +3,8 @@ import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/space_fav/datum.dart';
|
||||
import 'package:PiliPlus/models/space_fav/list.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/favorite/member_favorite_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/favorite/widget/item.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/favorite/member_favorite_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/favorite/widget/item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/season_series/controller.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/season_series/widget/season_series_card.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/video/member_video.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/member_contribute.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/season_series/controller.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/season_series/widget/season_series_card.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/video/member_video.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/member_contribute.dart';
|
||||
import 'package:PiliPlus/utils/grid.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -51,11 +51,7 @@ class _SeasonSeriesPageState extends State<SeasonSeriesPage>
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
||||
mainAxisSpacing: 2,
|
||||
maxCrossAxisExtent: Grid.mediumCardWidth * 2,
|
||||
childAspectRatio: StyleString.aspectRatio * 2.2,
|
||||
),
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (index == loadingState.response!.length - 1) {
|
||||
@@ -87,7 +87,7 @@ class SeasonSeriesCard extends StatelessWidget {
|
||||
Utils.dateFormat(item['meta']['ptime']),
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
||||
fontSize: 12,
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
overflow: TextOverflow.clip,
|
||||
@@ -6,10 +6,10 @@ import 'package:PiliPlus/common/widgets/scroll_physics.dart';
|
||||
import 'package:PiliPlus/common/widgets/video_card_h_member_video.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/space_archive/item.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/video/member_video_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/member_contribute.dart'
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/video/member_video_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/member_contribute.dart'
|
||||
show ContributeType;
|
||||
import 'package:PiliPlus/pages/member/new/controller.dart';
|
||||
import 'package:PiliPlus/pages/member/controller.dart';
|
||||
import 'package:PiliPlus/utils/grid.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -178,11 +178,7 @@ class _MemberVideoState extends State<MemberVideo>
|
||||
bottom: MediaQuery.of(context).padding.bottom + 80,
|
||||
),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
||||
mainAxisSpacing: 2,
|
||||
maxCrossAxisExtent: Grid.mediumCardWidth * 2,
|
||||
childAspectRatio: StyleString.aspectRatio * 2.2,
|
||||
),
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (widget.type != ContributeType.season &&
|
||||
@@ -5,7 +5,7 @@ import 'package:PiliPlus/models/space_archive/data.dart';
|
||||
import 'package:PiliPlus/models/space_archive/episodic_button.dart';
|
||||
import 'package:PiliPlus/models/space_archive/item.dart';
|
||||
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/member_contribute.dart'
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/member_contribute.dart'
|
||||
show ContributeType;
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/id_utils.dart';
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/article/member_article.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/audio/member_audio.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/season_series/season_series_page.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/video/member_video.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/member_contribute_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/article/member_article.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/audio/member_audio.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/season_series/season_series_page.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/video/member_video.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/member_contribute_ctr.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
@@ -3,12 +3,12 @@ import 'dart:math';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/space/tab2.dart';
|
||||
import 'package:PiliPlus/pages/common/common_data_controller.dart';
|
||||
import 'package:PiliPlus/pages/member/new/controller.dart';
|
||||
import 'package:PiliPlus/pages/member/controller.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../../../models/space/item.dart';
|
||||
import '../../../../models/space/item.dart';
|
||||
|
||||
class MemberContributeCtr extends CommonDataController
|
||||
with GetTickerProviderStateMixin {
|
||||
@@ -7,10 +7,10 @@ import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/space/data.dart';
|
||||
import 'package:PiliPlus/models/space/item.dart';
|
||||
import 'package:PiliPlus/pages/bangumi/widgets/bangumi_card_v_member_home.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/article/widget/item.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/member_contribute_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_home/widget/fav_item.dart';
|
||||
import 'package:PiliPlus/pages/member/new/controller.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/article/widget/item.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/member_contribute_ctr.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_home/widget/fav_item.dart';
|
||||
import 'package:PiliPlus/pages/member/controller.dart';
|
||||
import 'package:PiliPlus/pages/member_coin/index.dart';
|
||||
import 'package:PiliPlus/pages/member_like/index.dart';
|
||||
import 'package:PiliPlus/utils/grid.dart';
|
||||
@@ -172,11 +172,7 @@ class _MemberHomeState extends State<MemberHome>
|
||||
count: loadingState.response.article.count,
|
||||
),
|
||||
SliverGrid(
|
||||
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
mainAxisSpacing: 2,
|
||||
maxCrossAxisExtent: Grid.mediumCardWidth * 2,
|
||||
childAspectRatio: StyleString.aspectRatio * 2.2,
|
||||
),
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
return MemberArticleItem(
|
||||
@@ -1,205 +1,150 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/http/member.dart';
|
||||
import 'package:PiliPlus/http/video.dart';
|
||||
import 'package:PiliPlus/models/space/data.dart';
|
||||
import 'package:PiliPlus/models/space/item.dart';
|
||||
import 'package:PiliPlus/models/space/tab2.dart';
|
||||
import 'package:PiliPlus/pages/common/common_data_controller.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/http/member.dart';
|
||||
import 'package:PiliPlus/http/user.dart';
|
||||
import 'package:PiliPlus/http/video.dart';
|
||||
import 'package:PiliPlus/models/member/coin.dart';
|
||||
import 'package:PiliPlus/models/member/info.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../video/detail/introduction/widgets/group_panel.dart';
|
||||
enum MemberTabType { none, home, dynamic, contribute, favorite, bangumi }
|
||||
|
||||
class MemberController extends GetxController {
|
||||
int? mid;
|
||||
MemberController({this.mid});
|
||||
Rx<MemberInfoModel> memberInfo = MemberInfoModel().obs;
|
||||
late Map userStat;
|
||||
RxString face = ''.obs;
|
||||
String? heroTag;
|
||||
late int ownerMid;
|
||||
bool specialFollowed = false;
|
||||
// 投稿列表
|
||||
dynamic userInfo;
|
||||
RxInt attribute = (-1).obs;
|
||||
RxString attributeText = '关注'.obs;
|
||||
RxList<MemberCoinsDataModel> recentCoinsList = <MemberCoinsDataModel>[].obs;
|
||||
String? wwebid;
|
||||
extension MemberTabTypeExt on MemberTabType {
|
||||
String get title => ['默认', '首页', '动态', '投稿', '收藏', '番剧'][index];
|
||||
}
|
||||
|
||||
class MemberControllerNew extends CommonDataController<Data, dynamic>
|
||||
with GetTickerProviderStateMixin {
|
||||
MemberControllerNew({required this.mid});
|
||||
int mid;
|
||||
RxBool showUname = false.obs;
|
||||
String? username;
|
||||
int? ownerMid;
|
||||
RxBool isFollow = false.obs;
|
||||
RxInt relation = 1.obs;
|
||||
TabController? tabController;
|
||||
late List<Tab> tabs;
|
||||
List<Tab2>? tab2;
|
||||
RxInt contributeInitialIndex = 0.obs;
|
||||
double top = 0;
|
||||
bool? hasSeasonOrSeries;
|
||||
final fromViewAid = Get.parameters['from_view_aid'];
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
mid = mid ?? int.parse(Get.parameters['mid']!);
|
||||
userInfo = GStorage.userInfo.get('userInfoCache');
|
||||
ownerMid = userInfo != null ? userInfo.mid : -1;
|
||||
try {
|
||||
face.value = Get.arguments['face'] ?? '';
|
||||
heroTag = Get.arguments['heroTag'] ?? '';
|
||||
} catch (_) {}
|
||||
relationSearch();
|
||||
ownerMid = Accounts.main.mid;
|
||||
queryData();
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
Future<Map<String, dynamic>> getInfo() {
|
||||
return Future.wait([getMemberInfo(), getMemberStat(), getMemberView()])
|
||||
.then((res) => res[0]);
|
||||
}
|
||||
dynamic live;
|
||||
|
||||
Future<Map<String, dynamic>> getMemberInfo() async {
|
||||
wwebid ??= await Utils.getWwebid(mid);
|
||||
await getMemberStat();
|
||||
await getMemberView();
|
||||
var res = await MemberHttp.memberInfo(mid: mid, wwebid: wwebid);
|
||||
if (res['status']) {
|
||||
memberInfo.value = res['data'];
|
||||
face.value = res['data'].face;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
int? silence;
|
||||
String? endTime;
|
||||
|
||||
// 获取用户状态
|
||||
Future<Map<String, dynamic>> getMemberStat() async {
|
||||
var res = await MemberHttp.memberStat(mid: mid);
|
||||
if (res['status']) {
|
||||
userStat = res['data'];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
late final implTabs = const [
|
||||
'home',
|
||||
'dynamic',
|
||||
'contribute',
|
||||
'favorite',
|
||||
'bangumi',
|
||||
];
|
||||
|
||||
// 获取用户播放数 获赞数
|
||||
Future<Map<String, dynamic>> getMemberView() async {
|
||||
var res = await MemberHttp.memberView(mid: mid!);
|
||||
if (res['status']) {
|
||||
userStat.addAll(res['data']);
|
||||
@override
|
||||
bool customHandleResponse(bool isRefresh, Success<Data> response) {
|
||||
Data data = response.response;
|
||||
username = data.card?.name ?? '';
|
||||
isFollow.value = data.card?.relation?.isFollow == 1;
|
||||
relation.value = data.relSpecial == 1 ? 2 : data.relation ?? 1;
|
||||
tab2 = data.tab2;
|
||||
live = data.live;
|
||||
silence = data.card?.silence;
|
||||
if ((data.ugcSeason?.count != null && data.ugcSeason?.count != 0) ||
|
||||
data.series?.item?.isNotEmpty == true) {
|
||||
hasSeasonOrSeries = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Future delayedUpdateRelation() async {
|
||||
await Future.delayed(const Duration(milliseconds: 1000), () async {
|
||||
SmartDialog.showToast('更新状态');
|
||||
await relationSearch();
|
||||
memberInfo.update((val) {});
|
||||
});
|
||||
}
|
||||
|
||||
// 关注/取关up
|
||||
Future actionRelationMod(BuildContext context) async {
|
||||
if (userInfo == null) {
|
||||
SmartDialog.showToast('账号未登录');
|
||||
return;
|
||||
if (data.card?.endTime != null) {
|
||||
if (data.card!.endTime == 0) {
|
||||
endTime = ': 永久封禁';
|
||||
} else if (data.card!.endTime! >
|
||||
DateTime.now().millisecondsSinceEpoch ~/ 1000) {
|
||||
endTime =
|
||||
':至 ${DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.fromMillisecondsSinceEpoch(data.card!.endTime! * 1000))}';
|
||||
}
|
||||
}
|
||||
if (memberInfo.value.mid == null) {
|
||||
SmartDialog.showToast('尚未获取到用户信息');
|
||||
return;
|
||||
}
|
||||
if (attribute.value == 128) {
|
||||
blockUser(context);
|
||||
return;
|
||||
}
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('操作'),
|
||||
actions: [
|
||||
if (memberInfo.value.isFollowed!) ...[
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final res = await MemberHttp.addUsers(
|
||||
mid, specialFollowed ? '0' : '-10');
|
||||
SmartDialog.showToast(res['msg']);
|
||||
if (res['status']) {
|
||||
specialFollowed = !specialFollowed;
|
||||
}
|
||||
Get.back();
|
||||
},
|
||||
child: Text(specialFollowed ? '移除特别关注' : '加入特别关注'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await Get.bottomSheet(
|
||||
GroupPanel(mid: mid),
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
child: const Text('设置分组'),
|
||||
),
|
||||
],
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
var res = await VideoHttp.relationMod(
|
||||
mid: mid!,
|
||||
act: memberInfo.value.isFollowed! ? 2 : 1,
|
||||
reSrc: 11,
|
||||
);
|
||||
SmartDialog.showToast(res['status'] ? "操作成功" : res['msg']);
|
||||
if (res['status']) {
|
||||
memberInfo.value.isFollowed = !memberInfo.value.isFollowed!;
|
||||
}
|
||||
Get.back();
|
||||
},
|
||||
child: Text(memberInfo.value.isFollowed! ? '取消关注' : '关注'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Get.back(),
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
],
|
||||
tab2?.retainWhere((item) => implTabs.contains(item.param));
|
||||
if (tab2?.isNotEmpty == true) {
|
||||
if (!data.tab!.toJson().values.contains(true) &&
|
||||
tab2!.first.param == 'home') {
|
||||
// remove empty home tab
|
||||
tab2!.removeAt(0);
|
||||
}
|
||||
if (tab2!.isNotEmpty) {
|
||||
int initialIndex = -1;
|
||||
MemberTabType memberTab = GStorage.memberTab;
|
||||
if (memberTab != MemberTabType.none) {
|
||||
initialIndex = tab2!.indexWhere((item) {
|
||||
return item.param == memberTab.name;
|
||||
});
|
||||
}
|
||||
if (initialIndex == -1) {
|
||||
if (data.defaultTab == 'video') {
|
||||
data.defaultTab = 'contribute';
|
||||
}
|
||||
initialIndex = tab2!.indexWhere((item) {
|
||||
return item.param == data.defaultTab;
|
||||
});
|
||||
}
|
||||
tabs = tab2!.map((item) => Tab(text: item.title ?? '')).toList();
|
||||
tabController = TabController(
|
||||
vsync: this,
|
||||
length: tabs.length,
|
||||
initialIndex: max(0, initialIndex),
|
||||
);
|
||||
},
|
||||
);
|
||||
await delayedUpdateRelation();
|
||||
}
|
||||
|
||||
// 关系查询
|
||||
Future relationSearch() async {
|
||||
if (userInfo == null) return;
|
||||
if (mid == ownerMid) return;
|
||||
var res = await UserHttp.hasFollow(mid!);
|
||||
if (res['status']) {
|
||||
attribute.value = res['data']['attribute'];
|
||||
switch (attribute.value) {
|
||||
case 1:
|
||||
attributeText.value = '悄悄关注';
|
||||
memberInfo.value.isFollowed = true;
|
||||
break;
|
||||
case 2:
|
||||
attributeText.value = '已关注';
|
||||
memberInfo.value.isFollowed = true;
|
||||
break;
|
||||
case 6:
|
||||
attributeText.value = '已互关';
|
||||
memberInfo.value.isFollowed = true;
|
||||
break;
|
||||
case 128:
|
||||
attributeText.value = '已拉黑';
|
||||
memberInfo.value.isFollowed = false;
|
||||
break;
|
||||
default:
|
||||
attributeText.value = '关注';
|
||||
memberInfo.value.isFollowed = false;
|
||||
}
|
||||
if (res['data']['special'] == 1) {
|
||||
specialFollowed = true;
|
||||
attributeText.value += ' 🔔';
|
||||
} else {
|
||||
specialFollowed = false;
|
||||
}
|
||||
} else {
|
||||
SmartDialog.showToast(res['msg']);
|
||||
}
|
||||
loadingState.value = response;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 拉黑用户
|
||||
@override
|
||||
bool handleError(String? errMsg) {
|
||||
tab2 = [
|
||||
Tab2(title: '动态', param: 'dynamic'),
|
||||
Tab2(
|
||||
title: '投稿',
|
||||
param: 'contribute',
|
||||
items: [Item(title: '视频', param: 'video')],
|
||||
),
|
||||
Tab2(title: '收藏', param: 'favorite'),
|
||||
Tab2(title: '追番', param: 'bangumi'),
|
||||
];
|
||||
tabs = tab2!.map((item) => Tab(text: item.title)).toList();
|
||||
tabController = TabController(
|
||||
vsync: this,
|
||||
length: tabs.length,
|
||||
);
|
||||
showUname.value = true;
|
||||
username = errMsg;
|
||||
loadingState.value = LoadingState.success(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LoadingState<Data>> customGetData() => MemberHttp.space(
|
||||
mid: mid,
|
||||
fromViewAid: fromViewAid,
|
||||
);
|
||||
|
||||
Future blockUser(BuildContext context) async {
|
||||
if (userInfo == null) {
|
||||
if (ownerMid == 0) {
|
||||
SmartDialog.showToast('账号未登录');
|
||||
return;
|
||||
}
|
||||
@@ -208,10 +153,10 @@ class MemberController extends GetxController {
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('提示'),
|
||||
content: Text(attribute.value != 128 ? '确定拉黑UP主?' : '从黑名单移除UP主'),
|
||||
content: Text(relation.value != -1 ? '确定拉黑UP主?' : '从黑名单移除UP主'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Get.back(),
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'点错了',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
@@ -220,18 +165,7 @@ class MemberController extends GetxController {
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
var res = await VideoHttp.relationMod(
|
||||
mid: mid!,
|
||||
act: attribute.value != 128 ? 5 : 6,
|
||||
reSrc: 11,
|
||||
);
|
||||
if (res['status']) {
|
||||
attribute.value = attribute.value != 128 ? 128 : 0;
|
||||
attributeText.value = attribute.value == 128 ? '已拉黑' : '关注';
|
||||
memberInfo.value.isFollowed = false;
|
||||
relationSearch();
|
||||
memberInfo.update((val) {});
|
||||
}
|
||||
_onBlock();
|
||||
},
|
||||
child: const Text('确认'),
|
||||
)
|
||||
@@ -242,41 +176,46 @@ class MemberController extends GetxController {
|
||||
}
|
||||
|
||||
void shareUser() {
|
||||
Utils.shareText(
|
||||
'${memberInfo.value.name} - https://space.bilibili.com/$mid');
|
||||
Utils.shareText('https://space.bilibili.com/$mid');
|
||||
}
|
||||
|
||||
// 请求专栏
|
||||
Future getMemberSeasons() async {
|
||||
if (userInfo == null) return;
|
||||
var res = await MemberHttp.getMemberSeasons(mid, 1, 10);
|
||||
if (!res['status']) {
|
||||
SmartDialog.showToast("用户专栏请求异常:${res['msg']}");
|
||||
void _onBlock() async {
|
||||
dynamic res = await VideoHttp.relationMod(
|
||||
mid: mid,
|
||||
act: relation.value != -1 ? 5 : 6,
|
||||
reSrc: 11,
|
||||
);
|
||||
if (res['status']) {
|
||||
relation.value = relation.value != -1 ? -1 : 1;
|
||||
isFollow.value = false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 请求投币视频
|
||||
Future getRecentCoinVideo() async {
|
||||
// if (userInfo == null) return;
|
||||
// var res = await MemberHttp.getRecentCoinVideo(mid: mid!);
|
||||
// recentCoinsList.value = res['data'];
|
||||
// return res;
|
||||
void onFollow(BuildContext context) async {
|
||||
if (mid == ownerMid) {
|
||||
Get.toNamed('/editProfile');
|
||||
} else if (relation.value == -1) {
|
||||
_onBlock();
|
||||
} else {
|
||||
if (ownerMid == null) {
|
||||
SmartDialog.showToast('账号未登录');
|
||||
return;
|
||||
}
|
||||
Utils.actionRelationMod(
|
||||
context: context,
|
||||
mid: mid,
|
||||
isFollow: isFollow.value,
|
||||
callback: (attribute) {
|
||||
relation.value = attribute;
|
||||
isFollow.value = attribute != 0;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转查看动态
|
||||
void pushDynamicsPage() => Get.toNamed('/memberDynamics?mid=$mid');
|
||||
|
||||
// 跳转查看投稿
|
||||
void pushArchivesPage() async {
|
||||
wwebid ??= await Utils.getWwebid(mid);
|
||||
Get.toNamed('/memberArchive?mid=$mid&wwebid=$wwebid');
|
||||
}
|
||||
|
||||
// 跳转查看专栏
|
||||
void pushSeasonsPage() {}
|
||||
// 跳转查看最近投币
|
||||
void pushRecentCoinsPage() async {
|
||||
if (recentCoinsList.isNotEmpty) {}
|
||||
@override
|
||||
void onClose() {
|
||||
tabController?.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
library member;
|
||||
|
||||
export './controller.dart';
|
||||
export './view.dart';
|
||||
@@ -1,19 +1,21 @@
|
||||
import 'package:PiliPlus/common/widgets/dynamic_sliver_appbar.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget.dart';
|
||||
import 'package:PiliPlus/common/widgets/radio_widget.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/http/member.dart';
|
||||
import 'package:PiliPlus/models/space/data.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/bangumi/member_bangumi.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/content/favorite/member_favorite.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_contribute/member_contribute.dart';
|
||||
import 'package:PiliPlus/pages/member/new/content/member_home/member_home.dart';
|
||||
import 'package:PiliPlus/pages/member/new/controller.dart';
|
||||
import 'package:PiliPlus/pages/member/new/widget/user_info_card.dart';
|
||||
import 'package:PiliPlus/pages/member/view.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/bangumi/member_bangumi.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/content/favorite/member_favorite.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_contribute/member_contribute.dart';
|
||||
import 'package:PiliPlus/pages/member/content/member_home/member_home.dart';
|
||||
import 'package:PiliPlus/pages/member/controller.dart';
|
||||
import 'package:PiliPlus/pages/member/widget/user_info_card.dart';
|
||||
import 'package:PiliPlus/pages/member_dynamics/view.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/common/widgets/scroll_physics.dart';
|
||||
|
||||
@@ -298,3 +300,124 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class ReportPanel extends StatefulWidget {
|
||||
const ReportPanel({
|
||||
super.key,
|
||||
required this.name,
|
||||
required this.mid,
|
||||
});
|
||||
|
||||
final dynamic name;
|
||||
final dynamic mid;
|
||||
|
||||
@override
|
||||
State<ReportPanel> createState() => _ReportPanelState();
|
||||
}
|
||||
|
||||
class _ReportPanelState extends State<ReportPanel> {
|
||||
final List<bool> _reasonList = List.generate(3, (_) => false).toList();
|
||||
final Set<int> _reason = {};
|
||||
int? _reasonV2;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'举报: ${widget.name}',
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text('uid: ${widget.mid}'),
|
||||
const SizedBox(height: 10),
|
||||
const Text('举报内容(必选,可多选)'),
|
||||
...List.generate(
|
||||
3,
|
||||
(index) => _checkBoxWidget(
|
||||
_reasonList[index],
|
||||
(value) {
|
||||
setState(() => _reasonList[index] = value);
|
||||
if (value) {
|
||||
_reason.add(index + 1);
|
||||
} else {
|
||||
_reason.remove(index + 1);
|
||||
}
|
||||
},
|
||||
['头像违规', '昵称违规', '签名违规'][index],
|
||||
),
|
||||
),
|
||||
const Text('举报理由(单选,非必选)'),
|
||||
...List.generate(
|
||||
5,
|
||||
(index) => RadioWidget<int>(
|
||||
value: index,
|
||||
groupValue: _reasonV2,
|
||||
onChanged: (value) {
|
||||
setState(() => _reasonV2 = value);
|
||||
},
|
||||
title: const ['色情低俗', '不实信息', '违禁', '人身攻击', '赌博诈骗'][index],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'取消',
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
if (_reason.isEmpty) {
|
||||
SmartDialog.showToast('至少选择一项作为举报内容');
|
||||
} else {
|
||||
Get.back();
|
||||
dynamic result = await MemberHttp.reportMember(
|
||||
widget.mid,
|
||||
reason: _reason.join(','),
|
||||
reasonV2: _reasonV2 != null ? _reasonV2! + 1 : null,
|
||||
);
|
||||
if (result['msg'] is String && result['msg'].isNotEmpty) {
|
||||
SmartDialog.showToast(result['msg']);
|
||||
} else {
|
||||
SmartDialog.showToast('举报失败');
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const Text('确定'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _checkBoxWidget(
|
||||
bool defValue,
|
||||
ValueChanged onChanged,
|
||||
String title,
|
||||
) {
|
||||
return InkWell(
|
||||
onTap: () => onChanged(!defValue),
|
||||
child: Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: defValue,
|
||||
onChanged: onChanged,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
),
|
||||
Text(title),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/http/member.dart';
|
||||
import 'package:PiliPlus/http/video.dart';
|
||||
import 'package:PiliPlus/models/space/data.dart';
|
||||
import 'package:PiliPlus/models/space/item.dart';
|
||||
import 'package:PiliPlus/models/space/tab2.dart';
|
||||
import 'package:PiliPlus/pages/common/common_data_controller.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
enum MemberTabType { none, home, dynamic, contribute, favorite, bangumi }
|
||||
|
||||
extension MemberTabTypeExt on MemberTabType {
|
||||
String get title => ['默认', '首页', '动态', '投稿', '收藏', '番剧'][index];
|
||||
}
|
||||
|
||||
class MemberControllerNew extends CommonDataController<Data, dynamic>
|
||||
with GetTickerProviderStateMixin {
|
||||
MemberControllerNew({required this.mid});
|
||||
int mid;
|
||||
RxBool showUname = false.obs;
|
||||
String? username;
|
||||
int? ownerMid;
|
||||
RxBool isFollow = false.obs;
|
||||
RxInt relation = 1.obs;
|
||||
TabController? tabController;
|
||||
late List<Tab> tabs;
|
||||
List<Tab2>? tab2;
|
||||
RxInt contributeInitialIndex = 0.obs;
|
||||
double top = 0;
|
||||
bool? hasSeasonOrSeries;
|
||||
final fromViewAid = Get.parameters['from_view_aid'];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
ownerMid = Accounts.main.mid;
|
||||
queryData();
|
||||
}
|
||||
|
||||
dynamic live;
|
||||
|
||||
int? silence;
|
||||
String? endTime;
|
||||
|
||||
late final implTabs = const [
|
||||
'home',
|
||||
'dynamic',
|
||||
'contribute',
|
||||
'favorite',
|
||||
'bangumi',
|
||||
];
|
||||
|
||||
@override
|
||||
bool customHandleResponse(bool isRefresh, Success<Data> response) {
|
||||
Data data = response.response;
|
||||
username = data.card?.name ?? '';
|
||||
isFollow.value = data.card?.relation?.isFollow == 1;
|
||||
relation.value = data.relSpecial == 1 ? 2 : data.relation ?? 1;
|
||||
tab2 = data.tab2;
|
||||
live = data.live;
|
||||
silence = data.card?.silence;
|
||||
if ((data.ugcSeason?.count != null && data.ugcSeason?.count != 0) ||
|
||||
data.series?.item?.isNotEmpty == true) {
|
||||
hasSeasonOrSeries = true;
|
||||
}
|
||||
if (data.card?.endTime != null) {
|
||||
if (data.card!.endTime == 0) {
|
||||
endTime = ': 永久封禁';
|
||||
} else if (data.card!.endTime! >
|
||||
DateTime.now().millisecondsSinceEpoch ~/ 1000) {
|
||||
endTime =
|
||||
':至 ${DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.fromMillisecondsSinceEpoch(data.card!.endTime! * 1000))}';
|
||||
}
|
||||
}
|
||||
tab2?.retainWhere((item) => implTabs.contains(item.param));
|
||||
if (tab2?.isNotEmpty == true) {
|
||||
if (!data.tab!.toJson().values.contains(true) &&
|
||||
tab2!.first.param == 'home') {
|
||||
// remove empty home tab
|
||||
tab2!.removeAt(0);
|
||||
}
|
||||
if (tab2!.isNotEmpty) {
|
||||
int initialIndex = -1;
|
||||
MemberTabType memberTab = GStorage.memberTab;
|
||||
if (memberTab != MemberTabType.none) {
|
||||
initialIndex = tab2!.indexWhere((item) {
|
||||
return item.param == memberTab.name;
|
||||
});
|
||||
}
|
||||
if (initialIndex == -1) {
|
||||
if (data.defaultTab == 'video') {
|
||||
data.defaultTab = 'contribute';
|
||||
}
|
||||
initialIndex = tab2!.indexWhere((item) {
|
||||
return item.param == data.defaultTab;
|
||||
});
|
||||
}
|
||||
tabs = tab2!.map((item) => Tab(text: item.title ?? '')).toList();
|
||||
tabController = TabController(
|
||||
vsync: this,
|
||||
length: tabs.length,
|
||||
initialIndex: max(0, initialIndex),
|
||||
);
|
||||
}
|
||||
}
|
||||
loadingState.value = response;
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
bool handleError(String? errMsg) {
|
||||
tab2 = [
|
||||
Tab2(title: '动态', param: 'dynamic'),
|
||||
Tab2(
|
||||
title: '投稿',
|
||||
param: 'contribute',
|
||||
items: [Item(title: '视频', param: 'video')],
|
||||
),
|
||||
Tab2(title: '收藏', param: 'favorite'),
|
||||
Tab2(title: '追番', param: 'bangumi'),
|
||||
];
|
||||
tabs = tab2!.map((item) => Tab(text: item.title)).toList();
|
||||
tabController = TabController(
|
||||
vsync: this,
|
||||
length: tabs.length,
|
||||
);
|
||||
showUname.value = true;
|
||||
username = errMsg;
|
||||
loadingState.value = LoadingState.success(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LoadingState<Data>> customGetData() => MemberHttp.space(
|
||||
mid: mid,
|
||||
fromViewAid: fromViewAid,
|
||||
);
|
||||
|
||||
Future blockUser(BuildContext context) async {
|
||||
if (ownerMid == 0) {
|
||||
SmartDialog.showToast('账号未登录');
|
||||
return;
|
||||
}
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('提示'),
|
||||
content: Text(relation.value != -1 ? '确定拉黑UP主?' : '从黑名单移除UP主'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'点错了',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
_onBlock();
|
||||
},
|
||||
child: const Text('确认'),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void shareUser() {
|
||||
Utils.shareText('https://space.bilibili.com/$mid');
|
||||
}
|
||||
|
||||
void _onBlock() async {
|
||||
dynamic res = await VideoHttp.relationMod(
|
||||
mid: mid,
|
||||
act: relation.value != -1 ? 5 : 6,
|
||||
reSrc: 11,
|
||||
);
|
||||
if (res['status']) {
|
||||
relation.value = relation.value != -1 ? -1 : 1;
|
||||
isFollow.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
void onFollow(BuildContext context) async {
|
||||
if (mid == ownerMid) {
|
||||
Get.toNamed('/editProfile');
|
||||
} else if (relation.value == -1) {
|
||||
_onBlock();
|
||||
} else {
|
||||
if (ownerMid == null) {
|
||||
SmartDialog.showToast('账号未登录');
|
||||
return;
|
||||
}
|
||||
Utils.actionRelationMod(
|
||||
context: context,
|
||||
mid: mid,
|
||||
isFollow: isFollow.value,
|
||||
callback: (attribute) {
|
||||
relation.value = attribute;
|
||||
isFollow.value = attribute != 0;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
tabController?.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@@ -1,652 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:PiliPlus/common/widgets/radio_widget.dart';
|
||||
import 'package:PiliPlus/http/member.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/network_img_layer.dart';
|
||||
import 'package:PiliPlus/pages/member/index.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
|
||||
import 'widgets/conis.dart';
|
||||
import 'widgets/profile.dart';
|
||||
import 'widgets/seasons.dart';
|
||||
|
||||
@Deprecated('Use MemberPageNew instead')
|
||||
class MemberPage extends StatefulWidget {
|
||||
const MemberPage({super.key});
|
||||
|
||||
@override
|
||||
State<MemberPage> createState() => _MemberPageState();
|
||||
}
|
||||
|
||||
class _MemberPageState extends State<MemberPage> {
|
||||
late String heroTag;
|
||||
late MemberController _memberController;
|
||||
late Future _futureBuilderFuture;
|
||||
late Future _memberSeasonsFuture;
|
||||
late Future _memberCoinsFuture;
|
||||
final ScrollController _extendNestCtr = ScrollController();
|
||||
final StreamController<bool> appbarStream = StreamController<bool>();
|
||||
late int mid;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
mid = int.parse(Get.parameters['mid']!);
|
||||
heroTag = Get.arguments['heroTag'] ?? Utils.makeHeroTag(mid);
|
||||
_memberController = Get.put(MemberController(), tag: heroTag);
|
||||
_futureBuilderFuture = _memberController.getInfo();
|
||||
_memberSeasonsFuture = _memberController.getMemberSeasons();
|
||||
_memberCoinsFuture = _memberController.getRecentCoinVideo();
|
||||
_extendNestCtr.addListener(listener);
|
||||
}
|
||||
|
||||
void listener() {
|
||||
final double offset = _extendNestCtr.position.pixels;
|
||||
if (offset > 100) {
|
||||
appbarStream.add(true);
|
||||
} else {
|
||||
appbarStream.add(false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_extendNestCtr.removeListener(listener);
|
||||
_extendNestCtr.dispose();
|
||||
appbarStream.close();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isHorizontal = context.width > context.height;
|
||||
return Scaffold(
|
||||
primary: true,
|
||||
body: Column(
|
||||
children: [
|
||||
AppBar(
|
||||
title: StreamBuilder(
|
||||
stream: appbarStream.stream.distinct(),
|
||||
initialData: false,
|
||||
builder: (BuildContext context, AsyncSnapshot snapshot) {
|
||||
return AnimatedOpacity(
|
||||
opacity: snapshot.data ? 1 : 0,
|
||||
curve: Curves.easeOut,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: Row(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Obx(
|
||||
() => NetworkImgLayer(
|
||||
width: 35,
|
||||
height: 35,
|
||||
type: 'avatar',
|
||||
src: _memberController.face.value,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Obx(
|
||||
() => Text(
|
||||
_memberController.memberInfo.value.name ?? '',
|
||||
style: TextStyle(
|
||||
color:
|
||||
Theme.of(context).colorScheme.onSurface,
|
||||
fontSize: 14),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '搜索',
|
||||
onPressed: () => Get.toNamed(
|
||||
'/memberSearch?mid=$mid&uname=${_memberController.memberInfo.value.name!}'),
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
),
|
||||
PopupMenuButton(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
|
||||
if (_memberController.ownerMid != _memberController.mid) ...[
|
||||
PopupMenuItem(
|
||||
onTap: () => _memberController.blockUser(context),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.block, size: 19),
|
||||
const SizedBox(width: 10),
|
||||
Text(_memberController.attribute.value != 128
|
||||
? '加入黑名单'
|
||||
: '移除黑名单'),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
PopupMenuItem(
|
||||
onTap: () => _memberController.shareUser(),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.share_outlined, size: 19),
|
||||
const SizedBox(width: 10),
|
||||
Text(_memberController.ownerMid != _memberController.mid
|
||||
? '分享UP主'
|
||||
: '分享我的主页'),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_memberController.userInfo != null) ...[
|
||||
const PopupMenuDivider(),
|
||||
PopupMenuItem(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 16,
|
||||
),
|
||||
content: ReportPanel(
|
||||
name: _memberController.memberInfo.value.name,
|
||||
mid: mid,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
size: 19,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
'举报',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(
|
||||
parent: BouncingScrollPhysics(),
|
||||
),
|
||||
controller: _extendNestCtr,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).padding.bottom + 20,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
profileWidget(isHorizontal),
|
||||
Row(children: [
|
||||
const Spacer(),
|
||||
InkWell(
|
||||
onTap: _memberController.pushDynamicsPage,
|
||||
child: const Row(
|
||||
children: [
|
||||
Text('Ta的动态', style: TextStyle(height: 2)),
|
||||
SizedBox(width: 5),
|
||||
Icon(Icons.arrow_forward_ios, size: 19),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
InkWell(
|
||||
onTap: _memberController.pushArchivesPage,
|
||||
child: const Row(
|
||||
children: [
|
||||
Text('Ta的投稿', style: TextStyle(height: 2)),
|
||||
SizedBox(width: 5),
|
||||
Icon(Icons.arrow_forward_ios, size: 19),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
InkWell(
|
||||
onTap: () {},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text('Ta的专栏', style: TextStyle(height: 2)),
|
||||
SizedBox(width: 5),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
]),
|
||||
MediaQuery.removePadding(
|
||||
removeTop: true,
|
||||
removeBottom: true,
|
||||
context: context,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: StyleString.safeSpace,
|
||||
right: StyleString.safeSpace,
|
||||
),
|
||||
child: FutureBuilder(
|
||||
future: _memberSeasonsFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState ==
|
||||
ConnectionState.done) {
|
||||
if (snapshot.data == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
if (snapshot.data['status']) {
|
||||
Map data = snapshot.data as Map;
|
||||
if (data['data'].seasonsList.isEmpty) {
|
||||
return commonWidget('用户没有设置专栏');
|
||||
} else {
|
||||
return MemberSeasonsPanel(data: data['data']);
|
||||
}
|
||||
} else {
|
||||
// 请求错误
|
||||
return const SizedBox();
|
||||
}
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
/// 收藏
|
||||
|
||||
/// 追番
|
||||
/// 最近投币
|
||||
Obx(
|
||||
() => _memberController.recentCoinsList.isNotEmpty
|
||||
? ListTile(
|
||||
onTap: () {},
|
||||
title: const Text('最近投币的视频'),
|
||||
// trailing: const Icon(Icons.arrow_forward_outlined,
|
||||
// size: 19),
|
||||
)
|
||||
: const SizedBox(),
|
||||
),
|
||||
MediaQuery.removePadding(
|
||||
removeTop: true,
|
||||
removeBottom: true,
|
||||
context: context,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: StyleString.safeSpace,
|
||||
right: StyleString.safeSpace,
|
||||
),
|
||||
child: FutureBuilder(
|
||||
future: _memberCoinsFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState ==
|
||||
ConnectionState.done) {
|
||||
if (snapshot.data == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
if (snapshot.data['status']) {
|
||||
Map data = snapshot.data as Map;
|
||||
return MemberCoinsPanel(data: data['data']);
|
||||
} else {
|
||||
// 请求错误
|
||||
return const SizedBox();
|
||||
}
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
// 最近点赞
|
||||
// ListTile(
|
||||
// onTap: () {},
|
||||
// title: const Text('最近点赞的视频'),
|
||||
// trailing:
|
||||
// const Icon(Icons.arrow_forward_outlined, size: 19),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget profileWidget(bool isHorizontal) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 18, right: 18, bottom: 20),
|
||||
child: FutureBuilder(
|
||||
future: _futureBuilderFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasData) {
|
||||
Map data = snapshot.data!;
|
||||
if (data['status']) {
|
||||
return Obx(
|
||||
() => Stack(
|
||||
alignment: AlignmentDirectional.center,
|
||||
children: [profilePanelAndDetailInfo(isHorizontal, false)]),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
} else {
|
||||
// 骨架屏
|
||||
return profilePanelAndDetailInfo(isHorizontal, true);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget profilePanelAndDetailInfo(bool isHorizontal, bool loadingStatus) {
|
||||
if (isHorizontal) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ProfilePanel(
|
||||
ctr: _memberController, loadingStatus: loadingStatus)),
|
||||
const SizedBox(width: 20),
|
||||
Expanded(child: profileDetailInfo()),
|
||||
],
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ProfilePanel(ctr: _memberController, loadingStatus: loadingStatus),
|
||||
const SizedBox(height: 20),
|
||||
profileDetailInfo(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget profileDetailInfo() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
_memberController.memberInfo.value.name ?? '',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: _memberController.memberInfo.value.vip?.status !=
|
||||
null &&
|
||||
_memberController.memberInfo.value.vip!.status! >
|
||||
0 &&
|
||||
_memberController.memberInfo.value.vip!.type == 2
|
||||
? context.vipColor
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
)),
|
||||
const SizedBox(width: 2),
|
||||
if (_memberController.memberInfo.value.sex == '女')
|
||||
const Icon(
|
||||
FontAwesomeIcons.venus,
|
||||
size: 14,
|
||||
color: Colors.pink,
|
||||
semanticLabel: '女',
|
||||
),
|
||||
if (_memberController.memberInfo.value.sex == '男')
|
||||
const Icon(
|
||||
FontAwesomeIcons.mars,
|
||||
size: 14,
|
||||
color: Colors.blue,
|
||||
semanticLabel: '男',
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
if (_memberController.memberInfo.value.level != null)
|
||||
Image.asset(
|
||||
'assets/images/lv/lv${_memberController.memberInfo.value.level}.png',
|
||||
height: 11,
|
||||
semanticLabel: '等级${_memberController.memberInfo.value.level}',
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
if (_memberController.memberInfo.value.vip?.status == 1) ...[
|
||||
if (_memberController
|
||||
.memberInfo.value.vip?.label?['img_label_uri_hans'] !=
|
||||
'')
|
||||
CachedNetworkImage(
|
||||
imageUrl: (_memberController.memberInfo.value.vip!
|
||||
.label!['img_label_uri_hans'] as String)
|
||||
.http2https,
|
||||
height: 20,
|
||||
// semanticLabel:
|
||||
// _memberController.memberInfo.value.vip!.label!['text'],
|
||||
)
|
||||
else if (_memberController.memberInfo.value.vip
|
||||
?.label?['img_label_uri_hans_static'] !=
|
||||
'')
|
||||
CachedNetworkImage(
|
||||
imageUrl: (_memberController.memberInfo.value.vip!
|
||||
.label!['img_label_uri_hans_static'] as String)
|
||||
.http2https,
|
||||
height: 20,
|
||||
// semanticLabel:
|
||||
// _memberController.memberInfo.value.vip!.label!['text'],
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 5),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Utils.copyText(_memberController.mid.toString());
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8, vertical: 2.5),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
child: Text(
|
||||
'UID: ${_memberController.mid}',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
),
|
||||
strutStyle: const StrutStyle(
|
||||
height: 1,
|
||||
leading: 0,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (_memberController.memberInfo.value.official != null &&
|
||||
_memberController.memberInfo.value.official!['title'] != '') ...[
|
||||
const SizedBox(height: 6),
|
||||
Text.rich(
|
||||
maxLines: 2,
|
||||
TextSpan(
|
||||
text: _memberController.memberInfo.value.official!['role'] == 1
|
||||
? '个人认证:'
|
||||
: '机构认证:',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: _memberController.memberInfo.value.official!['title'],
|
||||
),
|
||||
],
|
||||
),
|
||||
softWrap: true,
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 6),
|
||||
SelectableText(
|
||||
_memberController.memberInfo.value.sign ?? '',
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget commonWidget(msg) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 20,
|
||||
bottom: 30,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
msg,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.copyWith(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ReportPanel extends StatefulWidget {
|
||||
const ReportPanel({
|
||||
super.key,
|
||||
required this.name,
|
||||
required this.mid,
|
||||
});
|
||||
|
||||
final dynamic name;
|
||||
final dynamic mid;
|
||||
|
||||
@override
|
||||
State<ReportPanel> createState() => _ReportPanelState();
|
||||
}
|
||||
|
||||
class _ReportPanelState extends State<ReportPanel> {
|
||||
final List<bool> _reasonList = List.generate(3, (_) => false).toList();
|
||||
final Set<int> _reason = {};
|
||||
int? _reasonV2;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'举报: ${widget.name}',
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text('uid: ${widget.mid}'),
|
||||
const SizedBox(height: 10),
|
||||
const Text('举报内容(必选,可多选)'),
|
||||
...List.generate(
|
||||
3,
|
||||
(index) => _checkBoxWidget(
|
||||
_reasonList[index],
|
||||
(value) {
|
||||
setState(() => _reasonList[index] = value);
|
||||
if (value) {
|
||||
_reason.add(index + 1);
|
||||
} else {
|
||||
_reason.remove(index + 1);
|
||||
}
|
||||
},
|
||||
['头像违规', '昵称违规', '签名违规'][index],
|
||||
),
|
||||
),
|
||||
const Text('举报理由(单选,非必选)'),
|
||||
...List.generate(
|
||||
5,
|
||||
(index) => RadioWidget<int>(
|
||||
value: index,
|
||||
groupValue: _reasonV2,
|
||||
onChanged: (value) {
|
||||
setState(() => _reasonV2 = value);
|
||||
},
|
||||
title: const ['色情低俗', '不实信息', '违禁', '人身攻击', '赌博诈骗'][index],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'取消',
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
if (_reason.isEmpty) {
|
||||
SmartDialog.showToast('至少选择一项作为举报内容');
|
||||
} else {
|
||||
Get.back();
|
||||
dynamic result = await MemberHttp.reportMember(
|
||||
widget.mid,
|
||||
reason: _reason.join(','),
|
||||
reasonV2: _reasonV2 != null ? _reasonV2! + 1 : null,
|
||||
);
|
||||
if (result['msg'] is String && result['msg'].isNotEmpty) {
|
||||
SmartDialog.showToast(result['msg']);
|
||||
} else {
|
||||
SmartDialog.showToast('举报失败');
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const Text('确定'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _checkBoxWidget(
|
||||
bool defValue,
|
||||
ValueChanged onChanged,
|
||||
String title,
|
||||
) {
|
||||
return InkWell(
|
||||
onTap: () => onChanged(!defValue),
|
||||
child: Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: defValue,
|
||||
onChanged: onChanged,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
),
|
||||
Text(title),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/models/member/coin.dart';
|
||||
import 'package:PiliPlus/pages/member_coin/widgets/item.dart';
|
||||
|
||||
class MemberCoinsPanel extends StatelessWidget {
|
||||
final List<MemberCoinsDataModel>? data;
|
||||
const MemberCoinsPanel({super.key, this.data});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, boxConstraints) {
|
||||
return GridView.builder(
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2, // Use a fixed count for GridView
|
||||
crossAxisSpacing: StyleString.safeSpace,
|
||||
mainAxisSpacing: StyleString.safeSpace,
|
||||
childAspectRatio: 0.94,
|
||||
),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemCount: data!.length,
|
||||
itemBuilder: (context, i) {
|
||||
return MemberCoinsItem(coinItem: data![i]);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
import 'package:PiliPlus/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart'
|
||||
show SourceModel;
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/common/widgets/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/member/info.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
|
||||
class ProfilePanel extends StatelessWidget {
|
||||
final dynamic ctr;
|
||||
final bool loadingStatus;
|
||||
const ProfilePanel({
|
||||
super.key,
|
||||
required this.ctr,
|
||||
this.loadingStatus = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
MemberInfoModel memberInfo = ctr.memberInfo.value;
|
||||
return Builder(
|
||||
builder: ((context) {
|
||||
return Row(
|
||||
children: [
|
||||
Hero(
|
||||
tag: !loadingStatus ? memberInfo.face : ctr.face.value,
|
||||
child: Stack(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => context.imageView(
|
||||
imgList: [
|
||||
SourceModel(
|
||||
url:
|
||||
!loadingStatus ? memberInfo.face : ctr.face.value,
|
||||
)
|
||||
],
|
||||
),
|
||||
child: NetworkImgLayer(
|
||||
width: 90,
|
||||
height: 90,
|
||||
type: 'avatar',
|
||||
src: !loadingStatus ? memberInfo.face : ctr.face.value,
|
||||
),
|
||||
),
|
||||
if (!loadingStatus &&
|
||||
memberInfo.liveRoom != null &&
|
||||
memberInfo.liveRoom!.liveStatus == 1)
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
left: 14,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// LiveItemModel liveItem = LiveItemModel.fromJson({
|
||||
// 'title': memberInfo.liveRoom!.title,
|
||||
// 'uname': memberInfo.name,
|
||||
// 'face': memberInfo.face,
|
||||
// 'roomid': memberInfo.liveRoom!.roomId,
|
||||
// 'watched_show': memberInfo.liveRoom!.watchedShow,
|
||||
// });
|
||||
Get.toNamed(
|
||||
'/liveRoom?roomid=${memberInfo.liveRoom!.roomId}',
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.fromLTRB(6, 2, 6, 2),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.circular(10)),
|
||||
),
|
||||
child: Row(children: [
|
||||
Image.asset(
|
||||
'assets/images/live.gif',
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
' 直播中',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize),
|
||||
)
|
||||
]),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 10, left: 10, right: 10),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
'/follow?mid=${memberInfo.mid}&name=${memberInfo.name}');
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
!loadingStatus
|
||||
? ctr.userStat!['following'].toString()
|
||||
: '-',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
'关注',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
'/fan?mid=${memberInfo.mid}&name=${memberInfo.name}');
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
!loadingStatus
|
||||
? ctr.userStat!['follower'] != null
|
||||
? Utils.numFormat(
|
||||
ctr.userStat!['follower'],
|
||||
)
|
||||
: '-'
|
||||
: '-',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
'粉丝',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: null,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
!loadingStatus
|
||||
? ctr.userStat!['likes'] != null
|
||||
? Utils.numFormat(
|
||||
ctr.userStat!['likes'],
|
||||
)
|
||||
: '-'
|
||||
: '-',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
'获赞',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize),
|
||||
)
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
if (ctr.ownerMid != ctr.mid && ctr.ownerMid != -1) ...[
|
||||
Row(
|
||||
children: [
|
||||
Obx(
|
||||
() => Expanded(
|
||||
child: TextButton(
|
||||
onPressed: () => ctr.actionRelationMod(context),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: ctr.attribute.value == -1
|
||||
? Colors.transparent
|
||||
: ctr.attribute.value != 0
|
||||
? Theme.of(context).colorScheme.outline
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.onPrimary,
|
||||
backgroundColor: ctr.attribute.value != 0
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.onInverseSurface
|
||||
: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
child: Obx(() => Text(ctr.attributeText.value)),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
Get.toNamed(
|
||||
'/whisperDetail',
|
||||
parameters: {
|
||||
'talkerId': ctr.mid.toString(),
|
||||
'name': memberInfo.name!,
|
||||
'face': memberInfo.face!,
|
||||
'mid': ctr.mid.toString(),
|
||||
},
|
||||
);
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.onInverseSurface,
|
||||
),
|
||||
child: const Text('发消息'),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
if (ctr.ownerMid == ctr.mid && ctr.ownerMid != -1) ...[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.toNamed('/webview', parameters: {
|
||||
'url': 'https://account.bilibili.com/account/home',
|
||||
'pageTitle': '个人中心(建议浏览器打开)',
|
||||
'type': 'url'
|
||||
});
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.onPrimary,
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
child: const Text(' 个人中心(web) '),
|
||||
)
|
||||
],
|
||||
if (ctr.ownerMid == -1) ...[
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.onInverseSurface,
|
||||
),
|
||||
child: const Text(' 未登录 '),
|
||||
)
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/badge.dart';
|
||||
import 'package:PiliPlus/models/member/seasons.dart';
|
||||
import 'package:PiliPlus/pages/member_seasons/widgets/item.dart';
|
||||
|
||||
import '../../../utils/grid.dart';
|
||||
|
||||
class MemberSeasonsPanel extends StatelessWidget {
|
||||
final MemberSeasonsDataModel? data;
|
||||
const MemberSeasonsPanel({super.key, this.data});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: data!.seasonsList!.length,
|
||||
itemBuilder: (context, index) {
|
||||
MemberSeasonsList item = data!.seasonsList![index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12, right: 4),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12, left: 4),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
item.meta!.name!,
|
||||
maxLines: 1,
|
||||
style: Theme.of(context).textTheme.titleSmall!,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
PBadge(
|
||||
stack: 'relative',
|
||||
size: 'small',
|
||||
text: item.meta!.total.toString(),
|
||||
),
|
||||
SizedBox(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: IconButton(
|
||||
tooltip: '前往',
|
||||
onPressed: () => Get.toNamed(
|
||||
'/memberSeasons?mid=${item.meta!.mid}&seasonId=${item.meta!.seasonId}'),
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
icon: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
LayoutBuilder(
|
||||
builder: (context, boxConstraints) {
|
||||
return GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
||||
mainAxisSpacing: StyleString.cardSpace,
|
||||
crossAxisSpacing: StyleString.cardSpace,
|
||||
maxCrossAxisExtent: Grid.smallCardWidth,
|
||||
childAspectRatio: 0.94,
|
||||
),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemCount: item.archives!.length,
|
||||
itemBuilder: (context, i) {
|
||||
return MemberSeasonsItem(seasonItem: item.archives![i]);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user