import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/common/dynamic/up_panel_position.dart'; import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/dynamics/up.dart'; import 'package:PiliPlus/pages/dynamics/controller.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; class UpPanel extends StatefulWidget { const UpPanel({ required this.dynamicsController, super.key, }); final DynamicsController dynamicsController; @override State createState() => _UpPanelState(); } class _UpPanelState extends State { List? get upList => widget.dynamicsController.upData.value.upList; List? get liveList => widget.dynamicsController.upData.value.liveUsers?.items; late final isTop = widget.dynamicsController.upPanelPosition == UpPanelPosition.top; @override Widget build(BuildContext context) { final theme = Theme.of(context); if (!widget.dynamicsController.isLogin.value) { return const SizedBox.shrink(); } return CustomScrollView( scrollDirection: isTop ? Axis.horizontal : Axis.vertical, physics: const AlwaysScrollableScrollPhysics(), controller: widget.dynamicsController.scrollController, slivers: [ SliverToBoxAdapter( child: InkWell( onTap: () => setState(() { widget.dynamicsController.showLiveItems = !widget.dynamicsController.showLiveItems; }), child: Container( alignment: Alignment.center, height: isTop ? 76 : 60, padding: isTop ? const EdgeInsets.only(left: 12, right: 6) : null, child: Text.rich( textAlign: TextAlign.center, style: TextStyle( fontSize: 13, color: theme.colorScheme.primary, ), TextSpan( children: [ TextSpan( text: 'Live(${widget.dynamicsController.upData.value.liveUsers?.count ?? 0})', ), if (!isTop) ...[ const TextSpan(text: '\n'), WidgetSpan( alignment: PlaceholderAlignment.middle, child: Icon( widget.dynamicsController.showLiveItems ? Icons.expand_less : Icons.expand_more, size: 12, color: theme.colorScheme.primary, ), ), ] else WidgetSpan( alignment: PlaceholderAlignment.middle, child: Icon( widget.dynamicsController.showLiveItems ? Icons.keyboard_arrow_right : Icons.keyboard_arrow_left, color: theme.colorScheme.primary, size: 14, ), ), ], ), ), ), ), ), if (widget.dynamicsController.showLiveItems && liveList?.isNotEmpty == true) SliverList.builder( itemCount: liveList!.length, itemBuilder: (context, index) { return upItemBuild(theme, liveList![index]); }, ), SliverToBoxAdapter( child: upItemBuild(theme, UpItem(face: '', uname: '全部动态', mid: -1)), ), SliverToBoxAdapter( child: upItemBuild( theme, UpItem( uname: '我', face: widget.dynamicsController.face, mid: widget.dynamicsController.ownerMid, ), ), ), if (upList?.isNotEmpty == true) SliverList.builder( itemCount: upList!.length, itemBuilder: (context, index) { return upItemBuild(theme, upList![index]); }, ), if (!isTop) const SliverToBoxAdapter(child: SizedBox(height: 200)), ], ); } void _onSelect(UserItem data) { widget.dynamicsController.currentMid = data.mid; widget.dynamicsController.onSelectUp(data.mid); data.hasUpdate = false; setState(() {}); } Widget upItemBuild(ThemeData theme, UserItem data) { bool isCurrent = widget.dynamicsController.currentMid == data.mid || widget.dynamicsController.currentMid == -1; final isLive = data is LiveUserItem; return SizedBox( height: 76, width: isTop ? 70 : null, child: InkWell( onTap: () { feedBack(); switch (data) { case UpItem(): _onSelect(data); break; case LiveUserItem(): Get.toNamed('/liveRoom?roomid=${data.roomId}'); } }, onDoubleTap: data is LiveUserItem ? () => _onSelect(data) : null, onLongPress: () { if (data.mid == -1) { return; } String heroTag = Utils.makeHeroTag(data.mid); Get.toNamed('/member?mid=${data.mid}', arguments: {'face': data.face, 'heroTag': heroTag}); }, child: AnimatedOpacity( opacity: isCurrent ? 1 : 0.6, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut, child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Stack( clipBehavior: Clip.none, children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: data.face != '' ? NetworkImgLayer( width: 38, height: 38, src: data.face, type: ImageType.avatar, ) : const CircleAvatar( backgroundColor: Color(0xFF5CB67B), backgroundImage: AssetImage( 'assets/images/logo/logo.png', ), ), ), Positioned( top: isLive && !isTop ? -5 : 0, right: isLive ? -6 : 4, child: Badge( smallSize: 8, label: isLive ? const Text(' Live ') : null, textColor: theme.colorScheme.onSecondaryContainer, alignment: AlignmentDirectional.topStart, isLabelVisible: isLive || (data is UpItem && (data.hasUpdate ?? false)), backgroundColor: isLive ? theme.colorScheme.secondaryContainer .withValues(alpha: 0.75) : theme.colorScheme.primary, ), ), ], ), const SizedBox(height: 4), Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: Text( isTop ? '${data.uname}\n' : data.uname!, maxLines: 2, textAlign: TextAlign.center, style: TextStyle( color: widget.dynamicsController.currentMid == data.mid ? theme.colorScheme.primary : theme.colorScheme.outline, height: 1.1, fontSize: 12.5, ), ), ), ], ), ), ), ); } }