mod: 用户页跳转&样式修改
This commit is contained in:
BIN
assets/images/live.gif
Normal file
BIN
assets/images/live.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
@ -199,6 +199,8 @@ class Api {
|
||||
|
||||
// 用户信息 需要Wbi签名
|
||||
// https://api.bilibili.com/x/space/wbi/acc/info?mid=503427686&token=&platform=web&web_location=1550101&w_rid=d709892496ce93e3d94d6d37c95bde91&wts=1689301482
|
||||
static const String memberInfo =
|
||||
'https://api.bilibili.com/x/space/wbi/acc/info';
|
||||
static const String memberInfo = '/x/space/wbi/acc/info';
|
||||
|
||||
// 用户名片信息
|
||||
static const String memberCardInfo = '/x/web-interface/card';
|
||||
}
|
||||
|
@ -19,10 +19,23 @@ class MemberHttp {
|
||||
}
|
||||
|
||||
static Future memberStat({int? mid}) async {
|
||||
var res = await Request().get(Api.userStat, data: {mid: mid});
|
||||
var res = await Request().get(Api.userStat, data: {'vmid': mid});
|
||||
if (res.data['code'] == 0) {
|
||||
print(res.data['data']);
|
||||
// return {'status': true, 'data': FansDataModel.fromJson(res.data['data'])};
|
||||
return {'status': true, 'data': res.data['data']};
|
||||
} else {
|
||||
return {
|
||||
'status': false,
|
||||
'data': [],
|
||||
'msg': res.data['message'],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static Future memberCardInfo({int? mid}) async {
|
||||
var res = await Request()
|
||||
.get(Api.memberCardInfo, data: {'mid': mid, 'photo': true});
|
||||
if (res.data['code'] == 0) {
|
||||
return {'status': true, 'data': res.data['data']};
|
||||
} else {
|
||||
return {
|
||||
'status': false,
|
||||
|
@ -7,6 +7,9 @@ class MemberInfoModel {
|
||||
this.sign,
|
||||
this.level,
|
||||
this.isFollowed,
|
||||
this.topPhoto,
|
||||
this.official,
|
||||
this.vip,
|
||||
});
|
||||
|
||||
int? mid;
|
||||
@ -16,14 +19,73 @@ class MemberInfoModel {
|
||||
String? sign;
|
||||
int? level;
|
||||
bool? isFollowed;
|
||||
String? topPhoto;
|
||||
Map? official;
|
||||
Vip? vip;
|
||||
LiveRoom? liveRoom;
|
||||
|
||||
MemberInfoModel.fromJson(Map<String, dynamic> json) {
|
||||
mid = json['mid'];
|
||||
name = json['name'];
|
||||
sex = json['sex'];
|
||||
face = json['face'];
|
||||
sign = json['sign'];
|
||||
sign = json['sign'] == '' ? '该用户还没有签名' : json['sign'];
|
||||
level = json['level'];
|
||||
isFollowed = json['is_followed'];
|
||||
topPhoto = json['top_photo'];
|
||||
official = json['official'];
|
||||
vip = Vip.fromJson(json['vip']);
|
||||
liveRoom = LiveRoom.fromJson(json['live_room']);
|
||||
}
|
||||
}
|
||||
|
||||
class Vip {
|
||||
Vip({
|
||||
this.type,
|
||||
this.status,
|
||||
this.dueDate,
|
||||
this.label,
|
||||
});
|
||||
|
||||
int? type;
|
||||
int? status;
|
||||
int? dueDate;
|
||||
Map? label;
|
||||
|
||||
Vip.fromJson(Map<String, dynamic> json) {
|
||||
type = json['type'];
|
||||
status = json['status'];
|
||||
dueDate = json['due_date'];
|
||||
label = json['label'];
|
||||
}
|
||||
}
|
||||
|
||||
class LiveRoom {
|
||||
LiveRoom({
|
||||
this.roomStatus,
|
||||
this.liveStatus,
|
||||
this.url,
|
||||
this.title,
|
||||
this.cover,
|
||||
this.roomId,
|
||||
this.roundStatus,
|
||||
});
|
||||
|
||||
int? roomStatus;
|
||||
int? liveStatus;
|
||||
String? url;
|
||||
String? title;
|
||||
String? cover;
|
||||
int? roomId;
|
||||
int? roundStatus;
|
||||
|
||||
LiveRoom.fromJson(Map<String, dynamic> json) {
|
||||
roomStatus = json['room_status'];
|
||||
liveStatus = json['live_status'];
|
||||
url = json['url'];
|
||||
title = json['title'];
|
||||
cover = json['cover'];
|
||||
roomId = json['room_id'];
|
||||
roundStatus = json['round_status'];
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ class SearchUserItemModel {
|
||||
usign = json['usign'];
|
||||
fans = json['fans'];
|
||||
videos = json['videos'];
|
||||
upic = json['upic'];
|
||||
upic = 'https:' + json['upic'];
|
||||
faceNft = json['face_nft'];
|
||||
faceNftType = json['face_nft_type'];
|
||||
verifyInfo = json['verify_info'];
|
||||
|
@ -1,15 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
Widget author(item, context) {
|
||||
String heroTag = Utils.makeHeroTag(item.modules.moduleAuthor.mid);
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(12, 12, 12, 8),
|
||||
child: Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () =>
|
||||
Get.toNamed('/member?mid=${item.modules.moduleAuthor.mid}'),
|
||||
onTap: () => Get.toNamed(
|
||||
'/member?mid=${item.modules.moduleAuthor.mid}',
|
||||
arguments: {
|
||||
'face': item.modules.moduleAuthor.face,
|
||||
'heroTag': heroTag
|
||||
}),
|
||||
child: Hero(
|
||||
tag: heroTag,
|
||||
child: NetworkImgLayer(
|
||||
width: 40,
|
||||
height: 40,
|
||||
@ -17,6 +25,7 @@ Widget author(item, context) {
|
||||
src: item.modules.moduleAuthor.face,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -174,12 +174,13 @@ class _UpPanelState extends State<UpPanel> {
|
||||
Badge(
|
||||
smallSize: 8,
|
||||
label: data.type == 'live' ? const Text('Live') : null,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
textColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
alignment: AlignmentDirectional.bottomCenter,
|
||||
padding: const EdgeInsets.only(left: 4, right: 4),
|
||||
padding: const EdgeInsets.only(left: 6, right: 6),
|
||||
isLabelVisible: data.type == 'live' ||
|
||||
(data.type == 'up' && (data.hasUpdate ?? false)),
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.secondaryContainer,
|
||||
child: NetworkImgLayer(
|
||||
width: 49,
|
||||
height: 49,
|
||||
|
@ -1,15 +1,22 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
Widget fanItem({item}) {
|
||||
String heroTag = Utils.makeHeroTag(item!.mid);
|
||||
return ListTile(
|
||||
onTap: () {},
|
||||
leading: NetworkImgLayer(
|
||||
onTap: () => Get.toNamed('/member?mid=${item.mid}',
|
||||
arguments: {'face': item.face, 'heroTag': heroTag}),
|
||||
leading: Hero(
|
||||
tag: heroTag,
|
||||
child: NetworkImgLayer(
|
||||
width: 38,
|
||||
height: 38,
|
||||
type: 'avatar',
|
||||
src: item.face,
|
||||
),
|
||||
),
|
||||
title: Text(item.uname),
|
||||
subtitle: Text(
|
||||
item.sign,
|
||||
|
@ -1,16 +1,22 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
Widget followItem({item}) {
|
||||
String heroTag = Utils.makeHeroTag(item!.mid);
|
||||
return ListTile(
|
||||
onTap: () {},
|
||||
leading: NetworkImgLayer(
|
||||
onTap: () => Get.toNamed('/member?mid=${item.mid}',
|
||||
arguments: {'face': item.face, 'heroTag': heroTag}),
|
||||
leading: Hero(
|
||||
tag: heroTag,
|
||||
child: NetworkImgLayer(
|
||||
width: 38,
|
||||
height: 38,
|
||||
type: 'avatar',
|
||||
src: item.face,
|
||||
),
|
||||
),
|
||||
title: Text(item.uname),
|
||||
subtitle: Text(
|
||||
item.sign,
|
||||
|
@ -23,7 +23,7 @@ class LiveRoomController extends GetxController {
|
||||
super.onInit();
|
||||
if (Get.arguments != null) {
|
||||
var args = Get.arguments['liveItem'];
|
||||
heroTag = Get.arguments['heroTag'];
|
||||
heroTag = Get.arguments['heroTag'] ?? '';
|
||||
liveItem = args;
|
||||
roomId = liveItem.roomId!;
|
||||
if (args.pic != null && args.pic != '') {
|
||||
|
@ -89,6 +89,7 @@ class _LiveRoomPageState extends State<LiveRoomPage> {
|
||||
controller: _meeduPlayerController!,
|
||||
),
|
||||
),
|
||||
if (_liveRoomController.liveItem.cover != null)
|
||||
Visibility(
|
||||
visible: isShowCover,
|
||||
child: Positioned(
|
||||
|
@ -1,18 +1,26 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/member.dart';
|
||||
import 'package:pilipala/models/member/info.dart';
|
||||
import 'package:pilipala/utils/wbi_sign.dart';
|
||||
|
||||
class MemberController extends GetxController {
|
||||
late int mid;
|
||||
Rx<MemberInfoModel> memberInfo = MemberInfoModel().obs;
|
||||
Map? userStat;
|
||||
String? face;
|
||||
String? heroTag;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
mid = int.parse(Get.parameters['mid']!);
|
||||
getInfo();
|
||||
face = Get.arguments['face']!;
|
||||
heroTag = Get.arguments['heroTag']!;
|
||||
}
|
||||
|
||||
getInfo() async {
|
||||
// 获取用户信息
|
||||
Future<Map<String, dynamic>> getInfo() async {
|
||||
await getMemberStat();
|
||||
String params = await WbiSign().makSign({
|
||||
'mid': mid,
|
||||
'token': '',
|
||||
@ -22,7 +30,25 @@ class MemberController extends GetxController {
|
||||
params = '?$params';
|
||||
var res = await MemberHttp.memberInfo(params: params);
|
||||
if (res['status']) {
|
||||
print(res['data']);
|
||||
}
|
||||
memberInfo.value = res['data'];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 获取用户状态
|
||||
Future<Map<String, dynamic>> getMemberStat() async {
|
||||
var res = await MemberHttp.memberStat(mid: mid);
|
||||
if (res['status']) {
|
||||
userStat = res['data'];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Future getMemberCardInfo() async {
|
||||
var res = await MemberHttp.memberCardInfo(mid: mid);
|
||||
if (res['status']) {
|
||||
print(userStat);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/models/user/stat.dart';
|
||||
import 'package:pilipala/pages/member/index.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
class MemberPage extends StatefulWidget {
|
||||
const MemberPage({super.key});
|
||||
@ -10,11 +13,379 @@ class MemberPage extends StatefulWidget {
|
||||
State<MemberPage> createState() => _MemberPageState();
|
||||
}
|
||||
|
||||
class _MemberPageState extends State<MemberPage> {
|
||||
class _MemberPageState extends State<MemberPage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
final MemberController _memberController = Get.put(MemberController());
|
||||
final ScrollController _extendNestCtr = ScrollController();
|
||||
late TabController _tabController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tabController = TabController(length: 3, vsync: this);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold();
|
||||
return Scaffold(
|
||||
primary: true,
|
||||
body: ExtendedNestedScrollView(
|
||||
controller: _extendNestCtr,
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
return <Widget>[
|
||||
SliverAppBar(
|
||||
pinned: false,
|
||||
primary: true,
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
forceElevated: innerBoxIsScrolled,
|
||||
expandedHeight: 300,
|
||||
actions: [
|
||||
IconButton(onPressed: () {}, icon: const Icon(Icons.more_vert)),
|
||||
const SizedBox(width: 4),
|
||||
],
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
background: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
bottom: 10,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fitWidth,
|
||||
image: NetworkImage(_memberController.face!),
|
||||
alignment: Alignment.topCenter,
|
||||
isAntiAlias: true,
|
||||
),
|
||||
),
|
||||
foregroundDecoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Theme.of(context)
|
||||
.colorScheme
|
||||
.background
|
||||
.withOpacity(0.44),
|
||||
Theme.of(context).colorScheme.background,
|
||||
],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
stops: const [0.0, 0.46],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
height: 20,
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 18, right: 18),
|
||||
child: FutureBuilder(
|
||||
future: _memberController.getInfo(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState ==
|
||||
ConnectionState.done) {
|
||||
Map data = snapshot.data!;
|
||||
if (data['status']) {
|
||||
return Obx(
|
||||
() => Stack(
|
||||
alignment: AlignmentDirectional.center,
|
||||
children: [
|
||||
Column(
|
||||
// mainAxisAlignment:
|
||||
// MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
profile(
|
||||
_memberController.memberInfo.value),
|
||||
const SizedBox(height: 14),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
_memberController
|
||||
.memberInfo.value.name!,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.copyWith(
|
||||
fontWeight:
|
||||
FontWeight.bold),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Image.asset(
|
||||
'assets/images/lv/lv${_memberController.memberInfo.value.level}.png',
|
||||
height: 11,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
if (_memberController.memberInfo
|
||||
.value.vip!.status ==
|
||||
1 &&
|
||||
_memberController.memberInfo
|
||||
.value.vip!.label![
|
||||
'img_label_uri_hans'] !=
|
||||
'') ...[
|
||||
Image.network(
|
||||
_memberController.memberInfo
|
||||
.value.vip!.label![
|
||||
'img_label_uri_hans'],
|
||||
height: 20,
|
||||
),
|
||||
] else if (_memberController
|
||||
.memberInfo
|
||||
.value
|
||||
.vip!
|
||||
.status ==
|
||||
1 &&
|
||||
_memberController.memberInfo
|
||||
.value.vip!.label![
|
||||
'img_label_uri_hans_static'] !=
|
||||
'') ...[
|
||||
Image.network(
|
||||
_memberController.memberInfo
|
||||
.value.vip!.label![
|
||||
'img_label_uri_hans_static'],
|
||||
height: 20,
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
if (_memberController.memberInfo.value
|
||||
.official!['title'] !=
|
||||
'') ...[
|
||||
const SizedBox(height: 6),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
_memberController
|
||||
.memberInfo
|
||||
.value
|
||||
.official![
|
||||
'role'] ==
|
||||
1
|
||||
? '个人认证:'
|
||||
: '企业认证:',
|
||||
),
|
||||
Text(
|
||||
_memberController.memberInfo
|
||||
.value.official!['title']!,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
if (_memberController
|
||||
.memberInfo.value.sign !=
|
||||
'')
|
||||
Text(
|
||||
_memberController
|
||||
.memberInfo.value.sign!,
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return SizedBox();
|
||||
}
|
||||
} else {
|
||||
// 骨架屏
|
||||
return profile(null, loadingStatus: true);
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
pinnedHeaderSliverHeightBuilder: () {
|
||||
return MediaQuery.of(context).padding.top + kToolbarHeight;
|
||||
},
|
||||
onlyOneScrollInBody: true,
|
||||
body: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: TabBar(controller: _tabController, tabs: [
|
||||
Tab(text: '主页'),
|
||||
Tab(text: '动态'),
|
||||
Tab(text: '投稿'),
|
||||
]),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
controller: _tabController,
|
||||
children: [
|
||||
Text('主页'),
|
||||
Text('动态'),
|
||||
Text('投稿'),
|
||||
],
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget profile(memberInfo, {loadingStatus = false}) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 3 * MediaQuery.of(context).padding.top),
|
||||
child: Row(
|
||||
children: [
|
||||
Hero(
|
||||
tag: _memberController.heroTag!,
|
||||
child: Stack(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: 90,
|
||||
height: 90,
|
||||
type: 'avatar',
|
||||
src: !loadingStatus
|
||||
? memberInfo.face
|
||||
: _memberController.face,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
left: 14,
|
||||
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(left: 10, right: 10),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
!loadingStatus
|
||||
? _memberController.userStat!['following']
|
||||
.toString()
|
||||
: '-',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
'关注',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize),
|
||||
)
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
!loadingStatus
|
||||
? Utils.numFormat(
|
||||
_memberController.userStat!['follower'],
|
||||
)
|
||||
: '-',
|
||||
style:
|
||||
const TextStyle(fontWeight: FontWeight.bold)),
|
||||
Text('粉丝',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize))
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
const Text('-',
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
'获赞',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.only(left: 42, right: 42),
|
||||
foregroundColor: !loadingStatus && memberInfo.isFollowed
|
||||
? null
|
||||
: Theme.of(context).colorScheme.onPrimary,
|
||||
backgroundColor: !loadingStatus && memberInfo.isFollowed
|
||||
? Theme.of(context).colorScheme.onInverseSurface
|
||||
: Theme.of(context).colorScheme.primary, // 设置按钮背景色
|
||||
),
|
||||
child: Text(!loadingStatus && memberInfo.isFollowed
|
||||
? '取关'
|
||||
: '关注'),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.only(left: 42, right: 42),
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.onInverseSurface,
|
||||
),
|
||||
child: const Text('发消息'),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
Widget searchUserPanel(BuildContext context, ctr, list) {
|
||||
TextStyle style = TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline);
|
||||
|
||||
return ListView.builder(
|
||||
controller: ctr!.scrollController,
|
||||
addAutomaticKeepAlives: false,
|
||||
@ -12,18 +15,23 @@ Widget searchUserPanel(BuildContext context, ctr, list) {
|
||||
itemCount: list!.length,
|
||||
itemBuilder: (context, index) {
|
||||
var i = list![index];
|
||||
String heroTag = Utils.makeHeroTag(i!.mid);
|
||||
return InkWell(
|
||||
onTap: () {},
|
||||
onTap: () => Get.toNamed('/member?mid=${i.mid}',
|
||||
arguments: {'heroTag': heroTag, 'face': i.upic}),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
Hero(
|
||||
tag: heroTag,
|
||||
child: NetworkImgLayer(
|
||||
width: 42,
|
||||
height: 42,
|
||||
src: i.upic,
|
||||
type: 'avatar',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
|
@ -360,9 +360,24 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
height: 26,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
),
|
||||
Row(
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
int mid = !widget.loadingStatus
|
||||
? widget.videoDetail!.owner!.mid
|
||||
: videoItem['owner'].mid;
|
||||
String face = !widget.loadingStatus
|
||||
? widget.videoDetail!.owner!.face
|
||||
: videoItem['owner'].face;
|
||||
Get.toNamed('/member?mid=$mid', arguments: {
|
||||
'face': face,
|
||||
'heroTag': (mid + 99).toString()
|
||||
});
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
Hero(
|
||||
tag: videoItem['owner'].mid + 99,
|
||||
child: NetworkImgLayer(
|
||||
type: 'avatar',
|
||||
src: !widget.loadingStatus
|
||||
? widget.videoDetail!.owner!.face
|
||||
@ -372,6 +387,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
fadeInDuration: Duration.zero,
|
||||
fadeOutDuration: Duration.zero,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -416,6 +432,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Divider(
|
||||
height: 26,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
|
@ -128,9 +128,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
_videoReplyController.currentPage = 0;
|
||||
return await _videoReplyController.queryReplyList();
|
||||
},
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Stack(
|
||||
child: Stack(
|
||||
children: [
|
||||
CustomScrollView(
|
||||
controller: _videoReplyController.scrollController,
|
||||
@ -165,8 +163,8 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
);
|
||||
} else {
|
||||
return ReplyItem(
|
||||
replyItem: _videoReplyController
|
||||
.replyList[index],
|
||||
replyItem:
|
||||
_videoReplyController.replyList[index],
|
||||
showReplyRow: true,
|
||||
replyLevel: replyLevel);
|
||||
}
|
||||
@ -237,7 +235,6 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -46,17 +46,20 @@ class ReplyItem extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget lfAvtar(context) {
|
||||
Widget lfAvtar(context, heroTag) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(top: 5),
|
||||
child: Stack(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
Hero(
|
||||
tag: heroTag,
|
||||
child: NetworkImgLayer(
|
||||
src: replyItem!.member!.avatar,
|
||||
width: 34,
|
||||
height: 34,
|
||||
type: 'avatar',
|
||||
),
|
||||
),
|
||||
if (replyItem!.member!.officialVerify != null &&
|
||||
replyItem!.member!.officialVerify!['type'] == 0)
|
||||
Positioned(
|
||||
@ -87,16 +90,18 @@ class ReplyItem extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget content(context) {
|
||||
String heroTag = Utils.makeHeroTag(replyItem!.mid);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
// 头像、昵称
|
||||
GestureDetector(
|
||||
// onTap: () =>
|
||||
// Get.toNamed('/member/${reply.userName}', parameters: {
|
||||
// 'memberAvatar': reply.avatar,
|
||||
// 'heroTag': reply.userName + heroTag,
|
||||
// }),
|
||||
onTap: () {
|
||||
Get.toNamed('/member?mid=${replyItem!.mid}', arguments: {
|
||||
'face': replyItem!.member!.avatar!,
|
||||
'heroTag': heroTag
|
||||
});
|
||||
},
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: Stack(
|
||||
@ -105,7 +110,7 @@ class ReplyItem extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
lfAvtar(context),
|
||||
lfAvtar(context, heroTag),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
replyItem!.member!.uname!,
|
||||
@ -367,8 +372,15 @@ class ReplyItemRow extends StatelessWidget {
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => {
|
||||
print('跳转至用户主页'),
|
||||
..onTap = () {
|
||||
String heroTag =
|
||||
Utils.makeHeroTag(replies![i].member.mid);
|
||||
Get.toNamed(
|
||||
'/member?mid=${replies![i].member.mid}',
|
||||
arguments: {
|
||||
'face': replies![i].member.avatar,
|
||||
'heroTag': heroTag
|
||||
});
|
||||
},
|
||||
),
|
||||
if (replies![i].isUp)
|
||||
@ -521,8 +533,12 @@ InlineSpan buildContent(BuildContext context, content) {
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => {
|
||||
print('跳转至用户主页'),
|
||||
..onTap = () {
|
||||
String heroTag = Utils.makeHeroTag(value);
|
||||
Get.toNamed(
|
||||
'/member?mid=$value',
|
||||
arguments: {'face': '', 'heroTag': heroTag},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
Reference in New Issue
Block a user